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.builder.factory;
51
52 import java.util.ArrayList;
53 import java.util.Enumeration;
54 import java.util.Iterator;
55 import java.util.LinkedList;
56 import java.util.List;
57
58 import org.apache.commons.lang.StringUtils;
59 import org.castor.core.util.StringUtil;
60 import org.exolab.castor.builder.AnnotationBuilder;
61 import org.exolab.castor.builder.BuilderConfiguration;
62 import org.exolab.castor.builder.FactoryState;
63 import org.exolab.castor.builder.GroupNaming;
64 import org.exolab.castor.builder.SGStateInfo;
65 import org.exolab.castor.builder.SGTypes;
66 import org.exolab.castor.builder.SourceGenerator;
67 import org.exolab.castor.builder.SourceGeneratorConstants;
68 import org.exolab.castor.builder.TypeConversion;
69 import org.exolab.castor.builder.binding.ExtendedBinding;
70 import org.exolab.castor.builder.binding.XMLBindingComponent;
71 import org.exolab.castor.builder.info.ClassInfo;
72 import org.exolab.castor.builder.info.FieldInfo;
73 import org.exolab.castor.builder.info.GroupInfo;
74 import org.exolab.castor.builder.info.XMLInfo;
75 import org.exolab.castor.builder.info.nature.JDOClassInfoNature;
76 import org.exolab.castor.builder.info.nature.JDOFieldInfoNature;
77 import org.exolab.castor.builder.info.nature.SolrjFieldInfoNature;
78 import org.exolab.castor.builder.info.nature.XMLInfoNature;
79 import org.exolab.castor.builder.info.nature.relation.JDOOneToManyNature;
80 import org.exolab.castor.builder.info.nature.relation.JDOOneToOneNature;
81 import org.exolab.castor.builder.types.XSClass;
82 import org.exolab.castor.builder.types.XSString;
83 import org.exolab.castor.builder.types.XSType;
84 import org.exolab.castor.mapping.AccessMode;
85 import org.exolab.castor.xml.schema.Annotated;
86 import org.exolab.castor.xml.schema.Annotation;
87 import org.exolab.castor.xml.schema.AppInfo;
88 import org.exolab.castor.xml.schema.AppInfoJpaNature;
89 import org.exolab.castor.xml.schema.AppInfoSolrjNature;
90 import org.exolab.castor.xml.schema.AttributeDecl;
91 import org.exolab.castor.xml.schema.AttributeGroupDecl;
92 import org.exolab.castor.xml.schema.ComplexType;
93 import org.exolab.castor.xml.schema.ContentModelGroup;
94 import org.exolab.castor.xml.schema.ContentType;
95 import org.exolab.castor.xml.schema.Documentation;
96 import org.exolab.castor.xml.schema.ElementDecl;
97 import org.exolab.castor.xml.schema.Facet;
98 import org.exolab.castor.xml.schema.Group;
99 import org.exolab.castor.xml.schema.ModelGroup;
100 import org.exolab.castor.xml.schema.Order;
101 import org.exolab.castor.xml.schema.Particle;
102 import org.exolab.castor.xml.schema.Schema;
103 import org.exolab.castor.xml.schema.SimpleContent;
104 import org.exolab.castor.xml.schema.SimpleType;
105 import org.exolab.castor.xml.schema.SimpleTypesFactory;
106 import org.exolab.castor.xml.schema.Structure;
107 import org.exolab.castor.xml.schema.Wildcard;
108 import org.exolab.castor.xml.schema.XMLType;
109 import org.exolab.castor.xml.schema.annotations.jdo.Column;
110 import org.exolab.castor.xml.schema.annotations.jdo.OneToMany;
111 import org.exolab.castor.xml.schema.annotations.jdo.OneToOne;
112 import org.exolab.castor.xml.schema.annotations.jdo.PrimaryKey;
113 import org.exolab.castor.xml.schema.annotations.jdo.Table;
114 import org.exolab.castor.xml.schema.annotations.solrj.Field;
115
116 import org.exolab.javasource.JAnnotation;
117 import org.exolab.javasource.JAnnotationType;
118 import org.exolab.javasource.JClass;
119 import org.exolab.javasource.JCollectionType;
120 import org.exolab.javasource.JConstructor;
121 import org.exolab.javasource.JDocComment;
122 import org.exolab.javasource.JDocDescriptor;
123 import org.exolab.javasource.JEnum;
124 import org.exolab.javasource.JField;
125 import org.exolab.javasource.JMethod;
126 import org.exolab.javasource.JParameter;
127 import org.exolab.javasource.JSourceCode;
128 import org.exolab.javasource.JType;
129
130
131
132
133
134
135
136
137 public final class SourceFactory extends BaseFactory {
138 private static final String ENUM_ACCESS_INTERFACE =
139 "org.exolab.castor.types.EnumeratedTypeAccess";
140
141 private static final short BASE_TYPE_ENUMERATION = 0;
142 private static final short OBJECT_TYPE_ENUMERATION = 1;
143
144 private static final String CLASS_METHOD_SUFFIX = "Class";
145 private static final String CLASS_KEYWORD = "class";
146 private static final String ITEM_NAME = "Item";
147
148
149 private ExtendedBinding _binding = null;
150
151 private MemberFactory _memberFactory = null;
152
153 private short _enumerationType = OBJECT_TYPE_ENUMERATION;
154
155
156
157
158
159 private boolean _createMarshalMethods = true;
160
161
162
163
164
165 private boolean _testable = false;
166
167 private boolean _sax1 = false;
168
169 private TypeConversion _typeConversion = null;
170
171 private final EnumerationFactory _enumerationFactory;
172
173
174
175
176
177
178
179
180
181 public SourceFactory(final BuilderConfiguration config,
182 final FieldInfoFactory infoFactory,
183 final GroupNaming groupNaming,
184 final SourceGenerator sourceGenerator) {
185 super(config, infoFactory, groupNaming, sourceGenerator);
186
187
188 infoFactory.setBoundProperties(config.boundPropertiesEnabled());
189
190 this._memberFactory = new MemberFactory(config, infoFactory, getGroupNaming(), sourceGenerator);
191 this._typeConversion = new TypeConversion(getConfig());
192 this._enumerationFactory =
193 new EnumerationFactory(getConfig(), getGroupNaming(), sourceGenerator);
194 }
195
196
197
198
199
200
201
202
203
204
205
206 public void setCreateMarshalMethods(final boolean createMarshalMethods) {
207 _createMarshalMethods = createMarshalMethods;
208 }
209
210
211
212
213
214
215
216
217
218
219 public void setCreateExtraMethods(final boolean extraMethods) {
220 getInfoFactory().setCreateExtraMethods(extraMethods);
221 }
222
223
224
225
226
227
228
229
230
231
232
233 public void setReferenceMethodSuffix(final String suffix) {
234 getInfoFactory().setReferenceMethodSuffix(suffix);
235 }
236
237
238
239
240
241
242
243 public void setTestable(final boolean testable) {
244 _testable = testable;
245 }
246
247
248
249
250
251
252
253 public void setSAX1(final boolean sax1) {
254 _sax1 = sax1;
255 }
256
257
258
259
260
261
262
263
264 public void setCaseInsensitive(final boolean caseInsensitive) {
265 _enumerationFactory.setCaseInsensitive(caseInsensitive);
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280 public JClass[] createSourceCode(final XMLBindingComponent component,
281 final SGStateInfo sgState) {
282 if (component == null) {
283 throw new IllegalStateException("XMLBindingComponent may not be null.");
284 }
285 if (sgState == null) {
286 throw new IllegalStateException("SGStateInfo may not be null.");
287 }
288
289
290 JClass[] classes = sgState.getSourceCode(component.getAnnotated());
291 if (classes != null) {
292 return classes;
293 }
294
295 _binding = component.getBinding();
296
297 if (sgState.verbose()) {
298 String name = component.getXMLName();
299 if (name == null) {
300 name = component.getJavaClassName();
301 }
302 String msg = "Creating classes for: " + name;
303 sgState.getDialog().notify(msg);
304 }
305
306
307 String packageName = component.getJavaPackage();
308 if (packageName == null || packageName.length() == 0) {
309 packageName = sgState.getPackageName();
310 }
311
312
313
314
315 String className = component.getQualifiedName();
316 if (className.indexOf('.') == -1) {
317
318 className = getJavaNaming().toJavaClassName(className);
319 className = resolveClassName(className, packageName);
320 }
321
322
323 boolean createGroupItem = component.createGroupItem();
324 if (createGroupItem) {
325 className += ITEM_NAME;
326 classes = new JClass[2];
327 } else {
328 classes = new JClass[1];
329 }
330
331
332 FactoryState state =
333 new FactoryState(className, sgState, packageName, component);
334 state.setCreateGroupItem(createGroupItem);
335 if (sgState.getCurrentFactoryState() != null) {
336 state.setParent(sgState.getCurrentFactoryState());
337 }
338 sgState.setCurrentFactoryState(state);
339
340
341 if (state.processed(component.getAnnotated())) {
342 return new JClass[0];
343 }
344
345
346
347 state.markAsProcessed(component.getAnnotated());
348
349
350
351
352
353
354
355 ClassInfo classInfo = state.getClassInfo();
356 JClass jClass = state.getJClass();
357 initialize(jClass);
358
359 if (classInfo.hasNature(XMLInfoNature.class.getName())) {
360 final XMLInfoNature xmlNature = new XMLInfoNature(classInfo);
361
362
363 xmlNature.setNodeName(component.getXMLName());
364
365
366 xmlNature.setNamespaceURI(component.getTargetNamespace());
367
368
369 XMLType type = component.getXMLType();
370 boolean createForSingleGroup = false;
371 boolean creatingForAnElement =
372 (component.getAnnotated().getStructureType() == Structure.ELEMENT);
373
374
375 xmlNature.setElementDefinition(creatingForAnElement);
376
377
378 if (creatingForAnElement) {
379 ElementDecl elementDeclaration = (ElementDecl) component.getAnnotated();
380 Enumeration<ElementDecl> possibleSubstitutes = elementDeclaration.getSubstitutionGroupMembers();
381 if (possibleSubstitutes.hasMoreElements()) {
382 List<String> substitutionGroupMembers = new ArrayList<String>();
383 while (possibleSubstitutes.hasMoreElements()) {
384 ElementDecl substitute = possibleSubstitutes.nextElement();
385 substitutionGroupMembers.add(substitute.getName());
386 }
387 xmlNature.setSubstitutionGroups(substitutionGroupMembers);
388 }
389 }
390
391 if (type != null) {
392 if (type.isComplexType()) {
393 processComplexType(component, sgState, state);
394 } else if (type.isSimpleType()) {
395 SimpleType simpleType = (SimpleType) type;
396
397 if (simpleType.hasFacet(Facet.ENUMERATION)) {
398 processSimpleTypeEnumeration(component, sgState, classInfo, simpleType);
399 } else {
400
401
402
403
404 return new JClass[0];
405 }
406 } else if (type.isAnyType()) {
407
408 xmlNature.setSchemaType(new XSClass(SGTypes.OBJECT));
409 return new JClass[0];
410 }
411 } else {
412
413
414 createForSingleGroup = processSchemaGroup(component, state, classInfo);
415 }
416
417
418 if (createGroupItem) {
419
420 if (component.hasBoundProperties()) {
421 createPropertyChangeMethods(jClass);
422 }
423
424 sgState.bindReference(jClass, classInfo);
425
426 classes[1] = jClass;
427
428
429 String fname = component.getJavaClassName() + ITEM_NAME;
430 fname = getJavaNaming().toJavaMemberName(fname, false);
431
432 FieldInfo fInfo = null;
433 if (createForSingleGroup) {
434
435 fInfo = getInfoFactory().createFieldInfo(new XSClass(jClass), fname);
436 } else {
437 fInfo = getInfoFactory().createCollection(
438 new XSClass(jClass), "_items", fname, getJavaNaming(), getConfig().useJava50());
439 }
440 fInfo.setContainer(true);
441 String newClassName = className.substring(0, className.length() - 4);
442 state = new FactoryState(newClassName, sgState, packageName, component);
443 classInfo = state.getClassInfo();
444 jClass = state.getJClass();
445 initialize(jClass);
446 if (type != null && type.isComplexType()) {
447 ComplexType complexType = (ComplexType) type;
448 if (complexType.isTopLevel() ^ creatingForAnElement) {
449
450 Annotated saved = component.getAnnotated();
451 processAttributes(component.getBinding(), complexType, state);
452 component.setView(saved);
453 if (complexType.getContentType() == ContentType.mixed) {
454 FieldInfo fieldInfo = _memberFactory.createFieldInfoForContent(
455 component, new XSString(), getConfig().useJava50());
456 handleField(fieldInfo, state, component);
457 } else if (complexType.getContentType().getType() == ContentType.SIMPLE) {
458 SimpleContent simpleContent = (SimpleContent) complexType.getContentType();
459 SimpleType temp = simpleContent.getSimpleType();
460 XSType xsType = _typeConversion.convertType(
461 temp, packageName, getConfig().useJava50());
462 FieldInfo fieldInfo = _memberFactory.createFieldInfoForContent(
463 component, xsType, getConfig().useJava50());
464 handleField(fieldInfo, state, component);
465 temp = null;
466 } else {
467
468 xmlNature.setSchemaType(new XSClass(jClass));
469 }
470 }
471 }
472
473 classInfo.addFieldInfo(fInfo);
474 fInfo.getMemberAndAccessorFactory().createJavaField(fInfo, jClass);
475 fInfo.getMemberAndAccessorFactory().createAccessMethods(
476 fInfo, jClass, getConfig().useJava50(), getConfig().getAnnotationBuilders());
477 fInfo.getMemberAndAccessorFactory().generateInitializerCode(
478 fInfo, jClass.getConstructor(0).getSourceCode());
479
480
481 XMLInfoNature xmlInfoNature = new XMLInfoNature(classInfo);
482 xmlInfoNature.setNodeName(component.getXMLName());
483
484
485 xmlInfoNature.setContainer(true);
486
487
488
489 String actSuperClass = classes[1].getSuperClassQualifiedName();
490 jClass.setSuperClass(actSuperClass);
491 classes[1].setSuperClass(null);
492 }
493
494 }
495
496 classes[0] = jClass;
497
498
499
500 String baseClass = component.getExtends();
501 if (baseClass != null && baseClass.length() > 0) {
502
503
504
505
506 if (jClass.getSuperClassQualifiedName() == null) {
507 jClass.setSuperClass(baseClass);
508 }
509 }
510
511
512 String[] implemented = component.getImplements();
513 if (implemented != null) {
514 for (int i = 0; i < implemented.length; i++) {
515 String interfaceName = implemented[i];
516 if ((interfaceName != null) && (interfaceName.length() > 0)) {
517 jClass.addInterface(interfaceName);
518 }
519 }
520 }
521
522
523 jClass.getModifiers().setFinal(component.isFinal());
524
525
526 if (component.isAbstract()) {
527 jClass.getModifiers().setAbstract(true);
528 classInfo.setAbstract(true);
529 }
530
531 processAppInfo(component.getAnnotated(), classInfo);
532 extractAnnotations(component.getAnnotated(), jClass);
533
534 createContructorForDefaultValueForSimpleContent(component.getAnnotated(), classInfo, sgState);
535 makeMethods(component, sgState, state, jClass, baseClass);
536
537 if (classInfo.hasNature(JDOClassInfoNature.class.getName())) {
538 JDOClassInfoNature jdoNature = new JDOClassInfoNature(classInfo);
539 if (jdoNature.getDetachable()) {
540 createJdoTimestampImplementations(jClass);
541 }
542 }
543
544 sgState.bindReference(jClass, classInfo);
545 sgState.bindReference(component.getAnnotated(), classInfo);
546
547
548 sgState.bindSourceCode(component.getAnnotated(), classes);
549
550
551 AnnotationBuilder[] annotationBuilders = getConfig().getAnnotationBuilders();
552 for (int i = 0; i < annotationBuilders.length; i++) {
553 AnnotationBuilder annotationBuilder = annotationBuilders[i];
554 annotationBuilder.addClassAnnotations(classInfo, jClass);
555 }
556
557 return classes;
558 }
559
560
561
562
563
564
565
566
567
568
569
570 private void createContructorForDefaultValueForSimpleContent(final Annotated annotated,
571 final ClassInfo classInfo,
572 final SGStateInfo sgStateInfo) {
573 FieldInfo textFieldInfo = classInfo.getTextField();
574
575 boolean generate = false;
576 boolean inherited = false;
577
578
579 if (annotated instanceof ElementDecl) {
580 XMLType type = ((ElementDecl) annotated).getType();
581 ClassInfo typeInfo = sgStateInfo.resolve(type);
582 if (typeInfo != null && typeInfo.getTextField() != null) {
583 textFieldInfo = typeInfo.getTextField();
584 inherited = true;
585 }
586 generate = (type.isComplexType() && ((ComplexType) type).isSimpleContent());
587 }
588
589
590 else if (annotated instanceof ComplexType && ((ComplexType) annotated).isSimpleContent()) {
591 generate = true;
592 }
593
594
595
596 if (textFieldInfo != null) {
597 XSType textFieldType = new XMLInfoNature(textFieldInfo).getSchemaType();
598 if (textFieldType != null && textFieldType.getJType().isArray()) {
599 generate = false;
600 }
601 }
602
603 if (!generate) {
604 return;
605 }
606
607 XMLInfoNature xmlNature = new XMLInfoNature(textFieldInfo);
608
609
610 JClass jClass = classInfo.getJClass();
611 JParameter parameter = new JParameter(new JClass("java.lang.String"), "defaultValue");
612 JConstructor constructor = jClass.createConstructor(new JParameter[] {parameter});
613 JSourceCode sourceCode = new JSourceCode();
614
615 if (inherited) {
616 sourceCode.add("super(defaultValue);");
617 } else {
618 sourceCode.add("try {");
619 String defaultValue =
620 xmlNature.getSchemaType().createDefaultValueWithString("defaultValue");
621 sourceCode.addIndented("setContent(" + defaultValue + ");");
622 sourceCode.add(" } catch(Exception e) {");
623 sourceCode.addIndented("throw new RuntimeException(\"Unable to cast default value for simple content!\");");
624 sourceCode.add(" } ");
625 }
626
627 constructor.setSourceCode(sourceCode);
628 jClass.addConstructor(constructor);
629 }
630
631
632
633
634
635
636 private void extractAnnotations(final Annotated annotated, final JClass jClass) {
637
638 String comment = extractCommentsFromAnnotations(annotated);
639 if (comment != null) {
640 jClass.getJDocComment().setComment(comment);
641
642 if (getConfig().generateExtraDocumentationMethods()) {
643 generateExtraDocumentationMethods(annotated, jClass);
644 }
645 }
646 }
647
648
649
650
651
652
653
654
655
656
657
658 private void generateExtraDocumentationMethods(final Annotated annotated,
659 final JClass jClass) {
660 JField documentationsField =
661 new JField(new JClass("java.util.Map"), "_xmlSchemaDocumentations");
662 documentationsField.setComment("The content of the <xsd:documentation> elements");
663 documentationsField.setInitString("new java.util.HashMap()");
664 jClass.addMember(documentationsField);
665
666 Enumeration<Annotation> annotations = annotated.getAnnotations();
667 while (annotations.hasMoreElements()) {
668 Annotation annotation = annotations.nextElement();
669 Enumeration<Documentation> documentations = annotation.getDocumentation();
670 while (documentations.hasMoreElements()) {
671 Documentation documentation = documentations.nextElement();
672 JConstructor defaultConstructor = jClass.getConstructor(0);
673 String documentationContent = normalize(documentation.getContent());
674 documentationContent =
675 StringUtil.replaceAll(documentationContent, "\n", "\"\n+ \" ");
676 defaultConstructor.getSourceCode().add("_xmlSchemaDocumentations.put(\""
677 + documentation.getSource() + "\", \""
678 + documentationContent + "\");");
679 }
680 }
681
682 JMethod aMethod = new JMethod("getXmlSchemaDocumentations",
683 new JClass("java.util.Map"),
684 " A collection of documentation elements.");
685 JSourceCode sourceCode = aMethod.getSourceCode();
686 sourceCode.add("return _xmlSchemaDocumentations;");
687 jClass.addMethod(aMethod);
688
689 JMethod anotherMethod = new JMethod("getXmlSchemaDocumentation",
690 new JClass("java.lang.String"),
691 " A specific XML schema documentation element.");
692 JParameter parameter = new JParameter(new JClass("java.lang.String"), "source");
693 anotherMethod.addParameter(parameter);
694 sourceCode = anotherMethod.getSourceCode();
695 sourceCode.add("return (java.lang.String) _xmlSchemaDocumentations.get(source);");
696 jClass.addMethod(anotherMethod);
697 }
698
699
700
701
702
703
704
705
706
707
708 private void makeMethods(
709 final XMLBindingComponent component,
710 final SGStateInfo sgState,
711 final FactoryState state,
712 final JClass jClass,
713 final String baseClass) {
714
715
716 if (_createMarshalMethods) {
717
718 createValidateMethods(jClass);
719
720
721 if (!component.isAbstract()) {
722
723 createMarshalMethods(jClass);
724
725 createUnmarshalMethods(jClass, sgState);
726 }
727 }
728
729
730 if (component.hasEquals()) {
731 createEqualsMethod(jClass);
732 createHashCodeMethod(jClass);
733 }
734
735
736 if (_testable) {
737 createTestableMethods(jClass, state);
738 }
739
740
741
742 String superclassQualifiedName = jClass.getSuperClassQualifiedName();
743 if (superclassQualifiedName == null || superclassQualifiedName.equals(baseClass)) {
744
745 if (component.hasBoundProperties()) {
746 createPropertyChangeMethods(jClass);
747 }
748 }
749 }
750
751 private boolean processSchemaGroup(final XMLBindingComponent component,
752 final FactoryState state, final ClassInfo classInfo) {
753 try {
754 Group group = (Group) component.getAnnotated();
755 processContentModel(group, state);
756 component.setView(group);
757
758
759 Order order = group.getOrder();
760 GroupInfo groupInfo = new XMLInfoNature(classInfo).getGroupInfo();
761 if (order == Order.choice) {
762 groupInfo.setAsChoice();
763 } else if (order == Order.sequence) {
764 groupInfo.setAsSequence();
765 } else {
766 groupInfo.setAsAll();
767 }
768
769 return group.getMaxOccurs() == 1;
770 } catch (ClassCastException ce) {
771
772 throw new IllegalArgumentException("Illegal binding component: " + ce.getMessage());
773 }
774 }
775
776 private void processSimpleTypeEnumeration(final XMLBindingComponent component,
777 final SGStateInfo sgState, final ClassInfo classInfo,
778 final SimpleType simpleType) {
779
780
781 String tns = simpleType.getSchema().getTargetNamespace();
782 boolean create = false;
783 if (tns == null) {
784 create = (component.getTargetNamespace() == null);
785 } else {
786 create = tns.equals(component.getTargetNamespace());
787 }
788
789 if (create) {
790 ClassInfo tmpInfo = sgState.resolve(simpleType);
791 JClass tmpClass = null;
792 if (tmpInfo != null) {
793 tmpClass = tmpInfo.getJClass();
794 } else {
795 tmpClass = createSourceCode(component.getBinding(), simpleType, sgState);
796 }
797 XMLInfoNature xmlNature = new XMLInfoNature(classInfo);
798 xmlNature.setSchemaType(new XSClass(tmpClass));
799 }
800 }
801
802 private void processComplexType(final XMLBindingComponent component, final SGStateInfo sgState,
803 final FactoryState state) {
804 XMLType type = component.getXMLType();
805 ClassInfo classInfo = state.getClassInfo();
806 JClass jClass = state.getJClass();
807 boolean creatingForAnElement =
808 (component.getAnnotated().getStructureType() == Structure.ELEMENT);
809
810 ComplexType complexType = (ComplexType) type;
811 if (complexType.isTopLevel() && creatingForAnElement) {
812
813 Annotated saved = component.getAnnotated();
814 String previousPackage = component.getJavaPackage();
815 XMLBindingComponent baseComponent = new XMLBindingComponent(
816 getConfig(), getGroupNaming());
817 baseComponent.setBinding(component.getBinding());
818 baseComponent.setView(complexType);
819
820 createSourceCode(baseComponent, sgState);
821 String baseClassName = null;
822 String basePackage = baseComponent.getJavaPackage();
823
824
825
826 if (basePackage != null && !basePackage.equals(previousPackage)) {
827 baseClassName = baseComponent.getQualifiedName();
828 if (baseClassName.indexOf('.') == -1) {
829
830 baseClassName = getJavaNaming().toJavaClassName(baseClassName);
831 }
832 } else {
833 baseClassName = baseComponent.getJavaClassName();
834 }
835 jClass.setSuperClass(baseClassName);
836 basePackage = null;
837 baseClassName = null;
838 component.setView(saved);
839 saved = null;
840 } else if (complexType.isTopLevel() || creatingForAnElement) {
841
842
843
844
845
846 if (complexType.getParticleCount() == 1) {
847 Particle particle = complexType.getParticle(0);
848 if (particle.getStructureType() == Structure.GROUP) {
849 Group group = (Group) particle;
850 if (group.getOrder() == Order.choice) {
851 new XMLInfoNature(classInfo).getGroupInfo().setAsChoice();
852 }
853 }
854 }
855 Annotated saved = component.getAnnotated();
856 processComplexType(complexType, state);
857 component.setView(saved);
858 saved = null;
859 }
860 }
861
862
863
864
865
866
867
868
869
870 public JClass createSourceCode(final ExtendedBinding binding,
871 final SimpleType simpleType, final SGStateInfo sgState) {
872 if (SimpleTypesFactory.isBuiltInType(simpleType.getTypeCode())) {
873 String err = "You cannot construct a ClassInfo for a built-in SimpleType.";
874 throw new IllegalArgumentException(err);
875 }
876 if (sgState == null) {
877 throw new IllegalArgumentException("SGStateInfo cannot be null.");
878 }
879
880
881
882
883
884
885 if (simpleType.getStructureType() == Structure.UNION) {
886 if (!sgState.getSuppressNonFatalWarnings()) {
887 String message = "warning: support for unions is incomplete.";
888 sgState.getDialog().notify(message);
889 }
890 return null;
891 }
892
893 ClassInfo cInfo = sgState.resolve(simpleType);
894 if (cInfo != null) {
895 return cInfo.getJClass();
896 }
897
898 boolean enumeration = false;
899
900
901 String typeName = simpleType.getName();
902 if (typeName == null) {
903 Structure struct = simpleType.getParent();
904 FactoryState fstate = null;
905 switch (struct.getStructureType()) {
906 case Structure.ATTRIBUTE:
907 typeName = ((AttributeDecl) struct).getName();
908 fstate = sgState.getCurrentFactoryState();
909 break;
910 case Structure.ELEMENT:
911 typeName = ((ElementDecl) struct).getName();
912 break;
913 default:
914
915 break;
916 }
917
918 if (fstate != null) {
919 typeName = getJavaNaming().toJavaClassName(typeName);
920 Structure attrDeclParent = ((AttributeDecl) struct).getParent();
921 if (attrDeclParent != null
922 && attrDeclParent.getStructureType() == Structure.ATTRIBUTE_GROUP) {
923 typeName = getJavaNaming().toJavaClassName(
924 ((AttributeGroupDecl) attrDeclParent).getName() + typeName);
925 } else {
926 typeName = fstate.getJClass().getLocalName() + typeName;
927 }
928 }
929
930 typeName += "Type";
931 }
932
933 String className = getJavaNaming().toJavaClassName(typeName);
934
935
936
937 XMLBindingComponent comp =
938 new XMLBindingComponent(getConfig(), getGroupNaming());
939 if (binding != null) {
940 comp.setBinding(binding);
941 }
942
943
944 if (simpleType.getName() == null) {
945 Annotated annotated = (Annotated) simpleType.getParent();
946 comp.setView(annotated);
947 } else {
948 comp.setView(simpleType);
949 }
950
951 String packageName = comp.getJavaPackage();
952 if ((packageName == null) || (packageName.length() == 0)) {
953 packageName = sgState.getPackageName();
954 }
955
956
957 if (simpleType.getName() == null) {
958 comp.setView(simpleType);
959 }
960
961 if (simpleType.hasFacet(Facet.ENUMERATION)) {
962 enumeration = true;
963
964
965 if ((packageName != null) && (packageName.length() > 0)) {
966 packageName = packageName + "." + SourceGeneratorConstants.TYPES_PACKAGE;
967 } else {
968 packageName = SourceGeneratorConstants.TYPES_PACKAGE;
969 }
970 }
971
972 String boundClassName = comp.getJavaClassName();
973 if ((boundClassName != null) && (boundClassName.length() > 0)) {
974 className = boundClassName;
975 typeName = boundClassName;
976 }
977
978 className = resolveClassName(className, packageName);
979
980 FactoryState state = new FactoryState(className, sgState, packageName, comp,
981 (enumeration && getConfig().useJava5Enums()));
982
983 state.setParent(sgState.getCurrentFactoryState());
984
985 ClassInfo classInfo = state.getClassInfo();
986 JClass jClass = state.getJClass();
987
988 initialize(jClass);
989
990
991 Schema schema = simpleType.getSchema();
992 XMLInfoNature xmlNature = new XMLInfoNature(classInfo);
993 xmlNature.setNamespaceURI(schema.getTargetNamespace());
994 xmlNature.setNodeName(typeName);
995
996 extractAnnotations(simpleType, jClass);
997
998 XSClass xsClass = new XSClass(jClass, typeName);
999
1000 xmlNature.setSchemaType(xsClass);
1001
1002
1003 if (enumeration) {
1004 xsClass.setAsEnumerated(true);
1005 processEnumeration(binding, simpleType, state);
1006 }
1007
1008
1009 if (state.hasBoundProperties() && !enumeration) {
1010 createPropertyChangeMethods(jClass);
1011 }
1012
1013 if (classInfo.hasNature(JDOClassInfoNature.class.getName())) {
1014 JDOClassInfoNature jdoNature = new JDOClassInfoNature(classInfo);
1015 if (jdoNature.getDetachable()) {
1016 createJdoTimestampImplementations(jClass);
1017 }
1018 }
1019
1020 sgState.bindReference(jClass, classInfo);
1021 sgState.bindReference(simpleType, classInfo);
1022
1023 return jClass;
1024 }
1025
1026 private void createJdoTimestampImplementations(final JClass jClass) {
1027
1028 jClass.addInterface("org.exolab.castor.jdo.TimeStampable");
1029
1030 JField jdoTimestamp = new JField(JType.LONG, "_jdoTimeStamp");
1031 jClass.addField(jdoTimestamp);
1032
1033 JMethod getTSMethod = new JMethod("jdoGetTimeStamp", JType.LONG,
1034 "returns the current time stamp");
1035 JSourceCode getSourceCode = getTSMethod.getSourceCode();
1036 getSourceCode.addIndented("return _jdoTimeStamp;");
1037 jClass.addMethod(getTSMethod);
1038
1039 JMethod setTSMethod = new JMethod("jdoSetTimeStamp");
1040 JParameter parameter = new JParameter(JType.LONG, "jdoTimeStamp");
1041 setTSMethod.addParameter(parameter);
1042 JSourceCode setSourceCode = setTSMethod.getSourceCode();
1043 setSourceCode.addIndented("this._jdoTimeStamp = jdoTimeStamp;");
1044 jClass.addMethod(setTSMethod);
1045 }
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 private void initialize(final JClass jClass) {
1057 jClass.addInterface("java.io.Serializable");
1058
1059 if (getConfig().useJava50()) {
1060 JAnnotation serial = new JAnnotation(new JAnnotationType("SuppressWarnings"));
1061 serial.setValue(new String[] {"\"serial\""});
1062 jClass.addAnnotation(serial);
1063 }
1064
1065
1066 JConstructor con = jClass.createConstructor();
1067 jClass.addConstructor(con);
1068 con.getSourceCode().add("super();");
1069 }
1070
1071
1072
1073
1074
1075 private void createPropertyChangeMethods(final JClass parent) {
1076
1077 String vName = "propertyChangeSupport";
1078 JField field = new JField(SGTypes.PROPERTY_CHANGE_SUPPORT, vName);
1079 field.getModifiers().makePrivate();
1080 parent.addField(field);
1081
1082
1083
1084
1085
1086 JMethod jMethod = new JMethod("notifyPropertyChangeListeners");
1087 jMethod.getModifiers().makeProtected();
1088
1089 JDocComment jdc = jMethod.getJDocComment();
1090 JDocDescriptor jdDesc = null;
1091 String desc = null;
1092
1093 desc = "Notifies all registered PropertyChangeListeners "
1094 + "when a bound property's value changes.";
1095 jdc.appendComment(desc);
1096
1097 jMethod.addParameter(new JParameter(SGTypes.STRING, "fieldName"));
1098 jdDesc = jdc.getParamDescriptor("fieldName");
1099 jdDesc.setDescription("the name of the property that has changed.");
1100
1101 jMethod.addParameter(new JParameter(SGTypes.OBJECT, "oldValue"));
1102 jdDesc = jdc.getParamDescriptor("oldValue");
1103 jdDesc.setDescription("the old value of the property.");
1104
1105 jMethod.addParameter(new JParameter(SGTypes.OBJECT, "newValue"));
1106 jdDesc = jdc.getParamDescriptor("newValue");
1107 jdDesc.setDescription("the new value of the property.");
1108
1109 parent.addMethod(jMethod);
1110 JSourceCode jsc = jMethod.getSourceCode();
1111
1112 jsc.add("if (");
1113 jsc.append(vName);
1114 jsc.append(" == null) return;");
1115
1116 jsc.add(vName);
1117 jsc.append(".firePropertyChange(fieldName,oldValue,newValue);");
1118
1119
1120
1121
1122
1123 JType jType = new JClass("java.beans.PropertyChangeListener");
1124 jMethod = new JMethod("addPropertyChangeListener");
1125
1126 desc = "Registers a PropertyChangeListener with this class.";
1127 jdc = jMethod.getJDocComment();
1128 jdc.appendComment(desc);
1129
1130 jMethod.addParameter(new JParameter(jType, "pcl"));
1131 desc = "The PropertyChangeListener to register.";
1132 jdDesc = jdc.getParamDescriptor("pcl");
1133 jdDesc.setDescription(desc);
1134
1135 parent.addMethod(jMethod);
1136
1137 jsc = jMethod.getSourceCode();
1138
1139 jsc.add("if (");
1140 jsc.append(vName);
1141 jsc.append(" == null) {");
1142 jsc.addIndented(vName + " = new java.beans.PropertyChangeSupport(this);");
1143 jsc.add("}");
1144 jsc.add(vName);
1145 jsc.append(".addPropertyChangeListener(pcl);");
1146
1147
1148
1149
1150
1151 jMethod = new JMethod("removePropertyChangeListener", JType.BOOLEAN,
1152 "always returns true if pcl != null");
1153
1154 desc = "Removes the given PropertyChangeListener "
1155 + "from this classes list of ProperyChangeListeners.";
1156 jdc = jMethod.getJDocComment();
1157 jdc.appendComment(desc);
1158
1159 jMethod.addParameter(new JParameter(jType, "pcl"));
1160 desc = "The PropertyChangeListener to remove.";
1161 jdDesc = jdc.getParamDescriptor("pcl");
1162 jdDesc.setDescription(desc);
1163
1164 parent.addMethod(jMethod);
1165
1166 jsc = jMethod.getSourceCode();
1167 jsc.add("if (");
1168 jsc.append(vName);
1169 jsc.append(" == null) return false;");
1170
1171 jsc.add(vName);
1172 jsc.append(".removePropertyChangeListener(pcl);");
1173 jsc.add("return true;");
1174 }
1175
1176
1177
1178
1179
1180 private void createMarshalMethods(final JClass parent) {
1181 createMarshalMethods(parent, false);
1182 }
1183
1184
1185
1186
1187
1188
1189 private void createMarshalMethods(final JClass parent, final boolean isAbstract) {
1190
1191 JMethod jMethod = new JMethod("marshal");
1192 jMethod.addException(SGTypes.MARSHAL_EXCEPTION,
1193 "if object is null or if any SAXException is thrown during marshaling");
1194 jMethod.addException(SGTypes.VALIDATION_EXCEPTION,
1195 "if this object is an invalid instance according to the schema");
1196 jMethod.addParameter(new JParameter(SGTypes.WRITER, "out"));
1197
1198
1199
1200
1201
1202 parent.addMethod(jMethod);
1203
1204 if (isAbstract) {
1205 jMethod.getModifiers().setAbstract(true);
1206 } else {
1207 JSourceCode jsc = jMethod.getSourceCode();
1208 jsc.add("org.exolab.castor.xml.Marshaller.marshal(this, out);");
1209 }
1210
1211
1212
1213
1214 jMethod = new JMethod("marshal");
1215 JClass jc = null;
1216 if (_sax1) {
1217 jc = new JClass("org.xml.sax.DocumentHandler");
1218 } else {
1219 jc = new JClass("org.xml.sax.ContentHandler");
1220 jMethod.addException(SGTypes.IO_EXCEPTION,
1221 "if an IOException occurs during marshaling");
1222 }
1223 jMethod.addException(SGTypes.MARSHAL_EXCEPTION,
1224 "if object is null or if any SAXException is thrown during marshaling");
1225 jMethod.addException(SGTypes.VALIDATION_EXCEPTION,
1226 "if this object is an invalid instance according to the schema");
1227 jMethod.addParameter(new JParameter(jc, "handler"));
1228 parent.addMethod(jMethod);
1229
1230 if (isAbstract) {
1231 jMethod.getModifiers().setAbstract(true);
1232 } else {
1233 JSourceCode jsc = jMethod.getSourceCode();
1234 jsc.add("org.exolab.castor.xml.Marshaller.marshal(this, handler);");
1235 }
1236 }
1237
1238 private void createUnmarshalMethods(final JClass parent, final SGStateInfo sgState) {
1239
1240 String methodName = "unmarshal";
1241 if (sgState.getSourceGenerator().mappingSchemaType2Java()) {
1242 methodName += parent.getLocalName();
1243 }
1244
1245
1246
1247
1248
1249 JClass returnType;
1250 if (!getConfig().useJava50()) {
1251 returnType = findBaseClass(parent, sgState);
1252 } else {
1253 returnType = parent;
1254 }
1255
1256 JMethod jMethod = new JMethod(methodName, returnType,
1257 "the unmarshaled " + returnType);
1258 jMethod.getModifiers().setStatic(true);
1259 jMethod.addException(SGTypes.MARSHAL_EXCEPTION,
1260 "if object is null or if any SAXException is thrown during marshaling");
1261 jMethod.addException(SGTypes.VALIDATION_EXCEPTION,
1262 "if this object is an invalid instance according to the schema");
1263 jMethod.addParameter(new JParameter(SGTypes.READER, "reader"));
1264 parent.addMethod(jMethod);
1265
1266 JSourceCode jsc = jMethod.getSourceCode();
1267 jsc.add("return (");
1268 jsc.append(returnType.getName());
1269 jsc.append(") org.exolab.castor.xml.Unmarshaller.unmarshal(");
1270 jsc.append(parent.getName());
1271 jsc.append(".class, reader);");
1272 }
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283 private JClass findBaseClass(final JClass jClass, final SGStateInfo sgState) {
1284 JClass returnType = jClass;
1285
1286 List<JClass> classes = new LinkedList<JClass>();
1287 classes.add(returnType);
1288
1289 while (returnType.getSuperClassQualifiedName() != null) {
1290 String superClassName = returnType.getSuperClassQualifiedName();
1291 JClass superClass = sgState.getSourceCode(superClassName);
1292 if (superClass == null) {
1293 superClass = sgState.getImportedSourceCode(superClassName);
1294 }
1295
1296
1297
1298 if (superClass == null && superClassName.indexOf('.') < 0) {
1299 String pkgName = returnType.getPackageName();
1300 if (pkgName != null && pkgName.length() > 0) {
1301 superClassName = pkgName + "." + superClassName;
1302 superClass = sgState.getSourceCode(superClassName);
1303 }
1304 }
1305
1306
1307 if (superClass == null) {
1308 break;
1309 }
1310
1311
1312 if (classes.contains(superClass)) {
1313 StringBuilder buffer = new StringBuilder(64);
1314 buffer.append("Loop found in class hierarchy: ");
1315 for (Iterator<JClass> i = classes.iterator(); i.hasNext(); ) {
1316 JClass element = i.next();
1317
1318
1319 buffer.append(element.getName());
1320 buffer.append(" -> ");
1321 }
1322 buffer.append(superClass.getName());
1323 sgState.getDialog().notify(buffer.toString());
1324
1325 break;
1326 }
1327
1328 classes.add(superClass);
1329 returnType = superClass;
1330 }
1331
1332 classes.clear();
1333 return returnType;
1334 }
1335
1336
1337
1338
1339
1340
1341 public void createHashCodeMethod(final JClass jclass) {
1342 if (jclass == null) {
1343 throw new IllegalArgumentException("JClass must not be null");
1344 }
1345
1346
1347 JField[] fields = jclass.getFields();
1348
1349
1350 JMethod jMethod = new JMethod("hashCode", JType.INT, "a hash code value for the object.");
1351 jMethod.setComment("Overrides the java.lang.Object.hashCode method.\n"
1352 + "<p>\n"
1353 + "The following steps came from "
1354 + "<b>Effective Java Programming Language Guide</b> "
1355 + "by Joshua Bloch, Chapter 3");
1356
1357
1358 jclass.addMethod(jMethod);
1359
1360 JSourceCode jsc = jMethod.getSourceCode();
1361 if (jclass.getSuperClassQualifiedName() == null) {
1362 jsc.add("int resultHc = 17;");
1363 } else {
1364 jsc.add("int resultHc = super.hashCode();");
1365 }
1366 jsc.add("");
1367 jsc.add("long tmp;");
1368
1369 for (int i = 0; i < fields.length; i++) {
1370 JField temp = fields[i];
1371
1372
1373 JType type = temp.getType();
1374 String name = temp.getName();
1375 if (type.isPrimitive()) {
1376 if (type == JType.BOOLEAN) {
1377
1378
1379 if (!name.startsWith("_has_") || jclass.getField(name.substring(5)) != null) {
1380 jsc.add("resultHc = 37 * resultHc + (" + name + "?0:1);");
1381 }
1382 } else if (type == JType.BYTE || type == JType.INT || type == JType.SHORT) {
1383 jsc.add("resultHc = 37 * resultHc + " + name + ";");
1384 } else if (type == JType.LONG) {
1385 jsc.add("resultHc = 37 * resultHc + (int)(" + name + "^(" + name + ">>>32));");
1386 } else if (type == JType.FLOAT) {
1387 jsc.add("resultHc = 37 * resultHc + java.lang.Float.floatToIntBits(" + name + ");");
1388 } else if (type == JType.DOUBLE) {
1389 jsc.add("tmp = java.lang.Double.doubleToLongBits(" + name + ");");
1390 jsc.add("resultHc = 37 * resultHc + (int)(tmp^(tmp>>>32));");
1391 }
1392 } else {
1393 if (getConfig().useCycleBreaker()) {
1394
1395 jsc.add("if (" + name + " != null");
1396 jsc.add(" && !org.castor.core.util.CycleBreaker.startingToCycle(" + name + ")) {");
1397 } else {
1398
1399 jsc.add("if (" + name + " != null) {");
1400 }
1401 jsc.add(" resultHc = 37 * resultHc + " + name + ".hashCode();");
1402
1403 if (getConfig().useCycleBreaker()) {
1404
1405 jsc.add(" org.castor.core.util.CycleBreaker.releaseCycleHandle(" + name + ");");
1406 }
1407 jsc.add("}");
1408 }
1409 }
1410 jsc.add("");
1411 jsc.add("return resultHc;");
1412 }
1413
1414
1415
1416
1417
1418
1419 public void createEqualsMethod(final JClass jclass) {
1420 if (jclass == null) {
1421 throw new IllegalArgumentException("JClass must not be null");
1422 }
1423
1424 JField[] fields = jclass.getFields();
1425 JMethod jMethod = new JMethod("equals", JType.BOOLEAN, "true if the objects are equal.");
1426 jMethod.setComment("Overrides the java.lang.Object.equals method.");
1427 jMethod.addParameter(new JParameter(SGTypes.OBJECT, "obj"));
1428
1429 if (getConfig().useJava50()) {
1430 jMethod.addAnnotation(new JAnnotation(new JAnnotationType("Override")));
1431 }
1432
1433 jclass.addMethod(jMethod);
1434 JSourceCode jsc = jMethod.getSourceCode();
1435 jsc.add("if ( this == obj )");
1436 jsc.indent();
1437 jsc.add("return true;");
1438 jsc.unindent();
1439 if (jclass.getSuperClassQualifiedName() != null) {
1440 jsc.add("");
1441 jsc.add("if (super.equals(obj)==false)");
1442 jsc.indent();
1443 jsc.add("return false;");
1444 jsc.unindent();
1445 }
1446 jsc.add("");
1447 jsc.add("if (obj instanceof ");
1448 jsc.append(jclass.getLocalName());
1449 jsc.append(") {");
1450 jsc.add("");
1451 if (fields.length > 0) {
1452 jsc.indent();
1453 jsc.add(jclass.getLocalName());
1454 jsc.append(" temp = (");
1455 jsc.append(jclass.getLocalName());
1456 jsc.append(")obj;");
1457
1458 if (getConfig().useCycleBreaker()) {
1459 jsc.add("boolean thcycle;");
1460 jsc.add("boolean tmcycle;");
1461 }
1462 }
1463 for (int i = 0; i < fields.length; i++) {
1464 JField temp = fields[i];
1465
1466
1467 String name = temp.getName();
1468 if (temp.getType().isPrimitive()) {
1469 jsc.add("if (this.");
1470 jsc.append(name);
1471 jsc.append(" != temp.");
1472 jsc.append(name);
1473 jsc.append(")");
1474 } else {
1475
1476
1477
1478
1479 jsc.add("if (this.");
1480 jsc.append(name);
1481 jsc.append(" != null) {");
1482 jsc.indent();
1483 jsc.add("if (temp.");
1484 jsc.append(name);
1485 jsc.append(" == null) ");
1486 jsc.indent();
1487 jsc.append("return false;");
1488 jsc.unindent();
1489
1490 if (getConfig().useCycleBreaker()) {
1491 jsc.add("if (this.");
1492 jsc.append(name);
1493 jsc.append(" != temp.");
1494 jsc.append(name);
1495 jsc.append(") {");
1496
1497
1498 jsc.indent();
1499 jsc.add("thcycle=org.castor.core.util.CycleBreaker.startingToCycle(this." + name + ");");
1500 jsc.add("tmcycle=org.castor.core.util.CycleBreaker.startingToCycle(temp." + name + ");");
1501
1502 jsc.add("if (thcycle!=tmcycle) {");
1503 jsc.indent();
1504 jsc.add("if (!thcycle) { org.castor.core.util.CycleBreaker.releaseCycleHandle(this."
1505 + name + "); };");
1506 jsc.add("if (!tmcycle) { org.castor.core.util.CycleBreaker.releaseCycleHandle(temp."
1507 + name + "); };");
1508 jsc.add("return false;");
1509 jsc.unindent();
1510 jsc.add("}");
1511 jsc.add("if (!thcycle) {");
1512 jsc.indent();
1513 }
1514 jsc.add("if (!");
1515
1516
1517 if (temp.getType().isArray()) {
1518 jsc.append("java.util.Arrays.equals(this.");
1519 jsc.append(name);
1520 jsc.append(", temp.");
1521 jsc.append(name);
1522 jsc.append(")");
1523 } else {
1524 jsc.append("this.");
1525 jsc.append(name);
1526 jsc.append(".equals(temp.");
1527 jsc.append(name);
1528 jsc.append(")");
1529 }
1530
1531 if (getConfig().useCycleBreaker()) {
1532 jsc.append(") {");
1533 } else {
1534 jsc.append(") ");
1535 }
1536 jsc.indent();
1537
1538 if (getConfig().useCycleBreaker()) {
1539 jsc.add("org.castor.core.util.CycleBreaker.releaseCycleHandle(this." + name + ");");
1540 jsc.add("org.castor.core.util.CycleBreaker.releaseCycleHandle(temp." + name + ");");
1541 }
1542 jsc.add("return false;");
1543 jsc.unindent();
1544
1545 if (getConfig().useCycleBreaker()) {
1546 jsc.add("}");
1547
1548 jsc.add("org.castor.core.util.CycleBreaker.releaseCycleHandle(this." + name + ");");
1549 jsc.add("org.castor.core.util.CycleBreaker.releaseCycleHandle(temp." + name + ");");
1550 }
1551
1552 jsc.unindent();
1553
1554 if (getConfig().useCycleBreaker()) {
1555 jsc.add("}");
1556 jsc.unindent();
1557 jsc.add("}");
1558 jsc.unindent();
1559 }
1560 jsc.add("} else if (temp.");
1561 jsc.append(name);
1562 jsc.append(" != null)");
1563 }
1564 jsc.indent();
1565 jsc.add("return false;");
1566 jsc.unindent();
1567 }
1568 jsc.add("return true;");
1569 jsc.unindent();
1570 jsc.add("}");
1571 jsc.add("return false;");
1572 }
1573
1574
1575
1576
1577
1578
1579
1580 public void createTestableMethods(final JClass jclass, final FactoryState state) {
1581 if (jclass == null) {
1582 throw new IllegalArgumentException("JClass must not be null");
1583 }
1584
1585 jclass.addInterface("org.castor.xmlctf.CastorTestable");
1586 jclass.addImport("org.castor.xmlctf.CastorTestable");
1587 jclass.addImport("org.castor.xmlctf.RandomHelper");
1588
1589 createRandomizeFields(jclass, state);
1590 createDumpFields(jclass);
1591 }
1592
1593
1594
1595
1596
1597
1598
1599
1600 private void createRandomizeFields(final JClass jclass, final FactoryState state) {
1601 JMethod jMethod = new JMethod("randomizeFields");
1602 jMethod.addException(new JClass("InstantiationException"),
1603 "if we try to instantiate an abstract class or interface");
1604 jMethod.addException(new JClass("IllegalAccessException"),
1605 "if we do not have access to the field, for example if it is private");
1606 jMethod.setComment("implementation of org.castor.xmlctf.CastorTestable");
1607 jclass.addMethod(jMethod);
1608 JSourceCode jsc = jMethod.getSourceCode();
1609 JField[] fields = jclass.getFields();
1610
1611 for (int i = 0; i < fields.length; i++) {
1612 JField temp = fields[i];
1613 JType type = temp.getType();
1614 String name = temp.getName();
1615
1616 if (state.getFieldInfoForChoice() != null
1617 && name.equals(state.getFieldInfoForChoice().getName())) {
1618 continue;
1619 }
1620
1621 if (name.startsWith("enumConstants")) {
1622 continue;
1623 }
1624
1625 if (name.startsWith("_")) {
1626 name = getJavaNaming().toJavaClassName(name.substring(1));
1627 } else {
1628 name = getJavaNaming().toJavaClassName(name);
1629 }
1630
1631 String setName = "set" + name;
1632 if (name.indexOf("Has") == -1) {
1633 if (type instanceof JCollectionType) {
1634
1635 int listLocat = name.lastIndexOf("List");
1636 String tempName = name;
1637 if (listLocat != -1) {
1638 tempName = tempName.substring(0, listLocat);
1639 }
1640 String methodName = getJavaNaming().toJavaClassName(tempName);
1641 methodName = "get" + methodName;
1642 JMethod method = jclass.getMethod(methodName, 0);
1643
1644 if (method == null) {
1645 continue;
1646 }
1647
1648 String componentName = method.getReturnType().getName();
1649
1650 jsc.add(temp.getName());
1651 jsc.append(" = RandomHelper.getRandom(");
1652 jsc.append(temp.getName());
1653 jsc.append(", ");
1654 jsc.append(componentName);
1655 jsc.append(".class);");
1656 } else if (type.isPrimitive()) {
1657
1658 jsc.add(setName);
1659 jsc.append("(RandomHelper.getRandom(");
1660 jsc.append(temp.getName());
1661 jsc.append("));");
1662 } else if (type.isArray()) {
1663
1664 jsc.add(setName);
1665 jsc.append("((");
1666 jsc.append(type.toString());
1667 jsc.append(")RandomHelper.getRandom(");
1668 jsc.append(temp.getName());
1669
1670 jsc.append(", java.lang.reflect.Array.class));");
1671 } else {
1672
1673 jsc.add(setName);
1674 jsc.append("((");
1675 jsc.append(type.getName());
1676 jsc.append(")RandomHelper.getRandom(");
1677 jsc.append(temp.getName());
1678 jsc.append(", ");
1679 jsc.append(type.getName());
1680 jsc.append(".class));");
1681 }
1682 jsc.add("");
1683 }
1684 }
1685 }
1686
1687
1688
1689
1690
1691
1692
1693 private void createDumpFields(final JClass jclass) {
1694 JMethod jMethod = new JMethod("dumpFields", SGTypes.STRING,
1695 "a String representation of all of the fields for " + jclass.getName());
1696 jMethod.setComment("implementation of org.castor.xmlctf.CastorTestable");
1697 jclass.addMethod(jMethod);
1698 JSourceCode jsc = jMethod.getSourceCode();
1699 jsc.add("StringBuffer stringBuffer = new StringBuffer(\"DumpFields() for element: ");
1700 jsc.append(jclass.getName());
1701 jsc.append("\\n\");");
1702
1703 JField[] fields = jclass.getFields();
1704 for (int i = 0; i < fields.length; i++) {
1705 JField temp = fields[i];
1706 String name = temp.getName();
1707 if ((temp.getType().isPrimitive())
1708 || temp.getType().getName().startsWith("java.lang.")) {
1709
1710
1711 jsc.add("stringBuffer.append(\"Field ");
1712 jsc.append(name);
1713 jsc.append(":\" +");
1714 jsc.append(name);
1715 jsc.append("+\"\\n\");");
1716 } else if (temp.getType().isArray()) {
1717 jsc.add("if (");
1718 jsc.append(name);
1719 jsc.append(" != null) {");
1720 jsc.indent();
1721 jsc.add("stringBuffer.append(\"[\");");
1722 jsc.add("for (int i = 0; i < ");
1723 jsc.append(name);
1724 jsc.append(".length; i++) {");
1725 jsc.indent();
1726 jsc.add("stringBuffer.append(");
1727 jsc.append(name);
1728 jsc.append("[i] + \" \");");
1729 jsc.unindent();
1730 jsc.add("}");
1731 jsc.add("stringBuffer.append(\"]\");");
1732 jsc.unindent();
1733 jsc.add("}");
1734 } else {
1735 jsc.add("if ( (");
1736 jsc.append(name);
1737 jsc.append(" != null) && (");
1738 jsc.append(name);
1739 jsc.append(".getClass().isAssignableFrom(CastorTestable.class)))");
1740 jsc.indent();
1741 jsc.add("stringBuffer.append(((CastorTestable)");
1742 jsc.append(name);
1743 jsc.append(").dumpFields());");
1744 jsc.unindent();
1745 jsc.add("else stringBuffer.append(\"Field ");
1746 jsc.append(name);
1747 jsc.append(":\" +");
1748 jsc.append(name);
1749 jsc.append("+\"\\n\");");
1750 }
1751 jsc.add("");
1752 }
1753 jsc.add("");
1754 jsc.add("return stringBuffer.toString();");
1755 }
1756
1757
1758
1759
1760
1761 private void createValidateMethods(final JClass jClass) {
1762 JMethod jMethod = null;
1763 JSourceCode jsc = null;
1764
1765
1766 jMethod = new JMethod("validate");
1767 jMethod.addException(SGTypes.VALIDATION_EXCEPTION,
1768 "if this object is an invalid instance according to the schema");
1769
1770 jClass.addMethod(jMethod);
1771 jsc = jMethod.getSourceCode();
1772 jsc.add("org.exolab.castor.xml.Validator validator = new ");
1773 jsc.append("org.exolab.castor.xml.Validator();");
1774 jsc.add("validator.validate(this);");
1775
1776
1777 jMethod = new JMethod("isValid", JType.BOOLEAN,
1778 "true if this object is valid according to the schema");
1779 jsc = jMethod.getSourceCode();
1780 jsc.add("try {");
1781 jsc.indent();
1782 jsc.add("validate();");
1783 jsc.unindent();
1784 jsc.add("} catch (org.exolab.castor.xml.ValidationException vex) {");
1785 jsc.indent();
1786 jsc.add("return false;");
1787 jsc.unindent();
1788 jsc.add("}");
1789 jsc.add("return true;");
1790 jClass.addMethod(jMethod);
1791 }
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804 private String resolveClassName(final String name, final String packageName) {
1805 if ((packageName != null) && (packageName.length() > 0)) {
1806 return packageName + "." + name;
1807 }
1808 return name;
1809 }
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832 private void processAppInfo(final Annotated annotated, final ClassInfo cInfo) {
1833 Enumeration<Annotation> annotations = annotated.getAnnotations();
1834 while (annotations.hasMoreElements()) {
1835 Annotation ann = annotations.nextElement();
1836 Enumeration<AppInfo> appInfos = ann.getAppInfo();
1837 while (appInfos.hasMoreElements()) {
1838 AppInfo appInfo = appInfos.nextElement();
1839 if (appInfo.hasNature(AppInfoJpaNature.class.getName())) {
1840 AppInfoJpaNature nature = new AppInfoJpaNature(appInfo);
1841 List<?> content = nature.getContent();
1842 if (content != null && !content.isEmpty()) {
1843 Iterator<?> it = content.iterator();
1844 if (it.hasNext()) {
1845 cInfo.addNature(JDOClassInfoNature.class.getName());
1846 JDOClassInfoNature cNature = new JDOClassInfoNature(cInfo);
1847 while (it.hasNext()) {
1848 Object tmpObject = it.next();
1849 if (tmpObject instanceof Table) {
1850 Table table = (Table) tmpObject;
1851 cNature.setTableName(table.getName());
1852 cNature.setAccessMode(AccessMode.valueOf("shared"));
1853 cNature.setDetachable(table.isDetachable());
1854
1855
1856 PrimaryKey pk = table.getPrimaryKey();
1857 Iterator<? extends String> pIt = pk.iterateKey();
1858 while (pIt.hasNext()) {
1859 cNature.addPrimaryKey(pIt.next());
1860 }
1861 }
1862 }
1863 }
1864 }
1865 }
1866 }
1867 }
1868 }
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885 private void processAppInfo(final Annotated annotated, final FieldInfo fInfo) {
1886 Enumeration<Annotation> annotations = annotated.getAnnotations();
1887
1888 while (annotations.hasMoreElements()) {
1889 Annotation ann = annotations.nextElement();
1890 Enumeration<AppInfo> appInfos = ann.getAppInfo();
1891 while (appInfos.hasMoreElements()) {
1892 AppInfo appInfo = appInfos.nextElement();
1893
1894 if (appInfo.hasNature(AppInfoSolrjNature.class.getName())) {
1895 AppInfoSolrjNature nature = new AppInfoSolrjNature(appInfo);
1896 Object solrjRawContent = nature.getContent();
1897 if (solrjRawContent != null) {
1898 fInfo.addNature(SolrjFieldInfoNature.class.getName());
1899 SolrjFieldInfoNature solrjNature = new SolrjFieldInfoNature(fInfo);
1900 if (solrjRawContent instanceof Field) {
1901 Field solrjField = (Field) solrjRawContent;
1902 if (StringUtils.isNotBlank(solrjField.getName())) {
1903 solrjNature.setFieldName(solrjField.getName());
1904 }
1905 }
1906 }
1907 }
1908
1909 if (appInfo.hasNature(AppInfoJpaNature.class.getName())) {
1910 AppInfoJpaNature nature = new AppInfoJpaNature(appInfo);
1911 List<?> content = nature.getContent();
1912 if (content != null && !content.isEmpty()) {
1913 Iterator<?> it = content.iterator();
1914 if (it.hasNext()) {
1915 while (it.hasNext()) {
1916 Object tmpObject = it.next();
1917 if (tmpObject instanceof Column) {
1918 fInfo.addNature(JDOFieldInfoNature.class.getName());
1919 JDOFieldInfoNature fNature = new JDOFieldInfoNature(fInfo);
1920 Column column = (Column) tmpObject;
1921 fNature.setColumnName(column.getName());
1922 fNature.setColumnType(column.getType());
1923 fNature.setReadOnly(column.isReadOnly());
1924 fNature.setDirty(false);
1925 fNature.setDirty(column.getDirty());
1926 } else if (tmpObject instanceof OneToOne) {
1927 OneToOne relation = (OneToOne) tmpObject;
1928 fInfo.addNature(JDOOneToOneNature.class.getName());
1929 JDOOneToOneNature oneNature = new JDOOneToOneNature(fInfo);
1930 oneNature.addForeignKey(relation.getName());
1931 oneNature.setDirty(relation.isDirty());
1932 oneNature.setReadOnly(relation.isReadOnly());
1933 } else if (tmpObject instanceof OneToMany) {
1934 OneToMany relation = (OneToMany) tmpObject;
1935 fInfo.addNature(JDOOneToManyNature.class.getName());
1936 JDOOneToManyNature manyNature = new JDOOneToManyNature(fInfo);
1937 manyNature.addForeignKey(relation.getName());
1938 manyNature.setDirty(relation.isDirty());
1939 manyNature.setReadOnly(relation.isReadOnly());
1940 }
1941 }
1942 }
1943 }
1944 }
1945 }
1946 }
1947 }
1948
1949
1950
1951
1952
1953
1954
1955 private void processAttributes(final ExtendedBinding binding,
1956 final ComplexType complexType,
1957 final FactoryState state) {
1958 if (complexType == null) {
1959 return;
1960 }
1961
1962 Enumeration<AttributeDecl> enumeration = complexType.getAttributeDecls();
1963 XMLBindingComponent component = new XMLBindingComponent(getConfig(), getGroupNaming());
1964 if (_binding != null) {
1965 component.setBinding(_binding);
1966 }
1967
1968 while (enumeration.hasMoreElements()) {
1969 AttributeDecl attr = enumeration.nextElement();
1970
1971 component.setView(attr);
1972
1973
1974 SimpleType sType = attr.getSimpleType();
1975
1976
1977 XMLType baseXMLType = complexType.getBaseType();
1978 while (sType == null) {
1979
1980
1981 if (baseXMLType == null || !(baseXMLType instanceof ComplexType)) {
1982 break;
1983 }
1984
1985
1986
1987 final ComplexType baseComplexType = (ComplexType) baseXMLType;
1988 AttributeDecl baseAttribute = baseComplexType.getAttributeDecl(attr.getName());
1989
1990 if (baseAttribute != null) {
1991
1992 sType = baseAttribute.getSimpleType();
1993 if (sType != null) {
1994 attr.setSimpleType(sType);
1995 break;
1996 }
1997 }
1998
1999
2000 baseXMLType = baseXMLType.getBaseType();
2001 }
2002
2003
2004
2005 if (sType == null && attr.getReference() != null) {
2006 SimpleType referencedSimpleType = attr.getReference().getSimpleType();
2007 attr.setSimpleType(referencedSimpleType);
2008 sType = referencedSimpleType;
2009 }
2010
2011 if (sType != null && !(SimpleTypesFactory.isBuiltInType(sType.getTypeCode()))) {
2012 if (sType.getSchema() == component.getSchema() && state.resolve(sType) == null) {
2013 if (sType.hasFacet(Facet.ENUMERATION)) {
2014 createSourceCode(component.getBinding(), sType, state.getSGStateInfo());
2015 }
2016 }
2017 }
2018
2019 FieldInfo fieldInfo = _memberFactory.createFieldInfo(component, state, getConfig().useJava50());
2020 handleField(fieldInfo, state, component);
2021 }
2022 }
2023
2024
2025
2026
2027
2028 private void processComplexType(final ComplexType complexType, final FactoryState state) {
2029 XMLBindingComponent component = new XMLBindingComponent(getConfig(), getGroupNaming());
2030 if (_binding != null) {
2031 component.setBinding(_binding);
2032 }
2033 component.setView(complexType);
2034
2035 String typeName = component.getXMLName();
2036
2037 ClassInfo classInfo = state.getClassInfo();
2038 XMLInfoNature xmlNature = new XMLInfoNature(classInfo);
2039 xmlNature.setSchemaType(new XSClass(state.getJClass(), typeName));
2040
2041
2042
2043
2044
2045 XMLType base = complexType.getBaseType();
2046
2047
2048 if (base != null) {
2049 if (base.isComplexType()) {
2050 String baseClassName = null;
2051
2052 component.setView(base);
2053
2054
2055
2056
2057
2058 if (base.getSchema() == complexType.getSchema()) {
2059 ClassInfo cInfo = state.resolve(base);
2060
2061
2062 if (cInfo == null) {
2063 JClass[] classes = createSourceCode(component, state.getSGStateInfo());
2064 cInfo = state.resolve(base);
2065 baseClassName = classes[0].getName();
2066 } else {
2067 baseClassName = cInfo.getJClass().getName();
2068 }
2069
2070 classInfo.setBaseClass(cInfo);
2071 } else {
2072
2073
2074 baseClassName = component.getQualifiedName();
2075 }
2076
2077
2078 component.setView(complexType);
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089 state.getJClass().setSuperClass(baseClassName);
2090 }
2091
2092
2093 if (complexType.getContentType().getType() == ContentType.SIMPLE) {
2094 SimpleContent simpleContent = (SimpleContent) complexType.getContentType();
2095 SimpleType temp = simpleContent.getSimpleType();
2096 SimpleType baseType = (SimpleType) temp.getBaseType();
2097 XSType xsType = _typeConversion.convertType(
2098 temp, state.getPackageName(), getConfig().useJava50());
2099
2100 FieldInfo fieldInfo = null;
2101 if ((baseType != null) && extendsSimpleType(state.getJClass(), baseType, state)) {
2102 if (xsType.isEnumerated()) {
2103 fieldInfo = _memberFactory.createFieldInfoForContent(
2104 component, xsType, getConfig().useJava50());
2105 fieldInfo.setBound(false);
2106
2107 handleField(fieldInfo, state, component);
2108
2109
2110 String mname = fieldInfo.getReadMethodName();
2111 JClass jClass = state.getJClass();
2112 JMethod method = jClass.getMethod(mname, 0);
2113 jClass.removeMethod(method);
2114
2115
2116 mname = fieldInfo.getWriteMethodName();
2117 method = jClass.getMethod(mname, 0);
2118 JSourceCode jsc = method.getSourceCode();
2119 jsc.add("super.");
2120 jsc.append(mname);
2121 jsc.append("(this.");
2122 jsc.append(fieldInfo.getName());
2123 jsc.append(".toString());");
2124 }
2125
2126
2127 } else {
2128
2129 while (temp.getBaseType() != null && !temp.isBuiltInType()) {
2130 temp = (SimpleType) temp.getBaseType();
2131 }
2132
2133 xsType = _typeConversion.convertType(
2134 temp, state.getPackageName(), getConfig().useJava50());
2135 fieldInfo = _memberFactory.createFieldInfoForContent(
2136 component, xsType, getConfig().useJava50());
2137 handleField(fieldInfo, state, component);
2138 }
2139 }
2140 }
2141
2142
2143
2144
2145
2146
2147 if (!state.isCreateGroupItem()) {
2148 processAttributes(component.getBinding(), complexType, state);
2149
2150 component.setView(complexType);
2151 if (complexType.getContentType() == ContentType.mixed) {
2152 FieldInfo fieldInfo = _memberFactory.createFieldInfoForContent(
2153 component, new XSString(), getConfig().useJava50());
2154 handleField(fieldInfo, state, component);
2155 }
2156 }
2157
2158 processContentModel(complexType, state);
2159 }
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169 private void processContentModel(final ContentModelGroup model,
2170 final FactoryState state) {
2171
2172
2173
2174
2175 ContentModelGroup contentModel = model;
2176 Enumeration<Annotated> enumeration = contentModel.enumerate();
2177
2178
2179 if (new XMLInfoNature(state.getClassInfo()).isChoice()
2180 && state.getFieldInfoForChoice() == null) {
2181 state.setFieldInfoForChoice(_memberFactory.createFieldInfoForChoiceValue());
2182 state.getFieldInfoForChoice().getMemberAndAccessorFactory().createJavaField(
2183 state.getFieldInfoForChoice(),
2184 state.getJClass());
2185 state.getFieldInfoForChoice().getMemberAndAccessorFactory().createAccessMethods(
2186 state.getFieldInfoForChoice(), state.getJClass(), getConfig().useJava50(),
2187 getConfig().getAnnotationBuilders());
2188 }
2189
2190 FieldInfo fieldInfo = null;
2191 XMLBindingComponent component = new XMLBindingComponent(getConfig(), getGroupNaming());
2192 if (_binding != null) {
2193 component.setBinding(_binding);
2194 }
2195
2196 while (enumeration.hasMoreElements()) {
2197 Annotated annotated = enumeration.nextElement();
2198 component.setView(annotated);
2199
2200 switch (annotated.getStructureType()) {
2201 case Structure.ELEMENT:
2202 fieldInfo = _memberFactory.createFieldInfo(
2203 component, state, getConfig().useJava50());
2204
2205
2206
2207 if (contentModel.getMinOccurs() == 0) {
2208 XMLInfoNature xmlNature = new XMLInfoNature(fieldInfo);
2209 xmlNature.setRequired(false);
2210 }
2211
2212 handleField(fieldInfo, state, component);
2213 break;
2214 case Structure.GROUP:
2215 Group group = (Group) annotated;
2216
2217 if ((contentModel instanceof ComplexType)
2218 || (contentModel instanceof ModelGroup)) {
2219 if (group.getOrder() == Order.choice) {
2220 new XMLInfoNature(state.getClassInfo()).getGroupInfo().setAsChoice();
2221 } else if (group.getOrder() == Order.all) {
2222 new XMLInfoNature(state.getClassInfo()).getGroupInfo().setAsAll();
2223 } else if (group.getOrder() == Order.sequence) {
2224 new XMLInfoNature(state.getClassInfo()).getGroupInfo().setAsSequence();
2225 }
2226 }
2227
2228
2229 if (!((contentModel instanceof ComplexType)
2230 || (contentModel instanceof ModelGroup))) {
2231 if (contentModel instanceof ModelGroup) {
2232 ModelGroup mg = (ModelGroup) contentModel;
2233 if (mg.isReference()) {
2234 contentModel = mg.getReference();
2235 }
2236 }
2237
2238 if (contentModel.getParticleCount() > 0) {
2239 fieldInfo = _memberFactory.createFieldInfo(
2240 component, state.getSGStateInfo(), getConfig().useJava50());
2241 handleField(fieldInfo, state, component);
2242 }
2243 } else {
2244
2245 processContentModel(group, state);
2246 }
2247 break;
2248
2249 case Structure.MODELGROUP:
2250 ModelGroup modelgroup = (ModelGroup) annotated;
2251
2252
2253
2254 if (modelgroup.getName() != null) {
2255
2256
2257
2258 if (modelgroup.isReference()) {
2259 modelgroup = modelgroup.getReference();
2260 }
2261
2262 if (modelgroup.getParticleCount() > 0) {
2263 fieldInfo = _memberFactory.createFieldInfo(
2264 component, state.getSGStateInfo(), getConfig().useJava50());
2265 handleField(fieldInfo, state, component);
2266 }
2267 break;
2268 }
2269
2270 processContentModel(modelgroup.getContentModelGroup(), state);
2271 break;
2272
2273 case Structure.WILDCARD:
2274 Wildcard wildcard = (Wildcard) annotated;
2275 FieldInfo fieldForAny = _memberFactory.createFieldInfoForAny(
2276 wildcard, getConfig().useJava50());
2277 handleField(fieldForAny, state, component);
2278 break;
2279
2280 default:
2281 break;
2282 }
2283 }
2284
2285 }
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297 private void processEnumeration(final ExtendedBinding binding,
2298 final SimpleType simpleType, final FactoryState state) {
2299
2300 if (getConfig().useEnumeratedTypeInterface()) {
2301 state.getJClass().addInterface(ENUM_ACCESS_INTERFACE);
2302 }
2303
2304 switch (_enumerationType) {
2305 case BASE_TYPE_ENUMERATION:
2306 processEnumerationAsBaseType(binding, simpleType, state);
2307 break;
2308 default:
2309 processEnumerationAsNewObject(binding, simpleType, state);
2310 break;
2311 }
2312 }
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323 private void processEnumerationAsNewObject(final ExtendedBinding binding,
2324 final SimpleType simpleType, final FactoryState state) {
2325 _enumerationFactory.processEnumerationAsNewObject(binding, simpleType, state);
2326 if (_testable && state.getJClass() instanceof JEnum) {
2327 createTestableMethods(state.getJClass(), state);
2328 }
2329 }
2330
2331
2332
2333
2334
2335
2336
2337
2338 private void processEnumerationAsBaseType(final ExtendedBinding binding,
2339 final SimpleType simpleType, final FactoryState state) {
2340 _enumerationFactory.processEnumerationAsBaseType(binding, simpleType, state);
2341 }
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351 private void handleField(final FieldInfo fieldInfo, final FactoryState state, final XMLBindingComponent component) {
2352 if (fieldInfo == null) {
2353 return;
2354 }
2355
2356 XMLInfoNature xmlNature = new XMLInfoNature(fieldInfo);
2357
2358 if (CLASS_METHOD_SUFFIX.equals(fieldInfo.getMethodSuffix())) {
2359 SGStateInfo sInfo = state.getSGStateInfo();
2360 if (!sInfo.getSuppressNonFatalWarnings()) {
2361 String warn = "warning a field name conflicts with \""
2362 + CLASS_KEYWORD + "\", please use a binding file to specify "
2363 + "a different name for the " + xmlNature.getNodeTypeName()
2364 + " '" + xmlNature.getNodeName() + "'.";
2365 sInfo.getDialog().notify(warn);
2366 }
2367 } else if (CLASS_KEYWORD.equals(xmlNature.getNodeName())) {
2368 SGStateInfo sInfo = state.getSGStateInfo();
2369 if (!sInfo.getSuppressNonFatalWarnings()) {
2370 String warn = "warning a field name conflicts with \""
2371 + CLASS_KEYWORD + "\" and is being replaced by \"clazz\". "
2372 + "You may use a binding file to specify a different "
2373 + "name for the " + xmlNature.getNodeTypeName()
2374 + " '" + xmlNature.getNodeName() + "'.";
2375 sInfo.getDialog().notify(warn);
2376 }
2377 }
2378
2379 processAppInfo(component.getAnnotated(), fieldInfo);
2380
2381 JSourceCode scInitializer = state.getJClass().getConstructor(0).getSourceCode();
2382
2383 ClassInfo base = state.getClassInfo().getBaseClass();
2384 boolean present = false;
2385 if (base != null) {
2386 switch (new XMLInfoNature(fieldInfo).getNodeType()) {
2387 case ATTRIBUTE:
2388 present = (base.getAttributeField(xmlNature.getNodeName()) != null);
2389 break;
2390 case ELEMENT:
2391 String baseNodeName = xmlNature.getNodeName();
2392
2393 if (baseNodeName != null
2394 && !(baseNodeName.equals(XMLInfo.CHOICE_NODE_NAME_ERROR_INDICATION))) {
2395
2396
2397
2398 FieldInfo inheritedFieldInfo = base.getElementField(baseNodeName);
2399
2400 if (inheritedFieldInfo != null) {
2401 String namespaceURI = xmlNature.getNamespaceURI();
2402 if (namespaceURI != null && namespaceURI.equals(new XMLInfoNature(inheritedFieldInfo).getNamespaceURI())) {
2403 present = true;
2404 }
2405 }
2406 }
2407 break;
2408 default:
2409 break;
2410 }
2411 }
2412
2413 state.getClassInfo().addFieldInfo(fieldInfo);
2414 present = present && !xmlNature.isMultivalued();
2415
2416
2417 if (!present) {
2418 if (state.getFieldInfoForChoice() != null) {
2419 if (fieldInfo != state.getFieldInfoForChoice()) {
2420 fieldInfo.setFieldInfoReference(state.getFieldInfoForChoice());
2421 }
2422 }
2423
2424 fieldInfo.getMemberAndAccessorFactory().createJavaField(fieldInfo, state.getJClass());
2425
2426 if (!fieldInfo.isTransient()) {
2427 fieldInfo.getMemberAndAccessorFactory().createAccessMethods(
2428 fieldInfo, state.getJClass(), getConfig().useJava50(),
2429 getConfig().getAnnotationBuilders());
2430 if (fieldInfo.isBound()) {
2431 state.setBoundProperties(true);
2432 }
2433 }
2434 }
2435
2436
2437 fieldInfo.getMemberAndAccessorFactory().generateInitializerCode(fieldInfo, scInitializer);
2438 }
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451 private boolean extendsSimpleType(final JClass jClass, final SimpleType type,
2452 final FactoryState state) {
2453 String superClassName = jClass.getSuperClassQualifiedName();
2454 if (superClassName != null) {
2455 ClassInfo cInfo = state.resolve(type);
2456 if (cInfo != null) {
2457 return superClassName.equals(cInfo.getJClass().getName());
2458 }
2459 }
2460 return false;
2461 }
2462
2463 }