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