1 package org.apache.commons.betwixt;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import java.beans.PropertyDescriptor;
21 import java.lang.reflect.Method;
22 import java.util.Map;
23
24 import org.apache.commons.beanutils.DynaProperty;
25 import org.apache.commons.betwixt.expression.DynaBeanExpression;
26 import org.apache.commons.betwixt.expression.DynaBeanUpdater;
27 import org.apache.commons.betwixt.expression.Expression;
28 import org.apache.commons.betwixt.expression.IteratorExpression;
29 import org.apache.commons.betwixt.expression.MethodExpression;
30 import org.apache.commons.betwixt.expression.MethodUpdater;
31 import org.apache.commons.betwixt.expression.Updater;
32 import org.apache.commons.betwixt.strategy.NameMapper;
33 import org.apache.commons.betwixt.strategy.SimpleTypeMapper;
34 import org.apache.commons.betwixt.strategy.TypeBindingStrategy;
35 import org.apache.commons.logging.Log;
36
37
38
39
40
41
42
43
44
45 public class BeanProperty {
46
47
48 private final String propertyName;
49
50 private final Class propertyType;
51
52 private Expression propertyExpression;
53
54 private Updater propertyUpdater;
55
56
57
58
59
60
61
62
63
64
65 public BeanProperty (
66 String propertyName,
67 Class propertyType,
68 Expression propertyExpression,
69 Updater propertyUpdater) {
70 this.propertyName = propertyName;
71 this.propertyType = propertyType;
72 this.propertyExpression = propertyExpression;
73 this.propertyUpdater = propertyUpdater;
74 }
75
76
77
78
79
80 public BeanProperty(PropertyDescriptor descriptor) {
81 this.propertyName = descriptor.getName();
82 this.propertyType = descriptor.getPropertyType();
83
84 Method readMethod = descriptor.getReadMethod();
85 if ( readMethod != null ) {
86 this.propertyExpression = new MethodExpression( readMethod );
87 }
88
89 Method writeMethod = descriptor.getWriteMethod();
90 if ( writeMethod != null ) {
91 this.propertyUpdater = new MethodUpdater( writeMethod );
92 }
93 }
94
95
96
97
98
99 public BeanProperty(DynaProperty dynaProperty) {
100 this.propertyName = dynaProperty.getName();
101 this.propertyType = dynaProperty.getType();
102 this.propertyExpression = new DynaBeanExpression( propertyName );
103 this.propertyUpdater = new DynaBeanUpdater( propertyName, propertyType );
104 }
105
106
107
108
109
110
111 public String getPropertyName() {
112 return propertyName;
113 }
114
115
116
117
118
119 public Class getPropertyType() {
120 return propertyType;
121 }
122
123
124
125
126
127
128 public Expression getPropertyExpression() {
129 return propertyExpression;
130 }
131
132
133
134
135
136
137 public Updater getPropertyUpdater() {
138 return propertyUpdater;
139 }
140
141
142
143
144
145
146
147
148
149 public Descriptor createXMLDescriptor( IntrospectionConfiguration configuration ) {
150 Log log = configuration.getIntrospectionLog();
151 if (log.isTraceEnabled()) {
152 log.trace("Creating descriptor for property: name="
153 + getPropertyName() + " type=" + getPropertyType());
154 }
155
156 NodeDescriptor descriptor = null;
157 Expression propertyExpression = getPropertyExpression();
158 Updater propertyUpdater = getPropertyUpdater();
159
160 if ( propertyExpression == null ) {
161 if (log.isTraceEnabled()) {
162 log.trace( "No read method for property: name="
163 + getPropertyName() + " type=" + getPropertyType());
164 }
165 return null;
166 }
167
168 if ( log.isTraceEnabled() ) {
169 log.trace( "Property expression=" + propertyExpression );
170 }
171
172
173
174
175
176
177
178 TypeBindingStrategy.BindingType bindingType
179 = configuration.getTypeBindingStrategy().bindingType( getPropertyType() ) ;
180 if ( bindingType.equals( TypeBindingStrategy.BindingType.PRIMITIVE ) ) {
181 descriptor =
182 createDescriptorForPrimitive(
183 configuration,
184 propertyExpression,
185 propertyUpdater);
186
187 } else if ( configuration.isLoopType( getPropertyType() ) ) {
188
189 if (log.isTraceEnabled()) {
190 log.trace("Loop type: " + getPropertyName());
191 log.trace("Wrap in collections? " + configuration.isWrapCollectionsInElement());
192 }
193
194 if ( Map.class.isAssignableFrom( getPropertyType() )) {
195 descriptor = createDescriptorForMap( configuration, propertyExpression );
196 } else {
197
198 descriptor
199 = createDescriptorForCollective( configuration, propertyUpdater, propertyExpression );
200 }
201 } else {
202 if (log.isTraceEnabled()) {
203 log.trace( "Standard property: " + getPropertyName());
204 }
205 descriptor =
206 createDescriptorForStandard(
207 propertyExpression,
208 propertyUpdater,
209 configuration);
210 }
211
212
213
214 if (log.isTraceEnabled()) {
215 log.trace( "Created descriptor:" );
216 log.trace( descriptor );
217 }
218 return descriptor;
219 }
220
221
222
223
224
225
226
227
228
229
230 private void configureDescriptor(
231 NodeDescriptor descriptor,
232 IntrospectionConfiguration configuration) {
233 NameMapper nameMapper = configuration.getElementNameMapper();
234 if (descriptor instanceof AttributeDescriptor) {
235
236 nameMapper = configuration.getAttributeNameMapper();
237
238 }
239 descriptor.setLocalName( nameMapper.mapTypeToElementName( propertyName ));
240 descriptor.setPropertyName( getPropertyName() );
241 descriptor.setPropertyType( getPropertyType() );
242 }
243
244
245
246
247
248
249
250 private ElementDescriptor createDescriptorForStandard(
251 Expression propertyExpression,
252 Updater propertyUpdater,
253 IntrospectionConfiguration configuration) {
254
255 ElementDescriptor result;
256
257 ElementDescriptor elementDescriptor = new ElementDescriptor();
258 elementDescriptor.setContextExpression( propertyExpression );
259 if ( propertyUpdater != null ) {
260 elementDescriptor.setUpdater( propertyUpdater );
261 }
262
263 elementDescriptor.setHollow(true);
264
265 result = elementDescriptor;
266
267 configureDescriptor(result, configuration);
268 return result;
269 }
270
271
272
273
274
275
276
277 private ElementDescriptor createDescriptorForMap(
278 IntrospectionConfiguration configuration,
279 Expression propertyExpression) {
280
281
282 ElementDescriptor result;
283
284 ElementDescriptor entryDescriptor = new ElementDescriptor();
285 entryDescriptor.setContextExpression(
286 new IteratorExpression( propertyExpression )
287 );
288
289 entryDescriptor.setLocalName( "entry" );
290 entryDescriptor.setPropertyName( getPropertyName() );
291 entryDescriptor.setPropertyType( getPropertyType() );
292
293
294 ElementDescriptor keyDescriptor = new ElementDescriptor( "key" );
295 keyDescriptor.setHollow( true );
296 entryDescriptor.addElementDescriptor( keyDescriptor );
297
298 ElementDescriptor valueDescriptor = new ElementDescriptor( "value" );
299 valueDescriptor.setHollow( true );
300 entryDescriptor.addElementDescriptor( valueDescriptor );
301
302
303 if ( configuration.isWrapCollectionsInElement() ) {
304 ElementDescriptor wrappingDescriptor = new ElementDescriptor();
305 wrappingDescriptor.setElementDescriptors( new ElementDescriptor[] { entryDescriptor } );
306 NameMapper nameMapper = configuration.getElementNameMapper();
307 wrappingDescriptor.setLocalName( nameMapper.mapTypeToElementName( propertyName ));
308 result = wrappingDescriptor;
309
310 } else {
311 result = entryDescriptor;
312 }
313 result.setCollective(true);
314 return result;
315 }
316
317
318
319
320
321
322
323
324 private ElementDescriptor createDescriptorForCollective(
325 IntrospectionConfiguration configuration,
326 Updater propertyUpdater,
327 Expression propertyExpression) {
328
329 ElementDescriptor result;
330
331 ElementDescriptor loopDescriptor = new ElementDescriptor();
332 loopDescriptor.setContextExpression(
333 new IteratorExpression( propertyExpression )
334 );
335 loopDescriptor.setPropertyName(getPropertyName());
336 loopDescriptor.setPropertyType(getPropertyType());
337 loopDescriptor.setHollow(true);
338
339
340 loopDescriptor.setUpdater(propertyUpdater);
341 loopDescriptor.setCollective(true);
342
343 if ( configuration.isWrapCollectionsInElement() ) {
344
345 ElementDescriptor wrappingDescriptor = new ElementDescriptor();
346 wrappingDescriptor.setElementDescriptors( new ElementDescriptor[] { loopDescriptor } );
347 wrappingDescriptor.setLocalName(
348 configuration.getElementNameMapper().mapTypeToElementName( propertyName ));
349 result = wrappingDescriptor;
350
351 } else {
352
353 result = loopDescriptor;
354 }
355 return result;
356 }
357
358
359
360
361
362
363
364
365
366
367 private NodeDescriptor createDescriptorForPrimitive(
368 IntrospectionConfiguration configuration,
369 Expression propertyExpression,
370 Updater propertyUpdater) {
371 Log log = configuration.getIntrospectionLog();
372 NodeDescriptor descriptor;
373 if (log.isTraceEnabled()) {
374 log.trace( "Primitive type: " + getPropertyName());
375 }
376 SimpleTypeMapper.Binding binding
377 = configuration.getSimpleTypeMapper().bind(
378 propertyName,
379 propertyType,
380 configuration);
381 if ( SimpleTypeMapper.Binding.ATTRIBUTE.equals( binding )) {
382 if (log.isTraceEnabled()) {
383 log.trace( "Adding property as attribute: " + getPropertyName() );
384 }
385 descriptor = new AttributeDescriptor();
386 } else {
387 if (log.isTraceEnabled()) {
388 log.trace( "Adding property as element: " + getPropertyName() );
389 }
390 descriptor = new ElementDescriptor();
391 }
392 descriptor.setTextExpression( propertyExpression );
393 if ( propertyUpdater != null ) {
394 descriptor.setUpdater( propertyUpdater );
395 }
396 configureDescriptor(descriptor, configuration);
397 return descriptor;
398 }
399 }