1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.xpath;
21
22 import com.puppycrawl.tools.checkstyle.api.DetailAST;
23 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
24 import com.puppycrawl.tools.checkstyle.utils.XpathUtil;
25 import net.sf.saxon.om.AxisInfo;
26 import net.sf.saxon.om.NodeInfo;
27 import net.sf.saxon.tree.iter.ArrayIterator;
28 import net.sf.saxon.tree.iter.AxisIterator;
29 import net.sf.saxon.tree.iter.EmptyIterator;
30 import net.sf.saxon.tree.iter.SingleNodeIterator;
31 import net.sf.saxon.tree.util.Navigator;
32 import net.sf.saxon.type.Type;
33
34
35
36
37
38 public class ElementNode extends AbstractNode {
39
40
41 private static final String TEXT_ATTRIBUTE_NAME = "text";
42
43
44 private static final AbstractNode[] EMPTY_ABSTRACT_NODE_ARRAY = new AbstractNode[0];
45
46
47 private final AbstractNode root;
48
49
50 private final AbstractNode parent;
51
52
53 private final DetailAST detailAst;
54
55
56 private final String text;
57
58
59 private AttributeNode attributeNode;
60
61
62
63
64
65
66
67
68 public ElementNode(AbstractNode root, AbstractNode parent, DetailAST detailAst) {
69 super(root.getTreeInfo());
70 this.parent = parent;
71 this.root = root;
72 this.detailAst = detailAst;
73 text = TokenUtil.getTokenName(detailAst.getType());
74 createTextAttribute();
75 createChildren();
76 }
77
78
79
80
81
82 private void createChildren() {
83 DetailAST currentChild = detailAst.getFirstChild();
84 while (currentChild != null) {
85 final AbstractNode child = new ElementNode(root, this, currentChild);
86 addChild(child);
87 currentChild = currentChild.getNextSibling();
88 }
89 }
90
91
92
93
94
95
96
97
98 @Override
99 public String getAttributeValue(String namespace, String localPart) {
100 final String result;
101 if (TEXT_ATTRIBUTE_NAME.equals(localPart)) {
102 if (attributeNode == null) {
103 result = null;
104 }
105 else {
106 result = attributeNode.getStringValue();
107 }
108 }
109 else {
110 result = null;
111 }
112 return result;
113 }
114
115
116
117
118
119
120
121 @Override
122 public String getLocalPart() {
123 return text;
124 }
125
126
127
128
129
130 @Override
131 public int getNodeKind() {
132 return Type.ELEMENT;
133 }
134
135
136
137
138
139 @Override
140 public NodeInfo getParent() {
141 return parent;
142 }
143
144
145
146
147
148 @Override
149 public NodeInfo getRoot() {
150 return root;
151 }
152
153
154
155
156
157
158
159 @Override
160 public String getStringValue() {
161 return text;
162 }
163
164
165
166
167
168
169
170
171 @Override
172 public AxisIterator iterateAxis(byte axisNumber) {
173 final AxisIterator result;
174 switch (axisNumber) {
175 case AxisInfo.ANCESTOR:
176 try (AxisIterator iterator = new Navigator.AncestorEnumeration(this, false)) {
177 result = iterator;
178 }
179 break;
180 case AxisInfo.ANCESTOR_OR_SELF:
181 try (AxisIterator iterator = new Navigator.AncestorEnumeration(this, true)) {
182 result = iterator;
183 }
184 break;
185 case AxisInfo.ATTRIBUTE:
186 try (AxisIterator iterator = SingleNodeIterator.makeIterator(attributeNode)) {
187 result = iterator;
188 }
189 break;
190 case AxisInfo.CHILD:
191 if (hasChildNodes()) {
192 try (AxisIterator iterator = new ArrayIterator.OfNodes(
193 getChildren().toArray(EMPTY_ABSTRACT_NODE_ARRAY))) {
194 result = iterator;
195 }
196 }
197 else {
198 result = EmptyIterator.OfNodes.THE_INSTANCE;
199 }
200 break;
201 case AxisInfo.DESCENDANT:
202 if (hasChildNodes()) {
203 try (AxisIterator iterator =
204 new Navigator.DescendantEnumeration(this, false, true)) {
205 result = iterator;
206 }
207 }
208 else {
209 result = EmptyIterator.OfNodes.THE_INSTANCE;
210 }
211 break;
212 case AxisInfo.DESCENDANT_OR_SELF:
213 try (AxisIterator iterator =
214 new Navigator.DescendantEnumeration(this, true, true)) {
215 result = iterator;
216 }
217 break;
218 case AxisInfo.PARENT:
219 try (AxisIterator iterator = SingleNodeIterator.makeIterator(parent)) {
220 result = iterator;
221 }
222 break;
223 case AxisInfo.SELF:
224 try (AxisIterator iterator = SingleNodeIterator.makeIterator(this)) {
225 result = iterator;
226 }
227 break;
228 default:
229 throw throwUnsupportedOperationException();
230 }
231 return result;
232 }
233
234
235
236
237
238 @Override
239 public int getLineNumber() {
240 return detailAst.getLineNo();
241 }
242
243
244
245
246
247 @Override
248 public int getColumnNumber() {
249 return detailAst.getColumnNo();
250 }
251
252
253
254
255
256 @Override
257 public int getTokenType() {
258 return detailAst.getType();
259 }
260
261
262
263
264
265
266
267 @Override
268 public DetailAST getUnderlyingNode() {
269 return detailAst;
270 }
271
272
273
274
275
276
277 private void createTextAttribute() {
278 AttributeNode attribute = null;
279 if (XpathUtil.supportsTextAttribute(detailAst)) {
280 attribute = new AttributeNode(TEXT_ATTRIBUTE_NAME,
281 XpathUtil.getTextAttributeValue(detailAst));
282 }
283 attributeNode = attribute;
284 }
285
286
287
288
289
290 private static UnsupportedOperationException throwUnsupportedOperationException() {
291 return new UnsupportedOperationException("Operation is not supported");
292 }
293
294 }