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