View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2018 the original author or authors.
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  
20  package com.puppycrawl.tools.checkstyle.xpath;
21  
22  import static com.puppycrawl.tools.checkstyle.internal.utils.XpathUtil.getXpathItems;
23  import static org.junit.Assert.assertArrayEquals;
24  import static org.junit.Assert.assertEquals;
25  import static org.junit.Assert.assertFalse;
26  import static org.junit.Assert.assertTrue;
27  import static org.junit.Assert.fail;
28  
29  import java.io.File;
30  import java.util.List;
31  
32  import org.junit.Test;
33  
34  import com.puppycrawl.tools.checkstyle.AbstractPathTestSupport;
35  import com.puppycrawl.tools.checkstyle.JavaParser;
36  import com.puppycrawl.tools.checkstyle.api.DetailAST;
37  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
38  import net.sf.saxon.om.AxisInfo;
39  import net.sf.saxon.om.Item;
40  import net.sf.saxon.trans.XPathException;
41  import net.sf.saxon.tree.iter.EmptyIterator;
42  
43  public class XpathMapperTest extends AbstractPathTestSupport {
44  
45      @Override
46      protected String getPackageLocation() {
47          return "com/puppycrawl/tools/checkstyle/xpath/xpathmapper";
48      }
49  
50      @Test
51      public void testFullPath() throws Exception {
52          final String xpath = "/CLASS_DEF/OBJBLOCK/METHOD_DEF[1]/SLIST/VARIABLE_DEF[2]";
53          final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
54          final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
55          final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
56                  TokenTypes.CLASS_DEF)
57                  .findFirstToken(TokenTypes.OBJBLOCK)
58                  .findFirstToken(TokenTypes.METHOD_DEF)
59                  .findFirstToken(TokenTypes.SLIST)
60                  .findFirstToken(TokenTypes.VARIABLE_DEF)
61                  .getNextSibling()
62                  .getNextSibling();
63          final DetailAST[] expected = {expectedVariableDefNode};
64          assertArrayEquals("Result nodes differ from expected", expected, actual);
65      }
66  
67      @Test
68      public void testParent() throws Exception {
69          final String xpath = "(//VARIABLE_DEF)[1]/..";
70          final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
71          final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
72          final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
73                  TokenTypes.CLASS_DEF)
74                  .findFirstToken(TokenTypes.OBJBLOCK)
75                  .findFirstToken(TokenTypes.METHOD_DEF)
76                  .findFirstToken(TokenTypes.SLIST);
77          final DetailAST[] expected = {expectedVariableDefNode};
78          assertArrayEquals("Result nodes differ from expected", expected, actual);
79      }
80  
81      @Test
82      public void testCurlyBrackets() throws Exception {
83          final String xpath = "(//RCURLY)[2]";
84          final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
85          final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
86          final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
87                  TokenTypes.CLASS_DEF)
88                  .findFirstToken(TokenTypes.OBJBLOCK)
89                  .findFirstToken(TokenTypes.METHOD_DEF)
90                  .findFirstToken(TokenTypes.SLIST)
91                  .findFirstToken(TokenTypes.RCURLY);
92          final DetailAST[] expected = {expectedVariableDefNode};
93          assertArrayEquals("Result nodes differ from expected", expected, actual);
94      }
95  
96      @Test
97      public void testOr() throws Exception {
98          final String xpath = "//CLASS_DEF | //METHOD_DEF";
99          final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
100         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
101         final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
102                 TokenTypes.CLASS_DEF);
103         final DetailAST expectedMethodDefNode1 = expectedClassDefNode
104                 .findFirstToken(TokenTypes.OBJBLOCK)
105                 .findFirstToken(TokenTypes.METHOD_DEF);
106         final DetailAST expectedMethodDefNode2 = expectedMethodDefNode1.getNextSibling();
107         final DetailAST[] expected = {expectedClassDefNode, expectedMethodDefNode1,
108             expectedMethodDefNode2};
109         assertArrayEquals("Result nodes differ from expected", expected, actual);
110     }
111 
112     @Test
113     public void testAttributeOr() throws Exception {
114         final String xpath = "//METHOD_DEF[@text='getSomeMethod' or @text='nonExistentMethod']";
115         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
116         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
117         final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
118                 TokenTypes.CLASS_DEF);
119         final DetailAST expectedMethodDefNode = expectedClassDefNode
120                 .findFirstToken(TokenTypes.OBJBLOCK)
121                 .findFirstToken(TokenTypes.METHOD_DEF)
122                 .getNextSibling();
123         final DetailAST[] expected = {expectedMethodDefNode};
124         assertArrayEquals("Result nodes differ from expected", expected, actual);
125     }
126 
127     @Test
128     public void testAttributeAnd() throws Exception {
129         final String xpath = "//METHOD_DEF[@text='callSomeMethod' and "
130                 + "../..[@text='InputXpathMapperAst']]";
131         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
132         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
133         final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
134                 TokenTypes.CLASS_DEF);
135         final DetailAST expectedMethodDefNode = expectedClassDefNode
136                 .findFirstToken(TokenTypes.OBJBLOCK)
137                 .findFirstToken(TokenTypes.METHOD_DEF);
138         final DetailAST[] expected = {expectedMethodDefNode};
139         assertArrayEquals("Result nodes differ from expected", expected, actual);
140     }
141 
142     @Test
143     public void testQueryAllElementsWithAttribute() throws Exception {
144         final String xpath = "//*[@text]";
145         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
146         final List<Item> nodes = getXpathItems(xpath, rootNode);
147         assertEquals("Invalid number of nodes", 18, nodes.size());
148     }
149 
150     @Test
151     public void testQueryElementByIndex() throws Exception {
152         final String xpath = "(//VARIABLE_DEF)[1]";
153         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
154         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
155         assertEquals("Invalid number of nodes", 1, actual.length);
156         final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
157                 TokenTypes.CLASS_DEF)
158                 .findFirstToken(TokenTypes.OBJBLOCK)
159                 .findFirstToken(TokenTypes.METHOD_DEF)
160                 .findFirstToken(TokenTypes.SLIST)
161                 .findFirstToken(TokenTypes.VARIABLE_DEF);
162         final DetailAST[] expected = {expectedVariableDefNode};
163         assertArrayEquals("Result nodes differ from expected", expected, actual);
164     }
165 
166     @Test
167     public void testQueryAllVariableDefinitionsWithAttribute() throws Exception {
168         final String xpath = "//VARIABLE_DEF[@*]";
169         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
170         final List<Item> nodes = getXpathItems(xpath, rootNode);
171         assertEquals("Invalid number of nodes", 4, nodes.size());
172     }
173 
174     @Test
175     public void testQueryAllVariableDefWrongAttribute() throws Exception {
176         final String xpath = "//VARIABLE_DEF[@qwe]";
177         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
178         final List<Item> nodes = getXpathItems(xpath, rootNode);
179         assertEquals("Invalid number of nodes", 0, nodes.size());
180     }
181 
182     @Test
183     public void testQueryAllMethodDefinitionsInContext() throws Exception {
184         final String objectXpath = "/CLASS_DEF[@text='InputXpathMapperAst']//OBJBLOCK";
185         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
186         final List<Item> objectNodes = getXpathItems(objectXpath, rootNode);
187         assertEquals("Invalid number of nodes", 1, objectNodes.size());
188         final AbstractNode objNode = (AbstractNode) objectNodes.get(0);
189         final String methodsXpath = "METHOD_DEF";
190         final List<Item> methodsNodes = getXpathItems(methodsXpath, objNode);
191         assertEquals("Invalid number of nodes", 2, methodsNodes.size());
192         final DetailAST[] actual = convertToArray(methodsNodes);
193         final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
194                 TokenTypes.CLASS_DEF)
195                 .findFirstToken(TokenTypes.OBJBLOCK)
196                 .findFirstToken(TokenTypes.METHOD_DEF);
197         final DetailAST[] expected = {expectedMethodDefNode,
198             expectedMethodDefNode.getNextSibling()};
199         assertArrayEquals("Result nodes differ from expected", expected, actual);
200     }
201 
202     @Test
203     public void testQueryAllClassDefinitions() throws Exception {
204         final String xpath = "CLASS_DEF";
205         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
206         final List<Item> nodes = getXpathItems(xpath, rootNode);
207         assertEquals("Invalid number of nodes", 1, nodes.size());
208         final AbstractNode classDefNode = (AbstractNode) nodes.get(0);
209         assertEquals("Invalid number of nodes", 3, classDefNode.getLineNumber());
210         assertEquals("Invalid number of nodes", 0, classDefNode.getColumnNumber());
211         final DetailAST[] actual = convertToArray(nodes);
212         final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
213                 TokenTypes.CLASS_DEF);
214         final DetailAST[] expected = {expectedClassDefNode};
215         assertArrayEquals("Result nodes differ from expected", expected, actual);
216     }
217 
218     @Test
219     public void testQueryByMethodName() throws Exception {
220         final String xpath = "//METHOD_DEF[@text='getSomeMethod']";
221         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
222         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
223         final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
224                 TokenTypes.CLASS_DEF)
225                 .findFirstToken(TokenTypes.OBJBLOCK)
226                 .findFirstToken(TokenTypes.METHOD_DEF)
227                 .getNextSibling();
228         final DetailAST[] expected = {expectedMethodDefNode};
229         assertArrayEquals("Result nodes differ from expected", expected, actual);
230     }
231 
232     @Test
233     public void testQueryMethodDefinitionsByClassName() throws Exception {
234         final String xpath = "/CLASS_DEF[@text='InputXpathMapperAst']//OBJBLOCK//METHOD_DEF";
235         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
236         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
237         final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
238                 TokenTypes.CLASS_DEF)
239                 .findFirstToken(TokenTypes.OBJBLOCK)
240                 .findFirstToken(TokenTypes.METHOD_DEF);
241         final DetailAST[] expected = {expectedMethodDefNode,
242             expectedMethodDefNode.getNextSibling()};
243         assertArrayEquals("Result nodes differ from expected", expected, actual);
244     }
245 
246     @Test
247     public void testQueryByClassNameAndMethodName() throws Exception {
248         final String xpath = "/CLASS_DEF[@text='InputXpathMapperAst']//OBJBLOCK"
249                 + "//METHOD_DEF[@text='getSomeMethod']";
250         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
251         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
252         final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
253                 TokenTypes.CLASS_DEF)
254                 .findFirstToken(TokenTypes.OBJBLOCK)
255                 .findFirstToken(TokenTypes.METHOD_DEF)
256                 .getNextSibling();
257         final DetailAST[] expected = {expectedMethodDefNode};
258         assertArrayEquals("Result nodes differ from expected", expected, actual);
259     }
260 
261     @Test
262     public void testQueryClassDefinitionByClassName() throws Exception {
263         final String xpath = "/CLASS_DEF[@text='InputXpathMapperAst']";
264         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
265         final List<Item> nodes = getXpathItems(xpath, rootNode);
266         final DetailAST[] actual = convertToArray(nodes);
267         final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
268                 TokenTypes.CLASS_DEF);
269         final DetailAST[] expected = {expectedClassDefNode};
270         final ElementNode classDefNode = (ElementNode) nodes.get(0);
271         assertEquals("Invalid number of nodes", "CLASS_DEF", classDefNode.getStringValue());
272         assertEquals("Invalid number of nodes", "InputXpathMapperAst",
273                 classDefNode.getAttributeValue("", "text"));
274         assertArrayEquals("Result nodes differ from expected", expected, actual);
275     }
276 
277     @Test
278     public void testQueryWrongClassName() throws Exception {
279         final String xpath = "/CLASS_DEF[@text='WrongName']";
280         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
281         final List<Item> nodes = getXpathItems(xpath, rootNode);
282         assertTrue("Should return true, because no item matches xpath", nodes.isEmpty());
283     }
284 
285     @Test
286     public void testQueryWrongXpath() throws Exception {
287         final String xpath = "/WRONG_XPATH";
288         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
289         final List<Item> nodes = getXpathItems(xpath, rootNode);
290         assertTrue("Should return true, because no item matches xpath", nodes.isEmpty());
291     }
292 
293     @Test
294     public void testQueryAncestor() throws Exception {
295         final String xpath = "//VARIABLE_DEF[@text='another']/ancestor::METHOD_DEF";
296         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
297         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
298         final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
299                 TokenTypes.CLASS_DEF)
300                 .findFirstToken(TokenTypes.OBJBLOCK)
301                 .findFirstToken(TokenTypes.METHOD_DEF);
302         final DetailAST[] expected = {expectedMethodDefNode};
303         assertArrayEquals("Result nodes differ from expected", expected, actual);
304     }
305 
306     @Test
307     public void testQueryAncestorOrSelf() throws Exception {
308         final String xpath = "//VARIABLE_DEF[@text='another']/ancestor-or-self::VARIABLE_DEF";
309         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
310         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
311         final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
312                 TokenTypes.CLASS_DEF)
313                 .findFirstToken(TokenTypes.OBJBLOCK)
314                 .findFirstToken(TokenTypes.METHOD_DEF)
315                 .findFirstToken(TokenTypes.SLIST)
316                 .findFirstToken(TokenTypes.VARIABLE_DEF)
317                 .getNextSibling()
318                 .getNextSibling();
319         final DetailAST[] expected = {expectedVariableDefNode};
320         assertArrayEquals("Result nodes differ from expected", expected, actual);
321     }
322 
323     @Test
324     public void testQueryDescendant() throws Exception {
325         final String xpath = "//METHOD_DEF/descendant::EXPR";
326         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
327         final List<Item> nodes = getXpathItems(xpath, rootNode);
328         assertEquals("Invalid number of nodes", 6, nodes.size());
329     }
330 
331     @Test
332     public void testQueryDescendantOrSelf() throws Exception {
333         final String xpath = "//METHOD_DEF/descendant-or-self::METHOD_DEF";
334         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
335         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
336         final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
337                 TokenTypes.CLASS_DEF)
338                 .findFirstToken(TokenTypes.OBJBLOCK)
339                 .findFirstToken(TokenTypes.METHOD_DEF);
340         final DetailAST[] expected = {expectedMethodDefNode,
341             expectedMethodDefNode.getNextSibling()};
342         assertArrayEquals("Result nodes differ from expected", expected, actual);
343     }
344 
345     @Test
346     public void testQueryNoChild() throws Exception {
347         final String xpath = "//RCURLY/METHOD_DEF";
348         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
349         final List<Item> nodes = getXpathItems(xpath, rootNode);
350         assertTrue("Should return true, because no item matches xpath", nodes.isEmpty());
351     }
352 
353     @Test
354     public void testQueryNoDescendant() throws Exception {
355         final String xpath = "//RCURLY/descendant::METHOD_DEF";
356         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
357         final List<Item> nodes = getXpathItems(xpath, rootNode);
358         assertTrue("Should return true, because no item matches xpath", nodes.isEmpty());
359     }
360 
361     @Test
362     public void testQueryRootNotImplementedAxis() throws Exception {
363         final String xpath = "//following-sibling::METHOD_DEF";
364         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
365         try {
366             getXpathItems(xpath, rootNode);
367             fail("Exception is excepted");
368         }
369         catch (XPathException ex) {
370             assertEquals("Invalid number of nodes", "Operation is not supported", ex.getMessage());
371         }
372     }
373 
374     @Test
375     public void testQueryElementNotImplementedAxis() throws Exception {
376         final String xpath = "/CLASS_DEF//following-sibling::METHOD_DEF";
377         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
378         try {
379             getXpathItems(xpath, rootNode);
380             fail("Exception is excepted");
381         }
382         catch (XPathException ex) {
383             assertEquals("Invalid number of nodes", "Operation is not supported", ex.getMessage());
384         }
385     }
386 
387     @Test
388     public void testQuerySelf() throws Exception {
389         final String objectXpath = "/CLASS_DEF[@text='InputXpathMapperAst']//OBJBLOCK";
390         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
391         final List<Item> objectNodes = getXpathItems(objectXpath, rootNode);
392         assertEquals("Invalid number of nodes", 1, objectNodes.size());
393         final AbstractNode objNode = (AbstractNode) objectNodes.get(0);
394         final String methodsXpath = "self::OBJBLOCK";
395         final DetailAST[] actual = convertToArray(getXpathItems(methodsXpath, objNode));
396         final DetailAST expectedObjBlockNode = getSiblingByType(rootNode.getUnderlyingNode(),
397                 TokenTypes.CLASS_DEF)
398                 .findFirstToken(TokenTypes.OBJBLOCK);
399         final DetailAST[] expected = {expectedObjBlockNode};
400         assertArrayEquals("Result nodes differ from expected", expected, actual);
401     }
402 
403     @Test
404     public void testRootWithNullDetailAst() {
405         final RootNode emptyRootNode = new RootNode(null);
406         assertFalse("Empty node should not have children", emptyRootNode.hasChildNodes());
407         assertEquals("Invalid number of nodes", EmptyIterator.OfNodes.THE_INSTANCE,
408                 emptyRootNode.iterateAxis(
409                 AxisInfo.DESCENDANT));
410         assertEquals("Invalid number of nodes", EmptyIterator.OfNodes.THE_INSTANCE,
411                 emptyRootNode.iterateAxis(AxisInfo.CHILD));
412     }
413 
414     @Test
415     public void testQueryNonExistentAttribute() throws Exception {
416         final String xpath = "/CLASS_DEF[@text='InputXpathMapperAst']";
417         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
418         final List<Item> nodes = getXpathItems(xpath, rootNode);
419         final ElementNode classDefNode = (ElementNode) nodes.get(0);
420         try {
421             classDefNode.getAttributeValue("", "noneExistingAttribute");
422             fail("Exception is excepted");
423         }
424         catch (UnsupportedOperationException ex) {
425             assertEquals("Invalid number of nodes", "Operation is not supported", ex.getMessage());
426         }
427     }
428 
429     @Test
430     public void testQueryRootSelf() throws Exception {
431         final String xpath = "self::node()";
432         final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
433         final List<Item> nodes = getXpathItems(xpath, rootNode);
434         assertEquals("Invalid number of nodes", 1, nodes.size());
435     }
436 
437     @Test
438     public void testQueryAnnotation() throws Exception {
439         final String xpath = "//ANNOTATION[@text='SuppressWarnings']";
440         final RootNode rootNode = getRootNode("InputXpathMapperAnnotation.java");
441         final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
442         final DetailAST expectedAnnotationNode = getSiblingByType(rootNode.getUnderlyingNode(),
443                 TokenTypes.CLASS_DEF)
444                 .findFirstToken(TokenTypes.MODIFIERS)
445                 .findFirstToken(TokenTypes.ANNOTATION);
446         final DetailAST[] expected = {expectedAnnotationNode};
447         assertArrayEquals("Result nodes differ from expected", expected, actual);
448     }
449 
450     @Test
451     public void testQueryNonExistentAnnotation() throws Exception {
452         final String xpath = "//ANNOTATION[@text='SpringBootApplication']";
453         final RootNode rootNode = getRootNode("InputXpathMapperAnnotation.java");
454         final List<Item> nodes = getXpathItems(xpath, rootNode);
455         assertEquals("Invalid number of nodes", 0, nodes.size());
456     }
457 
458     @Test
459     public void testQueryEnumDef() throws Exception {
460         final String xpath = "/ENUM_DEF";
461         final RootNode enumRootNode = getRootNode("InputXpathMapperEnum.java");
462         final DetailAST[] actual = convertToArray(getXpathItems(xpath, enumRootNode));
463         final DetailAST expectedEnumDefNode = getSiblingByType(enumRootNode.getUnderlyingNode(),
464                 TokenTypes.ENUM_DEF);
465         final DetailAST[] expected = {expectedEnumDefNode};
466         assertArrayEquals("Result nodes differ from expected", expected, actual);
467     }
468 
469     @Test
470     public void testQueryEnumElementsNumber() throws Exception {
471         final String xpath = "/ENUM_DEF/OBJBLOCK/ENUM_CONSTANT_DEF";
472         final RootNode enumRootNode = getRootNode("InputXpathMapperEnum.java");
473         final List<Item> nodes = getXpathItems(xpath, enumRootNode);
474         assertEquals("Invalid number of nodes", 3, nodes.size());
475     }
476 
477     @Test
478     public void testQueryEnumElementByName() throws Exception {
479         final String xpath = "//*[@text='TWO']";
480         final RootNode enumRootNode = getRootNode("InputXpathMapperEnum.java");
481         final DetailAST[] actual = convertToArray(getXpathItems(xpath, enumRootNode));
482         final DetailAST expectedEnumConstantDefNode = getSiblingByType(
483                 enumRootNode.getUnderlyingNode(),
484                 TokenTypes.ENUM_DEF)
485                 .findFirstToken(TokenTypes.OBJBLOCK)
486                 .findFirstToken(TokenTypes.ENUM_CONSTANT_DEF)
487                 .getNextSibling()
488                 .getNextSibling();
489         final DetailAST[] expected = {expectedEnumConstantDefNode};
490         assertArrayEquals("Result nodes differ from expected", expected, actual);
491     }
492 
493     @Test
494     public void testQueryInterfaceDef() throws Exception {
495         final String xpath = "/INTERFACE_DEF";
496         final RootNode interfaceRootNode = getRootNode("InputXpathMapperInterface.java");
497         final DetailAST[] actual = convertToArray(getXpathItems(xpath, interfaceRootNode));
498         final DetailAST expectedInterfaceDefNode = getSiblingByType(
499                 interfaceRootNode.getUnderlyingNode(),
500                 TokenTypes.INTERFACE_DEF);
501         final DetailAST[] expected = {expectedInterfaceDefNode};
502         assertArrayEquals("Result nodes differ from expected", expected, actual);
503     }
504 
505     @Test
506     public void testQueryInterfaceMethodDefNumber() throws Exception {
507         final String xpath = "/INTERFACE_DEF/OBJBLOCK/METHOD_DEF";
508         final RootNode interfaceRootNode = getRootNode("InputXpathMapperInterface.java");
509         final List<Item> nodes = getXpathItems(xpath, interfaceRootNode);
510         assertEquals("Invalid number of nodes", 4, nodes.size());
511     }
512 
513     @Test
514     public void testQueryInterfaceParameterDef() throws Exception {
515         final String xpath = "//PARAMETER_DEF[@text='someVariable']/../..";
516         final RootNode interfaceRootNode = getRootNode("InputXpathMapperInterface.java");
517         final DetailAST[] actual = convertToArray(getXpathItems(xpath, interfaceRootNode));
518         final DetailAST expectedMethodDefNode = getSiblingByType(
519                 interfaceRootNode.getUnderlyingNode(),
520                 TokenTypes.INTERFACE_DEF)
521                 .findFirstToken(TokenTypes.OBJBLOCK)
522                 .findFirstToken(TokenTypes.METHOD_DEF)
523                 .getNextSibling();
524         final DetailAST[] expected = {expectedMethodDefNode};
525         assertArrayEquals("Result nodes differ from expected", expected, actual);
526     }
527 
528     private RootNode getRootNode(String fileName) throws Exception {
529         final File file = new File(getPath(fileName));
530         final DetailAST rootAst = JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS);
531         return new RootNode(rootAst);
532     }
533 
534     private static DetailAST[] convertToArray(List<Item> nodes) {
535         final DetailAST[] result = new DetailAST[nodes.size()];
536         for (int i = 0; i < nodes.size(); i++) {
537             final AbstractNode abstractNode = (AbstractNode) nodes.get(i);
538             result[i] = abstractNode.getUnderlyingNode();
539         }
540         return result;
541     }
542 
543     private static DetailAST getSiblingByType(DetailAST node, int type) {
544         DetailAST returnValue = null;
545         for (DetailAST ast = node; ast != null; ast = ast.getNextSibling()) {
546             if (ast.getType() == type) {
547                 returnValue = ast;
548                 break;
549             }
550         }
551         return returnValue;
552     }
553 
554 }