org.exolab.castor.builder.binding.XMLBindingComponent Maven / Gradle / Ivy
Show all versions of castor-codegen Show documentation
/*
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
* statements and notices. Redistributions must also contain a
* copy of this document.
*
* 2. Redistributions in binary form must reproduce the
* above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. The name "Exolab" must not be used to endorse or promote
* products derived from this Software without prior written
* permission of Intalio, Inc. For written permission,
* please contact [email protected].
*
* 4. Products derived from this Software may not be called "Exolab"
* nor may "Exolab" appear in their names without prior written
* permission of Intalio, Inc. Exolab is a registered
* trademark of Intalio, Inc.
*
* 5. Due credit should be given to the Exolab Project
* (http://www.exolab.org/).
*
* THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright 2002-2004 (C) Intalio Inc. All Rights Reserved.
*
* Any portions of this file developed by Keith Visco after Jan 19 2005
* are Copyright (C) 2005 Keith Visco. All Rights Reserverd.
*
*
* $Id$
*/
package org.exolab.castor.builder.binding;
import java.util.Enumeration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.exolab.castor.builder.BindingComponent;
import org.exolab.castor.builder.BuilderConfiguration;
import org.exolab.castor.builder.GroupNaming;
import org.exolab.castor.builder.TypeConversion;
import org.exolab.castor.builder.binding.xml.ClassType;
import org.exolab.castor.builder.binding.xml.ComponentBindingType;
import org.exolab.castor.builder.binding.xml.ComponentBindingTypeChoice;
import org.exolab.castor.builder.binding.xml.EnumBindingType;
import org.exolab.castor.builder.binding.xml.FieldType;
import org.exolab.castor.builder.binding.xml.Interface;
import org.exolab.castor.builder.binding.xml.NamingXMLType;
import org.exolab.castor.builder.binding.xml.types.FieldTypeVisibilityType;
import org.exolab.castor.builder.types.XSClass;
import org.exolab.castor.builder.types.XSType;
import org.exolab.castor.xml.schema.Annotated;
import org.exolab.castor.xml.schema.AttributeDecl;
import org.exolab.castor.xml.schema.ComplexType;
import org.exolab.castor.xml.schema.ContentModelGroup;
import org.exolab.castor.xml.schema.ElementDecl;
import org.exolab.castor.xml.schema.Form;
import org.exolab.castor.xml.schema.Group;
import org.exolab.castor.xml.schema.ModelGroup;
import org.exolab.castor.xml.schema.Schema;
import org.exolab.castor.xml.schema.SimpleType;
import org.exolab.castor.xml.schema.Structure;
import org.exolab.castor.xml.schema.XMLType;
import org.exolab.javasource.JClass;
/**
* This class is the implementation of BindingComponent from an XML Schema point
* of view. This specific implementation wraps an XML Schema annotated
* structure.
*
* The XML Schema structure can be only of four different types:
*
* - Element: it represents an XML Schema element.
* - ComplexType: it represents an XML Schema complexType.
* - ModelGroup: it represents an XML Schema Model group definition.
* - Group: it represents an XML Schema Model Group.
*
*
* The three first items can be customized using a binding file. Thus the
* XMLBindingComponent class takes into account the presence or not of a custom
* binding document in the computation of the needed information for the Source
* Generator to generate java classes from an XML Schema.
*
* The customizable items are detailled in the binding file documentation.
*
* This class acts like a window on a particular XML Schema structure
* that the user controls by changing the view on the Annotated Structure he is
* interested in.
*
*
* @see org.exolab.castor.builder.BindingComponent
*
* @author Arnaud Blandin
* @author Keith Visco
* @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
*/
public final class XMLBindingComponent implements BindingComponent {
/**
* Log instance for all logging purposes.
*/
private static final Log LOG = LogFactory.getLog(XMLBindingComponent.class);
/**
* The Extended Binding used to retrieve the ComponentBindingType.
*/
private ExtendedBinding _binding;
/**
* The binding component to use, if no binding component is present then
* the default behavior applies.
*/
private ComponentBindingType _compBinding;
/**
* The BuilderConfiguration instance for obtaining default properties.
*/
private BuilderConfiguration _config = null;
/**
* The XML Schema Annotated structure encapsulated in that XMLBinding object.
*/
private Annotated _annotated;
/**
* The prefix used to generate the java names.
*/
private String _prefix;
/**
* The suffix used to generate the java names.
*/
private String _suffix;
/**
* The type of the XMLBinding. -1 is no component binding have been defined.
*/
private short _type = -1;
/**
* Caches of several computations.
*/
private int _hashCode = -1;
private String _javaClassName = null;
private String _javaMemberName = null;
private String _javaPackage = null;
private FieldType _member = null;
private ClassType _class = null;
private Interface _interface = null;
private EnumBindingType _enum = null;
private Schema _schema = null;
private boolean _userSpecifiedMemberName = false;
/**
* A GroupNaming helper class used to named anonymous groups.
*/
private GroupNaming _groupNaming = null;
/**
* Returns the current group naming scheme in use.
* @return The current group naming scheme
*/
private synchronized GroupNaming getGroupNaming() {
return _groupNaming;
}
/**
* Sets the group naming instance to be used.
* @param groupNaming The current group naming scheme to be used.
*/
private void setGroupNaming(final GroupNaming groupNaming) {
_groupNaming = groupNaming;
}
/**
* The TypeConversion to use when creating XSTypes from SimpleType.
*/
private TypeConversion _typeConversion = null;
private String _contentMemberName;
/**
* Constructs an XMLBindingComponent from an XML Schema Component.
*
* @param config the BuilderConfiguration instance (must not be null).
* @param groupNaming The group naming scheme to be used.
*/
public XMLBindingComponent(final BuilderConfiguration config, final GroupNaming groupNaming) {
if (config == null) {
String error = "The argument 'config' must not be null.";
throw new IllegalArgumentException(error);
}
_config = config;
_typeConversion = new TypeConversion(_config);
setGroupNaming(groupNaming);
} //-- XMLBindingComponent
/**
* Returns the Binding Object Model on which this XMLBindingComponent will
* query information.
*
* @return the Extended Binding Object Model that wraps the information
* located in a binding file
*/
public ExtendedBinding getBinding() {
return _binding;
} //-- getBinding
/**
* Sets the Binding Object Model on which this XMLBindingComponent will
* query information.
*
* @param binding the Extended Binding Object Model that wraps the
* information located in a binding file
*/
public void setBinding(final ExtendedBinding binding) {
_binding = binding;
}
/**
* Sets the window on the given Annotated XML Schema structure. Once
* the window is set on a particular XML Schema structure all the
* information returned by this class are relative to that XML Schema
* structure.
*
* @param annotated an Annotated XML Schema structure.
* @see org.exolab.castor.xml.schema.Annotated
*/
public void setView(final Annotated annotated) {
if (annotated == null) {
throw new IllegalArgumentException("The XML Schema annotated structure is null.");
}
_annotated = annotated;
//--reset all the variables
_javaClassName = null;
_javaMemberName = null;
_javaPackage = null;
_schema = null;
_member = null;
_class = null;
_interface = null;
_type = -1;
_prefix = null;
_suffix = null;
_userSpecifiedMemberName = false;
_compBinding = null;
//--look up for the particular componentBinding relative to the
//-- given annotated structure
if (_binding != null) {
_compBinding = _binding.getComponentBindingType(annotated);
NamingXMLType naming = _binding.getNamingXML();
if (naming != null) {
switch (annotated.getStructureType()) {
case Structure.COMPLEX_TYPE:
if (naming.getComplexTypeName() != null) {
_prefix = naming.getComplexTypeName().getPrefix();
_suffix = naming.getComplexTypeName().getSuffix();
}
break;
case Structure.ELEMENT:
if (naming.getElementName() != null) {
_prefix = naming.getElementName().getPrefix();
_suffix = naming.getElementName().getSuffix();
}
break;
case Structure.MODELGROUP:
if (naming.getModelGroupName() != null) {
_prefix = naming.getModelGroupName().getPrefix();
_suffix = naming.getModelGroupName().getSuffix();
}
break;
default:
break;
}
} //--naming != null;
} //--binding != null
if (_compBinding != null) {
ComponentBindingTypeChoice choice = _compBinding.getComponentBindingTypeChoice();
if (choice.getInterface() != null) {
_type = INTERFACE;
_interface = choice.getInterface();
} else if (choice.getJavaClass() != null) {
_type = CLASS;
_class = choice.getJavaClass();
} else if (choice.getMember() != null) {
_type = MEMBER;
_member = choice.getMember();
} else if (choice.getEnumDef() != null) {
_type = ENUM_TYPE;
_enum = choice.getEnumDef();
} else if (choice.getContentMember() != null) {
_type = CONTENT_MEMBER_TYPE;
_contentMemberName = choice.getContentMember().getName();
} else {
String err = "Illegal Binding component:";
err += "it does not define a class, an interface or a member binding.";
throw new IllegalStateException(err);
}
}
} //--setView
//--Object manipulation methods
/**
* Returns true if the given Object is equal to this instance of
* XMLBindingComponent.
*
* @return true if the given Object is equal to this instance of
* XMLBindingComponent.
* @param object {@inheritDoc}
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(final Object object) {
if (object == null) {
return false;
}
boolean result = false;
if (object instanceof XMLBindingComponent) {
XMLBindingComponent temp = (XMLBindingComponent) object;
result = _annotated.equals(temp.getAnnotated());
if (_compBinding != null) {
if (temp.getComponentBinding() != null) {
result = result && (_compBinding.equals(temp.getComponentBinding()));
} else {
result = false;
}
} else if (temp.getComponentBinding() != null) {
result = false;
}
} else {
result = false;
}
return result;
}
/**
* Returns the hashCode value for this object.
*
* @return the hashcode value for this object.
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
if (_hashCode == -1) {
int compBindingHash = 0;
if (_compBinding != null) {
compBindingHash = _compBinding.getName().hashCode();
}
//WARNING: THE CASTOR SOM doesn't override hashCode or equals
_hashCode = 37 * (_annotated.hashCode()) + compBindingHash;
}
return _hashCode;
}
/**
* Returns the ComponentBinding used in that XMLBindingComponent
* to retrieve customized information.
*
* @return the ComponentBinding used in that XMLBinding.
*/
protected ComponentBindingType getComponentBinding() {
return _compBinding;
}
//--XML Schema information methods
/**
* Returns the XML Schema annotated structure used in this XMLBindingComponent.
*
* @return the XML Schema annotated structure used in this XMLBindingComponent.
*/
public Annotated getAnnotated() {
return _annotated;
}
/**
* Returns true if the binding of this XMLBindingComponent will require the
* generation of 2 java classes. Indeed an a nested Model Group that can
* occur more than once is described by the SourceGenerator with a wrapper
* class.
*
* @return true if the binding of this XMLBindingComponent will require the
* generation of 2 java classes.
*/
public boolean createGroupItem() {
int maxOccurs = 0;
boolean result = false;
switch (_annotated.getStructureType()) {
case Structure.ELEMENT:
XMLType type = ((ElementDecl) _annotated).getType();
if (type.isComplexType()) {
maxOccurs = ((ComplexType) type).getMaxOccurs();
if (((maxOccurs > 1) || (maxOccurs < 0)) && (type.getName() == null)) {
result = true;
}
}
break;
case Structure.COMPLEX_TYPE:
maxOccurs = ((ComplexType) _annotated).getMaxOccurs();
if ((maxOccurs > 1) || (maxOccurs < 0)) {
result = true;
}
break;
case Structure.MODELGROUP:
case Structure.GROUP:
Group group = (Group) _annotated;
maxOccurs = group.getMaxOccurs();
if ((maxOccurs > 1) || (maxOccurs < 0)) {
result = true;
}
break;
case Structure.ATTRIBUTE:
default:
break;
}
return result;
}
/**
* Returns the schemaLocation of the parent schema of the wrapped structure.
*
* @return the schemaLocation of the parent schema of the wrapped structure.
*/
public String getSchemaLocation() {
String location = null;
Schema schema = getSchema();
if (schema != null) {
location = schema.getSchemaLocation();
}
return location;
}
/**
* Returns the targetNamespace of the parent schema of the wrapped structure.
*
* @return the targetNamespace of the parent schema of the wrapped structure.
*/
public String getTargetNamespace() {
String result = null;
Schema schema = null;
Form form = null;
switch (_annotated.getStructureType()) {
case Structure.ATTRIBUTE:
AttributeDecl attribute = (AttributeDecl) _annotated;
//-- resolve reference
if (attribute.isReference()) {
attribute = attribute.getReference();
}
schema = attribute.getSchema();
//-- top-level (use targetNamespace of schema)
if (attribute.getParent() == schema) {
break;
}
//-- check form (qualified or unqualified)
form = attribute.getForm();
if (form == null) {
form = schema.getAttributeFormDefault();
}
if ((form == null) || form.isUnqualified()) {
//-- no targetNamespace by default
return null;
}
//-- use targetNamespace of schema
break;
case Structure.ELEMENT:
//--resolve reference?
ElementDecl element = (ElementDecl) _annotated;
if (element.isReference()) {
element = element.getReference();
}
schema = element.getSchema();
//-- top-level (use targetNamespace of schema)
if (element.getParent() == schema) {
break;
}
//-- check form (qualified or unqualified)
form = element.getForm();
if (form == null) {
form = schema.getElementFormDefault();
}
//-- no targetNamespace by default
if ((form == null) || form.isUnqualified()) {
return null;
}
//-- use targetNamespace of schema
break;
case Structure.COMPLEX_TYPE:
ComplexType complexType = (ComplexType) _annotated;
schema = complexType.getSchema();
if (complexType.getParent() == schema) {
break;
}
return null;
case Structure.SIMPLE_TYPE:
SimpleType simpleType = (SimpleType) _annotated;
schema = simpleType.getSchema();
if (simpleType.getParent() == schema) {
break;
}
return null;
default:
break;
}
if (schema == null) {
schema = getSchema();
}
if (schema != null) {
result = schema.getTargetNamespace();
}
return result;
} //-- getTargetNamespace
/**
* Returns the underlying Schema of the wrapped structure.
*
* @return the parent schema of the wrapped structure.
*/
public Schema getSchema() {
if (_schema != null) {
return _schema;
}
switch (_annotated.getStructureType()) {
case Structure.ATTRIBUTE:
//--resolve reference?
AttributeDecl attribute = (AttributeDecl) _annotated;
if (attribute.isReference()) {
attribute = attribute.getReference();
}
_schema = attribute.getSchema();
attribute = null;
break;
case Structure.ELEMENT:
//--resolve reference?
ElementDecl element = (ElementDecl) _annotated;
if (element.isReference()) {
element = element.getReference();
}
_schema = element.getSchema();
element = null;
break;
case Structure.COMPLEX_TYPE:
_schema = ((ComplexType) _annotated).getSchema();
break;
case Structure.MODELGROUP:
//--resolve reference?
ModelGroup group = (ModelGroup) _annotated;
if (group.isReference()) {
group = group.getReference();
}
_schema = group.getSchema();
group = null;
break;
case Structure.GROUP:
Structure parent = ((Group) _annotated).getParent();
short structure = parent.getStructureType();
while (structure == Structure.GROUP) {
parent = ((Group) parent).getParent();
structure = parent.getStructureType();
}
if (structure == Structure.COMPLEX_TYPE) {
_schema = ((ComplexType) parent).getSchema();
} else if (structure == Structure.MODELGROUP) {
_schema = ((ModelGroup) parent).getSchema();
}
break;
case Structure.SIMPLE_TYPE:
case Structure.UNION:
case Structure.LIST:
_schema = ((SimpleType) _annotated).getSchema();
break;
default:
break;
}
return _schema;
}
/**
* Returns the XMLType of the underlying structure. The XMLType of an
* element being its XML Schema type, the XMLType of a ComplexType being
* itself and the XMLType of an attribute being its XML Schema simpleType.
* Null is returned for a Model Group.
*
* @return the XMLType of the underlying structure.
*/
public XMLType getXMLType() {
XMLType result = null;
switch (_annotated.getStructureType()) {
case Structure.ELEMENT:
result = ((ElementDecl) _annotated).getType();
break;
case Structure.COMPLEX_TYPE:
result = ((ComplexType) _annotated);
break;
case Structure.SIMPLE_TYPE:
result = ((SimpleType) _annotated);
break;
case Structure.ATTRIBUTE:
result = ((AttributeDecl) _annotated).getSimpleType();
break;
case Structure.MODELGROUP:
default:
break;
}
return result;
}
/**
* Returns the XML name declared in the XML Schema for this XMLBindingComponent.
*
* @return the XML name declared in the XML Schema for this XMLBindingComponent.
*/
public String getXMLName() {
String result = null;
if (_annotated != null) {
switch (_annotated.getStructureType()) {
case Structure.ELEMENT:
result = ((ElementDecl) _annotated).getName();
break;
case Structure.COMPLEX_TYPE:
result = ((ComplexType) _annotated).getName();
break;
case Structure.SIMPLE_TYPE:
result = ((SimpleType) _annotated).getName();
break;
case Structure.ATTRIBUTE:
result = ((AttributeDecl) _annotated).getName();
break;
case Structure.MODELGROUP:
case Structure.GROUP:
result = ((Group) _annotated).getName();
break;
default:
break;
}
}
return result;
}
//--Implementation of BindingComponent
/**
* Returns the value specified in the XML Schema for the XML Schema
* component wrapped in this XMLBindingComponent. The value returned is the
* default or fixed value for an Element or an Attribute.
*
* @return the value specified in the XML Schema for the XML Schema
* annotated structure wrapped in this XMLBindingComponent.
*/
public String getValue() {
String result = null;
switch (_annotated.getStructureType()) {
case Structure.ELEMENT:
result = ((ElementDecl) _annotated).getDefaultValue();
if (result == null) {
result = ((ElementDecl) _annotated).getFixedValue();
}
break;
case Structure.ATTRIBUTE:
result = ((AttributeDecl) _annotated).getDefaultValue();
if (result == null) {
result = ((AttributeDecl) _annotated).getFixedValue();
}
break;
case Structure.COMPLEX_TYPE:
case Structure.SIMPLE_TYPE:
case Structure.MODELGROUP:
default:
break;
}
return result;
}
/**
* Returns a valid Java Class Name corresponding to this XMLBindingComponent.
* This name is not qualified, this is only a local Java class name.
*
* @return a valid Java Class Name corresponding to this XMLBindingComponent.
* This name is not qualified, this is only a local Java class name.
* @see #getQualifiedName
*/
public String getJavaClassName() {
if (_javaClassName == null) {
String result = null;
//--is there a class name defined (local name)
if (_compBinding != null) {
switch (getType()) {
case CLASS:
result = _class.getName();
break;
case INTERFACE:
result = _interface.getName();
break;
default:
break;
}
}
if (result == null || result.length() <= 0) {
//--is there a reference?
if (_annotated != null && _annotated.getStructureType() == Structure.ELEMENT) {
ElementDecl element = (ElementDecl) _annotated;
if (element.isReference()) {
Annotated temp = _annotated;
setView(element.getReference());
result = getJavaClassName();
setView(temp);
temp = null;
} else if (_config.mappingSchemaType2Java()) {
// deal with (global) element declarations in type mode,
// where no Java class will be generated per definition;
// in this case, the class name to be used should be taken from the
// underlying (complex) type
XMLType xmlType = element.getType();
if (xmlType != null && xmlType.isComplexType()) {
ComplexType complexType = (ComplexType) xmlType;
Annotated temp = _annotated;
setView(complexType);
result = getJavaClassName();
setView(temp);
}
}
element = null;
}
//--Still null?
if (result == null || result.length() <= 0) {
//--create the name
result = getXMLName();
//--create a java name for an anonymous group
if (result == null
&& _annotated != null
&& (_annotated.getStructureType() == Structure.GROUP
|| _annotated.getStructureType() == Structure.MODELGROUP)) {
GroupNaming groupNaming = getGroupNaming();
result = groupNaming.createClassName((Group) _annotated, getJavaPackage());
if (result == null) {
String err = "Unable to create name for group.";
throw new IllegalStateException(err);
}
}
if (_prefix != null) {
result = _prefix + result;
}
if (_suffix != null) {
result = result + _suffix;
}
}
}
_javaClassName = _config.getJavaNaming().toJavaClassName(result);
}
// TODO ADD A SWITCH TO DETERMINE WETHER OR NOT TO USE JAVA CONVENTIONS
// FOR THE JAVA CLASS NAME (SEE JAXB)
return _javaClassName;
}
/**
* Returns a valid Java Member Name corresponding to this XMLBindingComponent.
* This name is not qualified, this is only a local Java Member name.
*
* @return a valid Java Member Name corresponding to this XMLBindingComponent.
* This name is not qualified, this is only a local Java member name.
* @see #getQualifiedName
*/
public String getJavaMemberName() {
if (_javaMemberName == null) {
String result = null;
if (_compBinding != null) {
switch (getType()) {
case CLASS:
result = _class.getName();
break;
case INTERFACE:
result = _interface.getName();
break;
case MEMBER:
result = _member.getName();
break;
default:
break;
}
}
if (result == null || result.length() <= 0) {
Annotated temp = null;
if (_annotated.getStructureType() == Structure.ATTRIBUTE) {
AttributeDecl att = (AttributeDecl) _annotated;
if (att.isReference()) {
temp = _annotated;
setView(att.getReference());
result = getJavaMemberName();
setView(temp);
}
att = null;
} else if (_annotated.getStructureType() == Structure.ELEMENT) {
ElementDecl element = (ElementDecl) _annotated;
if (element.isReference()) {
temp = _annotated;
setView(element.getReference());
result = getJavaMemberName();
boolean userSpecified = _userSpecifiedMemberName;
setView(temp);
//-- there might be more than once reference, so we
//-- need to do a little counting here.
if (!userSpecified) {
String refName = element.getReferenceName();
int count = 0;
int index = 0;
Structure structure = element.getParent();
if (structure instanceof ContentModelGroup) {
ContentModelGroup cmg = (ContentModelGroup) structure;
Enumeration enumeration = cmg.enumerate();
while (enumeration.hasMoreElements()) {
Structure tmpStruct = enumeration.nextElement();
if (tmpStruct.getStructureType() == Structure.ELEMENT) {
ElementDecl tmpDecl = (ElementDecl) tmpStruct;
if (tmpDecl.isReference()
&& tmpDecl.getReferenceName().equals(refName)) {
++count;
if (tmpDecl == element) {
index = count;
}
}
}
}
}
if (count > 1) {
result = result + index;
}
}
}
element = null;
}
temp = null;
//--Still null?
if (result == null || result.length() <= 0) {
//--create the name
result = getXMLName();
//--create a java name for an anonymous group
if (result == null
&& (_annotated.getStructureType() == Structure.GROUP
|| _annotated.getStructureType() == Structure.MODELGROUP)) {
result = getGroupNaming().createClassName(
(Group) _annotated, getJavaPackage());
if (result == null) {
String err = "Unable to create name for group.";
throw new IllegalStateException(err);
}
}
if (_prefix != null) {
result = _prefix + result;
}
if (_suffix != null) {
result = result + _suffix;
}
}
} else {
_userSpecifiedMemberName = true;
}
_javaMemberName = _config.getJavaNaming().toJavaMemberName(result);
}
// TODO ADD A SWITCH TO DETERMINE WETHER OR NOT TO USE JAVA CONVENTIONS
// FOR THE JAVA CLASS NAME (SEE JAXB)
return _javaMemberName;
}
/**
* Returns the fully qualified name used for generating a java name that
* represents this XMLBindingComponent.
*
* The fully qualified name is computed according the following priority
* order:
*
* - If the XMLBinding wraps a class binding then the package name is the
* name defined locally in the {@literal <java-class>} element. More
* precisely the package name will be the value of the attribute package.
* - Else the package name will be computed from the schemaLocation of
* the parent schema.
* - Else the package name will be computed from the target namespace of
* the parent schema.
*
*
* Note: the computation of the namespace is a direct look-up for a defined
* mapping (Namespace, package) or (schema location, package).
*
* @return the fully qualified name used for generating a java name that
* represents this XMLBindingComponent.
*/
public String getQualifiedName() {
String result = getJavaClassName();
String packageName = getJavaPackage();
if (packageName != null && packageName.length() > 0) {
packageName += '.';
result = packageName + result;
}
return result;
}
/**
* Returns the java package associated with this XML BindingComponent. The
* algorithm used to resolve the package is defined according to the
* following priorities:
*
* - The package defined locally in the class declaration inside the
* binding file is used.
* - If no package has been defined locally then a lookup to a defined
* mapping {targetNamespace, package name} is performed.
* - If no package has been defined locally then a lookup to a defined
* mapping {schema location, package name} is performed.
*
*
* @return the java package associated with this XML BindingComponent.
*/
public String getJavaPackage() {
if (_javaPackage == null) {
String packageName = null;
String schemaLocation = getSchemaLocation();
String targetNamespace = getTargetNamespace();
//-- adjust targetNamespace null -> ""
if (targetNamespace == null) {
targetNamespace = "";
}
if (_compBinding != null) {
switch (getType()) {
case CLASS:
packageName = _class.getPackage();
break;
default:
break;
} //--switch
}
if (isPackageNameNotSet(packageName)) {
if (isPackageNameNotSet(packageName)) {
// look for a namespace mapping
packageName = _config.lookupPackageByNamespace(targetNamespace);
}
if (schemaLocation != null && isPackageNameNotSet(packageName)) {
// look for schema location mapping
packageName = _config.lookupPackageByLocation(schemaLocation);
}
}
_javaPackage = packageName;
}
return _javaPackage;
}
/**
* Indicates whether a package name has already been set.
* @param packageName The package name to analyse.
* @return True if the package name has been set correctly.
*/
private boolean isPackageNameNotSet(final String packageName) {
return (packageName == null || packageName.length() == 0);
}
/**
* Returns the upper bound of the collection that is generated from this
* BindingComponent. The upper bound is a positive integer. -1 is returned
* to indicate that the upper bound is unbounded.
*
* In the case of an XML Schema component, the upper bound corresponds to
* the XML Schema maxOccurs attribute, if any.
*
* @return an int representing the lower bound of the collection generated
* from this BindingComponent. -1 is returned to indicate that the
* upper bound is unbounded. 1 is the default value.
*/
public int getUpperBound() {
switch (_annotated.getStructureType()) {
case Structure.ELEMENT:
return ((ElementDecl) _annotated).getMaxOccurs();
case Structure.COMPLEX_TYPE:
return ((ComplexType) _annotated).getMaxOccurs();
case Structure.GROUP:
case Structure.MODELGROUP:
return ((Group) _annotated).getMaxOccurs();
case Structure.ATTRIBUTE:
default:
break;
}
return 1;
}
/**
* Returns the lower bound of the collection that is generated from this
* BindingComponent. The lower bound is a positive integer. In the case of
* an XML Schema component, it corresponds to the XML Schema minOccurs
* attribute, if any.
*
* @return an int representing the lower bound of the collection generated
* from this BindingComponent. 0 is returned by default.
*/
public int getLowerBound() {
return getLowerBound(_annotated);
}
////////METHODS RELATED TO A CLASS BINDING
/**
* Returns the name of a super class for the current XMLBinding. Null is
* returned if this XMLBinding is not meant to be mapped to a java class.
*
* @return the name of a super class for the current XMLBinding. Null is
* returned if this XMLBinding is not meant to be mapped to a java
* class
*/
public String getExtends() {
if (getType() == CLASS) {
return _class.getExtends();
}
return _config.getProperty(BuilderConfiguration.Property.SUPER_CLASS, null);
} //-- getExtends
/**
* Returns an array of the different interface names implemented by the
* class that will represent the current XMLBindingComponent. Null is
* returned if no class binding is defined for the wrapped XML Schema
* structure.
*
* @return array of interface names
*/
public String[] getImplements() {
if (getType() == CLASS) {
return _class.getImplements();
}
return null;
}
/**
* Returns true if bound properties must be generated for the class that
* will represent the current XMLBindingComponent.
*
* @return true if bound properties must be generated for the class the
* class that will represent the current XMLBindingComponent.
*/
public boolean hasBoundProperties() {
if (getType() == CLASS && _class.hasBound()) {
return _class.getBound();
}
return _config.boundPropertiesEnabled();
}
/**
* Returns true if equal method must be generated for the class that will
* represent the current XMLBindingComponent.
*
* @return true if equal method must be generated for the class the class
* that will represent the current XMLBindingComponent.
*/
public boolean hasEquals() {
if (getType() == CLASS && _class.hasEquals()) {
return _class.getEquals();
}
return _config.equalsMethod();
}
/**
* Returns true if the class that will represent the current
* XMLBindingComponent must be abstract.
*
* @return true if the class that will represent the current
* XMLBindingComponent must be abstract.
*/
public boolean isAbstract() {
boolean result = false;
if (getType() == CLASS && _class.hasAbstract()) {
result = _class.getAbstract();
}
if (!result) {
switch(_annotated.getStructureType()) {
case Structure.COMPLEX_TYPE:
ComplexType cType = (ComplexType) _annotated;
result = cType.isAbstract();
//-- if we're in element-centric mode, then all
//-- complexTypes are treated as abstract
result = result || _config.mappingSchemaElement2Java();
break;
case Structure.ELEMENT:
ElementDecl eDecl = (ElementDecl) _annotated;
result = eDecl.isAbstract();
break;
default:
break;
}
}
return result;
}
/**
* Returns true if the class that will represent the current XMLBindingComponent
* must be final.
*
* @return true if the class that will represent the current XMLBindingComponent
* must be final.
*/
public boolean isFinal() {
if (getType() == CLASS) {
return _class.getFinal();
}
return false;
}
/**
* Returns true if the wrapped XML Schema component is fixed (i.e the value
* used is fixed).
*
* @return true if the wrapped XML Schema component is fixed (i.e the value
* used is fixed).
*/
public boolean isFixed() {
switch (_annotated.getStructureType()) {
case Structure.ELEMENT:
String fixed = ((ElementDecl) _annotated).getFixedValue();
return (fixed != null);
case Structure.ATTRIBUTE:
return ((AttributeDecl) _annotated).isFixed();
case Structure.GROUP:
case Structure.COMPLEX_TYPE:
case Structure.SIMPLE_TYPE:
case Structure.MODELGROUP:
default:
break;
}
return false;
}
/**
* Returns true if the wrapped XML Schema component is nillable.
*
* @return true if the wrapped XML Schema component is nillable.
*/
public boolean isNillable() {
switch (_annotated.getStructureType()) {
case Structure.ELEMENT:
return ((ElementDecl) _annotated).isNillable();
default:
break;
}
return false;
} //-- isNillable
////////METHODS RELATED TO A MEMBER BINDING
/**
* Returns true if the member represented by that XMLBindingComponent is to
* be represented by an Object wrapper. For instance an int will be
* represented by a java Integer if the property is set to true.
*
* @return true if the member represented by that XMLBindingComponent is to
* be represented by an Object wrapper.
*/
public boolean useWrapper() {
if (_type != BindingComponent.MEMBER) {
return _config.usePrimitiveWrapper();
}
if (_member.hasWrapper()) {
return _member.getWrapper();
}
return false;
}
/**
* Returns the XSType that corresponds to the Java type chosen to represent
* the XML Schema component represented by this XMLBindingComponent. An
* XSType is an abstraction of a Java type used in the Source Generator. It
* wraps a JType as well as the necessary methods to convert to/from String.
*
* If a name of java type is specified then this name will have higher
* priority than the simpleType resolution.
*
* @return an XSType
*/
public XSType getJavaType() {
//--no need for caching it is called only once
XSType result = null;
boolean useWrapper = useWrapper();
XMLType type = getXMLType();
if (type != null && type.isComplexType()) {
if (_type == MEMBER && _member.getJavaType() != null) {
String javaType = _member.getJavaType();
if (javaType != null && javaType.length() > 0) {
result = TypeConversion.convertType(javaType);
}
} else {
result = new XSClass(new JClass(getJavaClassName()));
}
} else {
if (_type == MEMBER) {
String javaType = _member.getJavaType();
if (javaType != null && javaType.length() > 0) {
result = TypeConversion.convertType(javaType);
}
}
}
if (result == null) {
//--simpleType or AnyType
if (type != null && type.isSimpleType()) {
String packageName = null;
String className = null;
if (((SimpleType) type).getSchema() != getSchema()) {
XMLBindingComponent comp = new XMLBindingComponent(_config, getGroupNaming());
comp.setBinding(_binding);
comp.setView(type);
packageName = comp.getJavaPackage();
if (comp.getClass() != null) {
className = comp.getJavaClassName();
}
} else {
packageName = getJavaPackage();
if (_class != null) {
className = getJavaClassName();
}
}
if ((packageName == null) || (packageName.length() == 0)) {
String ns = ((SimpleType) type).getSchema().getTargetNamespace();
packageName = _config.lookupPackageByNamespace(ns);
}
result = _typeConversion.convertType((SimpleType) type,
packageName, useWrapper, _config.useJava50(), className);
}
}
return result;
}
/**
* Returns the collection name specified in the binding file. If no
* collection was specified, null will be returned and the default
* collection settings will be used.
*
* @return a string that represents the collection name specified in the
* binding file. If no collection was specified, null will be
* returned and the default collection settings will be used.
*/
public String getCollectionType() {
String result = null;
if ((_type == MEMBER) && (_member.getCollection() != null)) {
result = _member.getCollection().toString();
}
return result;
}
/**
* Returns the fully qualified name of the Validator to use.
*
* @return the fully qualified name of the Validator to use.
*/
public String getValidator() {
if (_type == MEMBER) {
return _member.getValidator();
}
return null;
}
/**
* Returns the fully qualified name of the XMLFieldHandler to use.
*
* @return the fully qualified name of the XMLFieldHandler to use.
*/
public String getXMLFieldHandler() {
if (_type == MEMBER) {
return _member.getHandler();
}
return null;
}
/**
* Returns the visibility of the Java member to generate.
*
* @return the visibility of the Java member to generate.
*/
public String getVisiblity() {
if (_type == MEMBER) {
final FieldTypeVisibilityType visibility = _member.getVisibility();
if (visibility != null) {
return visibility.toString();
}
return "private";
}
return null;
}
/**
* Returns the type of this component binding. A component binding can be of
* three different types:
*
* - Interface: it represents the binding to a java interface.
* - Class: it represents the binding to a java class.
* - Member: it represents the binding to a java class member.
*
*
* -1 is returned if the component binding is null.
*
* @return the type of this component binding.
*/
public short getType() {
return _type;
}
/**
* Returns the lower bound of the collection that is generated from this
* BindingComponent. The lower bound is a positive integer. In the case of
* an XML Schema component, it corresponds to the XML Schema minOccurs
* attribute, if any.
*
* @param annotated an Annotated XML Schema structure.
* @return an int representing the lower bound of the collection generated
* from this BindingComponent. 0 is returned by default.
*/
private static int getLowerBound(final Annotated annotated) {
switch (annotated.getStructureType()) {
case Structure.ELEMENT:
return ((ElementDecl) annotated).getMinOccurs();
case Structure.COMPLEX_TYPE:
return ((ComplexType) annotated).getMinOccurs();
case Structure.MODELGROUP:
case Structure.GROUP:
Group group = (Group) annotated;
//-- if the group is top-level, then we always return 0
Structure parent = group.getParent();
if (parent != null && parent.getStructureType() == Structure.SCHEMA) {
return 0;
}
int minOccurs = group.getMinOccurs();
//-- if minOccurs == 1, then check to see if all elements inside group are
//-- optional, if so, we return 0, not 1.
if (minOccurs == 1) {
Enumeration enumeration = group.enumerate();
while (enumeration.hasMoreElements()) {
if (getLowerBound(enumeration.nextElement()) != 0) {
return 1;
}
}
//-- if we make it here, all items in group have a lowerbound of 0, so
//-- the group can be considered optional
return 0;
}
return minOccurs;
case Structure.ATTRIBUTE:
if (((AttributeDecl) annotated).isRequired()) {
return 1;
}
break;
default:
break;
}
return 0;
} //-- getLowerBound
/**
* Returns the EnumBindingType instance for the active binding component.
* @return The EnumBindingType instance
*/
public EnumBindingType getEnumBinding() {
return _enum;
}
/**
* Returns the name 'override' of a content member as specified in a binding file.
* @return the name of the name 'override' for the content member.
*/
public String getContentMemberName() {
return _contentMemberName;
}
} //-- class: XMLBindingComponent