1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jxpath.ri.model.beans;
18
19 import org.apache.commons.jxpath.JXPathException;
20 import org.apache.commons.jxpath.ri.model.NodeIterator;
21 import org.apache.commons.jxpath.ri.model.NodePointer;
22
23
24
25
26
27
28
29
30 public class PropertyIterator implements NodeIterator {
31 private boolean empty = false;
32 private boolean reverse;
33 private String name;
34 private int startIndex = 0;
35 private boolean targetReady = false;
36 private int position = 0;
37 private PropertyPointer propertyNodePointer;
38 private int startPropertyIndex;
39
40 private boolean includeStart = false;
41
42
43
44
45
46
47
48
49 public PropertyIterator(
50 PropertyOwnerPointer pointer,
51 String name,
52 boolean reverse,
53 NodePointer startWith) {
54 propertyNodePointer =
55 (PropertyPointer) pointer.getPropertyPointer().clone();
56 this.name = name;
57 this.reverse = reverse;
58 this.includeStart = true;
59 if (reverse) {
60 this.startPropertyIndex = PropertyPointer.UNSPECIFIED_PROPERTY;
61 this.startIndex = -1;
62 }
63 if (startWith != null) {
64 while (startWith != null
65 && startWith.getImmediateParentPointer() != pointer) {
66 startWith = startWith.getImmediateParentPointer();
67 }
68 if (startWith == null) {
69 throw new JXPathException(
70 "PropertyIerator startWith parameter is "
71 + "not a child of the supplied parent");
72 }
73 this.startPropertyIndex =
74 ((PropertyPointer) startWith).getPropertyIndex();
75 this.startIndex = startWith.getIndex();
76 if (this.startIndex == NodePointer.WHOLE_COLLECTION) {
77 this.startIndex = 0;
78 }
79 this.includeStart = false;
80 if (reverse && startIndex == -1) {
81 this.includeStart = true;
82 }
83 }
84 }
85
86
87
88
89
90 protected NodePointer getPropertyPointer() {
91 return propertyNodePointer;
92 }
93
94
95
96
97 public void reset() {
98 position = 0;
99 targetReady = false;
100 }
101
102 public NodePointer getNodePointer() {
103 if (position == 0) {
104 if (name != null) {
105 if (!targetReady) {
106 prepareForIndividualProperty(name);
107 }
108
109 if (empty) {
110 return null;
111 }
112 }
113 else {
114 if (!setPosition(1)) {
115 return null;
116 }
117 reset();
118 }
119 }
120 try {
121 return propertyNodePointer.getValuePointer();
122 }
123 catch (Throwable t) {
124 propertyNodePointer.handle(t);
125 NullPropertyPointer npp =
126 new NullPropertyPointer(
127 propertyNodePointer.getImmediateParentPointer());
128 npp.setPropertyName(propertyNodePointer.getPropertyName());
129 npp.setIndex(propertyNodePointer.getIndex());
130 return npp.getValuePointer();
131 }
132 }
133
134 public int getPosition() {
135 return position;
136 }
137
138 public boolean setPosition(int position) {
139 return name == null ? setPositionAllProperties(position) : setPositionIndividualProperty(position);
140 }
141
142
143
144
145
146
147 private boolean setPositionIndividualProperty(int position) {
148 this.position = position;
149 if (position < 1) {
150 return false;
151 }
152
153 if (!targetReady) {
154 prepareForIndividualProperty(name);
155 }
156
157 if (empty) {
158 return false;
159 }
160
161 int length = getLength();
162 int index;
163 if (!reverse) {
164 index = position + startIndex;
165 if (!includeStart) {
166 index++;
167 }
168 if (index > length) {
169 return false;
170 }
171 }
172 else {
173 int end = startIndex;
174 if (end == -1) {
175 end = length - 1;
176 }
177 index = end - position + 2;
178 if (!includeStart) {
179 index--;
180 }
181 if (index < 1) {
182 return false;
183 }
184 }
185 propertyNodePointer.setIndex(index - 1);
186 return true;
187 }
188
189
190
191
192
193
194 private boolean setPositionAllProperties(int position) {
195 this.position = position;
196 if (position < 1) {
197 return false;
198 }
199
200 int offset;
201 int count = propertyNodePointer.getPropertyCount();
202 if (!reverse) {
203 int index = 1;
204 for (int i = startPropertyIndex; i < count; i++) {
205 propertyNodePointer.setPropertyIndex(i);
206 int length = getLength();
207 if (i == startPropertyIndex) {
208 length -= startIndex;
209 if (!includeStart) {
210 length--;
211 }
212 offset = startIndex + position - index;
213 if (!includeStart) {
214 offset++;
215 }
216 }
217 else {
218 offset = position - index;
219 }
220 if (index <= position && position < index + length) {
221 propertyNodePointer.setIndex(offset);
222 return true;
223 }
224 index += length;
225 }
226 }
227 else {
228 int index = 1;
229 int start = startPropertyIndex;
230 if (start == PropertyPointer.UNSPECIFIED_PROPERTY) {
231 start = count - 1;
232 }
233 for (int i = start; i >= 0; i--) {
234 propertyNodePointer.setPropertyIndex(i);
235 int length = getLength();
236 if (i == startPropertyIndex) {
237 int end = startIndex;
238 if (end == -1) {
239 end = length - 1;
240 }
241 length = end + 1;
242 offset = end - position + 1;
243 if (!includeStart) {
244 offset--;
245 length--;
246 }
247 }
248 else {
249 offset = length - (position - index) - 1;
250 }
251
252 if (index <= position && position < index + length) {
253 propertyNodePointer.setIndex(offset);
254 return true;
255 }
256 index += length;
257 }
258 }
259 return false;
260 }
261
262
263
264
265
266 protected void prepareForIndividualProperty(String name) {
267 targetReady = true;
268 empty = true;
269
270 String[] names = propertyNodePointer.getPropertyNames();
271 if (!reverse) {
272 if (startPropertyIndex == PropertyPointer.UNSPECIFIED_PROPERTY) {
273 startPropertyIndex = 0;
274 }
275 if (startIndex == NodePointer.WHOLE_COLLECTION) {
276 startIndex = 0;
277 }
278 for (int i = startPropertyIndex; i < names.length; i++) {
279 if (names[i].equals(name)) {
280 propertyNodePointer.setPropertyIndex(i);
281 if (i != startPropertyIndex) {
282 startIndex = 0;
283 includeStart = true;
284 }
285 empty = false;
286 break;
287 }
288 }
289 }
290 else {
291 if (startPropertyIndex == PropertyPointer.UNSPECIFIED_PROPERTY) {
292 startPropertyIndex = names.length - 1;
293 }
294 if (startIndex == NodePointer.WHOLE_COLLECTION) {
295 startIndex = -1;
296 }
297 for (int i = startPropertyIndex; i >= 0; i--) {
298 if (names[i].equals(name)) {
299 propertyNodePointer.setPropertyIndex(i);
300 if (i != startPropertyIndex) {
301 startIndex = -1;
302 includeStart = true;
303 }
304 empty = false;
305 break;
306 }
307 }
308 }
309 }
310
311
312
313
314
315 private int getLength() {
316 int length;
317 try {
318 length = propertyNodePointer.getLength();
319 }
320 catch (Throwable t) {
321 propertyNodePointer.handle(t);
322 length = 0;
323 }
324 return length;
325 }
326 }