1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jxpath.ri.axes;
17
18 import java.util.Stack;
19
20 import org.apache.commons.jxpath.ri.EvalContext;
21 import org.apache.commons.jxpath.ri.compiler.NodeTest;
22 import org.apache.commons.jxpath.ri.model.NodeIterator;
23 import org.apache.commons.jxpath.ri.model.NodePointer;
24 import org.apache.commons.jxpath.ri.model.beans.PropertyIterator;
25
26 /***
27 * EvalContext that walks the "preceding::" and "following::" axes.
28 *
29 * @author Dmitri Plotnikov
30 * @version $Revision: 1.15 $ $Date: 2004/03/25 03:49:50 $
31 */
32 public class PrecedingOrFollowingContext extends EvalContext {
33 private NodeTest nodeTest;
34 private boolean setStarted = false;
35 private boolean started = false;
36 private Stack stack;
37 private Stack nameStack;
38 private NodePointer currentNodePointer;
39 private NodePointer currentRootLocation;
40 private boolean reverse;
41
42 public PrecedingOrFollowingContext(
43 EvalContext parentContext,
44 NodeTest nodeTest,
45 boolean reverse)
46 {
47 super(parentContext);
48 this.nodeTest = nodeTest;
49 this.reverse = reverse;
50 }
51
52 public NodePointer getCurrentNodePointer() {
53 return currentNodePointer;
54 }
55
56 public int getDocumentOrder() {
57 return reverse ? -1 : 1;
58 }
59
60 public void reset() {
61 super.reset();
62 stack = new Stack();
63 setStarted = false;
64 }
65
66 public boolean setPosition(int position) {
67 if (position < this.position) {
68 reset();
69 }
70
71 while (this.position < position) {
72 if (!nextNode()) {
73 return false;
74 }
75 }
76 return true;
77 }
78
79 public boolean nextNode() {
80 if (!setStarted) {
81 setStarted = true;
82 currentRootLocation = parentContext.getCurrentNodePointer();
83 NodePointer parent = currentRootLocation.getParent();
84 if (parent != null) {
85
86 stack.push(
87 parent.childIterator(null, reverse, currentRootLocation));
88 }
89 }
90
91 while (true) {
92 if (stack.isEmpty()) {
93 currentRootLocation = currentRootLocation.getParent();
94
95 if (currentRootLocation == null
96 || currentRootLocation.isRoot()) {
97 break;
98 }
99
100 NodePointer parent = currentRootLocation.getParent();
101 if (parent != null) {
102 stack.push(
103 parent.childIterator(
104 null,
105 reverse,
106 currentRootLocation));
107 }
108 }
109
110 while (!stack.isEmpty()) {
111 if (!reverse) {
112 NodeIterator it = (NodeIterator) stack.peek();
113 if (it.setPosition(it.getPosition() + 1)) {
114 currentNodePointer = it.getNodePointer();
115 if (!currentNodePointer.isLeaf()) {
116 stack.push(
117 currentNodePointer.childIterator(
118 null,
119 reverse,
120 null));
121 }
122 if (currentNodePointer.testNode(nodeTest)) {
123 super.setPosition(getCurrentPosition() + 1);
124 return true;
125 }
126 }
127 else {
128
129
130 stack.pop();
131 }
132 }
133 else {
134 NodeIterator it = (NodeIterator) stack.peek();
135 if (it.setPosition(it.getPosition() + 1)) {
136 currentNodePointer = it.getNodePointer();
137 if (!currentNodePointer.isLeaf()) {
138 stack.push(
139 currentNodePointer.childIterator(
140 null,
141 reverse,
142 null));
143 }
144 else if (currentNodePointer.testNode(nodeTest)) {
145 super.setPosition(getCurrentPosition() + 1);
146 return true;
147 }
148 }
149 else {
150 stack.pop();
151 if (!stack.isEmpty()) {
152 it = (PropertyIterator) stack.peek();
153 currentNodePointer = it.getNodePointer();
154 if (currentNodePointer.testNode(nodeTest)) {
155 super.setPosition(getCurrentPosition() + 1);
156 return true;
157 }
158 }
159 }
160 }
161 }
162 }
163 return false;
164 }
165 }