Source code: com/puppycrawl/tools/checkstyle/checks/xpath/DocumentNavigator.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2003 Oliver Burn
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ////////////////////////////////////////////////////////////////////////////////
19 package com.puppycrawl.tools.checkstyle.checks.xpath;
20
21 import java.util.ArrayList;
22 import java.util.Iterator;
23
24 import org.jaxen.DefaultNavigator;
25 import org.jaxen.XPath;
26 import org.jaxen.util.SingleObjectIterator;
27 import org.saxpath.SAXPathException;
28
29 import com.puppycrawl.tools.checkstyle.api.DetailAST;
30 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
31
32 /**
33 * Navigates around a DetailAST, using XPath semantics.
34 * Requires jaxen, http://jaxen.sourceforge.net and
35 * saxpath, http://sourceforge.net/projects/saxpath/.
36 * Idea shamelessly stolen from the equivalent PMD code (pmd.sourceforge.net).
37 * @author Rick Giles
38 */
39 public class DocumentNavigator
40 extends DefaultNavigator
41 {
42 /** Iterator for an empty sequence */
43 private static final Iterator EMPTY_ITERATOR = new ArrayList().iterator();
44
45 /**
46 * @see org.jaxen.DefaultNavigator#getAttributeName(java.lang.Object)
47 */
48 public String getAttributeName(Object aObject)
49 {
50 return ((Attribute) aObject).getName();
51 }
52
53 /**
54 * @see org.jaxen.DefaultNavigator#getAttributeNamespaceUri
55 */
56 public String getAttributeNamespaceUri(Object aObject)
57 {
58 return null;
59 }
60
61 /**
62 * @see org.jaxen.DefaultNavigator#getAttributeQName(java.lang.Object)
63 */
64 public String getAttributeQName(Object aObject)
65 {
66 return ((Attribute) aObject).getName();
67 }
68
69 /**
70 * @see org.jaxen.DefaultNavigator#getAttributeStringValue(java.lang.Object)
71 */
72 public String getAttributeStringValue(Object aObject)
73 {
74 return ((Attribute) aObject).getValue();
75 }
76
77 /**
78 * @see org.jaxen.DefaultNavigator#getCommentStringValue(java.lang.Object)
79 */
80 public String getCommentStringValue(Object aObject)
81 {
82 return null;
83 }
84
85 /**
86 * @see org.jaxen.DefaultNavigator#getElementName(java.lang.Object)
87 */
88 public String getElementName(Object aObject)
89 {
90 final int type = ((DetailAST) aObject).getType();
91 return TokenTypes.getTokenName(type);
92 }
93
94 /**
95 * @see org.jaxen.DefaultNavigator#getElementNamespaceUri(java.lang.Object)
96 */
97 public String getElementNamespaceUri(Object aObject)
98 {
99 return null;
100 }
101
102 /**
103 * @see org.jaxen.DefaultNavigator#getElementQName(java.lang.Object)
104 */
105 public String getElementQName(Object aObject)
106 {
107 return getElementName(aObject);
108 }
109
110 /**
111 * @see org.jaxen.DefaultNavigator#getElementStringValue(java.lang.Object)
112 */
113 public String getElementStringValue(Object aObject)
114 {
115 return null;
116 }
117
118 /**
119 * @see org.jaxen.DefaultNavigator#getNamespacePrefix(java.lang.Object)
120 */
121 public String getNamespacePrefix(Object aObject)
122 {
123 return null;
124 }
125
126 /**
127 * @see org.jaxen.DefaultNavigator#getNamespaceStringValue(java.lang.Object)
128 */
129 public String getNamespaceStringValue(Object aObject)
130 {
131 return null;
132 }
133
134 /**
135 * @see org.jaxen.DefaultNavigator#getTextStringValue(java.lang.Object)
136 */
137 public String getTextStringValue(Object aObject)
138 {
139 return null;
140 }
141
142 /**
143 * @see org.jaxen.DefaultNavigator#isAttribute(java.lang.Object)
144 */
145 public boolean isAttribute(Object aObject)
146 {
147 return aObject instanceof Attribute;
148 }
149
150 /**
151 * @see org.jaxen.DefaultNavigator#isComment(java.lang.Object)
152 */
153 public boolean isComment(Object aObject)
154 {
155 return false;
156 }
157
158 /**
159 * @see org.jaxen.DefaultNavigator#isDocument(java.lang.Object)
160 */
161 public boolean isDocument(Object aObject)
162 {
163 if (aObject instanceof DetailAST) {
164 final DetailAST node = (DetailAST) aObject;
165 return (node.getType() == TokenTypes.EOF);
166 }
167 else {
168 return false;
169 }
170 }
171
172 /**
173 * @see org.jaxen.DefaultNavigator#isElement(java.lang.Object)
174 */
175 public boolean isElement(Object aObject)
176 {
177 return aObject instanceof DetailAST;
178 }
179
180 /**
181 * @see org.jaxen.DefaultNavigator#isNamespace(java.lang.Object)
182 */
183 public boolean isNamespace(Object aObject)
184 {
185 return false;
186 }
187
188 /**
189 * @see org.jaxen.DefaultNavigator#isProcessingInstruction(java.lang.Object)
190 */
191 public boolean isProcessingInstruction(Object aObject)
192 {
193 return false;
194 }
195
196 /**
197 * @see org.jaxen.DefaultNavigator#isText(java.lang.Object)
198 */
199 public boolean isText(Object aObject)
200 {
201 return false;
202 }
203
204 /**
205 * @see org.jaxen.DefaultNavigator#parseXPath(java.lang.String)
206 */
207 public XPath parseXPath(String aObject)
208 throws SAXPathException
209 {
210 return null;
211 }
212
213 /**
214 * @see org.jaxen.Navigator#getParentNode(java.lang.Object)
215 */
216 public Object getParentNode(Object aObject)
217 {
218 if (aObject instanceof DetailAST) {
219 return ((DetailAST) aObject).getParent();
220 }
221 else {
222 return ((Attribute) aObject).getParent();
223 }
224 }
225
226 /**
227 * @see org.jaxen.Navigator#getAttributeAxisIterator(java.lang.Object)
228 */
229 public Iterator getAttributeAxisIterator(Object aObject)
230 {
231 final DetailAST contextNode = (DetailAST) aObject;
232 return new AttributeAxisIterator(contextNode);
233 }
234
235 /**
236 * Get an iterator over all of this node's children.
237 *
238 * @param aObject The context node for the child axis.
239 * @return A possibly-empty iterator (not null).
240 */
241 public Iterator getChildAxisIterator(Object aObject)
242 {
243 return new NodeIterator((DetailAST) aObject)
244 {
245 /** @see NodeIterator */
246 protected DetailAST getFirstNode(DetailAST aAST)
247 {
248 return getFirstChild(aAST);
249 }
250
251 /** @see NodeIterator */
252 protected DetailAST getNextNode(DetailAST aAST)
253 {
254 return getNextSibling(aAST);
255 }
256 };
257 }
258
259 /**
260 * Get a (single-member) iterator over this node's parent.
261 *
262 * @param aObject the context node for the parent axis.
263 * @return A possibly-empty iterator (not null).
264 */
265 public Iterator getParentAxisIterator(Object aObject)
266 {
267 if (isAttribute(aObject)) {
268 return new SingleObjectIterator(((Attribute) aObject).getParent());
269 }
270 else {
271 DetailAST parent = ((DetailAST) aObject).getParent();
272 if (parent != null) {
273 return new SingleObjectIterator(parent);
274 }
275 else {
276 return EMPTY_ITERATOR;
277 }
278 }
279 }
280
281 /**
282 * Get an iterator over all following siblings.
283 *
284 * @param aObject the context node for the sibling iterator.
285 * @return A possibly-empty iterator (not null).
286 */
287 public Iterator getFollowingSiblingAxisIterator(Object aObject)
288 {
289 return new NodeIterator((DetailAST) aObject)
290 {
291 /** @see NodeIterator */
292 protected DetailAST getFirstNode(DetailAST aAST)
293 {
294 return getNextNode(aAST);
295 }
296
297 /** @see NodeIterator */
298 protected DetailAST getNextNode(DetailAST aAST)
299 {
300 return getNextSibling(aAST);
301 }
302 };
303 }
304
305 /**
306 * Get an iterator over all preceding siblings.
307 *
308 * @param aObject The context node for the preceding sibling axis.
309 * @return A possibly-empty iterator (not null).
310 */
311 public Iterator getPrecedingSiblingAxisIterator(Object aObject)
312 {
313 return new NodeIterator((DetailAST) aObject)
314 {
315 /** @see NodeIterator */
316 protected DetailAST getFirstNode(DetailAST aAST)
317 {
318 return getNextNode(aAST);
319 }
320
321 /** @see NodeIterator */
322 protected DetailAST getNextNode(DetailAST aAST)
323 {
324 return getPreviousSibling(aAST);
325 }
326 };
327 }
328
329 /**
330 * Get an iterator over all following nodes, depth-first.
331 *
332 * @param aObject The context node for the following axis.
333 * @return A possibly-empty iterator (not null).
334 */
335 public Iterator getFollowingAxisIterator(Object aObject)
336 {
337 return new NodeIterator((DetailAST) aObject)
338 {
339 /** @see NodeIterator */
340 protected DetailAST getFirstNode(DetailAST aAST)
341 {
342 if (aAST == null) {
343 return null;
344 }
345 else {
346 final DetailAST sibling = getNextSibling(aAST);
347 if (sibling == null) {
348 return getFirstNode(aAST.getParent());
349 }
350 else {
351 return sibling;
352 }
353 }
354 }
355
356 /** @see NodeIterator */
357 protected DetailAST getNextNode(DetailAST aAST)
358 {
359 if (aAST == null) {
360 return null;
361 }
362 else {
363 DetailAST n = getFirstChild(aAST);
364 if (n == null) {
365 n = getNextSibling(aAST);
366 }
367 if (n == null) {
368 return getFirstNode(aAST.getParent());
369 }
370 else {
371 return n;
372 }
373 }
374 }
375 };
376 }
377
378 /**
379 * Get an iterator over all preceding nodes, depth-first.
380 *
381 * @param aObject The context node for the preceding axis.
382 * @return A possibly-empty iterator (not null).
383 */
384 public Iterator getPrecedingAxisIterator(Object aObject)
385 {
386 return new NodeIterator((DetailAST) aObject)
387 {
388 /** @see NodeIterator */
389 protected DetailAST getFirstNode(DetailAST aAST)
390 {
391 if (aAST == null) {
392 return null;
393 }
394 else {
395 final DetailAST sibling = getPreviousSibling(aAST);
396 if (sibling == null) {
397 return getFirstNode(aAST.getParent());
398 }
399 else {
400 return sibling;
401 }
402 }
403 }
404
405 /** @see NodeIterator */
406 protected DetailAST getNextNode(DetailAST aAST)
407 {
408 if (aAST == null) {
409 return null;
410 }
411 else {
412 DetailAST n = getLastChild(aAST);
413 if (n == null) {
414 n = getPreviousSibling(aAST);
415 }
416 if (n == null) {
417 return getFirstNode(aAST.getParent());
418 }
419 else {
420 return n;
421 }
422 }
423 }
424 };
425 }
426
427 /** @see org.jaxen.Navigator#getDocumentNode(java.lang.Object) */
428 public Object getDocumentNode(Object aObject)
429 {
430 if (isDocument(aObject)) {
431 return aObject;
432 }
433 else {
434 return getDocumentNode(getParentNode(aObject));
435 }
436 }
437 }