1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 package org.exolab.castor.mapping.loader;
37
38 import java.lang.reflect.Array;
39 import java.lang.reflect.Field;
40 import java.lang.reflect.Method;
41 import java.lang.reflect.Modifier;
42 import java.lang.reflect.InvocationTargetException;
43 import java.util.Enumeration;
44 import java.util.Iterator;
45
46 import org.castor.core.util.Messages;
47 import org.exolab.castor.core.exceptions.CastorIllegalStateException;
48 import org.exolab.castor.mapping.AbstractFieldHandler;
49 import org.exolab.castor.mapping.ExtendedFieldHandler;
50 import org.exolab.castor.mapping.FieldDescriptor;
51 import org.exolab.castor.mapping.FieldHandler;
52 import org.exolab.castor.mapping.GeneralizedFieldHandler;
53 import org.exolab.castor.mapping.TypeConvertor;
54 import org.exolab.castor.mapping.CollectionHandler;
55 import org.exolab.castor.mapping.MappingException;
56 import org.exolab.castor.mapping.MappingRuntimeException;
57 import org.exolab.castor.util.IteratorEnumeration;
58
59
60
61
62
63
64
65
66
67
68
69
70 public final class FieldHandlerImpl<T> extends AbstractFieldHandler<T> {
71
72
73
74 private static final String ADD_PREFIX = "add";
75
76
77
78
79 private static final String ENUM_PREFIX = "enum";
80
81
82
83
84 private static final String ITER_PREFIX = "iter";
85
86
87
88
89 private final FieldHandler<T> _handler;
90
91
92
93
94 private final Field _field;
95
96
97
98
99 private Method[] _getSequence;
100
101
102
103
104 private Method[] _setSequence;
105
106
107
108
109
110 private Method _addMethod;
111
112
113
114
115 private Method _enumMethod;
116
117
118
119
120 private Method _iterMethod;
121
122
123
124
125 private Method _getMethod;
126
127
128
129
130 private Method _setMethod;
131
132
133
134
135 private Method _hasMethod;
136
137
138
139
140 private Method _deleteMethod;
141
142
143
144
145 private Method _createMethod;
146
147
148
149
150 private final String _fieldName;
151
152
153
154
155 private final Class _fieldType;
156
157
158
159
160 private final boolean _immutable;
161
162
163
164
165 private final Object _default;
166
167
168
169
170
171 private TypeConvertor _convertTo = null;
172
173
174
175
176
177 private TypeConvertor _convertFrom = null;
178
179
180
181
182 private final CollectionHandler<T> _colHandler;
183
184
185
186
187
188
189
190
191
192 public FieldHandlerImpl(FieldHandler<T> handler, TypeInfo typeInfo) {
193 _handler = handler;
194 _field = null;
195 _fieldName = handler.toString();
196 _fieldType = Types.typeFromPrimitive(typeInfo.getFieldType());
197 _immutable = typeInfo.isImmutable();
198 _default = typeInfo.getDefaultValue();
199 _convertTo = typeInfo.getConvertorTo();
200 _convertFrom = typeInfo.getConvertorFrom();
201 _colHandler = typeInfo.getCollectionHandler();
202 }
203
204
205
206
207
208
209
210
211
212
213 public FieldHandlerImpl(Field field, TypeInfo typeInfo) throws MappingException {
214 if (field.getModifiers() != Modifier.PUBLIC
215 && field.getModifiers() != (Modifier.PUBLIC | Modifier.VOLATILE))
216 throw new MappingException("mapping.fieldNotAccessible", field.getName(),
217 field.getDeclaringClass().getName());
218 _handler = null;
219 _field = field;
220 _fieldType = Types.typeFromPrimitive(typeInfo.getFieldType());
221 _fieldName = field.getName() + "(" + field.getType().getName() + ")";
222 _immutable = typeInfo.isImmutable();
223
224
225 if (_field.getType().isPrimitive())
226 _default = typeInfo.getDefaultValue();
227 else
228 _default = null;
229 _convertTo = typeInfo.getConvertorTo();
230 _convertFrom = typeInfo.getConvertorFrom();
231 _colHandler = typeInfo.getCollectionHandler();
232 }
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250 public FieldHandlerImpl(String fieldName, Method[] getSequence, Method[] setSequence,
251 Method getMethod, Method setMethod, TypeInfo typeInfo) throws MappingException {
252 _handler = null;
253 _field = null;
254 if (fieldName == null)
255 throw new IllegalArgumentException("Argument 'fieldName' is null");
256
257
258
259
260
261
262 _getSequence = getSequence;
263 _setSequence = setSequence;
264
265 if (setMethod != null) {
266
267 if (setMethod.getName().startsWith(ADD_PREFIX)) {
268 Class<?> pType = setMethod.getParameterTypes()[0];
269 if (pType != typeInfo.getFieldType())
270 setAddMethod(setMethod);
271 else
272 setWriteMethod(setMethod);
273 }
274
275
276
277
278
279
280
281
282
283
284
285
286
287 else
288 setWriteMethod(setMethod);
289 }
290
291 if (getMethod != null) {
292
293 if (getMethod.getName().startsWith(ENUM_PREFIX)) {
294 Class<?> rType = getMethod.getReturnType();
295
296
297 if (Enumeration.class.isAssignableFrom(rType))
298 setEnumMethod(getMethod);
299 else
300
301
302 setReadMethod(getMethod);
303 } else if (getMethod.getName().startsWith(ITER_PREFIX)) {
304 Class<?> rType = getMethod.getReturnType();
305
306
307 if (Iterator.class.isAssignableFrom(rType))
308 setIterMethod(getMethod);
309 else
310
311
312 setReadMethod(getMethod);
313 } else
314 setReadMethod(getMethod);
315 }
316
317 _fieldType = Types.typeFromPrimitive(typeInfo.getFieldType());
318 _fieldName = fieldName + "(" + _fieldType.getName() + ")";
319 _immutable = typeInfo.isImmutable();
320
321
322
323 if (setMethod != null && setMethod.getParameterTypes()[0].isPrimitive())
324 _default = typeInfo.getDefaultValue();
325 else
326 _default = null;
327 _convertTo = typeInfo.getConvertorTo();
328 _convertFrom = typeInfo.getConvertorFrom();
329 _colHandler = typeInfo.getCollectionHandler();
330 }
331
332 public TypeConvertor getConvertFrom() {
333 return _convertFrom;
334 }
335
336 public TypeConvertor getConvertTo() {
337 return _convertTo;
338 }
339
340
341
342
343
344
345 @SuppressWarnings("unchecked")
346 public T getValue(Object object) {
347 T value;
348
349 try {
350
351
352
353
354 if (_handler != null) {
355 value = _handler.getValue(object);
356 } else if (_field != null) {
357 value = (T) _field.get(object);
358 } else if (_enumMethod != null) {
359
360
361 value = (T) _enumMethod.invoke(object, (Object[]) null);
362 } else if (_iterMethod != null) {
363
364
365 value =
366 (T) new IteratorEnumeration((Iterator<T>) _iterMethod.invoke(object, (Object[]) null));
367 } else if (_getMethod != null) {
368 if (_getSequence != null) {
369 for (int i = 0; i < _getSequence.length; i++) {
370 object = _getSequence[i].invoke(object, (Object[]) null);
371 if (object == null) {
372 break;
373 }
374 }
375 }
376
377
378
379
380
381
382 if (object == null || (_hasMethod != null
383 && !((Boolean) _hasMethod.invoke(object, (Object[]) null)).booleanValue())) {
384 value = null;
385 } else {
386 value = (T) _getMethod.invoke(object, (Object[]) null);
387 }
388 } else {
389 value = null;
390 }
391 } catch (IllegalAccessException except) {
392 throw new CastorIllegalStateException(
393 Messages.format("mapping.schemaChangeNoAccess", toString()), except);
394 } catch (InvocationTargetException except) {
395 throw new CastorIllegalStateException(
396 Messages.format("mapping.schemaChangeInvocation", toString(), except), except);
397 }
398
399
400
401
402 if (_colHandler != null && _enumMethod == null && _iterMethod == null && _convertFrom == null) {
403 if (value == null) {
404 return (T) new CollectionHandlers.EmptyEnumerator<T>();
405 }
406 return (T) _colHandler.elements(value);
407 }
408
409
410 if (_convertFrom == null || value == null) {
411 return value;
412 }
413
414 try {
415 return (T) _convertFrom.convert(value);
416 } catch (ClassCastException except) {
417 String errorMessage = Messages.format("mapping.wrongConvertor", value.getClass().getName());
418 throw new IllegalArgumentException(errorMessage, except);
419 }
420 }
421
422
423
424
425
426
427
428 @SuppressWarnings("unchecked")
429 public void setValue(Object object, T value) {
430 if (_colHandler == null || _addMethod != null) {
431
432
433 if (value != null && _convertTo != null) {
434 try {
435 value = (T) _convertTo.convert(value);
436 } catch (ClassCastException except) {
437 String errorMessage =
438 Messages.format("mapping.wrongConvertor", value.getClass().getName());
439 throw new IllegalArgumentException(errorMessage, except);
440 }
441 } else {
442
443
444
445
446
447
448
449 }
450
451 try {
452 if (_handler != null) {
453 _handler.setValue(object, value);
454 } else if (_field != null) {
455 _field.set(object, value == null ? _default : value);
456 } else {
457
458
459 Method setter = selectWriteMethod(value);
460
461 if (setter != null) {
462 if (_getSequence != null) {
463 for (int i = 0; i < _getSequence.length; i++) {
464 Object last;
465
466 last = object;
467 object = _getSequence[i].invoke(object, (Object[]) null);
468 if (object == null) {
469
470
471 if (value == null || _setSequence[i] == null) {
472 break;
473 }
474 object = Types.newInstance(_getSequence[i].getReturnType());
475 _setSequence[i].invoke(last, new Object[] {object});
476 }
477 }
478 }
479 if (object != null) {
480 if (value == null && _deleteMethod != null) {
481 _deleteMethod.invoke(object, (Object[]) null);
482 } else {
483 setter.invoke(object, new Object[] {value == null ? _default : value});
484 }
485 }
486 }
487 }
488
489
490 } catch (IllegalArgumentException except) {
491
492 if (value == null) {
493 String errorMessage = Messages.format("mapping.typeConversionNull", toString());
494 throw new IllegalArgumentException(errorMessage);
495 }
496 String errorMessage =
497 Messages.format("mapping.typeConversion", toString(), value.getClass().getName());
498 throw new IllegalArgumentException(errorMessage, except);
499 } catch (IllegalAccessException except) {
500
501 String errorMessage = Messages.format("mapping.schemaChangeNoAccess", toString());
502 throw new CastorIllegalStateException(errorMessage, except);
503 } catch (InvocationTargetException except) {
504
505 throw new MappingRuntimeException(except.getTargetException());
506 }
507 } else if (value != null) {
508 Object collect;
509 try {
510
511
512
513 if (_handler != null) {
514 collect = _handler.getValue(object);
515 collect = _colHandler.add(collect, value);
516 if (collect != null)
517 _handler.setValue(object, (T) collect);
518 } else if (_field != null) {
519 collect = _field.get(object);
520 if (collect == null) {
521
522 Class type = _field.getType();
523
524
525
526
527 if (type.isArray()) {
528 Class componentType = type.getComponentType();
529 Class valueType = value.getClass();
530 if (componentType.isPrimitive()
531 || ((!valueType.isArray()) && (valueType != componentType))) {
532 try {
533 collect = Array.newInstance(componentType, 0);
534 } catch (Exception e) {
535 String err = "Unable to instantiate an array of '" + componentType + "' : " + e;
536 throw new CastorIllegalStateException(err, e);
537 }
538 }
539 }
540 }
541 collect = _colHandler.add(collect, value);
542 if (collect != null)
543 _field.set(object, collect);
544
545 } else if (_getMethod != null) {
546 if (_getSequence != null)
547 for (int i = 0; i < _getSequence.length; i++)
548 object = _getSequence[i].invoke(object, (Object[]) null);
549 collect = _getMethod.invoke(object, (Object[]) null);
550
551
552
553
554
555 boolean setCollection = false;
556 if (collect == null) {
557
558
559 Class type = _getMethod.getReturnType();
560
561
562
563
564
565 if (type.isArray()) {
566 Class componentType = type.getComponentType();
567 Class valueType = value.getClass();
568 if (componentType.isPrimitive()
569 || ((!valueType.isArray()) && (valueType != componentType))) {
570 try {
571 collect = Array.newInstance(componentType, 0);
572 } catch (Exception e) {
573 String err = "Unable to instantiate an array of '" + componentType + "' : " + e;
574 throw new CastorIllegalStateException(err, e);
575 }
576 }
577 }
578 setCollection = true;
579 } else {
580 setCollection = collect.getClass().isArray();
581 }
582
583 Object tmp = _colHandler.add(collect, value);
584
585
586
587 if (tmp != null)
588 collect = tmp;
589
590 if (setCollection && (_setMethod != null))
591 _setMethod.invoke(object, new Object[] {collect});
592 }
593 } catch (IllegalAccessException except) {
594
595 throw new IllegalStateException(
596 Messages.format("mapping.schemaChangeNoAccess", toString()));
597 } catch (InvocationTargetException except) {
598
599 throw new MappingRuntimeException(except.getTargetException());
600 }
601 }
602 }
603
604 public void resetValue(Object object) {
605 if (_colHandler == null) {
606
607 try {
608 if (_handler != null)
609 _handler.resetValue(object);
610 else if (_field != null)
611 _field.set(object, _default);
612 else if (_setMethod != null) {
613 if (_getSequence != null)
614 for (int i = 0; i < _getSequence.length; i++) {
615 object = _getSequence[i].invoke(object, (Object[]) null);
616 if (object == null)
617 break;
618 }
619 if (object != null) {
620 if (_deleteMethod != null)
621 _deleteMethod.invoke(object, (Object[]) null);
622 else
623 _setMethod.invoke(object, new Object[] {_default});
624 }
625 }
626
627
628 } catch (IllegalArgumentException except) {
629
630 throw new IllegalArgumentException(
631 Messages.format("mapping.typeConversionNull", toString()));
632 } catch (IllegalAccessException except) {
633
634 throw new IllegalStateException(
635 Messages.format("mapping.schemaChangeNoAccess", toString()));
636 } catch (InvocationTargetException except) {
637
638 throw new MappingRuntimeException(except.getTargetException());
639 }
640
641 } else {
642 Object collect;
643
644 try {
645
646
647
648 if (_handler != null) {
649 _handler.resetValue(object);
650 } else if (_field != null) {
651 collect = _field.get(object);
652 collect = _colHandler.clear(collect);
653 if (collect != null)
654 _field.set(object, collect);
655 } else if (_getMethod != null) {
656 if (_getSequence != null)
657 for (int i = 0; i < _getSequence.length; i++)
658 object = _getSequence[i].invoke(object, (Object[]) null);
659 collect = _getMethod.invoke(object, (Object[]) null);
660 collect = _colHandler.clear(collect);
661 if (collect != null && _setMethod != null)
662 _setMethod.invoke(object, new Object[] {collect});
663 }
664 } catch (IllegalAccessException except) {
665
666 throw new IllegalStateException(
667 Messages.format("mapping.schemaChangeNoAccess", toString()));
668 } catch (InvocationTargetException except) {
669
670 throw new MappingRuntimeException(except.getTargetException());
671 }
672
673 }
674 }
675
676
677
678
679
680
681
682
683 public T newInstance(Object parent) throws IllegalStateException {
684 return newInstance(parent, null);
685 }
686
687
688
689
690
691
692
693
694
695 @SuppressWarnings("unchecked")
696 public T newInstance(Object parent, Object[] args) throws IllegalStateException {
697 if (_fieldType.isInterface() && _createMethod == null)
698 return null;
699
700 if ((_immutable) && ((args == null) || (args.length == 0)))
701 throw new IllegalStateException(Messages.format("mapping.classNotConstructable", _fieldType));
702
703 if (_handler != null) {
704 if (_handler instanceof ExtendedFieldHandler)
705 return (T) ((ExtendedFieldHandler<T>) _handler).newInstance(parent, args);
706 return _handler.newInstance(parent);
707 }
708
709 if (_createMethod != null && parent != null) {
710 try {
711 return (T) _createMethod.invoke(parent, args);
712 } catch (IllegalAccessException except) {
713
714 throw new IllegalStateException(
715 Messages.format("mapping.schemaChangeNoAccess", toString()));
716 } catch (InvocationTargetException except) {
717
718 throw new MappingRuntimeException(except.getTargetException());
719 }
720 }
721 return (T) Types.newInstance(_fieldType, args);
722 }
723
724
725
726
727 void setRequired(final boolean required) {}
728
729
730
731
732
733
734 public void setConvertFrom(TypeConvertor convertor) {
735 _convertFrom = convertor;
736 }
737
738
739
740
741
742
743 public void setConvertTo(TypeConvertor convertor) {
744 _convertTo = convertor;
745 }
746
747
748
749
750
751
752 public void setCreateMethod(Method method) throws MappingException {
753 if ((method.getModifiers() & Modifier.PUBLIC) == 0
754 || (method.getModifiers() & Modifier.STATIC) != 0)
755 throw new MappingException("mapping.accessorNotAccessible", method,
756 method.getDeclaringClass().getName());
757 if (method.getParameterTypes().length != 0)
758 throw new MappingException("mapping.createMethodNoParam", method,
759 method.getDeclaringClass().getName());
760 _createMethod = method;
761 }
762
763
764
765
766
767
768 public void setHasDeleteMethod(Method hasMethod, Method deleteMethod) throws MappingException {
769 if (hasMethod != null) {
770 if ((hasMethod.getModifiers() & Modifier.PUBLIC) == 0
771 || (hasMethod.getModifiers() & Modifier.STATIC) != 0)
772 throw new MappingException("mapping.accessorNotAccessible", hasMethod,
773 hasMethod.getDeclaringClass().getName());
774 if (hasMethod.getParameterTypes().length != 0)
775 throw new MappingException("mapping.createMethodNoParam", hasMethod,
776 hasMethod.getDeclaringClass().getName());
777 _hasMethod = hasMethod;
778 }
779
780 if (deleteMethod != null) {
781 if ((deleteMethod.getModifiers() & Modifier.PUBLIC) == 0
782 || (deleteMethod.getModifiers() & Modifier.STATIC) != 0)
783 throw new MappingException("mapping.accessorNotAccessible", deleteMethod,
784 deleteMethod.getDeclaringClass().getName());
785 if (deleteMethod.getParameterTypes().length != 0)
786 throw new MappingException("mapping.createMethodNoParam", deleteMethod,
787 deleteMethod.getDeclaringClass().getName());
788 _deleteMethod = deleteMethod;
789 }
790 }
791
792
793
794
795
796 public void setReadMethod(Method method) throws MappingException {
797 if ((method.getModifiers() & Modifier.PUBLIC) == 0
798 || (method.getModifiers() & Modifier.STATIC) != 0)
799 throw new MappingException("mapping.accessorNotAccessible", method,
800 method.getDeclaringClass().getName());
801 if (method.getParameterTypes().length != 0)
802 throw new MappingException("mapping.readMethodHasParam", method,
803 method.getDeclaringClass().getName());
804 _getMethod = method;
805 }
806
807
808
809
810
811 public void setWriteMethod(Method method) throws MappingException {
812 if ((method.getModifiers() & Modifier.PUBLIC) == 0
813 || (method.getModifiers() & Modifier.STATIC) != 0)
814 throw new MappingException("mapping.accessorNotAccessible", method,
815 method.getDeclaringClass().getName());
816 if (method.getParameterTypes().length != 1)
817 throw new MappingException("mapping.writeMethodNoParam", method,
818 method.getDeclaringClass().getName());
819 _setMethod = method;
820 }
821
822
823
824
825
826 public void setAddMethod(Method method) throws MappingException {
827 if ((method.getModifiers() & Modifier.PUBLIC) == 0
828 || (method.getModifiers() & Modifier.STATIC) != 0)
829 throw new MappingException("mapping.accessorNotAccessible", method,
830 method.getDeclaringClass().getName());
831 if (method.getParameterTypes().length != 1)
832 throw new MappingException("mapping.writeMethodNoParam", method,
833 method.getDeclaringClass().getName());
834 _addMethod = method;
835
836
837 if (_addMethod == _setMethod)
838 _setMethod = null;
839
840 }
841
842
843
844
845 public void setEnumMethod(Method method) throws MappingException {
846 if ((method.getModifiers() & Modifier.PUBLIC) == 0
847 || (method.getModifiers() & Modifier.STATIC) != 0)
848 throw new MappingException("mapping.accessorNotAccessible", method,
849 method.getDeclaringClass().getName());
850 if (method.getParameterTypes().length != 0)
851 throw new MappingException("mapping.readMethodHasParam", method,
852 method.getDeclaringClass().getName());
853
854 _enumMethod = method;
855 }
856
857
858
859
860 public void setIterMethod(Method method) throws MappingException {
861 if ((method.getModifiers() & Modifier.PUBLIC) == 0
862 || (method.getModifiers() & Modifier.STATIC) != 0)
863 throw new MappingException("mapping.accessorNotAccessible", method,
864 method.getDeclaringClass().getName());
865 if (method.getParameterTypes().length != 0)
866 throw new MappingException("mapping.readMethodHasParam", method,
867 method.getDeclaringClass().getName());
868
869 _iterMethod = method;
870 }
871
872
873
874
875
876
877
878 private Method selectWriteMethod(Object value) {
879 if (_setMethod != null) {
880
881 if (_addMethod == null)
882 return _setMethod;
883
884 if (value == null) {
885 if (_default != null)
886 value = _default;
887 else
888 return _setMethod;
889 }
890
891
892 Class paramType = _setMethod.getParameterTypes()[0];
893
894 if (paramType.isAssignableFrom(value.getClass()))
895 return _setMethod;
896 }
897
898 return _addMethod;
899
900 }
901
902
903
904
905 public boolean isCollection() {
906 return (_colHandler != null);
907 }
908
909 public String toString() {
910 return _fieldName;
911 }
912
913
914
915
916
917
918
919
920
921 public void setFieldDescriptor(FieldDescriptor fieldDesc) {
922 super.setFieldDescriptor(fieldDesc);
923 if (_handler != null) {
924 if (_handler instanceof GeneralizedFieldHandler) {
925 ((GeneralizedFieldHandler) _handler).setFieldDescriptor(fieldDesc);
926 }
927 }
928 }
929
930 }