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