View Javadoc
1   /*
2    * Redistribution and use of this software and associated documentation ("Software"), with or
3    * without modification, are permitted provided that the following conditions are met:
4    *
5    * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6    * must also contain a copy of this document.
7    *
8    * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9    * conditions and the following disclaimer in the documentation and/or other materials provided with
10   * the distribution.
11   *
12   * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13   * without prior written permission of Intalio, Inc. For written permission, please contact
14   * info@exolab.org.
15   *
16   * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17   * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18   * Intalio, Inc.
19   *
20   * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21   *
22   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29   * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * Copyright 1999-2004 (C) Intalio Inc. All Rights Reserved.
32   *
33   * This file was originally developed by Keith Visco during the course of employment at Intalio Inc.
34   * Portions of this file developed by Keith Visco after Jan 19 2005 are Copyright (C) 2005 Keith
35   * Visco. All Rights Reserverd.
36   *
37   * $Id$
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   * The "Factory" responsible for creating fields for the given schema components.
84   *
85   * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
86   * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
87   */
88  public final class MemberFactory extends BaseFactory {
89  
90    /**
91     * Creates a new MemberFactory using the given FieldInfo factory.
92     *
93     * @param config the BuilderConfiguration
94     * @param infoFactory the FieldInfoFactory to use
95     * @param groupNaming Grou pnaming scheme to be used.
96     * @param sourceGenerator Calling source generator
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   } // -- MemberFactory
112 
113   /**
114    * Creates a FieldInfo for content models that support "any" element.
115    *
116    * @param any the wildcard we will operate on
117    * @param useJava50 if true then we will generate code for Java 5
118    *
119    * @return the new FieldInfo
120    */
121   public FieldInfo createFieldInfoForAny(final Wildcard any, final boolean useJava50) {
122     if (any == null) {
123       return null;
124     }
125 
126     // --currently anyAttribute is not supported
127     if (any.isAttributeWildcard()) {
128       return null;
129     }
130 
131     XSType xsType = new XSClass(SGTypes.OBJECT, "any");
132     String vName = "_anyObject";
133     // if (getConfig().useOldFieldNaming()) {
134     // StringUtils.leftPad(vName, 1, '_');
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       // --LIMITATION:
161       // -- 1- we currently support only the FIRST namespace
162       // -- 2- ##other, ##any are not supported
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       } // --first namespace
176     }
177 
178     return result;
179   }
180 
181   /**
182    * Creates a FieldInfo to hold the value of a choice.
183    *
184    * @return the new FieldInfo
185    */
186   public FieldInfo createFieldInfoForChoiceValue() {
187     String fieldName = "_choiceValue";
188     // if (getConfig().useOldFieldNaming()) {
189     // StringUtils.leftPad(fieldName, 1, '_');
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    * Creates a FieldInfo for content.
211    * 
212    * @param component {@link XMLBindingComponent} instance for accessing binding information.
213    * @param xsType the type of content
214    * @param useJava50 if true, code will be generated for Java 5
215    *
216    * @return the new FieldInfo
217    */
218   public FieldInfo createFieldInfoForContent(final XMLBindingComponent component,
219       final XSType xsType, final boolean useJava50) {
220     String fieldName = "content";// new xsType()???
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    * Creates a FieldInfo object for the given XMLBindingComponent.
249    *
250    * @param component the XMLBindingComponent to create the FieldInfo for
251    * @param resolver resolver to use to find ClassInfo
252    * @param useJava50 if true, code will be generated for Java 5
253    * @return the FieldInfo for the given attribute declaration
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         // -- handle special case for enumerated types
287         if (simpleType.hasFacet(Facet.ENUMERATION)) {
288           // -- LOok FoR CLasSiNfO iF ReSoLvR is NoT NuLL
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           // handle special case where the list type uses an item type
309           // that has enumeration facets defined.
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         // -- Just treat as java.lang.Object.
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         // --if we use the type method then no class is output for
353         // --the element we are processing
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             // if we have not processed the <complexType> referenced
361             // by the ClassInfo yet, this will return null
362             // TODO find a way to resolve an unprocessed <complexType>
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       } // complexType
378     } else {
379       if (xsType == null) {
380         xsType = component.getJavaType();
381       }
382 
383       if (xsType == null) {
384         // -- patch for bug 1471 (No XMLType specified)
385         // -- treat unspecified type as anyType
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             // probably a model-group
401             break;
402         }
403       }
404     }
405 
406     // is the XSType found?
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     // create the fieldInfo
427     // check whether this should be a collection or not
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       // if xmlName is null it means that
434       // we are processing a container object (group)
435       // so we need to adjust the name of the members of the collection
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     // initialize the field
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     // -- handle namespace URI / prefix
490     String nsURI = component.getTargetNamespace();
491     if ((nsURI != null) && (nsURI.length() > 0)) {
492       xmlNature.setNamespaceURI(nsURI);
493       // TODO set the prefix used in the XML Schema
494       // in order to use it inside the Marshaling Framework
495     }
496 
497     // handle default value (if any is set)
498     handleDefaultValue(component, classInfo, xsType, fieldInfo, enumeration);
499 
500     // -- handle nillable values
501     if (component.isNillable()) {
502       fieldInfo.setNillable(true);
503     }
504 
505     // -- add annotated comments
506     String comment = createComment(component.getAnnotated());
507     if (comment != null) {
508       fieldInfo.setComment(comment);
509     }
510 
511     // --specific field handler or validator?
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     // deal with substitution groups
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    * Determines if the given <code>component</code> represents a choice.
550    * 
551    * @param component The XMLBindingComponent to check.
552    * @return <code>true</code> if and only if the given XMLBindingComponent represents a choice.
553    *         Otherwise returns <code>false</code>
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    * Returns the given <code>structure</code> as Group if it represents one.<br>
566    * <br>
567    * If the given <code>structure</code> has the structure type <code>GROUP</code> this method
568    * returns the given <code>structure</code> itself (casted to Group). If the structure is of any
569    * other type or is <code>null</code> this method will return <code>null</code>
570    * 
571    * @param structure The Structure to be returned as Group.
572    * @return The given <code>structure</code> if and only if it is a group; otherwise returns
573    *         <code>null</code>.
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    * Handle default or fixed value, if any is set.
589    * 
590    * @param component The component on which a default value is set
591    * @param classInfo The corresponding ClassInfo instance.
592    * @param xsType The schema type of the component.
593    * @param fieldInfo The FieldInfo into which to inject a default value
594    * @param enumeration If we are looking at an enumeration.
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     // TODO Need to change this...and to validate the value...to be done at reading time.
611 
612     // -- clean up value
613     // -- if the xsd field is mapped into a java.lang.String
614     if (xsType.getJType().toString().equals("java.lang.String")) {
615       char ch = value.charAt(0);
616       if (ch != '\'' && ch != '\"') {
617         value = '\"' + value + '\"';
618       }
619       // deals with special characters, e.g. line feed
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         // Castor marshals DATETIME_TYPE into java.util.Date(), so we need to convert it
652         if (xsType.getType() == XSType.DATETIME_TYPE) {
653           // FIXME This fails if the DateTIme has a time zone
654           // because we throw away the time zone in toDate()
655           value = "new org.exolab.castor.types.DateTime(\"" + value + "\").toDate()";
656         } else {
657           value = "new " + xsType.getJType().getName() + "(\"" + value + "\")";
658         }
659       } else {
660         // FIXME This works only if a constructor with String as parameter exists
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    * Adjusts the default value string represenation to reflect the semantics of various 'special'
674    * data types.
675    *
676    * @param xsType The XMl schems type of the value to adjust
677    * @param value The actual value to adjust
678    * @return an adjusted default value.
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 } // -- MemberFactory