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.xpath.iterators;
21
22 import net.sf.saxon.om.AxisInfo;
23 import net.sf.saxon.om.NodeInfo;
24 import net.sf.saxon.tree.iter.AxisIterator;
25
26 /**
27 * Recursive-free implementation of the preceding axis iterator.
28 */
29 public class PrecedingIterator implements AxisIterator {
30 /**
31 * Ancestor axis iterator.
32 */
33 private final AxisIterator ancestorEnum;
34 /**
35 * Preceding-sibling axis iterator.
36 */
37 private AxisIterator previousSiblingEnum;
38 /**
39 * Descendant axis iterator.
40 */
41 private AxisIterator descendantEnum;
42
43 /**
44 * Create an iterator over the "preceding" axis.
45 *
46 * @param start the initial context node.
47 */
48 public PrecedingIterator(NodeInfo start) {
49 ancestorEnum = start.iterateAxis(AxisInfo.ANCESTOR);
50 previousSiblingEnum = start.iterateAxis(AxisInfo.PRECEDING_SIBLING);
51 }
52
53 /**
54 * Get the next item in the sequence.
55 *
56 * @return the next Item. If there are no more nodes, return null.
57 */
58 @Override
59 public NodeInfo next() {
60 NodeInfo result = null;
61
62 while (result == null) {
63 if (descendantEnum != null) {
64 result = descendantEnum.next();
65 }
66
67 if (result == null && previousSiblingEnum != null) {
68 result = previousSiblingEnum.next();
69 if (result == null) {
70 previousSiblingEnum = null;
71 }
72 else {
73 descendantEnum = new ReverseDescendantIterator(result);
74 }
75 }
76
77 if (result == null) {
78 result = ancestorEnum.next();
79 if (result == null) {
80 break;
81 }
82 previousSiblingEnum = result.iterateAxis(AxisInfo.PRECEDING_SIBLING);
83 }
84 }
85 return result;
86 }
87 }