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 }