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.dynabeans;
19
20 import java.util.ArrayList;
21 import java.util.Arrays;
22
23 import org.apache.commons.beanutils.DynaBean;
24 import org.apache.commons.beanutils.DynaClass;
25 import org.apache.commons.beanutils.DynaProperty;
26 import org.apache.commons.jxpath.JXPathTypeConversionException;
27 import org.apache.commons.jxpath.ri.model.NodePointer;
28 import org.apache.commons.jxpath.ri.model.beans.PropertyPointer;
29 import org.apache.commons.jxpath.util.TypeUtils;
30 import org.apache.commons.jxpath.util.ValueUtils;
31
32
33
34
35 public class DynaBeanPropertyPointer extends PropertyPointer {
36
37 private static final String CLASS = "class";
38 private static final long serialVersionUID = 2094421509141267239L;
39
40
41
42
43 private final DynaBean dynaBean;
44
45
46
47
48 private String name;
49
50
51
52
53 private String[] names;
54
55
56
57
58
59
60
61 public DynaBeanPropertyPointer(final NodePointer parent, final DynaBean dynaBean) {
62 super(parent);
63 this.dynaBean = dynaBean;
64 }
65
66
67
68
69
70
71
72
73 private Object convert(final Object value, final boolean element) {
74 final DynaClass dynaClass = dynaBean.getDynaClass();
75 final DynaProperty property = dynaClass.getDynaProperty(getPropertyName());
76 Class type = property.getType();
77 if (element) {
78 if (!type.isArray()) {
79 return value;
80 }
81 type = type.getComponentType();
82 }
83 try {
84 return TypeUtils.convert(value, type);
85 } catch (final Exception ex) {
86 final String string = value == null ? "null" : value.getClass().getName();
87 throw new JXPathTypeConversionException("Cannot convert value of class " + string + " to type " + type, ex);
88 }
89 }
90
91 @Override
92 public Object getBaseValue() {
93 return dynaBean.get(getPropertyName());
94 }
95
96
97
98
99
100
101
102 @Override
103 public Object getImmediateNode() {
104 final String name = getPropertyName();
105 if (name.equals("*")) {
106 return null;
107 }
108 Object value;
109 if (index == WHOLE_COLLECTION) {
110 value = ValueUtils.getValue(dynaBean.get(name));
111 } else if (isIndexedProperty()) {
112
113
114
115
116 try {
117 value = ValueUtils.getValue(dynaBean.get(name, index));
118 } catch (final ArrayIndexOutOfBoundsException ex) {
119 value = null;
120 } catch (final IllegalArgumentException ex) {
121 value = dynaBean.get(name);
122 value = ValueUtils.getValue(value, index);
123 }
124 } else {
125 value = dynaBean.get(name);
126 if (ValueUtils.isCollection(value)) {
127 value = ValueUtils.getValue(value, index);
128 } else if (index != 0) {
129 value = null;
130 }
131 }
132 return value;
133 }
134
135 @Override
136 public int getPropertyCount() {
137 return getPropertyNames().length;
138 }
139
140
141
142
143
144
145 @Override
146 public int getPropertyIndex() {
147 if (propertyIndex == UNSPECIFIED_PROPERTY) {
148 final String[] names = getPropertyNames();
149 for (int i = 0; i < names.length; i++) {
150 if (names[i].equals(name)) {
151 propertyIndex = i;
152 name = null;
153 break;
154 }
155 }
156 }
157 return super.getPropertyIndex();
158 }
159
160
161
162
163
164
165 @Override
166 public String getPropertyName() {
167 if (name == null) {
168 final String[] names = getPropertyNames();
169 name = propertyIndex >= 0 && propertyIndex < names.length ? names[propertyIndex] : "*";
170 }
171 return name;
172 }
173
174 @Override
175 public String[] getPropertyNames() {
176
177 if (names == null) {
178 final DynaClass dynaClass = dynaBean.getDynaClass();
179 final DynaProperty[] dynaProperties = dynaClass.getDynaProperties();
180 final ArrayList<String> properties = new ArrayList<>(dynaProperties.length);
181 for (final DynaProperty element : dynaProperties) {
182 final String name = element.getName();
183 if (!CLASS.equals(name)) {
184 properties.add(name);
185 }
186 }
187 names = properties.toArray(new String[properties.size()]);
188 Arrays.sort(names);
189 }
190 return names;
191 }
192
193
194
195
196
197
198 @Override
199 protected boolean isActualProperty() {
200 final DynaClass dynaClass = dynaBean.getDynaClass();
201 return dynaClass.getDynaProperty(getPropertyName()) != null;
202 }
203
204
205
206
207
208
209 @Override
210 public boolean isContainer() {
211 return true;
212 }
213
214
215
216
217
218
219 protected boolean isIndexedProperty() {
220 final DynaClass dynaClass = dynaBean.getDynaClass();
221 final DynaProperty property = dynaClass.getDynaProperty(name);
222 return property.isIndexed();
223 }
224
225 @Override
226 public void remove() {
227 if (index == WHOLE_COLLECTION) {
228 dynaBean.set(getPropertyName(), null);
229 } else if (isIndexedProperty()) {
230 dynaBean.set(getPropertyName(), index, null);
231 } else if (isCollection()) {
232 final Object collection = ValueUtils.remove(getBaseValue(), index);
233 dynaBean.set(getPropertyName(), collection);
234 } else if (index == 0) {
235 dynaBean.set(getPropertyName(), null);
236 }
237 }
238
239
240
241
242
243
244 @Override
245 public void setPropertyIndex(final int index) {
246 if (propertyIndex != index) {
247 super.setPropertyIndex(index);
248 name = null;
249 }
250 }
251
252
253
254
255
256
257 @Override
258 public void setPropertyName(final String propertyName) {
259 setPropertyIndex(UNSPECIFIED_PROPERTY);
260 this.name = propertyName;
261 }
262
263
264
265
266
267
268
269 private void setValue(final int index, final Object value) {
270 if (index == WHOLE_COLLECTION) {
271 dynaBean.set(getPropertyName(), convert(value, false));
272 } else if (isIndexedProperty()) {
273 dynaBean.set(getPropertyName(), index, convert(value, true));
274 } else {
275 final Object baseValue = dynaBean.get(getPropertyName());
276 ValueUtils.setValue(baseValue, index, value);
277 }
278 }
279
280
281
282
283
284
285
286 @Override
287 public void setValue(final Object value) {
288 setValue(index, value);
289 }
290 }