View Javadoc
1   /*
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Intalio, Inc.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Intalio, Inc. Exolab is a registered
23   *    trademark of Intalio, Inc.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2002-2004 (C) Intalio Inc. All Rights Reserved.
42   *
43   * Any portions of this file developed by Keith Visco after Jan 19 2005
44   * are Copyright (C) 2005 Keith Visco. All Rights Reserverd.
45   *
46   *
47   * $Id$
48   */
49  package org.exolab.castor.builder.binding;
50  
51  import java.util.Enumeration;
52  
53  import org.apache.commons.logging.Log;
54  import org.apache.commons.logging.LogFactory;
55  import org.exolab.castor.builder.BindingComponent;
56  import org.exolab.castor.builder.BuilderConfiguration;
57  import org.exolab.castor.builder.GroupNaming;
58  import org.exolab.castor.builder.TypeConversion;
59  import org.exolab.castor.builder.binding.xml.ClassType;
60  import org.exolab.castor.builder.binding.xml.ComponentBindingType;
61  import org.exolab.castor.builder.binding.xml.ComponentBindingTypeChoice;
62  import org.exolab.castor.builder.binding.xml.EnumBindingType;
63  import org.exolab.castor.builder.binding.xml.FieldType;
64  import org.exolab.castor.builder.binding.xml.Interface;
65  import org.exolab.castor.builder.binding.xml.NamingXMLType;
66  import org.exolab.castor.builder.binding.xml.types.FieldTypeVisibilityType;
67  import org.exolab.castor.builder.types.XSClass;
68  import org.exolab.castor.builder.types.XSType;
69  import org.exolab.castor.xml.schema.Annotated;
70  import org.exolab.castor.xml.schema.AttributeDecl;
71  import org.exolab.castor.xml.schema.ComplexType;
72  import org.exolab.castor.xml.schema.ContentModelGroup;
73  import org.exolab.castor.xml.schema.ElementDecl;
74  import org.exolab.castor.xml.schema.Form;
75  import org.exolab.castor.xml.schema.Group;
76  import org.exolab.castor.xml.schema.ModelGroup;
77  import org.exolab.castor.xml.schema.Schema;
78  import org.exolab.castor.xml.schema.SimpleType;
79  import org.exolab.castor.xml.schema.Structure;
80  import org.exolab.castor.xml.schema.XMLType;
81  import org.exolab.javasource.JClass;
82  
83  /**
84   * This class is the implementation of BindingComponent from an XML Schema point
85   * of view. This specific implementation wraps an XML Schema annotated
86   * structure.
87   * <p>
88   * The XML Schema structure can be only of four different types:
89   * <ul>
90   *   <li>Element: it represents an XML Schema element.</li>
91   *   <li>ComplexType: it represents an XML Schema complexType.</li>
92   *   <li>ModelGroup: it represents an XML Schema Model group definition.</li>
93   *   <li>Group: it represents an XML Schema Model Group.</li>
94   * </ul>
95   * <p>
96   * The three first items can be customized using a binding file. Thus the
97   * XMLBindingComponent class takes into account the presence or not of a custom
98   * binding document in the computation of the needed information for the Source
99   * Generator to generate java classes from an XML Schema.
100  * <p>
101  * The customizable items are detailled in the binding file documentation.
102  * <p>
103  * This class acts like a <i>window</i> on a particular XML Schema structure
104  * that the user controls by changing the view on the Annotated Structure he is
105  * interested in.
106  * <p>
107  *
108  * @see org.exolab.castor.builder.BindingComponent
109  *
110  * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
111  * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
112  * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
113  */
114 public final class XMLBindingComponent implements BindingComponent {
115     
116     /**
117      * Log instance for all logging purposes.
118      */
119     private static final Log LOG = LogFactory.getLog(XMLBindingComponent.class);
120     
121    /**
122     * The Extended Binding used to retrieve the ComponentBindingType.
123     */
124    private ExtendedBinding _binding;
125 
126    /**
127     * The binding component to use, if no binding component is present then
128     * the default behavior applies.
129     */
130     private ComponentBindingType _compBinding;
131 
132     /**
133      * The BuilderConfiguration instance for obtaining default properties.
134      */
135     private BuilderConfiguration _config = null;
136 
137     /**
138      * The XML Schema Annotated structure encapsulated in that XMLBinding object.
139      */
140     private Annotated _annotated;
141 
142     /**
143      * The prefix used to generate the java names.
144      */
145     private String _prefix;
146 
147     /**
148      * The suffix used to generate the java names.
149      */
150     private String _suffix;
151 
152     /**
153      * The type of the XMLBinding. -1 is no component binding have been defined.
154      */
155     private short _type = -1;
156 
157     /**
158      * Caches of several computations.
159      */
160     private int _hashCode = -1;
161     private String _javaClassName = null;
162     private String _javaMemberName = null;
163     private String _javaPackage = null;
164     private FieldType _member = null;
165     private ClassType _class = null;
166     private Interface _interface = null;
167     private EnumBindingType _enum = null;
168     private Schema _schema = null;
169     private boolean _userSpecifiedMemberName = false;
170 
171     /**
172      * A GroupNaming helper class used to named anonymous groups.
173      */
174     private GroupNaming _groupNaming = null;
175 
176     /**
177      * Returns the current group naming scheme in use.
178      * @return The current group naming scheme
179      */
180     private synchronized GroupNaming getGroupNaming() {
181         return _groupNaming;
182     }
183 
184     /**
185      * Sets the group naming instance to be used.
186      * @param groupNaming The current group naming scheme to be used.
187      */
188     private void setGroupNaming(final GroupNaming groupNaming) {
189         _groupNaming = groupNaming;
190     }
191 
192     /**
193      * The TypeConversion to use when creating XSTypes from SimpleType.
194      */
195     private TypeConversion _typeConversion = null;
196 
197     private String _contentMemberName;
198 
199     /**
200      * Constructs an XMLBindingComponent from an XML Schema Component.
201      *
202      * @param config the BuilderConfiguration instance (must not be null).
203      * @param groupNaming The group naming scheme to be used.
204      */
205     public XMLBindingComponent(final BuilderConfiguration config, final GroupNaming groupNaming) {
206         if (config == null) {
207             String error = "The argument 'config' must not be null.";
208             throw new IllegalArgumentException(error);
209         }
210         _config = config;
211         _typeConversion = new TypeConversion(_config);
212         setGroupNaming(groupNaming);
213     } //-- XMLBindingComponent
214 
215     /**
216      * Returns the Binding Object Model on which this XMLBindingComponent will
217      * query information.
218      *
219      * @return the Extended Binding Object Model that wraps the information
220      *         located in a binding file
221      */
222     public ExtendedBinding getBinding() {
223         return _binding;
224     } //-- getBinding
225 
226     /**
227      * Sets the Binding Object Model on which this XMLBindingComponent will
228      * query information.
229      *
230      * @param binding the Extended Binding Object Model that wraps the
231      *        information located in a binding file
232      */
233     public void setBinding(final ExtendedBinding binding) {
234         _binding = binding;
235     }
236 
237    /**
238      * Sets the <i>window</i> on the given Annotated XML Schema structure. Once
239      * the window is set on a particular XML Schema structure all the
240      * information returned by this class are relative to that XML Schema
241      * structure.
242      *
243      * @param annotated an Annotated XML Schema structure.
244      * @see org.exolab.castor.xml.schema.Annotated
245      */
246     public void setView(final Annotated annotated) {
247         if (annotated == null) {
248             throw new IllegalArgumentException("The XML Schema annotated structure is null.");
249         }
250 
251         _annotated = annotated;
252 
253         //--reset all the variables
254         _javaClassName           = null;
255         _javaMemberName          = null;
256         _javaPackage             = null;
257         _schema                  = null;
258         _member                  = null;
259         _class                   = null;
260         _interface               = null;
261         _type                    = -1;
262         _prefix                  = null;
263         _suffix                  = null;
264         _userSpecifiedMemberName = false;
265         _compBinding             = null;
266 
267         //--look up for the particular componentBinding relative to the
268         //-- given annotated structure
269         if (_binding != null) {
270             _compBinding = _binding.getComponentBindingType(annotated);
271             NamingXMLType naming = _binding.getNamingXML();
272             if (naming != null) {
273                 switch (annotated.getStructureType()) {
274                     case Structure.COMPLEX_TYPE:
275                         if (naming.getComplexTypeName() != null) {
276                             _prefix = naming.getComplexTypeName().getPrefix();
277                             _suffix = naming.getComplexTypeName().getSuffix();
278                         }
279                         break;
280                     case Structure.ELEMENT:
281                         if (naming.getElementName() != null) {
282                             _prefix = naming.getElementName().getPrefix();
283                             _suffix = naming.getElementName().getSuffix();
284                         }
285                         break;
286                     case Structure.MODELGROUP:
287                         if (naming.getModelGroupName() != null) {
288                             _prefix = naming.getModelGroupName().getPrefix();
289                             _suffix = naming.getModelGroupName().getSuffix();
290                         }
291                         break;
292                     default:
293                         break;
294                 }
295             } //--naming != null;
296         } //--binding != null
297 
298         if (_compBinding != null) {
299             ComponentBindingTypeChoice choice = _compBinding.getComponentBindingTypeChoice();
300             if (choice.getInterface() != null) {
301                 _type = INTERFACE;
302                 _interface = choice.getInterface();
303             } else if (choice.getJavaClass() != null) {
304                 _type = CLASS;
305                 _class = choice.getJavaClass();
306             } else if (choice.getMember() != null) {
307                 _type = MEMBER;
308                 _member = choice.getMember();
309             } else if (choice.getEnumDef() != null) {
310                 _type = ENUM_TYPE;
311                 _enum = choice.getEnumDef();
312             } else if (choice.getContentMember() != null) {
313                 _type = CONTENT_MEMBER_TYPE;
314                 _contentMemberName = choice.getContentMember().getName();
315             } else {
316                 String err = "Illegal Binding component:";
317                 err += "it does not define a class, an interface or a member binding.";
318                 throw new IllegalStateException(err);
319             }
320         }
321     } //--setView
322 
323    //--Object manipulation methods
324 
325     /**
326      * Returns true if the given Object is equal to this instance of
327      * XMLBindingComponent.
328      *
329      * @return true if the given Object is equal to this instance of
330      *         XMLBindingComponent.
331      * @param object {@inheritDoc}
332      * @see java.lang.Object#equals(java.lang.Object)
333      */
334     public boolean equals(final Object object) {
335         if (object == null) {
336             return false;
337         }
338 
339         boolean result = false;
340         if (object instanceof XMLBindingComponent) {
341             XMLBindingComponent temp = (XMLBindingComponent) object;
342             result = _annotated.equals(temp.getAnnotated());
343             if (_compBinding != null) {
344                 if (temp.getComponentBinding() != null) {
345                     result = result && (_compBinding.equals(temp.getComponentBinding()));
346                 } else {
347                     result = false;
348                 }
349             } else if (temp.getComponentBinding() != null) {
350                 result = false;
351             }
352         } else {
353            result = false;
354         }
355         return result;
356     }
357 
358     /**
359      * Returns the hashCode value for this object.
360      *
361      * @return the hashcode value for this object.
362      * @see java.lang.Object#hashCode()
363      */
364     public int hashCode() {
365         if (_hashCode == -1) {
366             int compBindingHash = 0;
367             if (_compBinding != null) {
368                compBindingHash = _compBinding.getName().hashCode();
369             }
370             //WARNING: THE CASTOR SOM doesn't override hashCode or equals
371             _hashCode = 37 * (_annotated.hashCode()) + compBindingHash;
372         }
373         return _hashCode;
374     }
375 
376     /**
377      * Returns the ComponentBinding used in that XMLBindingComponent
378      * to retrieve customized information.
379      *
380      * @return the ComponentBinding used in that XMLBinding.
381      */
382     protected ComponentBindingType getComponentBinding() {
383         return _compBinding;
384     }
385 
386     //--XML Schema information methods
387 
388     /**
389      * Returns the XML Schema annotated structure used in this XMLBindingComponent.
390      *
391      * @return the XML Schema annotated structure used in this XMLBindingComponent.
392      */
393     public Annotated getAnnotated() {
394         return _annotated;
395     }
396 
397     /**
398      * Returns true if the binding of this XMLBindingComponent will require the
399      * generation of 2 java classes. Indeed an a nested Model Group that can
400      * occur more than once is described by the SourceGenerator with a wrapper
401      * class.
402      *
403      * @return true if the binding of this XMLBindingComponent will require the
404      *         generation of 2 java classes.
405      */
406     public boolean createGroupItem() {
407         int maxOccurs = 0;
408         boolean result = false;
409         switch (_annotated.getStructureType()) {
410             case Structure.ELEMENT:
411                 XMLType type = ((ElementDecl) _annotated).getType();
412                 if (type.isComplexType()) {
413                     maxOccurs = ((ComplexType) type).getMaxOccurs();
414                     if (((maxOccurs > 1) || (maxOccurs < 0)) && (type.getName() == null)) {
415                         result = true;
416                     }
417                 }
418                 break;
419             case Structure.COMPLEX_TYPE:
420                 maxOccurs = ((ComplexType) _annotated).getMaxOccurs();
421                 if ((maxOccurs > 1) || (maxOccurs < 0)) {
422                     result = true;
423                 }
424                 break;
425             case Structure.MODELGROUP:
426             case Structure.GROUP:
427                 Group group = (Group) _annotated;
428                 maxOccurs = group.getMaxOccurs();
429                 if ((maxOccurs > 1) || (maxOccurs < 0)) {
430                     result = true;
431                 }
432                 break;
433             case Structure.ATTRIBUTE:
434             default:
435                 break;
436 
437         }
438         return result;
439     }
440 
441     /**
442      * Returns the schemaLocation of the parent schema of the wrapped structure.
443      *
444      * @return the schemaLocation of the parent schema of the wrapped structure.
445      */
446     public String getSchemaLocation() {
447         String location = null;
448         Schema schema = getSchema();
449         if (schema != null) {
450             location = schema.getSchemaLocation();
451         }
452 
453         return location;
454     }
455 
456     /**
457      * Returns the targetNamespace of the parent schema of the wrapped structure.
458      *
459      * @return the targetNamespace of the parent schema of the wrapped structure.
460      */
461     public String getTargetNamespace() {
462         String result = null;
463         Schema schema = null;
464         Form   form   = null;
465 
466         switch (_annotated.getStructureType()) {
467             case Structure.ATTRIBUTE:
468                 AttributeDecl attribute = (AttributeDecl) _annotated;
469                 //-- resolve reference
470                 if (attribute.isReference()) {
471                     attribute = attribute.getReference();
472                 }
473 
474                 schema = attribute.getSchema();
475 
476                 //-- top-level (use targetNamespace of schema)
477                 if (attribute.getParent() == schema) {
478                     break;
479                 }
480 
481                 //-- check form (qualified or unqualified)
482                 form = attribute.getForm();
483                 if (form == null) {
484                     form = schema.getAttributeFormDefault();
485                 }
486 
487                 if ((form == null) || form.isUnqualified()) {
488                     //-- no targetNamespace by default
489                     return null;
490                 }
491                 //-- use targetNamespace of schema
492                 break;
493             case Structure.ELEMENT:
494                 //--resolve reference?
495                 ElementDecl element = (ElementDecl) _annotated;
496                 if (element.isReference()) {
497                     element = element.getReference();
498                 }
499 
500                 schema = element.getSchema();
501                 //-- top-level (use targetNamespace of schema)
502                 if (element.getParent() == schema) {
503                     break;
504                 }
505 
506                 //-- check form (qualified or unqualified)
507                 form = element.getForm();
508                 if (form == null) {
509                     form = schema.getElementFormDefault();
510                 }
511 
512                 //-- no targetNamespace by default
513                 if ((form == null) || form.isUnqualified()) {
514                     return null;
515                 }
516                 //-- use targetNamespace of schema
517                 break;
518             case Structure.COMPLEX_TYPE:
519                 ComplexType complexType = (ComplexType) _annotated;
520                 schema = complexType.getSchema();
521                 if (complexType.getParent() == schema) {
522                     break;
523                 }
524                 return null;
525             case Structure.SIMPLE_TYPE:
526                 SimpleType simpleType = (SimpleType) _annotated;
527                 schema = simpleType.getSchema();
528                 if (simpleType.getParent() == schema) {
529                     break;
530                 }
531                 return null;
532             default:
533                 break;
534         }
535         if (schema == null) {
536             schema = getSchema();
537         }
538 
539         if (schema != null) {
540             result = schema.getTargetNamespace();
541         }
542         return result;
543     } //-- getTargetNamespace
544 
545     /**
546      * Returns the underlying Schema of the wrapped structure.
547      *
548      * @return the parent schema of the wrapped structure.
549      */
550     public Schema getSchema() {
551         if (_schema != null) {
552             return _schema;
553         }
554 
555         switch (_annotated.getStructureType()) {
556             case Structure.ATTRIBUTE:
557                 //--resolve reference?
558                 AttributeDecl attribute = (AttributeDecl) _annotated;
559                 if (attribute.isReference()) {
560                     attribute = attribute.getReference();
561                 }
562                 _schema = attribute.getSchema();
563                 attribute = null;
564                 break;
565             case Structure.ELEMENT:
566                 //--resolve reference?
567                 ElementDecl element = (ElementDecl) _annotated;
568                 if (element.isReference()) {
569                     element = element.getReference();
570                 }
571                 _schema = element.getSchema();
572                 element = null;
573                 break;
574             case Structure.COMPLEX_TYPE:
575                 _schema = ((ComplexType) _annotated).getSchema();
576                 break;
577             case Structure.MODELGROUP:
578                 //--resolve reference?
579                 ModelGroup group = (ModelGroup) _annotated;
580                 if (group.isReference()) {
581                     group = group.getReference();
582                 }
583                 _schema = group.getSchema();
584                 group = null;
585                 break;
586             case Structure.GROUP:
587                 Structure parent = ((Group) _annotated).getParent();
588                 short structure = parent.getStructureType();
589                 while (structure == Structure.GROUP) {
590                     parent = ((Group) parent).getParent();
591                     structure = parent.getStructureType();
592                 }
593                 if (structure == Structure.COMPLEX_TYPE) {
594                     _schema = ((ComplexType) parent).getSchema();
595                 } else if (structure == Structure.MODELGROUP) {
596                     _schema = ((ModelGroup) parent).getSchema();
597                 }
598                 break;
599             case Structure.SIMPLE_TYPE:
600             case Structure.UNION:
601             case Structure.LIST:
602                 _schema = ((SimpleType) _annotated).getSchema();
603                 break;
604             default:
605                 break;
606         }
607 
608         return _schema;
609     }
610 
611     /**
612      * Returns the XMLType of the underlying structure. The XMLType of an
613      * element being its XML Schema type, the XMLType of a ComplexType being
614      * itself and the XMLType of an attribute being its XML Schema simpleType.
615      * Null is returned for a Model Group.
616      *
617      * @return the XMLType of the underlying structure.
618      */
619     public XMLType getXMLType() {
620         XMLType result = null;
621         switch (_annotated.getStructureType()) {
622             case Structure.ELEMENT:
623                 result = ((ElementDecl) _annotated).getType();
624                 break;
625             case Structure.COMPLEX_TYPE:
626                 result = ((ComplexType) _annotated);
627                 break;
628             case Structure.SIMPLE_TYPE:
629                 result = ((SimpleType) _annotated);
630                 break;
631             case Structure.ATTRIBUTE:
632                 result = ((AttributeDecl) _annotated).getSimpleType();
633                 break;
634             case Structure.MODELGROUP:
635             default:
636                 break;
637         }
638         return result;
639     }
640 
641     /**
642     * Returns the XML name declared in the XML Schema for this XMLBindingComponent.
643     *
644     * @return the XML name declared in the XML Schema for this XMLBindingComponent.
645     */
646     public String getXMLName() {
647         String result = null;
648 
649         if (_annotated != null) {
650         switch (_annotated.getStructureType()) {
651             case Structure.ELEMENT:
652                 result = ((ElementDecl) _annotated).getName();
653                 break;
654             case Structure.COMPLEX_TYPE:
655                 result = ((ComplexType) _annotated).getName();
656                 break;
657             case Structure.SIMPLE_TYPE:
658                 result = ((SimpleType) _annotated).getName();
659                 break;
660             case Structure.ATTRIBUTE:
661                 result = ((AttributeDecl) _annotated).getName();
662                 break;
663             case Structure.MODELGROUP:
664             case Structure.GROUP:
665                 result = ((Group) _annotated).getName();
666                 break;
667             default:
668                 break;
669 
670         }
671         }
672         return result;
673     }
674 
675     //--Implementation of BindingComponent
676 
677     /**
678      * Returns the value specified in the XML Schema for the XML Schema
679      * component wrapped in this XMLBindingComponent. The value returned is the
680      * <i>default</i> or <i>fixed</i> value for an Element or an Attribute.
681      *
682      * @return the value specified in the XML Schema for the XML Schema
683      *         annotated structure wrapped in this XMLBindingComponent.
684      */
685     public String getValue() {
686         String result = null;
687         switch (_annotated.getStructureType()) {
688             case Structure.ELEMENT:
689                 result = ((ElementDecl) _annotated).getDefaultValue();
690                 if (result == null) {
691                     result = ((ElementDecl) _annotated).getFixedValue();
692                 }
693                 break;
694             case Structure.ATTRIBUTE:
695                 result = ((AttributeDecl) _annotated).getDefaultValue();
696                 if (result == null) {
697                     result = ((AttributeDecl) _annotated).getFixedValue();
698                 }
699                 break;
700             case Structure.COMPLEX_TYPE:
701             case Structure.SIMPLE_TYPE:
702             case Structure.MODELGROUP:
703             default:
704                 break;
705         }
706 
707         return result;
708     }
709 
710    /**
711     * Returns a valid Java Class Name corresponding to this XMLBindingComponent.
712     * This name is not qualified, this is only a local Java class name.
713     *
714     * @return a valid Java Class Name corresponding to this XMLBindingComponent.
715     * This name is not qualified, this is only a local Java class name.
716     * @see #getQualifiedName
717     */
718     public String getJavaClassName() {
719         if (_javaClassName == null) {
720             String result = null;
721             //--is there a class name defined (local name)
722             if (_compBinding != null) {
723                 switch (getType()) {
724                     case CLASS:
725                         result =  _class.getName();
726                         break;
727                     case INTERFACE:
728                         result = _interface.getName();
729                         break;
730                     default:
731                         break;
732                 }
733             }
734 
735             if (result == null || result.length() <= 0) {
736                 //--is there a reference?
737                 if (_annotated != null && _annotated.getStructureType() == Structure.ELEMENT) {
738                     ElementDecl element = (ElementDecl) _annotated;
739                     if (element.isReference()) {
740                         Annotated temp = _annotated;
741                         setView(element.getReference());
742                         result = getJavaClassName();
743                         setView(temp);
744                         temp = null;
745                     } else if (_config.mappingSchemaType2Java()) {
746                         // deal with (global) element declarations in type mode,
747                         // where no Java class will be generated per definition;
748                         // in this case, the class name to be used should be taken from the
749                         // underlying (complex) type
750                         XMLType xmlType = element.getType();
751                         if (xmlType != null && xmlType.isComplexType()) {
752                             ComplexType complexType = (ComplexType) xmlType;
753                             Annotated temp = _annotated;
754                             setView(complexType);
755                             result = getJavaClassName();
756                             setView(temp);
757                         }
758                     }
759                     element = null;
760                 }
761 
762                 //--Still null?
763                 if (result == null || result.length() <= 0) {
764                     //--create the name
765                     result = getXMLName();
766                     //--create a java name for an anonymous group
767                     if (result == null
768                             && _annotated != null
769                             && (_annotated.getStructureType() == Structure.GROUP
770                                     || _annotated.getStructureType() == Structure.MODELGROUP)) {
771                         GroupNaming groupNaming = getGroupNaming();
772                         result = groupNaming.createClassName((Group) _annotated, getJavaPackage());
773                         if (result == null) {
774                             String err = "Unable to create name for group.";
775                             throw new IllegalStateException(err);
776                         }
777                     }
778 
779                     if (_prefix != null) {
780                         result = _prefix + result;
781                     }
782                     if (_suffix != null) {
783                         result = result + _suffix;
784                     }
785                 }
786             }
787 
788             _javaClassName = _config.getJavaNaming().toJavaClassName(result);
789         }
790 
791         // TODO ADD A SWITCH TO DETERMINE WETHER OR NOT TO USE JAVA CONVENTIONS
792         //      FOR THE JAVA CLASS NAME (SEE JAXB)
793         return _javaClassName;
794     }
795 
796     /**
797      * Returns a valid Java Member Name corresponding to this XMLBindingComponent.
798      * This name is not qualified, this is only a local Java Member name.
799      *
800      * @return a valid Java Member Name corresponding to this XMLBindingComponent.
801      * This name is not qualified, this is only a local Java member name.
802      * @see #getQualifiedName
803      */
804     public String getJavaMemberName() {
805         if (_javaMemberName == null) {
806             String result = null;
807             if (_compBinding != null) {
808                 switch (getType()) {
809                     case CLASS:
810                         result =  _class.getName();
811                         break;
812                     case INTERFACE:
813                         result = _interface.getName();
814                         break;
815                     case MEMBER:
816                         result = _member.getName();
817                         break;
818                     default:
819                         break;
820                 }
821             }
822 
823             if (result == null || result.length() <= 0) {
824                 Annotated temp = null;
825                 if (_annotated.getStructureType() == Structure.ATTRIBUTE) {
826                      AttributeDecl att = (AttributeDecl) _annotated;
827                      if (att.isReference()) {
828                          temp = _annotated;
829                          setView(att.getReference());
830                          result = getJavaMemberName();
831                          setView(temp);
832                      }
833                      att = null;
834                 } else if (_annotated.getStructureType() == Structure.ELEMENT) {
835                      ElementDecl element = (ElementDecl) _annotated;
836                      if (element.isReference()) {
837                          temp = _annotated;
838                          setView(element.getReference());
839                          result = getJavaMemberName();
840                          boolean userSpecified = _userSpecifiedMemberName;
841                          setView(temp);
842 
843                          //-- there might be more than once reference, so we
844                          //-- need to do a little counting here.
845                          if (!userSpecified) {
846                             String refName = element.getReferenceName();
847                             int count = 0;
848                             int index = 0;
849                             Structure structure = element.getParent();
850                             if (structure instanceof ContentModelGroup) {
851                                 ContentModelGroup cmg = (ContentModelGroup) structure;
852                                 Enumeration<Structure> enumeration = cmg.enumerate();
853                                 while (enumeration.hasMoreElements()) {
854                                     Structure tmpStruct = enumeration.nextElement();
855                                     if (tmpStruct.getStructureType() == Structure.ELEMENT) {
856                                         ElementDecl tmpDecl = (ElementDecl) tmpStruct;
857                                         if (tmpDecl.isReference()
858                                                 && tmpDecl.getReferenceName().equals(refName)) {
859                                             ++count;
860                                             if (tmpDecl == element) {
861                                                 index = count;
862                                             }
863                                         }
864                                     }
865                                 }
866                             }
867                             if (count > 1) {
868                                 result = result + index;
869                             }
870                          }
871                      }
872                      element = null;
873                 }
874                 temp = null;
875 
876                 //--Still null?
877                 if (result == null || result.length() <= 0) {
878                     //--create the name
879                     result = getXMLName();
880                     //--create a java name for an anonymous group
881                     if (result == null
882                         && (_annotated.getStructureType() == Structure.GROUP
883                             || _annotated.getStructureType() == Structure.MODELGROUP)) {
884                         result = getGroupNaming().createClassName(
885                                 (Group) _annotated, getJavaPackage());
886                         if (result == null) {
887                             String err = "Unable to create name for group.";
888                             throw new IllegalStateException(err);
889                         }
890                     }
891 
892                     if (_prefix != null) {
893                         result = _prefix + result;
894                     }
895                     if (_suffix != null) {
896                         result = result + _suffix;
897                     }
898                 }
899             } else {
900                 _userSpecifiedMemberName = true;
901             }
902             _javaMemberName = _config.getJavaNaming().toJavaMemberName(result);
903         }
904 
905         // TODO ADD A SWITCH TO DETERMINE WETHER OR NOT TO USE JAVA CONVENTIONS
906         //      FOR THE JAVA CLASS NAME (SEE JAXB)
907         return _javaMemberName;
908     }
909 
910     /**
911      * Returns the fully qualified name used for generating a java name that
912      * represents this XMLBindingComponent.
913      * <p>
914      * The fully qualified name is computed according the following priority
915      * order:
916      * <ul>
917      *   <li>If the XMLBinding wraps a class binding then the package name is the
918      *       name defined locally in the {@literal &lt;java-class>} element. More
919      *       precisely the package name will be the value of the attribute package.</li>
920      *   <li>Else the package name will be computed from the schemaLocation of
921      *       the parent schema.</li>
922      *   <li>Else the package name will be computed from the target namespace of
923      *       the parent schema.</li>
924      * </ul>
925      *
926      * Note: the computation of the namespace is a direct look-up for a defined
927      * mapping (Namespace, package) or (schema location, package).
928      *
929      * @return the fully qualified name used for generating a java name that
930      *         represents this XMLBindingComponent.
931      */
932     public String getQualifiedName() {
933         String result = getJavaClassName();
934         String packageName = getJavaPackage();
935         if (packageName != null && packageName.length() > 0) {
936              packageName += '.';
937              result = packageName + result;
938         }
939         return result;
940     }
941 
942     /**
943      * Returns the java package associated with this XML BindingComponent. The
944      * algorithm used to resolve the package is defined according to the
945      * following priorities:
946      * <ol>
947      *   <li>The package defined locally in the class declaration inside the
948      *       binding file is used.</li>
949      *   <li>If no package has been defined locally then a lookup to a defined
950      *       mapping {targetNamespace, package name} is performed.</li>
951      *   <li>If no package has been defined locally then a lookup to a defined
952      *       mapping {schema location, package name} is performed.</li>
953      * </ol>
954      *
955      * @return the java package associated with this XML BindingComponent.
956      */
957     public String getJavaPackage() {
958        if (_javaPackage == null) {
959             String packageName = null;
960             String schemaLocation = getSchemaLocation();
961             String targetNamespace = getTargetNamespace();
962             //-- adjust targetNamespace null -> ""
963             if (targetNamespace == null) {
964                 targetNamespace = "";
965             }
966 
967             if (_compBinding != null) {
968                 switch (getType()) {
969                     case CLASS:
970                         packageName = _class.getPackage();
971                         break;
972                     default:
973                         break;
974                 } //--switch
975             }
976 
977             if  (isPackageNameNotSet(packageName)) {
978                 
979                 if (isPackageNameNotSet(packageName)) {
980                     // look for a namespace mapping
981                     packageName = _config.lookupPackageByNamespace(targetNamespace);
982                 }
983 
984                 if (schemaLocation != null && isPackageNameNotSet(packageName)) {
985                     // look for schema location mapping
986                     packageName = _config.lookupPackageByLocation(schemaLocation);
987                 }
988                 
989             }
990             _javaPackage = packageName;
991         }
992         return _javaPackage;
993     }
994 
995     /**
996      * Indicates whether a package name has already been set.
997      * @param packageName The package name to analyse.
998      * @return True if the package name has been set correctly.
999      */
1000     private boolean isPackageNameNotSet(final String packageName) {
1001         return (packageName == null || packageName.length() == 0);
1002     }
1003 
1004    /**
1005      * Returns the upper bound of the collection that is generated from this
1006      * BindingComponent. The upper bound is a positive integer. -1 is returned
1007      * to indicate that the upper bound is unbounded.
1008      * <p>
1009      * In the case of an XML Schema component, the upper bound corresponds to
1010      * the XML Schema maxOccurs attribute, if any.
1011      *
1012      * @return an int representing the lower bound of the collection generated
1013      *         from this BindingComponent. -1 is returned to indicate that the
1014      *         upper bound is unbounded. 1 is the default value.
1015      */
1016     public int getUpperBound() {
1017         switch (_annotated.getStructureType()) {
1018 
1019             case Structure.ELEMENT:
1020                 return ((ElementDecl) _annotated).getMaxOccurs();
1021 
1022             case Structure.COMPLEX_TYPE:
1023                 return ((ComplexType) _annotated).getMaxOccurs();
1024 
1025             case Structure.GROUP:
1026             case Structure.MODELGROUP:
1027                 return ((Group) _annotated).getMaxOccurs();
1028 
1029             case Structure.ATTRIBUTE:
1030             default:
1031                break;
1032         }
1033         return 1;
1034     }
1035 
1036     /**
1037      * Returns the lower bound of the collection that is generated from this
1038      * BindingComponent. The lower bound is a positive integer. In the case of
1039      * an XML Schema component, it corresponds to the XML Schema minOccurs
1040      * attribute, if any.
1041      *
1042      * @return an int representing the lower bound of the collection generated
1043      *         from this BindingComponent. 0 is returned by default.
1044      */
1045     public int getLowerBound() {
1046         return getLowerBound(_annotated);
1047     }
1048 
1049     ////////METHODS RELATED TO A CLASS BINDING
1050 
1051     /**
1052      * Returns the name of a super class for the current XMLBinding. Null is
1053      * returned if this XMLBinding is not meant to be mapped to a java class.
1054      *
1055      * @return the name of a super class for the current XMLBinding. Null is
1056      *         returned if this XMLBinding is not meant to be mapped to a java
1057      *         class
1058      */
1059     public String getExtends() {
1060         if (getType() == CLASS) {
1061             return _class.getExtends();
1062         }
1063         return _config.getProperty(BuilderConfiguration.Property.SUPER_CLASS, null);
1064     } //-- getExtends
1065 
1066     /**
1067      * Returns an array of the different interface names implemented by the
1068      * class that will represent the current XMLBindingComponent. Null is
1069      * returned if no class binding is defined for the wrapped XML Schema
1070      * structure.
1071      *
1072      * @return array of interface names
1073      */
1074     public String[] getImplements() {
1075         if (getType() == CLASS) {
1076             return _class.getImplements();
1077         }
1078         return null;
1079     }
1080 
1081     /**
1082      * Returns true if bound properties must be generated for the class that
1083      * will represent the current XMLBindingComponent.
1084      *
1085      * @return true if bound properties must be generated for the class the
1086      *         class that will represent the current XMLBindingComponent.
1087      */
1088     public boolean hasBoundProperties() {
1089         if (getType() == CLASS && _class.hasBound()) {
1090             return _class.getBound();
1091         }
1092         return _config.boundPropertiesEnabled();
1093     }
1094 
1095     /**
1096      * Returns true if equal method must be generated for the class that will
1097      * represent the current XMLBindingComponent.
1098      *
1099      * @return true if equal method must be generated for the class the class
1100      *         that will represent the current XMLBindingComponent.
1101      */
1102     public boolean hasEquals() {
1103         if (getType() == CLASS && _class.hasEquals()) {
1104             return _class.getEquals();
1105         }
1106         return _config.equalsMethod();
1107     }
1108 
1109     /**
1110      * Returns true if the class that will represent the current
1111      * XMLBindingComponent must be abstract.
1112      *
1113      * @return true if the class that will represent the current
1114      *         XMLBindingComponent must be abstract.
1115      */
1116     public boolean isAbstract() {
1117         boolean result = false;
1118         if (getType() == CLASS && _class.hasAbstract()) {
1119             result = _class.getAbstract();
1120         }
1121 
1122         if (!result) {
1123             switch(_annotated.getStructureType()) {
1124                 case Structure.COMPLEX_TYPE:
1125                     ComplexType cType = (ComplexType) _annotated;
1126                     result = cType.isAbstract();
1127                     //-- if we're in element-centric mode, then all
1128                     //--  complexTypes are treated as abstract
1129                     result = result || _config.mappingSchemaElement2Java();
1130                     break;
1131                 case Structure.ELEMENT:
1132                     ElementDecl eDecl = (ElementDecl) _annotated;
1133                     result = eDecl.isAbstract();
1134                     break;
1135                 default:
1136                     break;
1137             }
1138         }
1139         return result;
1140     }
1141 
1142     /**
1143      * Returns true if the class that will represent the current XMLBindingComponent
1144      * must be final.
1145      *
1146      * @return true if the class that will represent the current XMLBindingComponent
1147      * must be final.
1148      */
1149     public boolean isFinal() {
1150         if (getType() == CLASS) {
1151             return _class.getFinal();
1152         }
1153         return false;
1154     }
1155 
1156     /**
1157      * Returns true if the wrapped XML Schema component is fixed (i.e the value
1158      * used is fixed).
1159      *
1160      * @return true if the wrapped XML Schema component is fixed (i.e the value
1161      * used is fixed).
1162      */
1163     public boolean isFixed() {
1164 
1165         switch (_annotated.getStructureType()) {
1166             case Structure.ELEMENT:
1167                 String fixed = ((ElementDecl) _annotated).getFixedValue();
1168                 return (fixed != null);
1169 
1170             case Structure.ATTRIBUTE:
1171                 return ((AttributeDecl) _annotated).isFixed();
1172 
1173             case Structure.GROUP:
1174             case Structure.COMPLEX_TYPE:
1175             case Structure.SIMPLE_TYPE:
1176             case Structure.MODELGROUP:
1177             default:
1178                 break;
1179         }
1180         return false;
1181     }
1182 
1183     /**
1184      * Returns true if the wrapped XML Schema component is nillable.
1185      *
1186      * @return true if the wrapped XML Schema component is nillable.
1187      */
1188     public boolean isNillable() {
1189         switch (_annotated.getStructureType()) {
1190             case Structure.ELEMENT:
1191                 return ((ElementDecl) _annotated).isNillable();
1192             default:
1193                 break;
1194         }
1195         return false;
1196     } //-- isNillable
1197 
1198     ////////METHODS RELATED TO A MEMBER BINDING
1199 
1200     /**
1201      * Returns true if the member represented by that XMLBindingComponent is to
1202      * be represented by an Object wrapper. For instance an int will be
1203      * represented by a java Integer if the property is set to true.
1204      *
1205      * @return true if the member represented by that XMLBindingComponent is to
1206      *         be represented by an Object wrapper.
1207      */
1208     public boolean useWrapper() {
1209         if (_type != BindingComponent.MEMBER) {
1210             return _config.usePrimitiveWrapper();
1211         }
1212 
1213         if (_member.hasWrapper()) {
1214             return _member.getWrapper();
1215         }
1216 
1217         return false;
1218     }
1219 
1220     /**
1221      * Returns the XSType that corresponds to the Java type chosen to represent
1222      * the XML Schema component represented by this XMLBindingComponent. An
1223      * XSType is an abstraction of a Java type used in the Source Generator. It
1224      * wraps a JType as well as the necessary methods to convert to/from String.
1225      * <p>
1226      * If a name of java type is specified then this name will have higher
1227      * priority than the simpleType resolution.
1228      *
1229      * @return an XSType
1230      */
1231     public XSType getJavaType() {
1232         //--no need for caching it is called only once
1233         XSType result = null;
1234         boolean useWrapper = useWrapper();
1235         XMLType type = getXMLType();
1236 
1237         if (type != null && type.isComplexType()) {
1238             if (_type == MEMBER && _member.getJavaType() != null) {
1239                 String javaType = _member.getJavaType();
1240                 if (javaType != null && javaType.length() > 0) {
1241                     result = TypeConversion.convertType(javaType);
1242                 }
1243             } else {
1244                 result = new XSClass(new JClass(getJavaClassName()));
1245             }
1246         } else {
1247             if (_type == MEMBER) {
1248                 String javaType = _member.getJavaType();
1249                 if (javaType != null && javaType.length() > 0) {
1250                     result = TypeConversion.convertType(javaType);
1251                 }
1252             }
1253         }
1254 
1255         if (result == null) {
1256             //--simpleType or AnyType
1257             if (type != null && type.isSimpleType()) {
1258                 String packageName = null;
1259                 String className = null;
1260                 if (((SimpleType) type).getSchema() != getSchema()) {
1261                     XMLBindingComponent comp = new XMLBindingComponent(_config, getGroupNaming());
1262                     comp.setBinding(_binding);
1263                     comp.setView(type);
1264                     packageName = comp.getJavaPackage();
1265                     if (comp.getClass() != null) {
1266                         className = comp.getJavaClassName();
1267                     }
1268                 } else {
1269                     packageName = getJavaPackage();
1270                     if (_class != null) {
1271                         className = getJavaClassName();
1272                     }
1273                 }
1274 
1275                 if ((packageName == null) || (packageName.length() == 0)) {
1276                     String ns = ((SimpleType) type).getSchema().getTargetNamespace();
1277                     packageName = _config.lookupPackageByNamespace(ns);
1278                 }
1279 
1280                 result = _typeConversion.convertType((SimpleType) type, 
1281                         packageName, useWrapper, _config.useJava50(), className);
1282             }
1283         }
1284 
1285         return result;
1286     }
1287 
1288     /**
1289      * Returns the collection name specified in the binding file. If no
1290      * collection was specified, null will be returned and the default
1291      * collection settings will be used.
1292      *
1293      * @return a string that represents the collection name specified in the
1294      *         binding file. If no collection was specified, null will be
1295      *         returned and the default collection settings will be used.
1296      */
1297     public String getCollectionType() {
1298         String result = null;
1299         if ((_type == MEMBER) && (_member.getCollection() != null)) {
1300             result = _member.getCollection().toString();
1301         }
1302         return result;
1303     }
1304 
1305    /**
1306     * Returns the fully qualified name of the Validator to use.
1307     *
1308     * @return the fully qualified name of the Validator to use.
1309     */
1310     public String getValidator() {
1311         if (_type == MEMBER) {
1312             return _member.getValidator();
1313         }
1314         return null;
1315     }
1316 
1317    /**
1318     * Returns the fully qualified name of the XMLFieldHandler to use.
1319     *
1320     * @return the fully qualified name of the XMLFieldHandler to use.
1321     */
1322     public String getXMLFieldHandler() {
1323         if (_type == MEMBER) {
1324             return _member.getHandler();
1325         }
1326         return null;
1327     }
1328 
1329     /**
1330      * Returns the visibility of the Java member to generate.
1331      *
1332      * @return the visibility of the Java member to generate.
1333      */
1334      public String getVisiblity() {
1335          if (_type == MEMBER) {
1336              final FieldTypeVisibilityType visibility = _member.getVisibility();
1337              if (visibility != null) {
1338                  return visibility.toString();
1339              }
1340              return "private";
1341          }
1342          return null;
1343      }
1344 
1345     /**
1346      * Returns the type of this component binding. A component binding can be of
1347      * three different types:
1348      * <ul>
1349      *   <li>Interface: it represents the binding to a java interface.</li>
1350      *   <li>Class: it represents the binding to a java class.</li>
1351      *   <li>Member: it represents the binding to a java class member.</li>
1352      * </ul>
1353      * <p>
1354      * -1 is returned if the component binding is null.
1355      *
1356      * @return the type of this component binding.
1357      */
1358     public short getType() {
1359         return _type;
1360     }
1361 
1362     /**
1363      * Returns the lower bound of the collection that is generated from this
1364      * BindingComponent. The lower bound is a positive integer. In the case of
1365      * an XML Schema component, it corresponds to the XML Schema minOccurs
1366      * attribute, if any.
1367      *
1368      * @param annotated an Annotated XML Schema structure.
1369      * @return an int representing the lower bound of the collection generated
1370      *         from this BindingComponent. 0 is returned by default.
1371      */
1372     private static int getLowerBound(final Annotated annotated) {
1373         switch (annotated.getStructureType()) {
1374             case Structure.ELEMENT:
1375                 return ((ElementDecl) annotated).getMinOccurs();
1376             case Structure.COMPLEX_TYPE:
1377                 return ((ComplexType) annotated).getMinOccurs();
1378             case Structure.MODELGROUP:
1379             case Structure.GROUP:
1380                 Group group = (Group) annotated;
1381                 //-- if the group is top-level, then we always return 0
1382                 Structure parent = group.getParent();
1383                 if (parent != null && parent.getStructureType() == Structure.SCHEMA) {
1384                     return 0;
1385                 }
1386                 int minOccurs = group.getMinOccurs();
1387                 //-- if minOccurs == 1, then check to see if all elements inside group are
1388                 //-- optional, if so, we return 0, not 1.
1389                 if (minOccurs == 1) {
1390                     Enumeration<Annotated> enumeration = group.enumerate();
1391                     while (enumeration.hasMoreElements()) {
1392                         if (getLowerBound(enumeration.nextElement()) != 0) {
1393                             return 1;
1394                         }
1395                     }
1396                     //-- if we make it here, all items in group have a lowerbound of 0, so
1397                     //-- the group can be considered optional
1398                     return 0;
1399                 }
1400                 return minOccurs;
1401 
1402             case Structure.ATTRIBUTE:
1403                 if (((AttributeDecl) annotated).isRequired()) {
1404                     return 1;
1405                 }
1406                 break;
1407             default:
1408                break;
1409         }
1410         return 0;
1411     } //-- getLowerBound
1412 
1413     /**
1414      * Returns the EnumBindingType instance for the active binding component.
1415      * @return The EnumBindingType instance
1416      */
1417     public EnumBindingType getEnumBinding() {
1418         return _enum;
1419     }
1420 
1421     /**
1422      * Returns the name 'override' of a content member as specified in a binding file.
1423      * @return the name of the name 'override' for the content member.
1424      */
1425     public String getContentMemberName() {
1426         return _contentMemberName;
1427     }
1428 
1429 } //-- class: XMLBindingComponent