1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jxpath.ri;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.NoSuchElementException;
25
26 import org.apache.commons.jxpath.BasicNodeSet;
27 import org.apache.commons.jxpath.ExpressionContext;
28 import org.apache.commons.jxpath.JXPathContext;
29 import org.apache.commons.jxpath.JXPathException;
30 import org.apache.commons.jxpath.NodeSet;
31 import org.apache.commons.jxpath.Pointer;
32 import org.apache.commons.jxpath.ri.axes.RootContext;
33 import org.apache.commons.jxpath.ri.model.NodePointer;
34 import org.apache.commons.jxpath.util.ReverseComparator;
35
36
37
38
39
40
41
42
43
44
45
46 public abstract class EvalContext implements ExpressionContext, Iterator {
47
48 protected EvalContext parentContext;
49
50
51 protected RootContext rootContext;
52
53
54 protected int position = 0;
55
56 private boolean startedSetIteration = false;
57 private boolean done = false;
58 private boolean hasPerformedIteratorStep = false;
59 private Iterator pointerIterator;
60
61
62
63
64
65 public EvalContext(EvalContext parentContext) {
66 this.parentContext = parentContext;
67 }
68
69 public Pointer getContextNodePointer() {
70 return getCurrentNodePointer();
71 }
72
73 public JXPathContext getJXPathContext() {
74 return getRootContext().getJXPathContext();
75 }
76
77 public int getPosition() {
78 return position;
79 }
80
81
82
83
84
85
86
87 public int getDocumentOrder() {
88 return parentContext != null && parentContext.isChildOrderingRequired() ? 1 : 0;
89 }
90
91
92
93
94
95
96
97 public boolean isChildOrderingRequired() {
98
99
100 return getDocumentOrder() != 0;
101 }
102
103
104
105
106
107 public boolean hasNext() {
108 if (pointerIterator != null) {
109 return pointerIterator.hasNext();
110 }
111 if (getDocumentOrder() != 0) {
112 return constructIterator();
113 }
114 if (!done && !hasPerformedIteratorStep) {
115 performIteratorStep();
116 }
117 return !done;
118 }
119
120
121
122
123
124 public Object next() {
125 if (pointerIterator != null) {
126 return pointerIterator.next();
127 }
128
129 if (getDocumentOrder() != 0) {
130 if (!constructIterator()) {
131 throw new NoSuchElementException();
132 }
133 return pointerIterator.next();
134 }
135 if (!done && !hasPerformedIteratorStep) {
136 performIteratorStep();
137 }
138 if (done) {
139 throw new NoSuchElementException();
140 }
141 hasPerformedIteratorStep = false;
142 return getCurrentNodePointer();
143 }
144
145
146
147
148 private void performIteratorStep() {
149 done = true;
150 if (position != 0 && nextNode()) {
151 done = false;
152 }
153 else {
154 while (nextSet()) {
155 if (nextNode()) {
156 done = false;
157 break;
158 }
159 }
160 }
161 hasPerformedIteratorStep = true;
162 }
163
164
165
166
167
168 public void remove() {
169 throw new UnsupportedOperationException(
170 "JXPath iterators cannot remove nodes");
171 }
172
173
174
175
176
177 private boolean constructIterator() {
178 HashSet set = new HashSet();
179 ArrayList list = new ArrayList();
180 while (nextSet()) {
181 while (nextNode()) {
182 NodePointer pointer = getCurrentNodePointer();
183 if (!set.contains(pointer)) {
184 set.add(pointer);
185 list.add(pointer);
186 }
187 }
188 }
189 if (list.isEmpty()) {
190 return false;
191 }
192
193 sortPointers(list);
194
195 pointerIterator = list.iterator();
196 return true;
197 }
198
199
200
201
202
203 protected void sortPointers(List l) {
204 switch (getDocumentOrder()) {
205 case 1:
206 Collections.sort(l);
207 break;
208 case -1:
209 Collections.sort(l, ReverseComparator.INSTANCE);
210 break;
211 default:
212 break;
213 }
214 }
215
216
217
218
219
220
221 public List getContextNodeList() {
222 int pos = position;
223 if (pos != 0) {
224 reset();
225 }
226 List list = new ArrayList();
227 while (nextNode()) {
228 list.add(getCurrentNodePointer());
229 }
230 if (pos != 0) {
231 setPosition(pos);
232 }
233 else {
234 reset();
235 }
236 return list;
237 }
238
239
240
241
242
243
244
245 public NodeSet getNodeSet() {
246 if (position != 0) {
247 throw new JXPathException(
248 "Simultaneous operations: "
249 + "should not request pointer list while "
250 + "iterating over an EvalContext");
251 }
252 BasicNodeSet set = new BasicNodeSet();
253 while (nextSet()) {
254 while (nextNode()) {
255 set.add((Pointer) getCurrentNodePointer().clone());
256 }
257 }
258
259 return set;
260 }
261
262
263
264
265
266
267
268 public Object getValue() {
269 return getNodeSet();
270 }
271
272 public String toString() {
273 Pointer ptr = getContextNodePointer();
274 return ptr == null ? "Empty expression context" : "Expression context [" + getPosition()
275 + "] " + ptr.asPath();
276 }
277
278
279
280
281
282
283 public RootContext getRootContext() {
284 if (rootContext == null) {
285 rootContext = parentContext.getRootContext();
286 }
287 return rootContext;
288 }
289
290
291
292
293 public void reset() {
294 position = 0;
295 }
296
297
298
299
300
301 public int getCurrentPosition() {
302 return position;
303 }
304
305
306
307
308
309
310 public Pointer getSingleNodePointer() {
311 reset();
312 while (nextSet()) {
313 if (nextNode()) {
314 return getCurrentNodePointer();
315 }
316 }
317 return null;
318 }
319
320
321
322
323
324
325 public abstract NodePointer getCurrentNodePointer();
326
327
328
329
330
331
332 public boolean nextSet() {
333 reset();
334
335
336
337
338 if (!startedSetIteration) {
339 startedSetIteration = true;
340 while (parentContext.nextSet()) {
341 if (parentContext.nextNode()) {
342 return true;
343 }
344 }
345 return false;
346 }
347
348
349
350 if (parentContext.nextNode()) {
351 return true;
352 }
353
354
355
356 while (parentContext.nextSet()) {
357 if (parentContext.nextNode()) {
358 return true;
359 }
360 }
361 return false;
362 }
363
364
365
366
367
368
369 public abstract boolean nextNode();
370
371
372
373
374
375
376
377
378
379 public boolean setPosition(int position) {
380 this.position = position;
381 return true;
382 }
383 }