View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 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.internal.utils;
21  
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import com.puppycrawl.tools.checkstyle.DetailAstImpl;
26  import com.puppycrawl.tools.checkstyle.api.DetailAST;
27  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
28  import com.puppycrawl.tools.checkstyle.xpath.RootNode;
29  import net.sf.saxon.om.NodeInfo;
30  
31  /**
32   * XpathIteratorUtil.
33   *
34   * @noinspection ClassOnlyUsedInOnePackage
35   * @noinspectionreason ClassOnlyUsedInOnePackage - class is internal tool, and only used in testing
36   */
37  public final class XpathIteratorUtil {
38  
39      /**
40       * Map from {@link NodeInfo#getLocalPart()} to {@link NodeInfo}.
41       */
42      private static final Map<String, NodeInfo> NODES_BY_LOCAL_PART = new HashMap<>();
43  
44      static {
45          fillMap(new RootNode(createTree()));
46      }
47  
48      private XpathIteratorUtil() {
49      }
50  
51      /**
52       * Finds node by its {@link NodeInfo#getLocalPart()} value.
53       *
54       * @param localPart text to be searched
55       *
56       * @return corresponding node
57       */
58      public static NodeInfo findNode(String localPart) {
59          return NODES_BY_LOCAL_PART.get(localPart);
60      }
61  
62      /**
63       * Iterates Xpath tree nodes and fills the map.
64       *
65       * @param cur current {@link NodeInfo} node
66       */
67      private static void fillMap(NodeInfo cur) {
68          NODES_BY_LOCAL_PART.put(cur.getLocalPart(), cur);
69          for (NodeInfo node : cur.children()) {
70              fillMap(node);
71          }
72      }
73  
74      /**
75       * Creates AST tree for iteration tests and returns root.
76       *
77       * <p>
78       * PACKAGE_DEF -> package [1:0]
79       * |--ANNOTATIONS -> ANNOTATIONS [1:8]
80       *     `--ANNOTATION_DEF -> ANNOTATIONS [1:8]
81       * `--CLASS_DEF -> CLASS_DEF [3:0]
82       *     `--OBJBLOCK -> OBJBLOCK [3:19]
83       *         |--LCURLY -> { [3:19]
84       *         |--METHOD_DEF -> METHOD_DEF [4:4]
85       *         |   |--PARAMETERS -> PARAMETERS [4:31]
86       *         |   `--SLIST -> { [4:33]
87       *         `--RCURLY -> } [8:0]
88       * </p>
89       *
90       * @return {@link DetailAST} object.
91       */
92      private static DetailAST createTree() {
93          final DetailAstImpl rootNode = createNode(TokenTypes.PACKAGE_DEF, 1, 0);
94  
95          final DetailAstImpl annotationsNode = createNode(rootNode, TokenTypes.ANNOTATIONS, 1, 8);
96          createNode(annotationsNode, TokenTypes.ANNOTATION_DEF, 1, 8);
97  
98          final DetailAstImpl classDefNode = createNode(rootNode, TokenTypes.CLASS_DEF, 3, 0);
99          final DetailAstImpl objblockNode = createNode(classDefNode, TokenTypes.OBJBLOCK, 3, 19);
100         createNode(objblockNode, TokenTypes.LCURLY, 3, 19);
101         final DetailAstImpl methodDefNode = createNode(objblockNode, TokenTypes.METHOD_DEF, 4, 4);
102         createNode(objblockNode, TokenTypes.RCURLY, 8, 0);
103 
104         createNode(methodDefNode, TokenTypes.PARAMETERS, 4, 31);
105         createNode(methodDefNode, TokenTypes.SLIST, 4, 33);
106 
107         return rootNode;
108     }
109 
110     /**
111      * Creates {@link DetailAstImpl} node with predefined parent.
112      *
113      * @param parent parent node
114      * @param tokenType token type, see {@link TokenTypes}
115      * @param lineNo line number
116      * @param columnNo column number
117      *
118      * @return {@link DetailAstImpl} object.
119      */
120     private static DetailAstImpl createNode(DetailAstImpl parent, int tokenType, int lineNo,
121                                             int columnNo) {
122         final DetailAstImpl result = createNode(tokenType, lineNo, columnNo);
123         parent.addChild(result);
124         return result;
125     }
126 
127     /**
128      * Creates {@link DetailAstImpl} node.
129      *
130      * @param tokenType token type, see {@link TokenTypes}
131      * @param lineNo line number
132      * @param columnNo column number
133      *
134      * @return {@link DetailAstImpl} object.
135      */
136     private static DetailAstImpl createNode(int tokenType, int lineNo, int columnNo) {
137         final DetailAstImpl result = new DetailAstImpl();
138         result.setType(tokenType);
139         result.setLineNo(lineNo);
140         result.setColumnNo(columnNo);
141         return result;
142     }
143 }