View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.ast.xpath;
5   
6   import java.util.ArrayList;
7   import java.util.Iterator;
8   
9   import net.sourceforge.pmd.lang.ast.Node;
10  import net.sourceforge.pmd.lang.ast.RootNode;
11  
12  import org.jaxen.DefaultNavigator;
13  import org.jaxen.XPath;
14  import org.jaxen.util.SingleObjectIterator;
15  
16  /**
17   * @author daniels
18   */
19  public class DocumentNavigator extends DefaultNavigator {
20  
21      private final static Iterator<Node> EMPTY_ITERATOR = new ArrayList<Node>().iterator();
22  
23      public String getAttributeName(Object arg0) {
24  	return ((Attribute) arg0).getName();
25      }
26  
27      public String getAttributeNamespaceUri(Object arg0) {
28  	return "";
29      }
30  
31      public String getAttributeQName(Object arg0) {
32  	return ((Attribute) arg0).getName();
33      }
34  
35      public String getAttributeStringValue(Object arg0) {
36  	return ((Attribute) arg0).getStringValue();
37      }
38  
39      public String getCommentStringValue(Object arg0) {
40  	return "";
41      }
42  
43      public String getElementName(Object node) {
44  	return node.toString();
45      }
46  
47      public String getElementNamespaceUri(Object arg0) {
48  	return "";
49      }
50  
51      public String getElementQName(Object arg0) {
52  	return getElementName(arg0);
53      }
54  
55      public String getElementStringValue(Object arg0) {
56  	return "";
57      }
58  
59      public String getNamespacePrefix(Object arg0) {
60  	return "";
61      }
62  
63      public String getNamespaceStringValue(Object arg0) {
64  	return "";
65      }
66  
67      public String getTextStringValue(Object arg0) {
68  	return "";
69      }
70  
71      public boolean isAttribute(Object arg0) {
72  	return arg0 instanceof Attribute;
73      }
74  
75      public boolean isComment(Object arg0) {
76  	return false;
77      }
78  
79      public boolean isDocument(Object arg0) {
80  	return arg0 instanceof RootNode;
81      }
82  
83      public boolean isElement(Object arg0) {
84  	return arg0 instanceof Node;
85      }
86  
87      public boolean isNamespace(Object arg0) {
88  	return false;
89      }
90  
91      public boolean isProcessingInstruction(Object arg0) {
92  	return false;
93      }
94  
95      public boolean isText(Object arg0) {
96  	return false;
97      }
98  
99      public XPath parseXPath(String arg0) {
100 	return null;
101     }
102 
103     @Override
104     public Object getParentNode(Object arg0) {
105 	if (arg0 instanceof Node) {
106 	    return ((Node) arg0).jjtGetParent();
107 	}
108 	return ((Attribute) arg0).getParent();
109     }
110 
111     @Override
112     public Iterator<Attribute> getAttributeAxisIterator(Object arg0) {
113 	if (arg0 instanceof AttributeNode) {
114 	    return ((AttributeNode) arg0).getAttributeIterator();
115 	} else {
116 	    return new AttributeAxisIterator((Node) arg0);
117 	}
118     }
119 
120     /**
121      * Get an iterator over all of this node's children.
122      *
123      * @param contextNode The context node for the child axis.
124      * @return A possibly-empty iterator (not null).
125      */
126     @Override
127     public Iterator<Node> getChildAxisIterator(Object contextNode) {
128 	return new NodeIterator((Node) contextNode) {
129 	    @Override
130 	    protected Node getFirstNode(Node node) {
131 		return getFirstChild(node);
132 	    }
133 
134 	    @Override
135 	    protected Node getNextNode(Node node) {
136 		return getNextSibling(node);
137 	    }
138 	};
139     }
140 
141     /**
142      * Get a (single-member) iterator over this node's parent.
143      *
144      * @param contextNode the context node for the parent axis.
145      * @return A possibly-empty iterator (not null).
146      */
147     @Override
148     public Iterator<Node> getParentAxisIterator(Object contextNode) {
149 	if (isAttribute(contextNode)) {
150 	    return new SingleObjectIterator(((Attribute) contextNode).getParent());
151 	}
152 	Node parent = ((Node) contextNode).jjtGetParent();
153 	if (parent != null) {
154 	    return new SingleObjectIterator(parent);
155 	} else {
156 	    return EMPTY_ITERATOR;
157 	}
158     }
159 
160     /**
161      * Get an iterator over all following siblings.
162      *
163      * @param contextNode the context node for the sibling iterator.
164      * @return A possibly-empty iterator (not null).
165      */
166     @Override
167     public Iterator<Node> getFollowingSiblingAxisIterator(Object contextNode) {
168 	return new NodeIterator((Node) contextNode) {
169 	    @Override
170 	    protected Node getFirstNode(Node node) {
171 		return getNextNode(node);
172 	    }
173 
174 	    @Override
175 	    protected Node getNextNode(Node node) {
176 		return getNextSibling(node);
177 	    }
178 	};
179     }
180 
181     /**
182      * Get an iterator over all preceding siblings.
183      *
184      * @param contextNode The context node for the preceding sibling axis.
185      * @return A possibly-empty iterator (not null).
186      */
187     @Override
188     public Iterator<Node> getPrecedingSiblingAxisIterator(Object contextNode) {
189 	return new NodeIterator((Node) contextNode) {
190 	    @Override
191 	    protected Node getFirstNode(Node node) {
192 		return getNextNode(node);
193 	    }
194 
195 	    @Override
196 	    protected Node getNextNode(Node node) {
197 		return getPreviousSibling(node);
198 	    }
199 	};
200     }
201 
202     /**
203      * Get an iterator over all following nodes, depth-first.
204      *
205      * @param contextNode The context node for the following axis.
206      * @return A possibly-empty iterator (not null).
207      */
208     @Override
209     public Iterator<Node> getFollowingAxisIterator(Object contextNode) {
210 	return new NodeIterator((Node) contextNode) {
211 	    @Override
212 	    protected Node getFirstNode(Node node) {
213 		if (node == null) {
214 		    return null;
215 		} else {
216 		    Node sibling = getNextSibling(node);
217 		    if (sibling == null) {
218 			return getFirstNode(node.jjtGetParent());
219 		    } else {
220 			return sibling;
221 		    }
222 		}
223 	    }
224 
225 	    @Override
226 	    protected Node getNextNode(Node node) {
227 		if (node == null) {
228 		    return null;
229 		} else {
230 		    Node n = getFirstChild(node);
231 		    if (n == null) {
232 			n = getNextSibling(node);
233 		    }
234 		    if (n == null) {
235 			return getFirstNode(node.jjtGetParent());
236 		    } else {
237 			return n;
238 		    }
239 		}
240 	    }
241 	};
242     }
243 
244     /**
245      * Get an iterator over all preceding nodes, depth-first.
246      *
247      * @param contextNode The context node for the preceding axis.
248      * @return A possibly-empty iterator (not null).
249      */
250     @Override
251     public Iterator<Node> getPrecedingAxisIterator(Object contextNode) {
252 	return new NodeIterator((Node) contextNode) {
253 	    @Override
254 	    protected Node getFirstNode(Node node) {
255 		if (node == null) {
256 		    return null;
257 		} else {
258 		    Node sibling = getPreviousSibling(node);
259 		    if (sibling == null) {
260 			return getFirstNode(node.jjtGetParent());
261 		    } else {
262 			return sibling;
263 		    }
264 		}
265 	    }
266 
267 	    @Override
268 	    protected Node getNextNode(Node node) {
269 		if (node == null) {
270 		    return null;
271 		} else {
272 		    Node n = getLastChild(node);
273 		    if (n == null) {
274 			n = getPreviousSibling(node);
275 		    }
276 		    if (n == null) {
277 			return getFirstNode(node.jjtGetParent());
278 		    } else {
279 			return n;
280 		    }
281 		}
282 	    }
283 	};
284     }
285 
286     @Override
287     public Object getDocumentNode(Object contextNode) {
288 	if (isDocument(contextNode)) {
289 	    return contextNode;
290 	}
291 	return getDocumentNode(getParentNode(contextNode));
292     }
293 }