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.List;
55
56 import org.apache.commons.lang.StringUtils;
57 import org.exolab.castor.builder.BuilderConfiguration;
58 import org.exolab.castor.builder.ClassInfoResolver;
59 import org.exolab.castor.builder.GroupNaming;
60 import org.exolab.castor.builder.SGTypes;
61 import org.exolab.castor.builder.SourceGenerator;
62 import org.exolab.castor.builder.SourceGeneratorConstants;
63 import org.exolab.castor.builder.binding.XMLBindingComponent;
64 import org.exolab.castor.builder.info.ClassInfo;
65 import org.exolab.castor.builder.info.CollectionInfo;
66 import org.exolab.castor.builder.info.FieldInfo;
67 import org.exolab.castor.builder.info.XMLInfo;
68 import org.exolab.castor.builder.info.NodeType;
69 import org.exolab.castor.builder.info.nature.XMLInfoNature;
70 import org.exolab.castor.builder.types.XSList;
71 import org.exolab.castor.builder.types.XSListType;
72 import org.exolab.castor.builder.types.XSClass;
73 import org.exolab.castor.builder.types.XSString;
74 import org.exolab.castor.builder.types.XSType;
75 import org.exolab.castor.xml.schema.AttributeDecl;
76 import org.exolab.castor.xml.schema.ComplexType;
77 import org.exolab.castor.xml.schema.ElementDecl;
78 import org.exolab.castor.xml.schema.Facet;
79 import org.exolab.castor.xml.schema.Group;
80 import org.exolab.castor.xml.schema.Order;
81 import org.exolab.castor.xml.schema.Schema;
82 import org.exolab.castor.xml.schema.SchemaNames;
83 import org.exolab.castor.xml.schema.SimpleType;
84 import org.exolab.castor.xml.schema.Structure;
85 import org.exolab.castor.xml.schema.Wildcard;
86 import org.exolab.castor.xml.schema.XMLType;
87 import org.exolab.castor.xml.schema.simpletypes.ListType;
88 import org.exolab.javasource.JArrayType;
89 import org.exolab.javasource.JClass;
90 import org.exolab.javasource.JPrimitiveType;
91 import org.exolab.javasource.JType;
92
93
94
95
96
97
98
99 public final class MemberFactory extends BaseFactory {
100
101
102
103
104
105
106
107
108
109 public MemberFactory(final BuilderConfiguration config,
110 final FieldInfoFactory infoFactory,
111 final GroupNaming groupNaming,
112 final SourceGenerator sourceGenerator) {
113 super(config, infoFactory, groupNaming, sourceGenerator);
114
115 if (getConfig().generateExtraCollectionMethods()) {
116 this.getInfoFactory().setCreateExtraMethods(true);
117 }
118 String suffix = getConfig().getProperty(CollectionInfo.REFERENCE_SUFFIX_PROPERTY, null);
119 this.getInfoFactory().setReferenceMethodSuffix(suffix);
120
121 if (getConfig().boundPropertiesEnabled()) {
122 this.getInfoFactory().setBoundProperties(true);
123 }
124 }
125
126
127
128
129
130
131
132
133
134 public FieldInfo createFieldInfoForAny(final Wildcard any, final boolean useJava50) {
135 if (any == null) {
136 return null;
137 }
138
139
140 if (any.isAttributeWildcard()) {
141 return null;
142 }
143
144 XSType xsType = new XSClass(SGTypes.OBJECT, "any");
145 String vName = "_anyObject";
146
147
148
149 String xmlName = null;
150 FieldInfo result = null;
151
152 if (any.getMaxOccurs() > 1 || any.getMaxOccurs() < 0) {
153 result = this.getInfoFactory().createCollection(xsType, vName, "anyObject", getJavaNaming(), useJava50);
154 XSListType xsList = ((CollectionInfo) result).getXSList();
155 xsList.setMinimumSize(any.getMinOccurs());
156 xsList.setMaximumSize(any.getMaxOccurs());
157 } else {
158 result = this.getInfoFactory().createFieldInfo(xsType, vName);
159 }
160
161 if (result.hasNature(XMLInfoNature.class.getName())) {
162 XMLInfoNature xmlNature = new XMLInfoNature(result);
163
164 if (any.getMinOccurs() > 0) {
165 xmlNature.setRequired(true);
166 } else {
167 xmlNature.setRequired(false);
168 }
169
170 xmlNature.setNodeName(xmlName);
171
172
173
174
175 if (any.getNamespaces().hasMoreElements()) {
176 String nsURI = (String) any.getNamespaces().nextElement();
177 if (nsURI.length() > 0) {
178 if (nsURI.equals("##targetNamespace")) {
179 Schema schema = any.getSchema();
180 if (schema != null) {
181 xmlNature.setNamespaceURI(schema.getTargetNamespace());
182 }
183 } else if (!nsURI.startsWith("##")) {
184 xmlNature.setNamespaceURI(nsURI);
185 }
186 }
187 }
188 }
189
190 return result;
191 }
192
193
194
195
196
197
198 public FieldInfo createFieldInfoForChoiceValue() {
199 String fieldName = "_choiceValue";
200
201
202
203 XSType xsType = new XSClass(SGTypes.OBJECT, "any");
204 FieldInfo fInfo = null;
205 fInfo = this.getInfoFactory().createFieldInfo(xsType, fieldName);
206 fInfo.setComment("Internal choice value storage");
207 fInfo.setTransient(true);
208 fInfo.setMethods(FieldInfo.READ_METHOD);
209
210 if (fInfo.hasNature(XMLInfoNature.class.getName())) {
211 XMLInfoNature xmlNature = new XMLInfoNature(fInfo);
212
213 xmlNature.setNodeType(NodeType.ELEMENT);
214 xmlNature.setRequired(false);
215 xmlNature.setNodeName("##any");
216 }
217
218 return fInfo;
219 }
220
221
222
223
224
225
226
227
228
229 public FieldInfo createFieldInfoForContent(final XMLBindingComponent component, final XSType xsType, final boolean useJava50) {
230 String fieldName = "content";
231 if (getConfig().useOldFieldNaming()) {
232 StringUtils.leftPad(fieldName, 1, '_');
233 }
234 if (component.getContentMemberName() != null) {
235 fieldName = component.getContentMemberName();
236 }
237 FieldInfo fInfo = null;
238 if (xsType.isCollection()) {
239 fInfo = this.getInfoFactory().createCollection(
240 ((XSListType) xsType).getContentType(), fieldName, null, getJavaNaming(), useJava50);
241 } else {
242 fInfo = this.getInfoFactory().createFieldInfo(xsType, fieldName);
243 }
244 fInfo.setComment("internal content storage");
245 if (xsType instanceof XSString) {
246 fInfo.setDefaultValue("\"\"");
247 }
248 if (fInfo.hasNature(XMLInfoNature.class.getName())) {
249 XMLInfoNature xmlNature = new XMLInfoNature(fInfo);
250 xmlNature.setNodeType(NodeType.TEXT);
251 xmlNature.setRequired(false);
252 xmlNature.setNodeName("#text");
253 }
254 return fInfo;
255 }
256
257
258
259
260
261
262
263
264
265 public FieldInfo createFieldInfo(final XMLBindingComponent component,
266 final ClassInfoResolver resolver, final boolean useJava50) {
267 String xmlName = component.getXMLName();
268 String memberName = component.getJavaMemberName();
269 if (getConfig().useOldFieldNaming()) {
270 if (!memberName.startsWith("_")) {
271 memberName = "_" + memberName;
272 }
273 }
274
275 XMLType xmlType = component.getXMLType();
276
277 ClassInfo classInfo = resolver.resolve(component);
278
279 XSType xsType = null;
280 FieldInfo fieldInfo = null;
281 boolean enumeration = false;
282 boolean simpleTypeCollection = false;
283
284 if (xmlType != null) {
285 if (xmlType.isSimpleType() ) {
286 SimpleType simpleType = (SimpleType) xmlType;
287
288 SimpleType baseType = null;
289 String derivationMethod = simpleType.getDerivationMethod();
290 if (derivationMethod != null) {
291 if (SchemaNames.RESTRICTION.equals(derivationMethod)) {
292 baseType = (SimpleType) simpleType.getBaseType();
293 }
294 }
295
296
297 if (simpleType.hasFacet(Facet.ENUMERATION)) {
298
299 enumeration = true;
300 if (resolver != null) {
301 classInfo = resolver.resolve(xmlType);
302 }
303 if (classInfo != null) {
304 XMLInfoNature xmlNature = new XMLInfoNature(classInfo);
305 xsType = xmlNature.getSchemaType();
306 }
307 } else if ((simpleType instanceof ListType) || (baseType instanceof ListType)) {
308 if (baseType != null) {
309 if (!baseType.isBuiltInType()) {
310 simpleTypeCollection = true;
311 }
312 } else {
313 if (!simpleType.isBuiltInType()) {
314 simpleTypeCollection = true;
315 }
316 }
317
318
319
320 ListType listType = (ListType) simpleType;
321 if (listType == null) {
322 listType = (ListType) baseType;
323 }
324 SimpleType itemType = listType.getItemType();
325 if (itemType.hasFacet(Facet.ENUMERATION)) {
326 ClassInfo itemClassInfo = resolver.resolve(itemType);
327 if (itemClassInfo != null) {
328 xsType = new XMLInfoNature(itemClassInfo).getSchemaType();
329 } else {
330 XMLBindingComponent temp = new XMLBindingComponent(
331 getConfig(), getGroupNaming());
332 temp.setBinding(component.getBinding());
333 temp.setView(itemType);
334 String packageName = temp.getJavaPackage();
335 if (packageName != null && packageName.length() > 0) {
336 packageName = packageName + "." + SourceGeneratorConstants.TYPES_PACKAGE;
337 } else {
338 packageName = SourceGeneratorConstants.TYPES_PACKAGE;
339 }
340 JClass tempClass = new JClass(packageName+ "." + temp.getJavaClassName(), getConfig().useOldFieldNaming());
341 xsType = new XSClass(tempClass);
342 xsType.setAsEnumerated(true);
343 }
344 }
345
346
347 }
348
349 if (xsType == null) {
350 xsType = component.getJavaType();
351 }
352 } else if (xmlType.isAnyType()) {
353
354 if (classInfo != null) {
355 XMLInfoNature xmlNature = new XMLInfoNature(classInfo);
356 xsType = xmlNature.getSchemaType();
357 }
358 if (xsType == null) {
359 xsType = new XSClass(SGTypes.OBJECT);
360 }
361 } else if (xmlType.isComplexType() && (xmlType.getName() != null)) {
362
363
364 if (getConfig().mappingSchemaType2Java()) {
365 XMLBindingComponent temp = new XMLBindingComponent(
366 getConfig(), getGroupNaming());
367 temp.setBinding(component.getBinding());
368 temp.setView(xmlType);
369 ClassInfo typeInfo = resolver.resolve(xmlType);
370 if (typeInfo != null) {
371
372
373
374 XMLInfoNature xmlNature = new XMLInfoNature(typeInfo);
375 xsType = xmlNature.getSchemaType();
376 } else {
377 String className = temp.getQualifiedName();
378 if (className != null) {
379 JClass jClass = new JClass(className,getConfig().useOldFieldNaming());
380 if (((ComplexType) xmlType).isAbstract()) {
381 jClass.getModifiers().setAbstract(true);
382 }
383 xsType = new XSClass(jClass);
384 className = null;
385 }
386 }
387 }
388 }
389 } else {
390 if (xsType == null) {
391 xsType = component.getJavaType();
392 }
393
394 if (xsType == null) {
395
396
397 switch (component.getAnnotated().getStructureType()) {
398 case Structure.ATTRIBUTE:
399 AttributeDecl attribute = (AttributeDecl) component.getAnnotated();
400 if (!attribute.hasXMLType()) {
401 xsType = new XSClass(SGTypes.OBJECT);
402 }
403 break;
404 case Structure.ELEMENT:
405 ElementDecl element = (ElementDecl) component.getAnnotated();
406 if (!element.hasXMLType()) {
407 xsType = new XSClass(SGTypes.OBJECT);
408 }
409 break;
410 default:
411
412 break;
413 }
414 }
415 }
416
417
418 if (xsType == null) {
419 String className = component.getQualifiedName();
420 JClass jClass = new JClass(className, getConfig().useOldFieldNaming());
421 if (component.isAbstract()) {
422 jClass.getModifiers().setAbstract(true);
423 }
424 if (getConfig().isAutomaticConflictResolution()) {
425 getSourceGenerator().getXMLInfoRegistry().bind(jClass,
426 component, "field");
427 }
428 xsType = new XSClass(jClass);
429 if (xmlType != null && xmlType.isComplexType()) {
430 ComplexType complexType = (ComplexType) xmlType;
431 if (complexType.isAbstract() || getConfig().mappingSchemaElement2Java()) {
432 jClass.getModifiers().setAbstract(true);
433 }
434 }
435 className = null;
436 }
437
438
439
440 int maxOccurs = component.getUpperBound();
441 int minOccurs = component.getLowerBound();
442 if (simpleTypeCollection
443 || ((maxOccurs < 0 || maxOccurs > 1) && !this.isChoice(component))) {
444 String vName = memberName + "List";
445
446
447
448
449 CollectionInfo cInfo;
450 cInfo = this.getInfoFactory().createCollection(xsType, vName, memberName,
451 component.getCollectionType(), getJavaNaming(), useJava50);
452
453 XSListType xsList = cInfo.getXSList();
454 if (!simpleTypeCollection) {
455 xsList.setMaximumSize(maxOccurs);
456 xsList.setMinimumSize(minOccurs);
457 } else {
458 if (xsList instanceof XSList) {
459 ((XSList) xsList).setDerivedFromXSList(true);
460 }
461 }
462 fieldInfo = cInfo;
463 } else {
464 switch (xsType.getType()) {
465 case XSType.ID_TYPE:
466 fieldInfo = this.getInfoFactory().createIdentity(memberName);
467 break;
468 case XSType.COLLECTION:
469 case XSType.IDREFS_TYPE:
470 case XSType.NMTOKENS_TYPE:
471 String collectionName = component.getCollectionType();
472 XSType contentType = ((XSListType) xsType).getContentType();
473 fieldInfo = this.getInfoFactory().createCollection(contentType,
474 memberName, memberName,
475 collectionName, getJavaNaming(), useJava50);
476 break;
477 default:
478 fieldInfo = this.getInfoFactory().createFieldInfo(xsType, memberName);
479 break;
480 }
481 }
482
483
484 XMLInfoNature xmlNature = new XMLInfoNature(fieldInfo);
485 xmlNature.setNodeName(xmlName);
486 xmlNature.setRequired(minOccurs > 0);
487 switch (component.getAnnotated().getStructureType()) {
488 case Structure.ELEMENT:
489 xmlNature.setNodeType(NodeType.ELEMENT);
490 break;
491 case Structure.ATTRIBUTE:
492 xmlNature.setNodeType(NodeType.ATTRIBUTE);
493 break;
494 case Structure.MODELGROUP:
495 case Structure.GROUP:
496 xmlNature.setNodeName(XMLInfo.CHOICE_NODE_NAME_ERROR_INDICATION);
497 fieldInfo.setContainer(true);
498 break;
499 default:
500 break;
501 }
502
503
504 String nsURI = component.getTargetNamespace();
505 if ((nsURI != null) && (nsURI.length() > 0)) {
506 xmlNature.setNamespaceURI(nsURI);
507
508
509 }
510
511
512 handleDefaultValue(component, classInfo, xsType, fieldInfo, enumeration);
513
514
515 if (component.isNillable()) {
516 fieldInfo.setNillable(true);
517 }
518
519
520 String comment = createComment(component.getAnnotated());
521 if (comment != null) {
522 fieldInfo.setComment(comment);
523 }
524
525
526 if (component.getXMLFieldHandler() != null) {
527 fieldInfo.setXMLFieldHandler(component.getXMLFieldHandler());
528 }
529
530 if (component.getValidator() != null) {
531 fieldInfo.setValidator(component.getValidator());
532 }
533
534 if (component.getVisiblity() != null) {
535 String visibility = component.getVisiblity();
536 fieldInfo.setVisibility(visibility);
537 }
538
539
540 switch (component.getAnnotated().getStructureType()) {
541 case Structure.ELEMENT:
542 ElementDecl elementDeclaration = (ElementDecl) component.getAnnotated();
543 if (elementDeclaration.isReference()) {
544 elementDeclaration = elementDeclaration.getReference();
545 }
546 Enumeration<ElementDecl> possibleSubstitutes = elementDeclaration.getSubstitutionGroupMembers();
547 if (possibleSubstitutes.hasMoreElements()) {
548 List<String> substitutionGroupMembers = new ArrayList<String>();
549 while (possibleSubstitutes.hasMoreElements()) {
550 ElementDecl substitute = possibleSubstitutes.nextElement();
551 substitutionGroupMembers.add(substitute.getName());
552 }
553 fieldInfo.setSubstitutionGroupMembers(substitutionGroupMembers);
554 }
555 default:
556 }
557
558 return fieldInfo;
559 }
560
561
562
563
564
565
566
567
568
569 private boolean isChoice(final XMLBindingComponent component) {
570 Group group = this.getGroup(component.getAnnotated());
571 if (group == null || group.getOrder() == null) {
572 return false;
573 }
574
575 return group.getOrder() == Order.choice;
576 }
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591 private Group getGroup(final Structure structure) {
592 if (structure == null) {
593 return null;
594 }
595
596 if (structure.getStructureType() == Structure.GROUP) {
597 return (Group) structure;
598 }
599
600 return null;
601 }
602
603
604
605
606
607
608
609
610
611 private void handleDefaultValue(final XMLBindingComponent component, final ClassInfo classInfo,
612 final XSType xsType, final FieldInfo fieldInfo, final boolean enumeration) {
613
614 String value = component.getValue();
615 if (value == null) {
616 return;
617 }
618
619 value = adjustDefaultValue(xsType, value);
620
621 if (value.length() == 0) {
622 value = "\"\"";
623 }
624
625
626
627
628
629 if (xsType.getJType().toString().equals("java.lang.String")) {
630 char ch = value.charAt(0);
631 if (ch != '\'' && ch != '\"') {
632 value = '\"' + value + '\"';
633 }
634
635 StringBuffer buffer = new StringBuffer(value.length());
636 for (int i = 0; i < value.length(); i++) {
637 char character = value.charAt(i);
638 switch(character) {
639 case '\n':
640 buffer.append("\\n");
641 break;
642 default:
643 buffer.append(character);
644 }
645 }
646 value = buffer.toString();
647 } else if (enumeration) {
648 JType jType = (classInfo != null) ? classInfo.getJClass() : xsType.getJType();
649 if (getSourceGenerator().useJava5Enums()) {
650 value = jType.getName() + ".fromValue(\"" + value + "\")";
651 } else {
652 value = jType.getName() + ".valueOf(\"" + value + "\")";
653 }
654 } else if (xsType.getJType().isArray()) {
655 JType componentType = ((JArrayType) xsType.getJType()).getComponentType();
656 if (componentType.isPrimitive()) {
657 JPrimitiveType primitive = (JPrimitiveType) componentType;
658 value = "new " + primitive.getName() + "[] { "
659 + primitive.getWrapperName() + ".valueOf(\"" + value
660 + "\")." + primitive.getName() + "Value() }";
661 } else {
662 value = "new " + componentType.getName() + "[] { "
663 + componentType.getName() + ".valueOf(\"" + value + "\") }";
664
665 }
666 } else if (!(xsType.getJType().isPrimitive())) {
667 if (xsType.isDateTime()) {
668
669 if (xsType.getType() == XSType.DATETIME_TYPE) {
670
671
672 value = "new org.exolab.castor.types.DateTime(\"" + value + "\").toDate()";
673 } else {
674 value = "new " + xsType.getJType().getName() + "(\"" + value + "\")";
675 }
676 } else {
677
678 value = "new " + xsType.getJType().getName() + "(\"" + value + "\")";
679 }
680 }
681
682 if (component.isFixed()) {
683 fieldInfo.setFixedValue(value);
684 } else {
685 fieldInfo.setDefaultValue(value);
686 }
687 }
688
689
690
691
692
693
694
695
696
697 private String adjustDefaultValue(final XSType xsType, final String value) {
698 switch (xsType.getType()) {
699 case XSType.FLOAT_TYPE:
700 return value + 'f';
701 case XSType.BOOLEAN_TYPE:
702 Boolean bool = new Boolean(value);
703 return bool.toString();
704 default:
705 break;
706 }
707 return value;
708 }
709
710 }