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