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 java.util.Collections;
23  import java.util.List;
24  import java.util.Optional;
25  
26  import com.puppycrawl.tools.checkstyle.xpath.iterators.DescendantIterator;
27  import com.puppycrawl.tools.checkstyle.xpath.iterators.FollowingIterator;
28  import com.puppycrawl.tools.checkstyle.xpath.iterators.PrecedingIterator;
29  import com.puppycrawl.tools.checkstyle.xpath.iterators.ReverseListIterator;
30  import net.sf.saxon.om.AxisInfo;
31  import net.sf.saxon.om.NamespaceUri;
32  import net.sf.saxon.om.NodeInfo;
33  import net.sf.saxon.tree.iter.ArrayIterator;
34  import net.sf.saxon.tree.iter.AxisIterator;
35  import net.sf.saxon.tree.iter.EmptyIterator;
36  import net.sf.saxon.tree.iter.SingleNodeIterator;
37  import net.sf.saxon.tree.util.Navigator;
38  import net.sf.saxon.type.Type;
39  
40  
41  
42  
43  public abstract class AbstractElementNode extends AbstractNode {
44  
45      
46      protected static final String TEXT_ATTRIBUTE_NAME = "text";
47  
48      
49      private static final AbstractNode[] EMPTY_ABSTRACT_NODE_ARRAY = new AbstractNode[0];
50  
51      
52      private static final AttributeNode ATTRIBUTE_NODE_UNINITIALIZED = new AttributeNode(null, null);
53  
54      
55      private final AbstractNode root;
56  
57      
58      private final AbstractNode parent;
59  
60      
61      private final int depth;
62  
63      
64      private final int indexAmongSiblings;
65  
66      
67      private AttributeNode attributeNode = ATTRIBUTE_NODE_UNINITIALIZED;
68  
69      
70  
71  
72  
73  
74  
75  
76  
77      protected AbstractElementNode(AbstractNode root, AbstractNode parent,
78              int depth, int indexAmongSiblings) {
79          super(root.getTreeInfo());
80          this.parent = parent;
81          this.root = root;
82          this.depth = depth;
83          this.indexAmongSiblings = indexAmongSiblings;
84      }
85  
86      
87  
88  
89  
90  
91      protected abstract AttributeNode createAttributeNode();
92  
93      
94  
95  
96  
97  
98  
99      @Override
100     public int compareOrder(NodeInfo other) {
101         int result = 0;
102         if (other instanceof AbstractNode node) {
103             result = Integer.compare(depth, node.getDepth());
104             if (result == 0) {
105                 result = compareCommonAncestorChildrenOrder(this, other);
106             }
107         }
108         return result;
109     }
110 
111     
112 
113 
114 
115 
116 
117 
118 
119 
120 
121     private static int compareCommonAncestorChildrenOrder(NodeInfo first, NodeInfo second) {
122         NodeInfo child1 = first;
123         NodeInfo child2 = second;
124         while (!child1.getParent().equals(child2.getParent())) {
125             child1 = child1.getParent();
126             child2 = child2.getParent();
127         }
128         final int index1 = ((AbstractElementNode) child1).indexAmongSiblings;
129         final int index2 = ((AbstractElementNode) child2).indexAmongSiblings;
130         return Integer.compare(index1, index2);
131     }
132 
133     
134 
135 
136 
137 
138     @Override
139     public int getDepth() {
140         return depth;
141     }
142 
143     
144 
145 
146 
147 
148 
149 
150     @Override
151     public String getAttributeValue(NamespaceUri namespace, String localPart) {
152         final String result;
153         if (TEXT_ATTRIBUTE_NAME.equals(localPart)) {
154             result = Optional.ofNullable(getAttributeNode())
155                 .map(AttributeNode::getStringValue)
156                 .orElse(null);
157         }
158         else {
159             result = null;
160         }
161         return result;
162     }
163 
164     
165 
166 
167 
168 
169     @Override
170     public int getNodeKind() {
171         return Type.ELEMENT;
172     }
173 
174     
175 
176 
177 
178 
179     @Override
180     public NodeInfo getParent() {
181         return parent;
182     }
183 
184     
185 
186 
187 
188 
189     @Override
190     public AbstractNode getRoot() {
191         return root;
192     }
193 
194     
195 
196 
197 
198 
199 
200 
201 
202 
203 
204 
205 
206     @Override
207     public AxisIterator iterateAxis(int axisNumber) {
208         return switch (axisNumber) {
209             case AxisInfo.ANCESTOR -> new Navigator.AncestorEnumeration(this, false);
210             case AxisInfo.ANCESTOR_OR_SELF -> new Navigator.AncestorEnumeration(this, true);
211             case AxisInfo.ATTRIBUTE -> SingleNodeIterator.makeIterator(getAttributeNode());
212             case AxisInfo.CHILD -> {
213                 if (hasChildNodes()) {
214                     yield new ArrayIterator.OfNodes<>(
215                             getChildren().toArray(EMPTY_ABSTRACT_NODE_ARRAY));
216                 }
217                 yield EmptyIterator.ofNodes();
218             }
219             case AxisInfo.DESCENDANT -> {
220                 if (hasChildNodes()) {
221                     yield new DescendantIterator(this, DescendantIterator.StartWith.CHILDREN);
222                 }
223                 yield EmptyIterator.ofNodes();
224             }
225             case AxisInfo.DESCENDANT_OR_SELF ->
226                 new DescendantIterator(this, DescendantIterator.StartWith.CURRENT_NODE);
227             case AxisInfo.PARENT -> SingleNodeIterator.makeIterator(parent);
228             case AxisInfo.SELF -> SingleNodeIterator.makeIterator(this);
229             case AxisInfo.FOLLOWING_SIBLING -> getFollowingSiblingsIterator();
230             case AxisInfo.PRECEDING_SIBLING -> getPrecedingSiblingsIterator();
231             case AxisInfo.FOLLOWING -> new FollowingIterator(this);
232             case AxisInfo.PRECEDING -> new PrecedingIterator(this);
233             default -> throw throwUnsupportedOperationException();
234         };
235     }
236 
237     
238 
239 
240 
241 
242 
243 
244 
245 
246 
247     private AxisIterator getPrecedingSiblingsIterator() {
248         final AxisIterator result;
249         if (indexAmongSiblings == 0) {
250             result = EmptyIterator.ofNodes();
251         }
252         else {
253             result = new ReverseListIterator(getPrecedingSiblings());
254         }
255         return result;
256     }
257 
258     
259 
260 
261 
262 
263 
264 
265 
266 
267 
268     private AxisIterator getFollowingSiblingsIterator() {
269         final AxisIterator result;
270         if (indexAmongSiblings == parent.getChildren().size() - 1) {
271             result = EmptyIterator.ofNodes();
272         }
273         else {
274             result = new ArrayIterator.OfNodes<>(
275                     getFollowingSiblings().toArray(EMPTY_ABSTRACT_NODE_ARRAY));
276         }
277         return result;
278     }
279 
280     
281 
282 
283 
284 
285     private List<AbstractNode> getFollowingSiblings() {
286         final List<AbstractNode> siblings = parent.getChildren();
287         return siblings.subList(indexAmongSiblings + 1, siblings.size());
288     }
289 
290     
291 
292 
293 
294 
295     private List<AbstractNode> getPrecedingSiblings() {
296         final List<AbstractNode> siblings = parent.getChildren();
297         return Collections.unmodifiableList(siblings.subList(0, indexAmongSiblings));
298     }
299 
300     
301 
302 
303 
304 
305 
306 
307     private AttributeNode getAttributeNode() {
308         if (attributeNode == ATTRIBUTE_NODE_UNINITIALIZED) {
309             attributeNode = createAttributeNode();
310         }
311         return attributeNode;
312     }
313 
314     
315 
316 
317 
318 
319     private static UnsupportedOperationException throwUnsupportedOperationException() {
320         return new UnsupportedOperationException("Operation is not supported");
321     }
322 }