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         if (arg0 instanceof Attribute) {
109             return ((Attribute) arg0).getParent();
110         }
111         // can't navigate to parent node...
112         return null;
113     }
114 
115     @Override
116     public Iterator<Attribute> getAttributeAxisIterator(Object arg0) {
117 	if (arg0 instanceof AttributeNode) {
118 	    return ((AttributeNode) arg0).getAttributeIterator();
119 	} else {
120 	    return new AttributeAxisIterator((Node) arg0);
121 	}
122     }
123 
124     /**
125      * Get an iterator over all of this node's children.
126      *
127      * @param contextNode The context node for the child axis.
128      * @return A possibly-empty iterator (not null).
129      */
130     @Override
131     public Iterator<Node> getChildAxisIterator(Object contextNode) {
132 	return new NodeIterator((Node) contextNode) {
133 	    @Override
134 	    protected Node getFirstNode(Node node) {
135 		return getFirstChild(node);
136 	    }
137 
138 	    @Override
139 	    protected Node getNextNode(Node node) {
140 		return getNextSibling(node);
141 	    }
142 	};
143     }
144 
145     /**
146      * Get a (single-member) iterator over this node's parent.
147      *
148      * @param contextNode the context node for the parent axis.
149      * @return A possibly-empty iterator (not null).
150      */
151     @Override
152     public Iterator<Node> getParentAxisIterator(Object contextNode) {
153 	if (isAttribute(contextNode)) {
154 	    return new SingleObjectIterator(((Attribute) contextNode).getParent());
155 	}
156 	Node parent = ((Node) contextNode).jjtGetParent();
157 	if (parent != null) {
158 	    return new SingleObjectIterator(parent);
159 	} else {
160 	    return EMPTY_ITERATOR;
161 	}
162     }
163 
164     /**
165      * Get an iterator over all following siblings.
166      *
167      * @param contextNode the context node for the sibling iterator.
168      * @return A possibly-empty iterator (not null).
169      */
170     @Override
171     public Iterator<Node> getFollowingSiblingAxisIterator(Object contextNode) {
172 	return new NodeIterator((Node) contextNode) {
173 	    @Override
174 	    protected Node getFirstNode(Node node) {
175 		return getNextNode(node);
176 	    }
177 
178 	    @Override
179 	    protected Node getNextNode(Node node) {
180 		return getNextSibling(node);
181 	    }
182 	};
183     }
184 
185     /**
186      * Get an iterator over all preceding siblings.
187      *
188      * @param contextNode The context node for the preceding sibling axis.
189      * @return A possibly-empty iterator (not null).
190      */
191     @Override
192     public Iterator<Node> getPrecedingSiblingAxisIterator(Object contextNode) {
193 	return new NodeIterator((Node) contextNode) {
194 	    @Override
195 	    protected Node getFirstNode(Node node) {
196 		return getNextNode(node);
197 	    }
198 
199 	    @Override
200 	    protected Node getNextNode(Node node) {
201 		return getPreviousSibling(node);
202 	    }
203 	};
204     }
205 
206     /**
207      * Get an iterator over all following nodes, depth-first.
208      *
209      * @param contextNode The context node for the following axis.
210      * @return A possibly-empty iterator (not null).
211      */
212     @Override
213     public Iterator<Node> getFollowingAxisIterator(Object contextNode) {
214 	return new NodeIterator((Node) contextNode) {
215 	    @Override
216 	    protected Node getFirstNode(Node node) {
217 		if (node == null) {
218 		    return null;
219 		} else {
220 		    Node sibling = getNextSibling(node);
221 		    if (sibling == null) {
222 			return getFirstNode(node.jjtGetParent());
223 		    } else {
224 			return sibling;
225 		    }
226 		}
227 	    }
228 
229 	    @Override
230 	    protected Node getNextNode(Node node) {
231 		if (node == null) {
232 		    return null;
233 		} else {
234 		    Node n = getFirstChild(node);
235 		    if (n == null) {
236 			n = getNextSibling(node);
237 		    }
238 		    if (n == null) {
239 			return getFirstNode(node.jjtGetParent());
240 		    } else {
241 			return n;
242 		    }
243 		}
244 	    }
245 	};
246     }
247 
248     /**
249      * Get an iterator over all preceding nodes, depth-first.
250      *
251      * @param contextNode The context node for the preceding axis.
252      * @return A possibly-empty iterator (not null).
253      */
254     @Override
255     public Iterator<Node> getPrecedingAxisIterator(Object contextNode) {
256 	return new NodeIterator((Node) contextNode) {
257 	    @Override
258 	    protected Node getFirstNode(Node node) {
259 		if (node == null) {
260 		    return null;
261 		} else {
262 		    Node sibling = getPreviousSibling(node);
263 		    if (sibling == null) {
264 			return getFirstNode(node.jjtGetParent());
265 		    } else {
266 			return sibling;
267 		    }
268 		}
269 	    }
270 
271 	    @Override
272 	    protected Node getNextNode(Node node) {
273 		if (node == null) {
274 		    return null;
275 		} else {
276 		    Node n = getLastChild(node);
277 		    if (n == null) {
278 			n = getPreviousSibling(node);
279 		    }
280 		    if (n == null) {
281 			return getFirstNode(node.jjtGetParent());
282 		    } else {
283 			return n;
284 		    }
285 		}
286 	    }
287 	};
288     }
289 
290     @Override
291     public Object getDocumentNode(Object contextNode) {
292         if (isDocument(contextNode)) {
293             return contextNode;
294         }
295         if (null == contextNode) {
296             throw new RuntimeException("contextNode may not be null");
297         }
298         return getDocumentNode(getParentNode(contextNode));
299     }
300 }