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