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
47
48
49
50 package org.exolab.castor.xml.util;
51
52 import java.lang.reflect.Array;
53 import java.util.ArrayList;
54 import java.util.Collection;
55 import java.util.HashMap;
56 import java.util.HashSet;
57 import java.util.LinkedList;
58 import java.util.List;
59 import java.util.Map;
60 import java.util.Set;
61
62 import org.exolab.castor.mapping.AbstractFieldHandler;
63 import org.exolab.castor.mapping.AccessMode;
64 import org.exolab.castor.mapping.ClassDescriptor;
65 import org.exolab.castor.mapping.FieldDescriptor;
66 import org.exolab.castor.mapping.FieldHandler;
67 import org.exolab.castor.xml.FieldValidator;
68 import org.exolab.castor.xml.NodeType;
69 import org.exolab.castor.xml.TypeValidator;
70 import org.exolab.castor.xml.UnmarshalState;
71 import org.exolab.castor.xml.ValidationContext;
72 import org.exolab.castor.xml.ValidationException;
73 import org.exolab.castor.xml.Validator;
74 import org.exolab.castor.xml.XMLClassDescriptor;
75 import org.exolab.castor.xml.XMLFieldDescriptor;
76 import org.exolab.castor.xml.location.XPathLocation;
77 import org.exolab.castor.xml.util.resolvers.ResolveHelpers;
78
79
80
81
82
83
84
85
86 public class XMLClassDescriptorImpl extends Validator implements XMLClassDescriptor {
87
88
89 private static final short ALL = 0;
90
91
92
93 private static final short CHOICE = 1;
94
95
96 private static final short SEQUENCE = 2;
97
98
99 private static final String NULL_CLASS_ERR =
100 "The Class passed as an argument to the constructor of "
101 + "XMLClassDescriptorImpl may not be null.";
102
103 private static final String WILDCARD = "*";
104
105
106 private XMLFieldDescriptors _attributes = null;
107
108
109 private XMLFieldDescriptor[] _attArray = null;
110
111
112 private Class<?> _class = null;
113
114
115 private int _containerCount = 0;
116
117
118 private XMLFieldDescriptor _contentDescriptor = null;
119
120
121 private TypeValidator _validator = null;
122
123
124 private XMLFieldDescriptors _elements = null;
125
126
127 private XMLFieldDescriptor[] _elemArray = null;
128
129
130 private String _nsPrefix = null;
131
132
133 private String _nsURI = null;
134
135
136 private String _xmlName;
137
138
139
140
141
142 private boolean _elementDefinition = false;
143
144
145
146 private XMLClassDescriptor _extends;
147
148
149 private FieldDescriptor _identity;
150
151
152 private AccessMode _accessMode;
153
154
155
156 private boolean _introspected = false;
157
158 private short _compositor = ALL;
159
160
161
162 private List<XMLFieldDescriptor> _sequenceOfElements = new ArrayList<XMLFieldDescriptor>();
163
164 private List<String> _substitutes = new LinkedList<String>();
165
166
167 private Map<String, Object> _properties = new HashMap<String, Object>();
168
169
170 private Set<String> _natures = new HashSet<String>();
171
172
173
174
175
176
177 public XMLClassDescriptorImpl(final Class<?> type) {
178 this();
179 if (type == null) {
180 throw new IllegalArgumentException(NULL_CLASS_ERR);
181 }
182
183 _class = type;
184
185 }
186
187
188
189
190
191
192 public XMLClassDescriptorImpl(Class<?> type, String xmlName) {
193 this();
194
195 if (type == null) {
196 throw new IllegalArgumentException(NULL_CLASS_ERR);
197 }
198
199 this._class = type;
200 setXMLName(xmlName);
201 }
202
203
204
205
206 protected XMLClassDescriptorImpl() {
207 _attributes = new XMLFieldDescriptors(5);
208 _elements = new XMLFieldDescriptors(7);
209 }
210
211
212
213
214
215
216
217
218
219
220
221
222 public void addFieldDescriptor(XMLFieldDescriptor descriptor) {
223 addFieldDescriptor(descriptor, true);
224 }
225
226
227
228
229
230
231
232
233 public boolean contains(XMLFieldDescriptor descriptor) {
234 if (descriptor == null) {
235 return false;
236 }
237
238 if (_attributes.contains(descriptor)) {
239 return true;
240 }
241 if (_elements.contains(descriptor)) {
242 return true;
243 }
244
245 return descriptor.equals(_contentDescriptor);
246 }
247
248
249
250
251
252
253
254
255 public XMLFieldDescriptor[] getAttributeDescriptors() {
256 return getAttributeArray().clone();
257 }
258
259
260
261
262
263
264
265
266 public XMLFieldDescriptor getContentDescriptor() {
267 return _contentDescriptor;
268 }
269
270
271
272
273
274
275
276
277 public XMLFieldDescriptor[] getElementDescriptors() {
278 return getElementArray().clone();
279 }
280
281
282
283
284
285
286
287 public void checkDescriptorForCorrectOrderWithinSequence(
288 final XMLFieldDescriptor elementDescriptor, UnmarshalState parentState, String xmlName) throws ValidationException {
289 if (_compositor == SEQUENCE && _sequenceOfElements.size() > 0) {
290
291 if (parentState.getExpectedIndex() == _sequenceOfElements.size() ) {
292 throw new ValidationException ("Element with name " + xmlName + " passed to type " + getXMLName() + " in incorrect order; It is not allowed to be the last element of this sequence!");
293 }
294
295 XMLFieldDescriptor expectedElementDescriptor = _sequenceOfElements.get(parentState.getExpectedIndex());
296
297 String expectedElementName = expectedElementDescriptor.getXMLName();
298 String elementName = xmlName;
299
300 boolean anyNode = expectedElementDescriptor.getFieldName().equals("_anyObject") && expectedElementName == null;
301
302
303 if (!anyNode && expectedElementDescriptor.getXMLName().equals("-error-if-this-is-used-")) {
304
305
306 List<String> possibleNames = new ArrayList<String>();
307 fillPossibleNames(possibleNames, expectedElementDescriptor);
308
309
310 if (!possibleNames.contains(elementName)) {
311 if (!expectedElementDescriptor.isRequired()) {
312 parentState.setExpectedIndex(parentState.getExpectedIndex() + 1);
313 checkDescriptorForCorrectOrderWithinSequence(elementDescriptor, parentState, xmlName);
314 } else {
315 throw new ValidationException ("Element with name " + elementName + " passed to type " + getXMLName() + " in incorrect order; expected element has to be member of the expected choice.");
316 }
317 } else {
318 parentState.setExpectedIndex(parentState.getExpectedIndex() + 1);
319 }
320 return;
321 }
322
323
324 if (expectedElementDescriptor.isMultivalued() && !parentState.isWithinMultivaluedElement()) {
325 parentState.setWithinMultivaluedElement(true);
326 }
327
328 if (!anyNode && !(expectedElementName).equals(elementName)) {
329
330
331 List<String> substitutes = expectedElementDescriptor.getSubstitutes();
332 if (substitutes != null && !substitutes.isEmpty()) {
333 if (substitutes.contains(elementName)) {
334 if (!parentState.isWithinMultivaluedElement()) {
335 parentState.setExpectedIndex(parentState.getExpectedIndex() + 1);
336 }
337 return;
338 }
339 }
340
341 if (expectedElementDescriptor.isMultivalued()) {
342 parentState.setWithinMultivaluedElement(false);
343 parentState.setExpectedIndex(parentState.getExpectedIndex() + 1);
344 checkDescriptorForCorrectOrderWithinSequence(elementDescriptor, parentState, xmlName);
345 return;
346 }
347
348 if (expectedElementDescriptor.isRequired()) {
349 throw new ValidationException ("Element with name " + elementName + " passed to type " + getXMLName() + " in incorrect order; expected element with name '" + expectedElementName + "' or any other optional element declared prior to it.");
350 }
351
352
353 parentState.setExpectedIndex(parentState.getExpectedIndex() + 1);
354 checkDescriptorForCorrectOrderWithinSequence(elementDescriptor, parentState, xmlName);
355 return;
356
357 }
358
359 if (!parentState.isWithinMultivaluedElement()) {
360 parentState.setExpectedIndex(parentState.getExpectedIndex() + 1);
361 }
362 }
363 }
364
365
366 private void fillPossibleNames(List<String> possibleNames, XMLFieldDescriptor descriptor) {
367 XMLFieldDescriptor[] descriptors = ((XMLClassDescriptor)descriptor.getClassDescriptor()).getElementDescriptors();
368 if (descriptors.length == 0) {
369 return;
370 }
371 for (XMLFieldDescriptor fieldDescriptor : descriptors) {
372 if ("_items".equals(fieldDescriptor.getFieldName() )
373 || "-error-if-this-is-used-".equals(fieldDescriptor.getXMLName())) {
374 fillPossibleNames(possibleNames, fieldDescriptor);
375 } else {
376 possibleNames.add(fieldDescriptor.getXMLName());
377 }
378 }
379 }
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 public XMLFieldDescriptor getFieldDescriptor(String name, String namespace,
397 NodeType nodeType) {
398 boolean wild = ((nodeType == null) || _introspected);
399 XMLFieldDescriptor result = null;
400
401 XMLFieldDescriptor[] attributes = _attArray;
402 XMLFieldDescriptor[] elements = _elemArray;
403
404
405 String location = null;
406 if (name != null) {
407 int idx = name.lastIndexOf('/');
408 if (idx >= 0) {
409 location = name.substring(0, idx);
410 name = name.substring(idx+1);
411 }
412 }
413
414 if (wild || (nodeType == NodeType.Element)) {
415
416 if (elements == null) elements = getElementArray();
417
418
419
420
421
422
423
424
425
426
427
428 for (int i = 0; i < elements.length; i++) {
429 XMLFieldDescriptor desc = elements[i];
430
431 if (desc == null) continue;
432
433 if (location != null) {
434 if (!location.equals(desc.getLocationPath()))
435 continue;
436 }
437
438 if (desc.matches(name)) {
439 if (!desc.matches(WILDCARD)) {
440
441
442
443
444 if (namespace == null
445 || ResolveHelpers.namespaceEquals(namespace, desc.getNameSpaceURI())) {
446 return desc;
447 }
448 } else {
449
450
451
452 if (name.equals(desc.getXMLName()))
453 return desc;
454
455 result = desc;
456 }
457 }
458
459
460 if ( desc.isContainer() ) {
461 XMLClassDescriptor xcd = (XMLClassDescriptor)desc.getClassDescriptor();
462
463 if (xcd != this) {
464
465 if (xcd.getFieldDescriptor(name, namespace, NodeType.Element) != null) {
466 result = desc;
467 break;
468 }
469 }
470 }
471 }
472
473 if (result != null)
474 return result;
475 }
476
477
478 if (wild || (nodeType == NodeType.Attribute))
479 {
480 if (attributes == null) attributes = getAttributeArray();
481 for (int i = 0; i < attributes.length; i++) {
482 XMLFieldDescriptor desc = attributes[i];
483 if (desc == null) continue;
484 if (desc.matches(name)) {
485 return desc;
486 }
487 }
488 }
489
490
491 if (nodeType == NodeType.Namespace) {
492 if (attributes == null) attributes = getAttributeArray();
493 for (int i = 0; i < attributes.length; i++) {
494 if (attributes[i] == null) continue;
495 if (attributes[i].getNodeType() == NodeType.Namespace) {
496 return attributes[i];
497 }
498 }
499 }
500
501
502
503 if (nodeType == NodeType.Attribute) {
504 if (elements == null) elements = getElementArray();
505 for (int i = 0; i < elements.length; i++) {
506 XMLFieldDescriptor desc = elements[i];
507 if (desc.isContainer()) {
508 XMLClassDescriptor xcd = (XMLClassDescriptor)desc.getClassDescriptor();
509
510 if (xcd != this) {
511
512 XMLFieldDescriptor temp = xcd.getFieldDescriptor(name, namespace, NodeType.Attribute);
513 if (temp != null) {
514 return desc;
515 }
516 }
517 }
518 }
519 }
520
521 return null;
522
523 }
524
525
526
527
528
529 public String getNameSpacePrefix() {
530 return _nsPrefix;
531 }
532
533
534
535
536 public String getNameSpaceURI() {
537 return _nsURI;
538 }
539
540
541
542
543
544
545
546
547
548
549 public TypeValidator getValidator() {
550 if (_validator != null)
551 return _validator;
552 return this;
553 }
554
555
556
557
558
559
560 public String getXMLName() {
561 return _xmlName;
562 }
563
564
565
566
567
568 public boolean isElementDefinition() {
569 return _elementDefinition;
570 }
571
572
573
574
575
576
577
578
579
580
581
582 public boolean hasContainerFields() {
583 return (_containerCount > 0);
584 }
585
586
587
588
589
590
591
592 public boolean removeFieldDescriptor(XMLFieldDescriptor descriptor) {
593
594 if (descriptor == null) return false;
595
596 boolean removed = false;
597 NodeType nodeType = descriptor.getNodeType();
598 switch(nodeType.getType()) {
599 case NodeType.NAMESPACE:
600 case NodeType.ATTRIBUTE:
601 if (_attributes.remove(descriptor)) {
602 removed = true;
603 _attArray = null;
604 }
605 break;
606 case NodeType.TEXT:
607 if (_contentDescriptor == descriptor) {
608 _contentDescriptor = null;
609 removed = true;
610 }
611 break;
612 default:
613 if (_elements.remove(descriptor)) {
614 _elemArray = null;
615 removed = true;
616 if (descriptor.isContainer()) --_containerCount;
617 }
618 break;
619 }
620 return removed;
621 }
622
623
624
625
626
627 public void setCompositorAsAll() {
628 _compositor = ALL;
629 }
630
631
632
633
634
635 public void setCompositorAsChoice() {
636 _compositor = CHOICE;
637 }
638
639
640
641
642
643 public void setCompositorAsSequence() {
644 _compositor = SEQUENCE;
645 }
646
647
648
649
650
651
652 public void setExtends(XMLClassDescriptor classDesc) {
653
654 FieldDescriptor[] fields = null;
655
656 if (_extends != null) {
657 sortDescriptors();
658 fields = _extends.getFields();
659 for (int i = 0; i < fields.length; i++) {
660 removeFieldDescriptor((XMLFieldDescriptor)fields[i]);
661 }
662 }
663
664 this._extends = classDesc;
665
666
667 if (_extends != null) {
668 fields = classDesc.getFields();
669 for (int i = 0; i < fields.length; i++) {
670 addFieldDescriptor((XMLFieldDescriptor)fields[i], false);
671 }
672 }
673
674 }
675
676
677
678
679
680
681 public void setIdentity(XMLFieldDescriptor fieldDesc) {
682 if (fieldDesc != null) {
683 if ( (! _attributes.contains(fieldDesc)) &&
684 (! _elements.contains(fieldDesc))) {
685 addFieldDescriptor(fieldDesc);
686 }
687 }
688 this._identity = fieldDesc;
689 }
690
691
692
693
694
695
696
697 public void setNameSpacePrefix(String nsPrefix) {
698 this._nsPrefix = nsPrefix;
699 }
700
701
702
703
704
705
706
707 public void setNameSpaceURI(String nsURI) {
708 this._nsURI = nsURI;
709 }
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729 public void setXMLName(String xmlName) {
730 if (xmlName == null) {
731 if (_xmlName == null && _class != null) {
732 _xmlName = _class.getName();
733 }
734 }
735 else this._xmlName = xmlName;
736 }
737
738
739
740
741
742
743
744
745 public void setElementDefinition(boolean elementDefinition){
746 this._elementDefinition = elementDefinition;
747 }
748
749
750
751
752
753
754
755 public void sortDescriptors() {
756
757
758 XMLFieldDescriptor[] descriptors = getAttributeArray();
759 for (int i = 0; i < descriptors.length; i++) {
760 XMLFieldDescriptor fieldDesc = descriptors[i];
761 switch (fieldDesc.getNodeType().getType()) {
762 case NodeType.ELEMENT:
763 _elements.add(fieldDesc);
764 _attributes.remove(fieldDesc);
765 _attArray = null;
766 break;
767 case NodeType.TEXT:
768 _attributes.remove(fieldDesc);
769 _attArray = null;
770 break;
771 default:
772 break;
773 }
774 }
775
776
777 descriptors = getElementArray();
778 for (int i = 0; i < descriptors.length; i++) {
779 XMLFieldDescriptor fieldDesc = descriptors[i];
780 switch (fieldDesc.getNodeType().getType()) {
781 case NodeType.NAMESPACE:
782 case NodeType.ATTRIBUTE:
783 _attributes.add(fieldDesc);
784 _elements.remove(fieldDesc);
785 _elemArray = null;
786 break;
787 case NodeType.TEXT:
788 _elements.remove(fieldDesc);
789 _elemArray = null;
790 break;
791 default:
792 break;
793 }
794 }
795
796 }
797
798
799
800
801
802
803 public String toString() {
804
805 String str = super.toString() + "; descriptor for class: ";
806
807
808 if (_class != null)
809 str += _class.getName();
810 else
811 str += "[null]";
812
813
814 str += "; xml name: " + _xmlName;
815
816 return str;
817 }
818
819
820
821
822
823
824 public void validate(Object object)
825 throws ValidationException
826 {
827 validate(object, (ValidationContext)null);
828 }
829
830
831
832
833
834
835 public void validate(Object object, ValidationContext context)
836 throws ValidationException {
837 if (object == null) {
838 throw new ValidationException("Cannot validate a null object.");
839 }
840 Class<?> a = getJavaClass();
841 ClassLoader acl = a.getClassLoader();
842 Class<? extends Object> b = object.getClass();
843 ClassLoader bcl = b.getClassLoader();
844 if (!getJavaClass().isAssignableFrom(object.getClass())) {
845 String err = "The given object is not an instance of the class"
846 + " described by this ClassDecriptor.";
847 throw new ValidationException(err);
848 }
849
850
851
852
853
854 XMLFieldDescriptor[] localElements = getElementArray();
855 XMLFieldDescriptor[] localAttributes = getAttributeArray();
856
857 if (_extends != null) {
858
859
860 if (_extends instanceof XMLClassDescriptorImpl) {
861 ((XMLClassDescriptorImpl) _extends).validate(object, context);
862 } else {
863 TypeValidator baseValidator = _extends.getValidator();
864 if (baseValidator != null) {
865 baseValidator.validate(object, context);
866 }
867 }
868
869
870 XMLFieldDescriptor[] inheritedElements = _extends.getElementDescriptors();
871 XMLFieldDescriptor[] allElements = localElements;
872 localElements = new XMLFieldDescriptor[allElements.length - inheritedElements.length];
873 int localIdx = 0;
874 for (int i = 0; i < allElements.length; i++) {
875 XMLFieldDescriptor desc = allElements[i];
876 boolean isInherited = false;
877 for (int idx = 0; idx < inheritedElements.length; idx++) {
878 if (inheritedElements[idx].equals(desc)) {
879 isInherited = true;
880 break;
881 }
882 }
883 if (!isInherited) {
884 localElements[localIdx] = desc;
885 ++localIdx;
886 }
887 }
888
889
890 XMLFieldDescriptor[] inheritedAttributes = _extends.getAttributeDescriptors();
891 XMLFieldDescriptor[] allAttributes = localAttributes;
892 localAttributes =
893 new XMLFieldDescriptor[allAttributes.length - inheritedAttributes.length];
894 localIdx = 0;
895 for (int i = 0; i < allAttributes.length; i++) {
896 XMLFieldDescriptor desc = allAttributes[i];
897 boolean isInherited = false;
898 for (int idx = 0; idx < inheritedAttributes.length; idx++) {
899 if (inheritedAttributes[idx].equals(desc)) {
900 isInherited = true;
901 break;
902 }
903 }
904 if (!isInherited) {
905 localAttributes[localIdx] = desc;
906 ++localIdx;
907 }
908 }
909
910 }
911
912 switch (_compositor) {
913
914 case CHOICE:
915
916 boolean found = false;
917 boolean hasLocalDescs = (localElements.length > 0);
918 XMLFieldDescriptor fieldDesc = null;
919
920 for (int i = 0; i < localElements.length; i++) {
921 XMLFieldDescriptor desc = localElements[i];
922
923 if (desc == null) {
924 continue;
925 }
926
927 FieldHandler handler = desc.getHandler();
928
929 if (handler.getValue(object) != null) {
930
931
932 if (desc.isMultivalued()) {
933 Object temp = handler.getValue(object);
934
935 if (Array.getLength(temp) == 0) {
936 temp = null;
937 continue;
938 }
939 temp = null;
940 }
941
942 if (found) {
943 String err = null;
944 if (desc.isContainer()) {
945 err = "The group '" + desc.getFieldName();
946 err += "' cannot exist at the same time that ";
947 if (fieldDesc.isContainer()) {
948 err += "the group '" + fieldDesc.getFieldName();
949 } else {
950 err += "the element '" + fieldDesc.getXMLName();
951 }
952 err += "' also exists.";
953 } else {
954 err = "The element '" + desc.getXMLName();
955 err += "' cannot exist at the same time that ";
956 err += "element '" + fieldDesc.getXMLName() + "' also exists.";
957 }
958 throw new ValidationException(err);
959 }
960 found = true;
961 fieldDesc = desc;
962
963 FieldValidator fieldValidator = desc.getValidator();
964 if (fieldValidator != null) {
965 fieldValidator.validate(object, context);
966 }
967 }
968 }
969
970
971
972 if ((!found) && (hasLocalDescs)) {
973 StringBuffer buffer = new StringBuffer(40);
974 boolean existsOptionalElement = false;
975 buffer.append('(');
976 String sep = " | ";
977 for (int i = 0; i < localElements.length; i++) {
978 XMLFieldDescriptor desc = localElements[i];
979 if (desc == null) {
980 continue;
981 }
982
983 FieldValidator fieldValidator = desc.getValidator();
984 if (fieldValidator.getMinOccurs() == 0) {
985 existsOptionalElement = true;
986 break;
987 }
988 buffer.append(sep);
989 buffer.append(desc.getXMLName());
990 }
991 buffer.append(')');
992 if (!existsOptionalElement) {
993 String err = "In the choice contained in <" + this.getXMLName()
994 + ">, at least one of these elements must appear:\n"
995 + buffer.toString();
996 throw new ValidationException(err);
997 }
998 }
999
1000 for (int i = 0; i < localAttributes.length; i++) {
1001 validateField(object, context, localAttributes[i]);
1002 }
1003
1004 if (_contentDescriptor != null) {
1005 validateField(object, context, _contentDescriptor);
1006 }
1007 break;
1008
1009 case SEQUENCE:
1010
1011 default:
1012
1013
1014
1015 for (int i = 0; i < localElements.length; i++) {
1016 final XMLFieldDescriptor fieldDescriptor = localElements[i];
1017 if (fieldDescriptor == null) {
1018 continue;
1019 }
1020 validateField(object, context, fieldDescriptor);
1021 }
1022
1023
1024 for (int i = 0; i < localAttributes.length; i++) {
1025 validateField(object, context, localAttributes[i]);
1026 }
1027
1028 if (_contentDescriptor != null) {
1029 validateField(object, context, _contentDescriptor);
1030 }
1031 break;
1032 }
1033
1034 }
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 private void validateField(final Object object, final ValidationContext context,
1046 final XMLFieldDescriptor fieldDescriptor) throws ValidationException {
1047 FieldValidator fieldValidator = fieldDescriptor.getValidator();
1048 if (fieldValidator != null) {
1049 try {
1050 fieldValidator.validate(object, context);
1051 } catch (ValidationException e) {
1052 if (fieldDescriptor.getNodeType() == NodeType.Attribute
1053 || fieldDescriptor.getNodeType() == NodeType.Element) {
1054 addLocationInformation(fieldDescriptor, e);
1055 }
1056 throw e;
1057 }
1058 }
1059 }
1060
1061
1062
1063
1064
1065
1066
1067 private void addLocationInformation(final XMLFieldDescriptor localElement,
1068 final ValidationException e) {
1069 XPathLocation loc = (XPathLocation) e.getLocation();
1070 if (loc == null) {
1071 loc = new XPathLocation();
1072 e.setLocation(loc);
1073 if (localElement.getNodeType() == NodeType.Attribute) {
1074 loc.addAttribute(localElement.getXMLName());
1075 } else {
1076 loc.addChild(localElement.getXMLName());
1077 }
1078 }
1079 }
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090 public Class<?> getJavaClass() {
1091 return _class;
1092 }
1093
1094
1095
1096
1097
1098
1099
1100 public FieldDescriptor[] getFields() {
1101 int size = _attributes.size();
1102 size += _elements.size();
1103 if (_contentDescriptor != null) ++size;
1104
1105
1106 XMLFieldDescriptor[] fields = new XMLFieldDescriptor[size];
1107
1108 _attributes.toArray(fields);
1109 _elements.toArray(fields, _attributes.size());
1110
1111 if (_contentDescriptor != null) {
1112 fields[size-1] = _contentDescriptor;
1113 }
1114 return fields;
1115 }
1116
1117
1118
1119
1120
1121
1122
1123
1124 public ClassDescriptor getExtends() {
1125 return _extends;
1126 }
1127
1128
1129
1130
1131
1132
1133
1134 public FieldDescriptor getIdentity() {
1135 return _identity;
1136 }
1137
1138
1139
1140
1141
1142
1143
1144 public AccessMode getAccessMode() {
1145 return _accessMode;
1146 }
1147
1148
1149
1150
1151
1152 public boolean canAccept(String name, String namespace, Object object) {
1153
1154 boolean result = false;
1155 boolean hasValue = false;
1156 XMLFieldDescriptor[] fields = null;
1157 int i = 0;
1158
1159 XMLFieldDescriptor fieldDesc = this.getFieldDescriptor(name, namespace, NodeType.Element);
1160 if (fieldDesc == null)
1161 fieldDesc = this.getFieldDescriptor(name, namespace, NodeType.Attribute);
1162
1163
1164 if (fieldDesc == null)
1165 return false;
1166
1167 Object tempObject;
1168
1169 if (fieldDesc.isMultivalued()) {
1170
1171 FieldValidator validator = fieldDesc.getValidator();
1172 if (validator != null) {
1173 if (validator.getMaxOccurs() < 0) {
1174 result = true;
1175 }
1176 else {
1177
1178 tempObject = fieldDesc.getHandler().getValue(object);
1179 int current = Array.getLength(tempObject);
1180 int newTotal = current + 1;
1181 result = (newTotal <= validator.getMaxOccurs());
1182 }
1183 }
1184 else {
1185
1186 result = true;
1187 }
1188 }
1189
1190 else if (fieldDesc.isContainer()) {
1191 tempObject = fieldDesc.getHandler().getValue(object);
1192
1193 if (tempObject == null)
1194 result = true;
1195 else
1196 result = ((XMLClassDescriptor)fieldDesc.getClassDescriptor()).canAccept(name, namespace, tempObject);
1197 }
1198
1199 else {
1200 FieldHandler handler = fieldDesc.getHandler();
1201
1202 boolean checkPrimitiveValue = true;
1203 if (handler instanceof AbstractFieldHandler) {
1204 hasValue = ((AbstractFieldHandler)handler).hasValue( object );
1205
1206
1207
1208
1209
1210
1211
1212 }
1213 else {
1214 hasValue = (handler.getValue(object) != null);
1215 }
1216
1217
1218
1219
1220
1221
1222
1223 if (hasValue &&
1224 checkPrimitiveValue &&
1225 fieldDesc.getFieldType().isPrimitive())
1226 {
1227 if (isDefaultPrimitiveValue(handler.getValue( object ))) {
1228 hasValue = false;
1229 }
1230 }
1231
1232 result = !hasValue;
1233 }
1234
1235
1236
1237 if (result && (_compositor == CHOICE)
1238 && (fieldDesc.getNodeType() == NodeType.Element) ) {
1239 fields = getElementArray();
1240 i = 0;
1241 while (result && i<fields.length) {
1242 XMLFieldDescriptor desc = fields[i];
1243 if (desc != fieldDesc && (object!=null) ) {
1244 Object tempObj = desc.getHandler().getValue(object);
1245 hasValue = (tempObj != null);
1246 if (hasValue) {
1247 result = false;
1248
1249 if (tempObj.getClass().isArray()) {
1250 result = Array.getLength(tempObj) == 0;
1251 }
1252
1253 if (tempObj instanceof Collection) {
1254 result = ((Collection) tempObj).isEmpty();
1255 }
1256 }
1257 }
1258 i++;
1259 }
1260 }
1261 return result;
1262 }
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278 static boolean isPrimitive(Class<?> type) {
1279
1280 if (type == null) return false;
1281
1282
1283 if (type.isPrimitive()) return true;
1284
1285
1286 if ((type == Boolean.class) || (type == Character.class))
1287 return true;
1288
1289 return (type.getSuperclass() == Number.class);
1290 }
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302 static boolean isDefaultPrimitiveValue(Object value) {
1303 if (value == null) return false;
1304
1305 Class<?> type = value.getClass();
1306 if (type.isPrimitive()) {
1307 try {
1308 return (value.equals(type.newInstance()));
1309 }
1310 catch(java.lang.IllegalAccessException iax) {
1311
1312
1313 }
1314 catch(java.lang.InstantiationException ix) {
1315
1316
1317 }
1318 }
1319 else if (type.getSuperclass() == Number.class) {
1320 return ((Number)value).intValue() == 0;
1321 }
1322 else if (type == Boolean.class) {
1323 return value.equals(Boolean.FALSE);
1324 }
1325 else if (type == Character.class) {
1326 return ((Character)value).charValue() == '\0';
1327 }
1328
1329 return false;
1330 }
1331
1332
1333
1334
1335
1336
1337
1338 public void setJavaClass(Class<?> type) {
1339 this._class = type;
1340 }
1341
1342 protected void setExtendsWithoutFlatten(XMLClassDescriptor classDesc) {
1343 this._extends = classDesc;
1344 }
1345
1346
1347
1348
1349
1350
1351
1352
1353 protected void setIntrospected(boolean introspected) {
1354 this._introspected = introspected;
1355 }
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376 private void addFieldDescriptor(XMLFieldDescriptor descriptor, boolean relink) {
1377
1378 if (descriptor == null) return;
1379
1380 boolean added = false;
1381
1382 NodeType nodeType = descriptor.getNodeType();
1383 switch(nodeType.getType()) {
1384 case NodeType.NAMESPACE:
1385 case NodeType.ATTRIBUTE:
1386 added = _attributes.add(descriptor);
1387 if (added) {
1388 _attArray = null;
1389 }
1390 break;
1391 case NodeType.TEXT:
1392 _contentDescriptor = descriptor;
1393 added = true;
1394 break;
1395 default:
1396 added = _elements.add(descriptor);
1397 if (added) {
1398 _elemArray = null;
1399 if (descriptor.isContainer()) ++_containerCount;
1400 }
1401 break;
1402 }
1403
1404 if ((added) && (relink)) {
1405 descriptor.setContainingClassDescriptor( this );
1406 }
1407
1408 }
1409
1410
1411 private XMLFieldDescriptor[] getAttributeArray() {
1412
1413
1414
1415 XMLFieldDescriptor[] descriptors = _attArray;
1416 if (descriptors == null) {
1417 descriptors = _attributes.toArray();
1418 _attArray = descriptors;
1419 }
1420 return descriptors;
1421 }
1422
1423 private XMLFieldDescriptor[] getElementArray() {
1424
1425
1426
1427 XMLFieldDescriptor[] descriptors = _elemArray;
1428 if (descriptors == null) {
1429 descriptors = _elements.toArray();
1430 _elemArray = descriptors;
1431 }
1432 return descriptors;
1433 }
1434
1435
1436
1437
1438
1439
1440 protected void addSequenceElement(XMLFieldDescriptor element) {
1441 _sequenceOfElements.add(element);
1442 }
1443
1444 public List<String> getSubstitutes() {
1445 return _substitutes;
1446 }
1447
1448 public void setSubstitutes(List<String> substitutes) {
1449 _substitutes = substitutes;
1450 }
1451
1452 public boolean isChoice() {
1453 return this._compositor == CHOICE;
1454 }
1455
1456
1457
1458
1459
1460
1461
1462
1463 public Object getProperty(final String name) {
1464 return _properties.get(name);
1465 }
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475 public void setProperty(final String name, final Object value) {
1476 _properties.put(name, value);
1477 }
1478
1479
1480
1481
1482
1483
1484
1485 public void addNature(final String nature) {
1486 _natures.add(nature);
1487 }
1488
1489
1490
1491
1492
1493
1494
1495
1496 public boolean hasNature(final String nature) {
1497 return _natures.contains(nature);
1498 }
1499
1500 }