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 java.beans.IndexedPropertyDescriptor;
20 import java.beans.PropertyDescriptor;
21
22 import org.apache.commons.jxpath.JXPathBeanInfo;
23 import org.apache.commons.jxpath.JXPathContext;
24 import org.apache.commons.jxpath.JXPathInvalidAccessException;
25 import org.apache.commons.jxpath.ri.model.NodePointer;
26 import org.apache.commons.jxpath.util.ValueUtils;
27
28
29
30
31
32
33
34 public class BeanPropertyPointer extends PropertyPointer {
35 private static final long serialVersionUID = -6008991447676468786L;
36
37 private static final Object UNINITIALIZED = new Object();
38
39 private String propertyName;
40 private JXPathBeanInfo beanInfo;
41 private Object baseValue = UNINITIALIZED;
42 private Object value = UNINITIALIZED;
43 private transient String[] names;
44 private transient PropertyDescriptor[] propertyDescriptors;
45 private transient PropertyDescriptor propertyDescriptor;
46
47
48
49
50
51
52 public BeanPropertyPointer(NodePointer parent, JXPathBeanInfo beanInfo) {
53 super(parent);
54 this.beanInfo = beanInfo;
55 }
56
57
58
59
60
61 public boolean isContainer() {
62 return true;
63 }
64
65 public int getPropertyCount() {
66 if (beanInfo.isAtomic()) {
67 return 0;
68 }
69 return getPropertyDescriptors().length;
70 }
71
72
73
74
75
76 public String[] getPropertyNames() {
77 if (names == null) {
78 PropertyDescriptor[] pds = getPropertyDescriptors();
79 names = new String[pds.length];
80 for (int i = 0; i < names.length; i++) {
81 names[i] = pds[i].getName();
82 }
83 }
84 return names;
85 }
86
87
88
89
90
91 public void setPropertyName(String propertyName) {
92 setPropertyIndex(UNSPECIFIED_PROPERTY);
93 this.propertyName = propertyName;
94 }
95
96
97
98
99
100 public void setPropertyIndex(int index) {
101 if (propertyIndex != index) {
102 super.setPropertyIndex(index);
103 propertyName = null;
104 propertyDescriptor = null;
105 baseValue = UNINITIALIZED;
106 value = UNINITIALIZED;
107 }
108 }
109
110
111
112
113
114 public Object getBaseValue() {
115 if (baseValue == UNINITIALIZED) {
116 PropertyDescriptor pd = getPropertyDescriptor();
117 if (pd == null) {
118 return null;
119 }
120 baseValue = ValueUtils.getValue(getBean(), pd);
121 }
122 return baseValue;
123 }
124
125 public void setIndex(int index) {
126 if (this.index == index) {
127 return;
128 }
129
130
131 if (this.index != WHOLE_COLLECTION
132 || index != 0
133 || isCollection()) {
134 super.setIndex(index);
135 value = UNINITIALIZED;
136 }
137 }
138
139
140
141
142
143
144
145
146 public Object getImmediateNode() {
147 if (value == UNINITIALIZED) {
148 if (index == WHOLE_COLLECTION) {
149 value = ValueUtils.getValue(getBaseValue());
150 }
151 else {
152 PropertyDescriptor pd = getPropertyDescriptor();
153 if (pd == null) {
154 value = null;
155 }
156 else {
157 value = ValueUtils.getValue(getBean(), pd, index);
158 }
159 }
160 }
161 return value;
162 }
163
164 protected boolean isActualProperty() {
165 return getPropertyDescriptor() != null;
166 }
167
168 public boolean isCollection() {
169 PropertyDescriptor pd = getPropertyDescriptor();
170 if (pd == null) {
171 return false;
172 }
173
174 if (pd instanceof IndexedPropertyDescriptor) {
175 return true;
176 }
177
178 int hint = ValueUtils.getCollectionHint(pd.getPropertyType());
179 if (hint == -1) {
180 return false;
181 }
182 if (hint == 1) {
183 return true;
184 }
185
186 Object value = getBaseValue();
187 return value != null && ValueUtils.isCollection(value);
188 }
189
190
191
192
193
194
195 public int getLength() {
196 PropertyDescriptor pd = getPropertyDescriptor();
197 if (pd == null) {
198 return 1;
199 }
200
201 if (pd instanceof IndexedPropertyDescriptor) {
202 return ValueUtils.getIndexedPropertyLength(
203 getBean(),
204 (IndexedPropertyDescriptor) pd);
205 }
206
207 int hint = ValueUtils.getCollectionHint(pd.getPropertyType());
208 if (hint == -1) {
209 return 1;
210 }
211 return super.getLength();
212 }
213
214
215
216
217
218
219
220 public void setValue(Object value) {
221 PropertyDescriptor pd = getPropertyDescriptor();
222 if (pd == null) {
223 throw new JXPathInvalidAccessException(
224 "Cannot set property: " + asPath() + " - no such property");
225 }
226
227 if (index == WHOLE_COLLECTION) {
228 ValueUtils.setValue(getBean(), pd, value);
229 }
230 else {
231 ValueUtils.setValue(getBean(), pd, index, value);
232 }
233 this.value = value;
234 }
235
236 public NodePointer createPath(JXPathContext context) {
237 if (getImmediateNode() == null) {
238 super.createPath(context);
239 baseValue = UNINITIALIZED;
240 value = UNINITIALIZED;
241 }
242 return this;
243 }
244
245 public void remove() {
246 if (index == WHOLE_COLLECTION) {
247 setValue(null);
248 }
249 else if (isCollection()) {
250 Object o = getBaseValue();
251 Object collection = ValueUtils.remove(getBaseValue(), index);
252 if (collection != o) {
253 ValueUtils.setValue(getBean(), getPropertyDescriptor(), collection);
254 }
255 }
256 else if (index == 0) {
257 index = WHOLE_COLLECTION;
258 setValue(null);
259 }
260 }
261
262
263
264
265
266 public String getPropertyName() {
267 if (propertyName == null) {
268 PropertyDescriptor pd = getPropertyDescriptor();
269 if (pd != null) {
270 propertyName = pd.getName();
271 }
272 }
273 return propertyName != null ? propertyName : "*";
274 }
275
276
277
278
279
280
281 private PropertyDescriptor getPropertyDescriptor() {
282 if (propertyDescriptor == null) {
283 int inx = getPropertyIndex();
284 if (inx == UNSPECIFIED_PROPERTY) {
285 propertyDescriptor =
286 beanInfo.getPropertyDescriptor(propertyName);
287 }
288 else {
289 PropertyDescriptor[] propertyDescriptors =
290 getPropertyDescriptors();
291 if (inx >= 0 && inx < propertyDescriptors.length) {
292 propertyDescriptor = propertyDescriptors[inx];
293 }
294 else {
295 propertyDescriptor = null;
296 }
297 }
298 }
299 return propertyDescriptor;
300 }
301
302
303
304
305
306 protected synchronized PropertyDescriptor[] getPropertyDescriptors() {
307 if (propertyDescriptors == null) {
308 propertyDescriptors = beanInfo.getPropertyDescriptors();
309 }
310 return propertyDescriptors;
311 }
312 }