1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jxpath.ri.axes;
18
19 import java.util.Stack;
20
21 import org.apache.commons.jxpath.Pointer;
22 import org.apache.commons.jxpath.ri.Compiler;
23 import org.apache.commons.jxpath.ri.EvalContext;
24 import org.apache.commons.jxpath.ri.compiler.NodeTest;
25 import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
26 import org.apache.commons.jxpath.ri.model.NodeIterator;
27 import org.apache.commons.jxpath.ri.model.NodePointer;
28
29
30
31
32
33
34
35
36 public class DescendantContext extends EvalContext {
37 private NodeTest nodeTest;
38 private boolean setStarted = false;
39 private Stack stack = null;
40 private NodePointer currentNodePointer = null;
41 private boolean includeSelf;
42 private static final NodeTest ELEMENT_NODE_TEST =
43 new NodeTypeTest(Compiler.NODE_TYPE_NODE);
44
45
46
47
48
49
50
51 public DescendantContext(EvalContext parentContext, boolean includeSelf,
52 NodeTest nodeTest) {
53 super(parentContext);
54 this.includeSelf = includeSelf;
55 this.nodeTest = nodeTest;
56 }
57
58 public boolean isChildOrderingRequired() {
59 return true;
60 }
61
62 public NodePointer getCurrentNodePointer() {
63 if (position == 0 && !setPosition(1)) {
64 return null;
65 }
66 return currentNodePointer;
67 }
68
69 public void reset() {
70 super.reset();
71 setStarted = false;
72 }
73
74 public boolean setPosition(int position) {
75 if (position < this.position) {
76 reset();
77 }
78
79 while (this.position < position) {
80 if (!nextNode()) {
81 return false;
82 }
83 }
84 return true;
85 }
86
87 public boolean nextNode() {
88 if (!setStarted) {
89 setStarted = true;
90 if (stack == null) {
91 stack = new Stack();
92 }
93 else {
94 stack.clear();
95 }
96 currentNodePointer = parentContext.getCurrentNodePointer();
97 if (currentNodePointer != null) {
98 if (!currentNodePointer.isLeaf()) {
99 stack.push(
100 currentNodePointer.childIterator(
101 ELEMENT_NODE_TEST,
102 false,
103 null));
104 }
105 if (includeSelf && currentNodePointer.testNode(nodeTest)) {
106 position++;
107 return true;
108 }
109 }
110 }
111
112 while (!stack.isEmpty()) {
113 NodeIterator it = (NodeIterator) stack.peek();
114 if (it.setPosition(it.getPosition() + 1)) {
115 currentNodePointer = it.getNodePointer();
116 if (!isRecursive()) {
117 if (!currentNodePointer.isLeaf()) {
118 stack.push(
119 currentNodePointer.childIterator(
120 ELEMENT_NODE_TEST,
121 false,
122 null));
123 }
124 if (currentNodePointer.testNode(nodeTest)) {
125 position++;
126 return true;
127 }
128 }
129 }
130 else {
131
132
133 stack.pop();
134 }
135 }
136 return false;
137 }
138
139
140
141
142
143
144 private boolean isRecursive() {
145 Object node = currentNodePointer.getNode();
146 for (int i = stack.size() - 1; --i >= 0;) {
147 NodeIterator it = (NodeIterator) stack.get(i);
148 Pointer pointer = it.getNodePointer();
149 if (pointer != null && pointer.getNode() == node) {
150 return true;
151 }
152 }
153 return false;
154 }
155 }