0001: /*
0002: * Redistribution and use of this software and associated documentation
0003: * ("Software"), with or without modification, are permitted provided
0004: * that the following conditions are met:
0005: *
0006: * 1. Redistributions of source code must retain copyright
0007: * statements and notices. Redistributions must also contain a
0008: * copy of this document.
0009: *
0010: * 2. Redistributions in binary form must reproduce the
0011: * above copyright notice, this list of conditions and the
0012: * following disclaimer in the documentation and/or other
0013: * materials provided with the distribution.
0014: *
0015: * 3. The name "Exolab" must not be used to endorse or promote
0016: * products derived from this Software without prior written
0017: * permission of Intalio, Inc. For written permission,
0018: * please contact info@exolab.org.
0019: *
0020: * 4. Products derived from this Software may not be called "Exolab"
0021: * nor may "Exolab" appear in their names without prior written
0022: * permission of Intalio, Inc. Exolab is a registered
0023: * trademark of Intalio, Inc.
0024: *
0025: * 5. Due credit should be given to the Exolab Project
0026: * (http://www.exolab.org/).
0027: *
0028: * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
0029: * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
0030: * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
0031: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
0032: * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
0033: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0034: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
0035: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0036: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0037: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0038: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
0039: * OF THE POSSIBILITY OF SUCH DAMAGE.
0040: *
0041: * Copyright 2002-2004 (C) Intalio Inc. All Rights Reserved.
0042: *
0043: * Any portions of this file developed by Keith Visco after Jan 19 2005
0044: * are Copyright (C) 2005 Keith Visco. All Rights Reserverd.
0045: *
0046: *
0047: * $Id: XMLBindingComponent.java 7005 2007-06-02 08:50:04Z wguttmn $
0048: */
0049: package org.exolab.castor.builder.binding;
0050:
0051: import java.util.Enumeration;
0052:
0053: import org.apache.commons.logging.Log;
0054: import org.apache.commons.logging.LogFactory;
0055: import org.exolab.castor.builder.BindingComponent;
0056: import org.exolab.castor.builder.BuilderConfiguration;
0057: import org.exolab.castor.builder.GroupNaming;
0058: import org.exolab.castor.builder.TypeConversion;
0059: import org.exolab.castor.builder.binding.xml.ClassType;
0060: import org.exolab.castor.builder.binding.xml.ComponentBindingType;
0061: import org.exolab.castor.builder.binding.xml.ComponentBindingTypeChoice;
0062: import org.exolab.castor.builder.binding.xml.EnumBindingType;
0063: import org.exolab.castor.builder.binding.xml.FieldType;
0064: import org.exolab.castor.builder.binding.xml.Interface;
0065: import org.exolab.castor.builder.binding.xml.NamingXMLType;
0066: import org.exolab.castor.builder.binding.xml.types.FieldTypeVisibilityType;
0067: import org.exolab.castor.builder.types.XSClass;
0068: import org.exolab.castor.builder.types.XSType;
0069: import org.exolab.castor.xml.JavaNaming;
0070: import org.exolab.castor.xml.schema.Annotated;
0071: import org.exolab.castor.xml.schema.AttributeDecl;
0072: import org.exolab.castor.xml.schema.ComplexType;
0073: import org.exolab.castor.xml.schema.ContentModelGroup;
0074: import org.exolab.castor.xml.schema.ElementDecl;
0075: import org.exolab.castor.xml.schema.Form;
0076: import org.exolab.castor.xml.schema.Group;
0077: import org.exolab.castor.xml.schema.ModelGroup;
0078: import org.exolab.castor.xml.schema.Schema;
0079: import org.exolab.castor.xml.schema.SimpleType;
0080: import org.exolab.castor.xml.schema.Structure;
0081: import org.exolab.castor.xml.schema.XMLType;
0082: import org.exolab.javasource.JClass;
0083:
0084: /**
0085: * This class is the implementation of BindingComponent from an XML Schema point
0086: * of view. This specific implementation wraps an XML Schema annotated
0087: * structure.
0088: * <p>
0089: * The XML Schema structure can be only of four different types:
0090: * <ul>
0091: * <li>Element: it represents an XML Schema element.</li>
0092: * <li>ComplexType: it represents an XML Schema complexType.</li>
0093: * <li>ModelGroup: it represents an XML Schema Model group definition.</li>
0094: * <li>Group: it represents an XML Schema Model Group.</li>
0095: * </ul>
0096: * <p>
0097: * The three first items can be customized using a binding file. Thus the
0098: * XMLBindingComponent class takes into account the presence or not of a custom
0099: * binding document in the computation of the needed information for the Source
0100: * Generator to generate java classes from an XML Schema.
0101: * <p>
0102: * The customizable items are detailled in the binding file documentation.
0103: * <p>
0104: * This class acts like a <i>window</i> on a particular XML Schema structure
0105: * that the user controls by changing the view on the Annotated Structure he is
0106: * interested in.
0107: * <p>
0108: *
0109: * @see org.exolab.castor.builder.BindingComponent
0110: *
0111: * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
0112: * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
0113: * @version $Revision: 7005 $ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
0114: */
0115: public final class XMLBindingComponent implements BindingComponent {
0116:
0117: /**
0118: * Log instance for all logging purposes
0119: */
0120: private static final Log LOG = LogFactory
0121: .getLog(XMLBindingComponent.class);
0122:
0123: /**
0124: * The Extended Binding used to retrieve the ComponentBindingType.
0125: */
0126: private ExtendedBinding _binding;
0127:
0128: /**
0129: * The binding component to use, if no binding component is present then
0130: * the default behavior applies.
0131: */
0132: private ComponentBindingType _compBinding;
0133:
0134: /**
0135: * The BuilderConfiguration instance for obtaining default properties.
0136: */
0137: private BuilderConfiguration _config = null;
0138:
0139: /**
0140: * The XML Schema Annotated structure encapsulated in that XMLBinding object.
0141: */
0142: private Annotated _annotated;
0143:
0144: /**
0145: * The prefix used to generate the java names.
0146: */
0147: private String _prefix;
0148:
0149: /**
0150: * The suffix used to generate the java names.
0151: */
0152: private String _suffix;
0153:
0154: /**
0155: * The type of the XMLBinding. -1 is no component binding have been defined.
0156: */
0157: private short _type = -1;
0158:
0159: /**
0160: * Caches of several computations.
0161: */
0162: private int _hashCode = -1;
0163: private String _javaClassName = null;
0164: private String _javaMemberName = null;
0165: private String _javaPackage = null;
0166: private FieldType _member = null;
0167: private ClassType _class = null;
0168: private Interface _interface = null;
0169: private EnumBindingType _enum = null;
0170: private Schema _schema = null;
0171: private boolean _userSpecifiedMemberName = false;
0172:
0173: /**
0174: * A GroupNaming helper class used to named anonymous groups.
0175: */
0176: private GroupNaming _groupNaming = null;
0177:
0178: /**
0179: * Returns the current group naming scheme in use.
0180: * @return The current group naming scheme
0181: */
0182: private synchronized GroupNaming getGroupNaming() {
0183: return _groupNaming;
0184: }
0185:
0186: /**
0187: * Sets the group naming instance to be used.
0188: * @param groupNaming The current group naming scheme to be used.
0189: */
0190: private void setGroupNaming(final GroupNaming groupNaming) {
0191: _groupNaming = groupNaming;
0192: }
0193:
0194: /**
0195: * The TypeConversion to use when creating XSTypes from SimpleType.
0196: */
0197: private TypeConversion _typeConversion = null;
0198:
0199: private String _contentMemberName;
0200:
0201: /**
0202: * Constructs an XMLBindingComponent from an XML Schema Component.
0203: *
0204: * @param config the BuilderConfiguration instance (must not be null).
0205: * @param groupNaming The group naming scheme to be used.
0206: */
0207: public XMLBindingComponent(final BuilderConfiguration config,
0208: final GroupNaming groupNaming) {
0209: if (config == null) {
0210: String error = "The argument 'config' must not be null.";
0211: throw new IllegalArgumentException(error);
0212: }
0213: _config = config;
0214: _typeConversion = new TypeConversion(_config);
0215: setGroupNaming(groupNaming);
0216: } //-- XMLBindingComponent
0217:
0218: /**
0219: * Returns the Binding Object Model on which this XMLBindingComponent will
0220: * query information.
0221: *
0222: * @return the Extended Binding Object Model that wraps the information
0223: * located in a binding file
0224: */
0225: public ExtendedBinding getBinding() {
0226: return _binding;
0227: } //-- getBinding
0228:
0229: /**
0230: * Sets the Binding Object Model on which this XMLBindingComponent will
0231: * query information.
0232: *
0233: * @param binding the Extended Binding Object Model that wraps the
0234: * information located in a binding file
0235: */
0236: public void setBinding(final ExtendedBinding binding) {
0237: _binding = binding;
0238: }
0239:
0240: /**
0241: * Sets the <i>window</i> on the given Annotated XML Schema structure. Once
0242: * the window is set on a particular XML Schema structure all the
0243: * information returned by this class are relative to that XML Schema
0244: * structure.
0245: *
0246: * @param annotated an Annotated XML Schema structure.
0247: * @see org.exolab.castor.xml.schema.Annotated
0248: */
0249: public void setView(final Annotated annotated) {
0250: if (annotated == null) {
0251: throw new IllegalArgumentException(
0252: "The XML Schema annotated structure is null.");
0253: }
0254:
0255: _annotated = annotated;
0256:
0257: //--reset all the variables
0258: _javaClassName = null;
0259: _javaMemberName = null;
0260: _javaPackage = null;
0261: _schema = null;
0262: _member = null;
0263: _class = null;
0264: _interface = null;
0265: _type = -1;
0266: _prefix = null;
0267: _suffix = null;
0268: _userSpecifiedMemberName = false;
0269: _compBinding = null;
0270:
0271: //--look up for the particular componentBinding relative to the
0272: //-- given annotated structure
0273: if (_binding != null) {
0274: _compBinding = _binding.getComponentBindingType(annotated);
0275: NamingXMLType naming = _binding.getNamingXML();
0276: if (naming != null) {
0277: switch (annotated.getStructureType()) {
0278: case Structure.COMPLEX_TYPE:
0279: if (naming.getComplexTypeName() != null) {
0280: _prefix = naming.getComplexTypeName()
0281: .getPrefix();
0282: _suffix = naming.getComplexTypeName()
0283: .getSuffix();
0284: }
0285: break;
0286: case Structure.ELEMENT:
0287: if (naming.getElementName() != null) {
0288: _prefix = naming.getElementName().getPrefix();
0289: _suffix = naming.getElementName().getSuffix();
0290: }
0291: break;
0292: case Structure.MODELGROUP:
0293: if (naming.getModelGroupName() != null) {
0294: _prefix = naming.getModelGroupName()
0295: .getPrefix();
0296: _suffix = naming.getModelGroupName()
0297: .getSuffix();
0298: }
0299: break;
0300: default:
0301: break;
0302: }
0303: } //--naming != null;
0304: } //--binding != null
0305:
0306: if (_compBinding != null) {
0307: ComponentBindingTypeChoice choice = _compBinding
0308: .getComponentBindingTypeChoice();
0309: if (choice.getInterface() != null) {
0310: _type = INTERFACE;
0311: _interface = choice.getInterface();
0312: } else if (choice.getJavaClass() != null) {
0313: _type = CLASS;
0314: _class = choice.getJavaClass();
0315: } else if (choice.getMember() != null) {
0316: _type = MEMBER;
0317: _member = choice.getMember();
0318: } else if (choice.getEnumDef() != null) {
0319: _type = ENUM_TYPE;
0320: _enum = choice.getEnumDef();
0321: } else if (choice.getContentMember() != null) {
0322: _type = CONTENT_MEMBER_TYPE;
0323: _contentMemberName = choice.getContentMember()
0324: .getName();
0325: } else {
0326: String err = "Illegal Binding component:";
0327: err += "it does not define a class, an interface or a member binding.";
0328: throw new IllegalStateException(err);
0329: }
0330: }
0331: } //--setView
0332:
0333: //--Object manipulation methods
0334:
0335: /**
0336: * Returns true if the given Object is equal to this instance of
0337: * XMLBindingComponent.
0338: *
0339: * @return true if the given Object is equal to this instance of
0340: * XMLBindingComponent.
0341: * @param object {@inheritDoc}
0342: * @see java.lang.Object#equals(java.lang.Object)
0343: */
0344: public boolean equals(final Object object) {
0345: if (object == null) {
0346: return false;
0347: }
0348:
0349: boolean result = false;
0350: if (object instanceof XMLBindingComponent) {
0351: XMLBindingComponent temp = (XMLBindingComponent) object;
0352: result = _annotated.equals(temp.getAnnotated());
0353: if (_compBinding != null) {
0354: if (temp.getComponentBinding() != null) {
0355: result = result
0356: && (_compBinding.equals(temp
0357: .getComponentBinding()));
0358: } else {
0359: result = false;
0360: }
0361: } else if (temp.getComponentBinding() != null) {
0362: result = false;
0363: }
0364: } else {
0365: result = false;
0366: }
0367: return result;
0368: }
0369:
0370: /**
0371: * Returns the hashCode value for this object.
0372: *
0373: * @return the hashcode value for this object.
0374: * @see java.lang.Object#hashCode()
0375: */
0376: public int hashCode() {
0377: if (_hashCode == -1) {
0378: int compBindingHash = 0;
0379: if (_compBinding != null) {
0380: compBindingHash = _compBinding.getName().hashCode();
0381: }
0382: //WARNING: THE CASTOR SOM doesn't override hashCode or equals
0383: _hashCode = 37 * (_annotated.hashCode()) + compBindingHash;
0384: }
0385: return _hashCode;
0386: }
0387:
0388: /**
0389: * Returns the ComponentBinding used in that XMLBindingComponent
0390: * to retrieve customized information.
0391: *
0392: * @return the ComponentBinding used in that XMLBinding.
0393: */
0394: protected ComponentBindingType getComponentBinding() {
0395: return _compBinding;
0396: }
0397:
0398: //--XML Schema information methods
0399:
0400: /**
0401: * Returns the XML Schema annotated structure used in this XMLBindingComponent.
0402: *
0403: * @return the XML Schema annotated structure used in this XMLBindingComponent.
0404: */
0405: public Annotated getAnnotated() {
0406: return _annotated;
0407: }
0408:
0409: /**
0410: * Returns true if the binding of this XMLBindingComponent will require the
0411: * generation of 2 java classes. Indeed an a nested Model Group that can
0412: * occur more than once is described by the SourceGenerator with a wrapper
0413: * class.
0414: *
0415: * @return true if the binding of this XMLBindingComponent will require the
0416: * generation of 2 java classes.
0417: */
0418: public boolean createGroupItem() {
0419: int maxOccurs = 0;
0420: boolean result = false;
0421: switch (_annotated.getStructureType()) {
0422: case Structure.ELEMENT:
0423: XMLType type = ((ElementDecl) _annotated).getType();
0424: if (type.isComplexType()) {
0425: maxOccurs = ((ComplexType) type).getMaxOccurs();
0426: if (((maxOccurs > 1) || (maxOccurs < 0))
0427: && (type.getName() == null)) {
0428: result = true;
0429: }
0430: }
0431: break;
0432: case Structure.COMPLEX_TYPE:
0433: maxOccurs = ((ComplexType) _annotated).getMaxOccurs();
0434: if ((maxOccurs > 1) || (maxOccurs < 0)) {
0435: result = true;
0436: }
0437: break;
0438: case Structure.MODELGROUP:
0439: case Structure.GROUP:
0440: Group group = (Group) _annotated;
0441: maxOccurs = group.getMaxOccurs();
0442: if ((maxOccurs > 1) || (maxOccurs < 0)) {
0443: result = true;
0444: }
0445: break;
0446: case Structure.ATTRIBUTE:
0447: default:
0448: break;
0449:
0450: }
0451: return result;
0452: }
0453:
0454: /**
0455: * Returns the schemaLocation of the parent schema of the wrapped structure.
0456: *
0457: * @return the schemaLocation of the parent schema of the wrapped structure.
0458: */
0459: public String getSchemaLocation() {
0460: String location = null;
0461: Schema schema = getSchema();
0462: if (schema != null) {
0463: location = schema.getSchemaLocation();
0464: }
0465:
0466: return location;
0467: }
0468:
0469: /**
0470: * Returns the targetNamespace of the parent schema of the wrapped structure.
0471: *
0472: * @return the targetNamespace of the parent schema of the wrapped structure.
0473: */
0474: public String getTargetNamespace() {
0475: String result = null;
0476: Schema schema = null;
0477: Form form = null;
0478:
0479: switch (_annotated.getStructureType()) {
0480: case Structure.ATTRIBUTE:
0481: AttributeDecl attribute = (AttributeDecl) _annotated;
0482: //-- resolve reference
0483: if (attribute.isReference()) {
0484: attribute = attribute.getReference();
0485: }
0486:
0487: schema = attribute.getSchema();
0488:
0489: //-- top-level (use targetNamespace of schema)
0490: if (attribute.getParent() == schema) {
0491: break;
0492: }
0493:
0494: //-- check form (qualified or unqualified)
0495: form = attribute.getForm();
0496: if (form == null) {
0497: form = schema.getAttributeFormDefault();
0498: }
0499:
0500: if ((form == null) || form.isUnqualified()) {
0501: //-- no targetNamespace by default
0502: return null;
0503: }
0504: //-- use targetNamespace of schema
0505: break;
0506: case Structure.ELEMENT:
0507: //--resolve reference?
0508: ElementDecl element = (ElementDecl) _annotated;
0509: if (element.isReference()) {
0510: element = element.getReference();
0511: }
0512:
0513: schema = element.getSchema();
0514: //-- top-level (use targetNamespace of schema)
0515: if (element.getParent() == schema) {
0516: break;
0517: }
0518:
0519: //-- check form (qualified or unqualified)
0520: form = element.getForm();
0521: if (form == null) {
0522: form = schema.getElementFormDefault();
0523: }
0524:
0525: //-- no targetNamespace by default
0526: if ((form == null) || form.isUnqualified()) {
0527: return null;
0528: }
0529: //-- use targetNamespace of schema
0530: break;
0531: case Structure.COMPLEX_TYPE:
0532: ComplexType complexType = (ComplexType) _annotated;
0533: schema = complexType.getSchema();
0534: if (complexType.getParent() == schema) {
0535: break;
0536: }
0537: return null;
0538: case Structure.SIMPLE_TYPE:
0539: SimpleType simpleType = (SimpleType) _annotated;
0540: schema = simpleType.getSchema();
0541: if (simpleType.getParent() == schema) {
0542: break;
0543: }
0544: return null;
0545: default:
0546: break;
0547: }
0548: if (schema == null) {
0549: schema = getSchema();
0550: }
0551:
0552: if (schema != null) {
0553: result = schema.getTargetNamespace();
0554: }
0555: return result;
0556: } //-- getTargetNamespace
0557:
0558: /**
0559: * Returns the underlying Schema of the wrapped structure.
0560: *
0561: * @return the parent schema of the wrapped structure.
0562: */
0563: public Schema getSchema() {
0564: if (_schema != null) {
0565: return _schema;
0566: }
0567:
0568: switch (_annotated.getStructureType()) {
0569: case Structure.ATTRIBUTE:
0570: //--resolve reference?
0571: AttributeDecl attribute = (AttributeDecl) _annotated;
0572: if (attribute.isReference()) {
0573: attribute = attribute.getReference();
0574: }
0575: _schema = attribute.getSchema();
0576: attribute = null;
0577: break;
0578: case Structure.ELEMENT:
0579: //--resolve reference?
0580: ElementDecl element = (ElementDecl) _annotated;
0581: if (element.isReference()) {
0582: element = element.getReference();
0583: }
0584: _schema = element.getSchema();
0585: element = null;
0586: break;
0587: case Structure.COMPLEX_TYPE:
0588: _schema = ((ComplexType) _annotated).getSchema();
0589: break;
0590: case Structure.MODELGROUP:
0591: //--resolve reference?
0592: ModelGroup group = (ModelGroup) _annotated;
0593: if (group.isReference()) {
0594: group = group.getReference();
0595: }
0596: _schema = group.getSchema();
0597: group = null;
0598: break;
0599: case Structure.GROUP:
0600: Structure parent = ((Group) _annotated).getParent();
0601: short structure = parent.getStructureType();
0602: while (structure == Structure.GROUP) {
0603: parent = ((Group) parent).getParent();
0604: structure = parent.getStructureType();
0605: }
0606: if (structure == Structure.COMPLEX_TYPE) {
0607: _schema = ((ComplexType) parent).getSchema();
0608: } else if (structure == Structure.MODELGROUP) {
0609: _schema = ((ModelGroup) parent).getSchema();
0610: }
0611: break;
0612: case Structure.SIMPLE_TYPE:
0613: case Structure.UNION:
0614: _schema = ((SimpleType) _annotated).getSchema();
0615: break;
0616: default:
0617: break;
0618: }
0619:
0620: return _schema;
0621: }
0622:
0623: /**
0624: * Returns the XMLType of the underlying structure. The XMLType of an
0625: * element being its XML Schema type, the XMLType of a ComplexType being
0626: * itself and the XMLType of an attribute being its XML Schema simpleType.
0627: * Null is returned for a Model Group.
0628: *
0629: * @return the XMLType of the underlying structure.
0630: */
0631: public XMLType getXMLType() {
0632: XMLType result = null;
0633: switch (_annotated.getStructureType()) {
0634: case Structure.ELEMENT:
0635: result = ((ElementDecl) _annotated).getType();
0636: break;
0637: case Structure.COMPLEX_TYPE:
0638: result = ((ComplexType) _annotated);
0639: break;
0640: case Structure.SIMPLE_TYPE:
0641: result = ((SimpleType) _annotated);
0642: break;
0643: case Structure.ATTRIBUTE:
0644: result = ((AttributeDecl) _annotated).getSimpleType();
0645: break;
0646: case Structure.MODELGROUP:
0647: default:
0648: break;
0649: }
0650: return result;
0651: }
0652:
0653: /**
0654: * Returns the XML name declared in the XML Schema for this XMLBindingComponent.
0655: *
0656: * @return the XML name declared in the XML Schema for this XMLBindingComponent.
0657: */
0658: public String getXMLName() {
0659: String result = null;
0660:
0661: if (_annotated != null) {
0662: switch (_annotated.getStructureType()) {
0663: case Structure.ELEMENT:
0664: result = ((ElementDecl) _annotated).getName();
0665: break;
0666: case Structure.COMPLEX_TYPE:
0667: result = ((ComplexType) _annotated).getName();
0668: break;
0669: case Structure.SIMPLE_TYPE:
0670: result = ((SimpleType) _annotated).getName();
0671: break;
0672: case Structure.ATTRIBUTE:
0673: result = ((AttributeDecl) _annotated).getName();
0674: break;
0675: case Structure.MODELGROUP:
0676: case Structure.GROUP:
0677: result = ((Group) _annotated).getName();
0678: break;
0679: default:
0680: break;
0681:
0682: }
0683: }
0684: return result;
0685: }
0686:
0687: //--Implementation of BindingComponent
0688:
0689: /**
0690: * Returns the value specified in the XML Schema for the XML Schema
0691: * component wrapped in this XMLBindingComponent. The value returned is the
0692: * <i>default</i> or <i>fixed</i> value for an Element or an Attribute.
0693: *
0694: * @return the value specified in the XML Schema for the XML Schema
0695: * annotated structure wrapped in this XMLBindingComponent.
0696: */
0697: public String getValue() {
0698: String result = null;
0699: switch (_annotated.getStructureType()) {
0700: case Structure.ELEMENT:
0701: result = ((ElementDecl) _annotated).getDefaultValue();
0702: if (result == null) {
0703: result = ((ElementDecl) _annotated).getFixedValue();
0704: }
0705: break;
0706: case Structure.ATTRIBUTE:
0707: result = ((AttributeDecl) _annotated).getDefaultValue();
0708: if (result == null) {
0709: result = ((AttributeDecl) _annotated).getFixedValue();
0710: }
0711: break;
0712: case Structure.COMPLEX_TYPE:
0713: case Structure.SIMPLE_TYPE:
0714: case Structure.MODELGROUP:
0715: default:
0716: break;
0717: }
0718:
0719: return result;
0720: }
0721:
0722: /**
0723: * Returns a valid Java Class Name corresponding to this XMLBindingComponent.
0724: * This name is not qualified, this is only a local Java class name.
0725: *
0726: * @return a valid Java Class Name corresponding to this XMLBindingComponent.
0727: * This name is not qualified, this is only a local Java class name.
0728: * @see #getQualifiedName
0729: */
0730: public String getJavaClassName() {
0731: if (_javaClassName == null) {
0732: String result = null;
0733: //--is there a class name defined (local name)
0734: if (_compBinding != null) {
0735: switch (getType()) {
0736: case CLASS:
0737: result = _class.getName();
0738: break;
0739: case INTERFACE:
0740: result = _interface.getName();
0741: break;
0742: default:
0743: break;
0744: }
0745: }
0746:
0747: if (result == null || result.length() <= 0) {
0748: //--is there a reference?
0749: if (_annotated != null
0750: && _annotated.getStructureType() == Structure.ELEMENT) {
0751: ElementDecl element = (ElementDecl) _annotated;
0752: if (element.isReference()) {
0753: Annotated temp = _annotated;
0754: setView(element.getReference());
0755: result = getJavaClassName();
0756: setView(temp);
0757: temp = null;
0758: } else if (_config.mappingSchemaType2Java()) {
0759: // deal with (global) element declarations in type mode,
0760: // where no Java class will be generated per definition;
0761: // in this case, the class name to be used should be taken from the
0762: // underlying (complex) type
0763: XMLType xmlType = element.getType();
0764: if (xmlType != null && xmlType.isComplexType()) {
0765: ComplexType complexType = (ComplexType) xmlType;
0766: Annotated temp = _annotated;
0767: setView(complexType);
0768: result = getJavaClassName();
0769: setView(temp);
0770: }
0771: }
0772: element = null;
0773: }
0774:
0775: //--Still null?
0776: if (result == null || result.length() <= 0) {
0777: //--create the name
0778: result = getXMLName();
0779: //--create a java name for an anonymous group
0780: if (result == null
0781: && _annotated != null
0782: && (_annotated.getStructureType() == Structure.GROUP || _annotated
0783: .getStructureType() == Structure.MODELGROUP)) {
0784: GroupNaming groupNaming = getGroupNaming();
0785: result = groupNaming.createClassName(
0786: (Group) _annotated, getJavaPackage());
0787: if (result == null) {
0788: String err = "Unable to create name for group.";
0789: throw new IllegalStateException(err);
0790: }
0791: }
0792:
0793: if (_prefix != null) {
0794: result = _prefix + result;
0795: }
0796: if (_suffix != null) {
0797: result = result + _suffix;
0798: }
0799: }
0800: }
0801:
0802: _javaClassName = JavaNaming.toJavaClassName(result);
0803: }
0804:
0805: // TODO ADD A SWITCH TO DETERMINE WETHER OR NOT TO USE JAVA CONVENTIONS
0806: // FOR THE JAVA CLASS NAME (SEE JAXB)
0807: return _javaClassName;
0808: }
0809:
0810: /**
0811: * Returns a valid Java Member Name corresponding to this XMLBindingComponent.
0812: * This name is not qualified, this is only a local Java Member name.
0813: *
0814: * @return a valid Java Member Name corresponding to this XMLBindingComponent.
0815: * This name is not qualified, this is only a local Java member name.
0816: * @see #getQualifiedName
0817: */
0818: public String getJavaMemberName() {
0819: if (_javaMemberName == null) {
0820: String result = null;
0821: if (_compBinding != null) {
0822: switch (getType()) {
0823: case CLASS:
0824: result = _class.getName();
0825: break;
0826: case INTERFACE:
0827: result = _interface.getName();
0828: break;
0829: case MEMBER:
0830: result = _member.getName();
0831: break;
0832: default:
0833: break;
0834: }
0835: }
0836:
0837: if (result == null || result.length() <= 0) {
0838: Annotated temp = null;
0839: if (_annotated.getStructureType() == Structure.ATTRIBUTE) {
0840: AttributeDecl att = (AttributeDecl) _annotated;
0841: if (att.isReference()) {
0842: temp = _annotated;
0843: setView(att.getReference());
0844: result = getJavaMemberName();
0845: setView(temp);
0846: }
0847: att = null;
0848: } else if (_annotated.getStructureType() == Structure.ELEMENT) {
0849: ElementDecl element = (ElementDecl) _annotated;
0850: if (element.isReference()) {
0851: temp = _annotated;
0852: setView(element.getReference());
0853: result = getJavaMemberName();
0854: boolean userSpecified = _userSpecifiedMemberName;
0855: setView(temp);
0856:
0857: //-- there might be more than once reference, so we
0858: //-- need to do a little counting here.
0859: if (!userSpecified) {
0860: String refName = element.getReferenceName();
0861: int count = 0;
0862: int index = 0;
0863: Structure structure = element.getParent();
0864: if (structure instanceof ContentModelGroup) {
0865: ContentModelGroup cmg = (ContentModelGroup) structure;
0866: Enumeration enumeration = cmg
0867: .enumerate();
0868: while (enumeration.hasMoreElements()) {
0869: Structure tmpStruct = (Structure) enumeration
0870: .nextElement();
0871: if (tmpStruct.getStructureType() == Structure.ELEMENT) {
0872: ElementDecl tmpDecl = (ElementDecl) tmpStruct;
0873: if (tmpDecl.isReference()
0874: && tmpDecl
0875: .getReferenceName()
0876: .equals(refName)) {
0877: ++count;
0878: if (tmpDecl == element) {
0879: index = count;
0880: }
0881: }
0882: }
0883: }
0884: }
0885: if (count > 1) {
0886: result = result + index;
0887: }
0888: }
0889: }
0890: element = null;
0891: }
0892: temp = null;
0893:
0894: //--Still null?
0895: if (result == null || result.length() <= 0) {
0896: //--create the name
0897: result = getXMLName();
0898: //--create a java name for an anonymous group
0899: if (result == null
0900: && (_annotated.getStructureType() == Structure.GROUP || _annotated
0901: .getStructureType() == Structure.MODELGROUP)) {
0902: result = getGroupNaming().createClassName(
0903: (Group) _annotated, getJavaPackage());
0904: if (result == null) {
0905: String err = "Unable to create name for group.";
0906: throw new IllegalStateException(err);
0907: }
0908: }
0909:
0910: if (_prefix != null) {
0911: result = _prefix + result;
0912: }
0913: if (_suffix != null) {
0914: result = result + _suffix;
0915: }
0916: }
0917: } else {
0918: _userSpecifiedMemberName = true;
0919: }
0920: _javaMemberName = JavaNaming.toJavaMemberName(result);
0921: }
0922:
0923: // TODO ADD A SWITCH TO DETERMINE WETHER OR NOT TO USE JAVA CONVENTIONS
0924: // FOR THE JAVA CLASS NAME (SEE JAXB)
0925: return _javaMemberName;
0926: }
0927:
0928: /**
0929: * Returns the fully qualified name used for generating a java name that
0930: * represents this XMLBindingComponent.
0931: * <p>
0932: * The fully qualified name is computed according the following priority
0933: * order:
0934: * <ul>
0935: * <li>If the XMLBinding wraps a class binding then the package name is the
0936: * name defined locally in the {@literal <java-class>} element. More
0937: * precisely the package name will be the value of the attribute package.</li>
0938: * <li>Else the package name will be computed from the schemaLocation of
0939: * the parent schema.</li>
0940: * <li>Else the package name will be computed from the target namespace of
0941: * the parent schema.</li>
0942: * </ul>
0943: *
0944: * Note: the computation of the namespace is a direct look-up for a defined
0945: * mapping (Namespace, package) or (schema location, package).
0946: *
0947: * @return the fully qualified name used for generating a java name that
0948: * represents this XMLBindingComponent.
0949: */
0950: public String getQualifiedName() {
0951: String result = getJavaClassName();
0952: String packageName = getJavaPackage();
0953: if (packageName != null && packageName.length() > 0) {
0954: packageName += '.';
0955: result = packageName + result;
0956: }
0957: return result;
0958: }
0959:
0960: /**
0961: * Returns the java package associated with this XML BindingComponent. The
0962: * algorithm used to resolve the package is defined according to the
0963: * following priorities:
0964: * <ol>
0965: * <li>The package defined locally in the class declaration inside the
0966: * binding file is used.</li>
0967: * <li>If no package has been defined locally then a lookup to a defined
0968: * mapping {targetNamespace, package name} is performed.</li>
0969: * <li>If no package has been defined locally then a lookup to a defined
0970: * mapping {schema location, package name} is performed.</li>
0971: * </ol>
0972: *
0973: * @return the java package associated with this XML BindingComponent.
0974: */
0975: public String getJavaPackage() {
0976: if (_javaPackage == null) {
0977: String packageName = null;
0978: String schemaLocation = getSchemaLocation();
0979: String targetNamespace = getTargetNamespace();
0980: //-- adjust targetNamespace null -> ""
0981: if (targetNamespace == null) {
0982: targetNamespace = "";
0983: }
0984:
0985: if (_compBinding != null) {
0986: switch (getType()) {
0987: case CLASS:
0988: packageName = _class.getPackage();
0989: break;
0990: default:
0991: break;
0992: } //--switch
0993: }
0994:
0995: if (isPackageNameNotSet(packageName)) {
0996:
0997: if (isPackageNameNotSet(packageName)) {
0998: // look for a namespace mapping
0999: packageName = _config
1000: .lookupPackageByNamespace(targetNamespace);
1001: }
1002:
1003: if (schemaLocation != null
1004: && isPackageNameNotSet(packageName)) {
1005: // look for schema location mapping
1006: packageName = _config
1007: .lookupPackageByLocation(schemaLocation);
1008: }
1009:
1010: }
1011: _javaPackage = packageName;
1012: }
1013: return _javaPackage;
1014: }
1015:
1016: /**
1017: * Indicates whether a package name has already been set.
1018: * @param packageName The package name to analyse.
1019: * @return True if the package name has been set correctly.
1020: */
1021: private boolean isPackageNameNotSet(final String packageName) {
1022: return (packageName == null || packageName.length() == 0);
1023: }
1024:
1025: /**
1026: * Returns the upper bound of the collection that is generated from this
1027: * BindingComponent. The upper bound is a positive integer. -1 is returned
1028: * to indicate that the upper bound is unbounded.
1029: * <p>
1030: * In the case of an XML Schema component, the upper bound corresponds to
1031: * the XML Schema maxOccurs attribute, if any.
1032: *
1033: * @return an int representing the lower bound of the collection generated
1034: * from this BindingComponent. -1 is returned to indicate that the
1035: * upper bound is unbounded. 1 is the default value.
1036: */
1037: public int getUpperBound() {
1038: switch (_annotated.getStructureType()) {
1039:
1040: case Structure.ELEMENT:
1041: return ((ElementDecl) _annotated).getMaxOccurs();
1042:
1043: case Structure.COMPLEX_TYPE:
1044: return ((ComplexType) _annotated).getMaxOccurs();
1045:
1046: case Structure.GROUP:
1047: case Structure.MODELGROUP:
1048: return ((Group) _annotated).getMaxOccurs();
1049:
1050: case Structure.ATTRIBUTE:
1051: default:
1052: break;
1053: }
1054: return 1;
1055: }
1056:
1057: /**
1058: * Returns the lower bound of the collection that is generated from this
1059: * BindingComponent. The lower bound is a positive integer. In the case of
1060: * an XML Schema component, it corresponds to the XML Schema minOccurs
1061: * attribute, if any.
1062: *
1063: * @return an int representing the lower bound of the collection generated
1064: * from this BindingComponent. 0 is returned by default.
1065: */
1066: public int getLowerBound() {
1067: return getLowerBound(_annotated);
1068: }
1069:
1070: ////////METHODS RELATED TO A CLASS BINDING
1071:
1072: /**
1073: * Returns the name of a super class for the current XMLBinding. Null is
1074: * returned if this XMLBinding is not meant to be mapped to a java class.
1075: *
1076: * @return the name of a super class for the current XMLBinding. Null is
1077: * returned if this XMLBinding is not meant to be mapped to a java
1078: * class
1079: */
1080: public String getExtends() {
1081: if (getType() == CLASS) {
1082: return _class.getExtends();
1083: }
1084: return _config.getProperty(
1085: BuilderConfiguration.Property.SUPER_CLASS, null);
1086: } //-- getExtends
1087:
1088: /**
1089: * Returns an array of the different interface names implemented by the
1090: * class that will represent the current XMLBindingComponent. Null is
1091: * returned if no class binding is defined for the wrapped XML Schema
1092: * structure.
1093: *
1094: * @return array of interface names
1095: */
1096: public String[] getImplements() {
1097: if (getType() == CLASS) {
1098: return _class.getImplements();
1099: }
1100: return null;
1101: }
1102:
1103: /**
1104: * Returns true if bound properties must be generated for the class that
1105: * will represent the current XMLBindingComponent.
1106: *
1107: * @return true if bound properties must be generated for the class the
1108: * class that will represent the current XMLBindingComponent.
1109: */
1110: public boolean hasBoundProperties() {
1111: if (getType() == CLASS && _class.hasBound()) {
1112: return _class.getBound();
1113: }
1114: return _config.boundPropertiesEnabled();
1115: }
1116:
1117: /**
1118: * Returns true if equal method must be generated for the class that will
1119: * represent the current XMLBindingComponent.
1120: *
1121: * @return true if equal method must be generated for the class the class
1122: * that will represent the current XMLBindingComponent.
1123: */
1124: public boolean hasEquals() {
1125: if (getType() == CLASS && _class.hasEquals()) {
1126: return _class.getEquals();
1127: }
1128: return _config.equalsMethod();
1129: }
1130:
1131: /**
1132: * Returns true if the class that will represent the current
1133: * XMLBindingComponent must be abstract.
1134: *
1135: * @return true if the class that will represent the current
1136: * XMLBindingComponent must be abstract.
1137: */
1138: public boolean isAbstract() {
1139: boolean result = false;
1140: if (getType() == CLASS && _class.hasAbstract()) {
1141: result = _class.getAbstract();
1142: }
1143:
1144: if (!result) {
1145: switch (_annotated.getStructureType()) {
1146: case Structure.COMPLEX_TYPE:
1147: ComplexType cType = (ComplexType) _annotated;
1148: result = cType.isAbstract();
1149: //-- if we're in element-centric mode, then all
1150: //-- complexTypes are treated as abstract
1151: result = result || _config.mappingSchemaElement2Java();
1152: break;
1153: case Structure.ELEMENT:
1154: ElementDecl eDecl = (ElementDecl) _annotated;
1155: result = eDecl.isAbstract();
1156: break;
1157: default:
1158: break;
1159: }
1160: }
1161: return result;
1162: }
1163:
1164: /**
1165: * Returns true if the class that will represent the current XMLBindingComponent
1166: * must be final.
1167: *
1168: * @return true if the class that will represent the current XMLBindingComponent
1169: * must be final.
1170: */
1171: public boolean isFinal() {
1172: if (getType() == CLASS) {
1173: return _class.getFinal();
1174: }
1175: return false;
1176: }
1177:
1178: /**
1179: * Returns true if the wrapped XML Schema component is fixed (i.e the value
1180: * used is fixed).
1181: *
1182: * @return true if the wrapped XML Schema component is fixed (i.e the value
1183: * used is fixed).
1184: */
1185: public boolean isFixed() {
1186:
1187: switch (_annotated.getStructureType()) {
1188: case Structure.ELEMENT:
1189: String fixed = ((ElementDecl) _annotated).getFixedValue();
1190: return (fixed != null);
1191:
1192: case Structure.ATTRIBUTE:
1193: return ((AttributeDecl) _annotated).isFixed();
1194:
1195: case Structure.GROUP:
1196: case Structure.COMPLEX_TYPE:
1197: case Structure.SIMPLE_TYPE:
1198: case Structure.MODELGROUP:
1199: default:
1200: break;
1201: }
1202: return false;
1203: }
1204:
1205: /**
1206: * Returns true if the wrapped XML Schema component is nillable.
1207: *
1208: * @return true if the wrapped XML Schema component is nillable.
1209: */
1210: public boolean isNillable() {
1211: switch (_annotated.getStructureType()) {
1212: case Structure.ELEMENT:
1213: return ((ElementDecl) _annotated).isNillable();
1214: default:
1215: break;
1216: }
1217: return false;
1218: } //-- isNillable
1219:
1220: ////////METHODS RELATED TO A MEMBER BINDING
1221:
1222: /**
1223: * Returns true if the member represented by that XMLBindingComponent is to
1224: * be represented by an Object wrapper. For instance an int will be
1225: * represented by a java Integer if the property is set to true.
1226: *
1227: * @return true if the member represented by that XMLBindingComponent is to
1228: * be represented by an Object wrapper.
1229: */
1230: public boolean useWrapper() {
1231: if (_type != BindingComponent.MEMBER) {
1232: return _config.usePrimitiveWrapper();
1233: }
1234:
1235: if (_member.hasWrapper()) {
1236: return _member.getWrapper();
1237: }
1238:
1239: return false;
1240: }
1241:
1242: /**
1243: * Returns the XSType that corresponds to the Java type chosen to represent
1244: * the XML Schema component represented by this XMLBindingComponent. An
1245: * XSType is an abstraction of a Java type used in the Source Generator. It
1246: * wraps a JType as well as the necessary methods to convert to/from String.
1247: * <p>
1248: * If a name of java type is specified then this name will have higher
1249: * priority than the simpleType resolution.
1250: *
1251: * @return an XSType
1252: */
1253: public XSType getJavaType() {
1254: //--no need for caching it is called only once
1255: XSType result = null;
1256: boolean useWrapper = useWrapper();
1257: XMLType type = getXMLType();
1258:
1259: if (type != null && type.isComplexType()) {
1260: if (_type == MEMBER && _member.getJavaType() != null) {
1261: String javaType = _member.getJavaType();
1262: if (javaType != null && javaType.length() > 0) {
1263: result = TypeConversion.convertType(javaType);
1264: }
1265: } else {
1266: result = new XSClass(new JClass(getJavaClassName()));
1267: }
1268: } else {
1269: if (_type == MEMBER) {
1270: String javaType = _member.getJavaType();
1271: if (javaType != null && javaType.length() > 0) {
1272: result = TypeConversion.convertType(javaType);
1273: }
1274: }
1275: }
1276:
1277: if (result == null) {
1278: //--simpleType or AnyType
1279: if (type != null && type.isSimpleType()) {
1280: String packageName = null;
1281: if (((SimpleType) type).getSchema() != getSchema()) {
1282: XMLBindingComponent comp = new XMLBindingComponent(
1283: _config, getGroupNaming());
1284: comp.setBinding(_binding);
1285: comp.setView(type);
1286: packageName = comp.getJavaPackage();
1287: } else {
1288: packageName = getJavaPackage();
1289: }
1290:
1291: if ((packageName == null)
1292: || (packageName.length() == 0)) {
1293: String ns = ((SimpleType) type).getSchema()
1294: .getTargetNamespace();
1295: packageName = _config.lookupPackageByNamespace(ns);
1296: }
1297:
1298: result = _typeConversion.convertType((SimpleType) type,
1299: packageName, useWrapper, _config.useJava50());
1300: }
1301: }
1302:
1303: return result;
1304: }
1305:
1306: /**
1307: * Returns the collection name specified in the binding file. If no
1308: * collection was specified, null will be returned and the default
1309: * collection settings will be used.
1310: *
1311: * @return a string that represents the collection name specified in the
1312: * binding file. If no collection was specified, null will be
1313: * returned and the default collection settings will be used.
1314: */
1315: public String getCollectionType() {
1316: String result = null;
1317: if ((_type == MEMBER) && (_member.getCollection() != null)) {
1318: result = _member.getCollection().toString();
1319: }
1320: return result;
1321: }
1322:
1323: /**
1324: * Returns the fully qualified name of the Validator to use.
1325: *
1326: * @return the fully qualified name of the Validator to use.
1327: */
1328: public String getValidator() {
1329: if (_type == MEMBER) {
1330: return _member.getValidator();
1331: }
1332: return null;
1333: }
1334:
1335: /**
1336: * Returns the fully qualified name of the XMLFieldHandler to use.
1337: *
1338: * @return the fully qualified name of the XMLFieldHandler to use.
1339: */
1340: public String getXMLFieldHandler() {
1341: if (_type == MEMBER) {
1342: return _member.getHandler();
1343: }
1344: return null;
1345: }
1346:
1347: /**
1348: * Returns the visibility of the Java member to generate.
1349: *
1350: * @return the visibility of the Java member to generate.
1351: */
1352: public String getVisiblity() {
1353: if (_type == MEMBER) {
1354: final FieldTypeVisibilityType visibility = _member
1355: .getVisibility();
1356: if (visibility != null) {
1357: return visibility.toString();
1358: }
1359: return "private";
1360: }
1361: return null;
1362: }
1363:
1364: /**
1365: * Returns the type of this component binding. A component binding can be of
1366: * three different types:
1367: * <ul>
1368: * <li>Interface: it represents the binding to a java interface.</li>
1369: * <li>Class: it represents the binding to a java class.</li>
1370: * <li>Member: it represents the binding to a java class member.</li>
1371: * </ul>
1372: * <p>
1373: * -1 is returned if the component binding is null.
1374: *
1375: * @return the type of this component binding.
1376: */
1377: public short getType() {
1378: return _type;
1379: }
1380:
1381: /**
1382: * Returns the lower bound of the collection that is generated from this
1383: * BindingComponent. The lower bound is a positive integer. In the case of
1384: * an XML Schema component, it corresponds to the XML Schema minOccurs
1385: * attribute, if any.
1386: *
1387: * @param annotated an Annotated XML Schema structure.
1388: * @return an int representing the lower bound of the collection generated
1389: * from this BindingComponent. 0 is returned by default.
1390: */
1391: private static int getLowerBound(final Annotated annotated) {
1392: switch (annotated.getStructureType()) {
1393: case Structure.ELEMENT:
1394: return ((ElementDecl) annotated).getMinOccurs();
1395: case Structure.COMPLEX_TYPE:
1396: return ((ComplexType) annotated).getMinOccurs();
1397: case Structure.MODELGROUP:
1398: case Structure.GROUP:
1399: Group group = (Group) annotated;
1400: //-- if the group is top-level, then we always return 0
1401: Structure parent = group.getParent();
1402: if (parent != null
1403: && parent.getStructureType() == Structure.SCHEMA) {
1404: return 0;
1405: }
1406: int minOccurs = group.getMinOccurs();
1407: //-- if minOccurs == 1, then check to see if all elements inside group are
1408: //-- optional, if so, we return 0, not 1.
1409: if (minOccurs == 1) {
1410: Enumeration enumeration = group.enumerate();
1411: while (enumeration.hasMoreElements()) {
1412: if (getLowerBound((Annotated) enumeration
1413: .nextElement()) != 0) {
1414: return 1;
1415: }
1416: }
1417: //-- if we make it here, all items in group have a lowerbound of 0, so
1418: //-- the group can be considered optional
1419: return 0;
1420: }
1421: return minOccurs;
1422:
1423: case Structure.ATTRIBUTE:
1424: if (((AttributeDecl) annotated).isRequired()) {
1425: return 1;
1426: }
1427: break;
1428: default:
1429: break;
1430: }
1431: return 0;
1432: } //-- getLowerBound
1433:
1434: /**
1435: * Returns the EnumBindingType instance for the active binding component.
1436: * @return The EnumBindingType instance
1437: */
1438: public EnumBindingType getEnumBinding() {
1439: return _enum;
1440: }
1441:
1442: /**
1443: * Returns the name 'override' of a content member as specified in a binding file.
1444: * @return the name of the name 'override' for the content member.
1445: */
1446: public String getContentMemberName() {
1447: return _contentMemberName;
1448: }
1449:
1450: } //-- class: XMLBindingComponent
|