Index: codegen/src/test/java/org/exolab/castor/builder/JClassRegistryTest.java =================================================================== --- codegen/src/test/java/org/exolab/castor/builder/JClassRegistryTest.java (Revision 0) +++ codegen/src/test/java/org/exolab/castor/builder/JClassRegistryTest.java (Revision 0) @@ -0,0 +1,170 @@ +package org.exolab.castor.builder; + +import org.exolab.castor.builder.binding.XMLBindingComponent; +import org.exolab.castor.xml.schema.ComplexType; +import org.exolab.castor.xml.schema.ElementDecl; +import org.exolab.castor.xml.schema.Group; +import org.exolab.castor.xml.schema.Order; +import org.exolab.castor.xml.schema.Schema; +import org.exolab.castor.xml.schema.SchemaException; +import org.exolab.javasource.JClass; + +import junit.framework.TestCase; + +public class JClassRegistryTest extends TestCase { + + /** + * JClassRegistry instance used for testing + */ + private JClassRegistry registry; + + protected void setUp() throws Exception { + super.setUp(); + this.registry = new JClassRegistry(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + this.registry = null; + } + + public void testSinlgeLocalNotionalElements() throws SchemaException { + + JClass jClass = new JClass("xml.c1451.generated.Notional"); + + Schema schema = new Schema("http://test"); + + ElementDecl notional = createElementWithinComplexType(schema, "Bond", "notional"); + + registry.bind(jClass, notional, "field"); + + assertNotNull(jClass); + assertEquals("xml.c1451.generated.Notional", jClass.getName()); + } + + public void testMultipleLocalNotionalElements() throws SchemaException { + + JClass jClass = new JClass("xml.c1451.generated.Notional"); + + Schema schema = new Schema("http://test"); + + ElementDecl bondNotional = + createElementWithinComplexType(schema, "Bond", "notional"); + + registry.bind(jClass, bondNotional, "field"); + + assertNotNull(jClass); + assertEquals("xml.c1451.generated.Notional", jClass.getName()); + + ElementDecl swapNotional = + createElementWithinComplexType(schema, "Swap", "notional"); + JClass swapJClass = new JClass("xml.c1451.generated.Notional"); + + registry.bind(swapJClass, swapNotional, "field"); + + assertNotNull(swapJClass); + assertEquals("xml.c1451.generated.SwapNotional", swapJClass.getName()); + + ElementDecl indexNotional = + createElementWithinComplexType(schema, "Index", "notional"); + JClass indexJClass = new JClass("xml.c1451.generated.Notional"); + + registry.bind(indexJClass, indexNotional, "field"); + + assertNotNull(indexJClass); + assertEquals("xml.c1451.generated.IndexNotional", indexJClass.getName()); + + } + + public void testSingleLocalReference() throws SchemaException { + + registry.prebindGlobalElement("/bond"); + + JClass jClass = new JClass("xml.c1451.generated.Bond"); + + Schema schema = new Schema("http://test"); + + ElementDecl global = createGlobalElement(schema, "bond"); + + registry.bind(jClass, global, "field"); + + assertNotNull(jClass); + assertEquals("xml.c1451.generated.Bond", jClass.getName()); + + ElementDecl local = createReferenceWithinComplexType(schema, "Product", global); + JClass localJClass = new JClass("xml.c1451.generated.Bond"); + + registry.bind(localJClass, local, "field"); + + assertNotNull(localJClass); + assertEquals("xml.c1451.generated.Bond", jClass.getName()); + } + + private ElementDecl createReferenceWithinComplexType(final Schema schema, + final String complexTypeName, + final ElementDecl globalElement) throws SchemaException { + ComplexType complexType = new ComplexType(schema, complexTypeName); + Group sequence = new Group(); + sequence.setOrder(Order.seq); + complexType.addGroup(sequence); + schema.addComplexType(complexType); + ElementDecl localElement = new ElementDecl(schema); + localElement.setReference(globalElement); + sequence.addElementDecl(localElement); + return localElement; + } + + public void testSinlgeLocalElementsWithGlobalConflict() throws SchemaException { + + registry.prebindGlobalElement("/bond"); + + JClass jClass = new JClass("xml.c1451.generated.Bond"); + + Schema schema = new Schema("http://test"); + + ElementDecl notional = createElementWithinComplexType(schema, "Product", "bond"); + + registry.bind(jClass, notional, "field"); + + assertNotNull(jClass); + assertEquals("xml.c1451.generated.ProductBond", jClass.getName()); + } + + public void testGlobalElementWithGlobalConflict() throws SchemaException { + + registry.prebindGlobalElement("/bond"); + + JClass jClass = new JClass("xml.c1451.generated.Bond"); + + Schema schema = new Schema("http://test"); + + ElementDecl notional = createGlobalElement(schema, "bond"); + + registry.bind(jClass, notional, "field"); + + assertNotNull(jClass); + assertEquals("xml.c1451.generated.Bond", jClass.getName()); + } + + + private ElementDecl createElementWithinComplexType(final Schema schema, + final String complexTypeName, + final String elementName) throws SchemaException { + ComplexType complexType = new ComplexType(schema, complexTypeName); + Group sequence = new Group(); + sequence.setOrder(Order.seq); + complexType.addGroup(sequence); + schema.addComplexType(complexType); + ElementDecl notional = new ElementDecl(schema, elementName); + sequence.addElementDecl(notional); + return notional; + } + + private ElementDecl createGlobalElement(final Schema schema, + final String elementName) throws SchemaException { + ElementDecl globalElement = new ElementDecl(schema, elementName); + schema.addElementDecl(globalElement); + return globalElement; + } + +} Index: codegen/src/main/java/org/exolab/javasource/JClass.java =================================================================== --- codegen/src/main/java/org/exolab/javasource/JClass.java (Revision 6793) +++ codegen/src/main/java/org/exolab/javasource/JClass.java (Arbeitskopie) @@ -247,5 +247,19 @@ buffer.setLength(0); } + + /** + * Changes the local name of this class type. + * @param localName The new local name to be used. + */ + public void changeLocalName(final String localName) { + String packageName = getPackageName(); + if (packageName != null) { + setName(packageName + "." + localName); + } else { + setName(localName); + } + } + //-------------------------------------------------------------------------- } Index: codegen/src/main/java/org/exolab/javasource/JType.java =================================================================== --- codegen/src/main/java/org/exolab/javasource/JType.java (Revision 6793) +++ codegen/src/main/java/org/exolab/javasource/JType.java (Arbeitskopie) @@ -91,7 +91,7 @@ protected JType(final String name) { super(); - _name = name; + setName(name); } //-------------------------------------------------------------------------- @@ -132,6 +132,14 @@ public final boolean isPrimitive() { return (this instanceof JPrimitiveType); } + + /** + * Sets the qualified name of this type. + * @param name the (qualified) name of the type + */ + protected void setName(final String name) { + this._name = name; + } //-------------------------------------------------------------------------- } Index: codegen/src/main/java/org/exolab/castor/builder/MemberFactory.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/MemberFactory.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/MemberFactory.java (Arbeitskopie) @@ -93,10 +93,13 @@ * @param config the BuilderConfiguration * @param infoFactory the FieldInfoFactory to use * @param groupNaming Grou pnaming scheme to be used. + * @param sourceGenerator Calling source generator */ public MemberFactory(final BuilderConfiguration config, - final FieldInfoFactory infoFactory, final GroupNaming groupNaming) { - super(config, infoFactory, groupNaming); + final FieldInfoFactory infoFactory, + final GroupNaming groupNaming, + final SourceGenerator sourceGenerator) { + super(config, infoFactory, groupNaming, sourceGenerator); if (getConfig().generateExtraCollectionMethods()) { this.getInfoFactory().setCreateExtraMethods(true); @@ -334,10 +337,14 @@ if (xsType == null) { String className = component.getQualifiedName(); JClass jClass = new JClass(className); + if (getConfig().isAutomaticConflictResolution()) { + getSourceGenerator().getXMLInfoRegistry().bind(jClass, + component, "field"); + } xsType = new XSClass(jClass); if (xmlType != null && xmlType.isComplexType()) { ComplexType complexType = (ComplexType) xmlType; - if (complexType.isAbstract()) { + if (complexType.isAbstract() || getConfig().mappingSchemaElement2Java()) { jClass.getModifiers().setAbstract(true); } } Index: codegen/src/main/java/org/exolab/castor/builder/BaseFactory.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/BaseFactory.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/BaseFactory.java (Arbeitskopie) @@ -32,15 +32,23 @@ /** A GroupNaming helper class used to named anonymous groups. */ private GroupNaming _groupNaming = null; + + /** + * The calling instance of {@link SourceGenerator}. + */ + private SourceGenerator _sourceGenerator; /** * Creates an instance of this class. * @param config XML code generator configuration * @param infoFactory the FieldInfoFactory to use * @param groupNaming Group naming scheme to be used. + * @param sourceGenerator The calling source generator. */ public BaseFactory(final BuilderConfiguration config, - final FieldInfoFactory infoFactory, final GroupNaming groupNaming) { + final FieldInfoFactory infoFactory, + final GroupNaming groupNaming, + final SourceGenerator sourceGenerator) { if (config == null) { String err = "The 'BuilderConfiguration' argument must not be null."; throw new IllegalArgumentException(err); @@ -53,6 +61,7 @@ this._infoFactory = infoFactory; } _groupNaming = groupNaming; + _sourceGenerator = sourceGenerator; } /** @@ -135,4 +144,12 @@ _groupNaming = groupNaming; } + /** + * Returns the calling {@link SourceGenerator} instance. + * @return the calling source generator + */ + protected SourceGenerator getSourceGenerator() { + return _sourceGenerator; + } + } Index: codegen/src/main/java/org/exolab/castor/builder/conflictresolution/WarningViaDialogClassNameCRStrategy.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/conflictresolution/WarningViaDialogClassNameCRStrategy.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/conflictresolution/WarningViaDialogClassNameCRStrategy.java (Arbeitskopie) @@ -16,9 +16,10 @@ package org.exolab.castor.builder.conflictresolution; import java.util.Enumeration; +import java.util.Map; import org.exolab.castor.builder.SGStateInfo; -import org.exolab.castor.builder.binding.ExtendedBinding; +import org.exolab.castor.builder.binding.XPathHelper; import org.exolab.castor.builder.info.ClassInfo; import org.exolab.castor.util.dialog.ConsoleDialog; import org.exolab.castor.xml.schema.Annotated; @@ -66,10 +67,10 @@ * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy * #dealWithClassNameConflict(org.exolab.castor.builder.SGStateInfo, * org.exolab.castor.builder.info.ClassInfo, - * org.exolab.javasource.JClass) + * org.exolab.javasource.JClass, Map) */ public SGStateInfo dealWithClassNameConflict(final SGStateInfo state, - final ClassInfo newClassInfo, final JClass conflict) { + final ClassInfo newClassInfo, final JClass conflict, Map knownGlobalElements) { if (!state.getSuppressNonFatalWarnings()) { // -- if the ClassInfo are equal, we can just return ClassInfo oldClassInfo = state.resolve(conflict); @@ -102,7 +103,7 @@ if (a1 != null) { error.append(SchemaNames.getStructureName(a1)); error.append(" '"); - error.append(ExtendedBinding.getSchemaLocation(a1)); + error.append(XPathHelper.getSchemaLocation(a1)); } else { error.append(newClassInfo.getNodeTypeName()); error.append(" '"); @@ -112,7 +113,7 @@ if (a2 != null) { error.append(SchemaNames.getStructureName(a2)); error.append(" '"); - error.append(ExtendedBinding.getSchemaLocation(a2)); + error.append(XPathHelper.getSchemaLocation(a2)); } else { error.append(oldClassInfo.getNodeTypeName()); error.append(" '"); @@ -188,4 +189,8 @@ return this._dialog; } + public SGStateInfo dealWithClassNameConflictAgainstGlobal(SGStateInfo state, ClassInfo classInfo) { + return state; + } + } Index: codegen/src/main/java/org/exolab/castor/builder/conflictresolution/InformViaLogClassNameCRStrategy.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/conflictresolution/InformViaLogClassNameCRStrategy.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/conflictresolution/InformViaLogClassNameCRStrategy.java (Arbeitskopie) @@ -16,11 +16,12 @@ package org.exolab.castor.builder.conflictresolution; import java.util.Enumeration; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.exolab.castor.builder.SGStateInfo; -import org.exolab.castor.builder.binding.ExtendedBinding; +import org.exolab.castor.builder.binding.XPathHelper; import org.exolab.castor.builder.info.ClassInfo; import org.exolab.castor.util.dialog.ConsoleDialog; import org.exolab.castor.xml.schema.Annotated; @@ -36,7 +37,7 @@ * @author Werner Guttmann * @since 1.1 */ -public final class InformViaLogClassNameCRStrategy +public class InformViaLogClassNameCRStrategy extends BaseClassNameCRStrategy implements ClassNameCRStrategy { /** Logger instance used for logging naming conflicts. */ @@ -58,14 +59,16 @@ * @param state SourceGeneration state * @param newClassInfo ClassInfo for the new class * @param conflict JClass for the existing class + * @param knownGlobalElements known global elements * @return the provided source generator state, as modified by the strategy * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy * #dealWithClassNameConflict(org.exolab.castor.builder.SGStateInfo, * org.exolab.castor.builder.info.ClassInfo, - * org.exolab.javasource.JClass) + * org.exolab.javasource.JClass, Map) */ public SGStateInfo dealWithClassNameConflict(final SGStateInfo state, - final ClassInfo newClassInfo, final JClass conflict) { + final ClassInfo newClassInfo, final JClass conflict, + final Map knownGlobalElements) { // If the ClassInfo are equal, we can just return ClassInfo oldClassInfo = state.resolve(conflict); if (oldClassInfo == newClassInfo) { @@ -97,7 +100,7 @@ if (a1 != null) { message.append(SchemaNames.getStructureName(a1)); message.append(" '"); - message.append(ExtendedBinding.getSchemaLocation(a1)); + message.append(XPathHelper.getSchemaLocation(a1)); } else { message.append(newClassInfo.getNodeTypeName()); message.append(" '"); @@ -107,7 +110,7 @@ if (a2 != null) { message.append(SchemaNames.getStructureName(a2)); message.append(" '"); - message.append(ExtendedBinding.getSchemaLocation(a2)); + message.append(XPathHelper.getSchemaLocation(a2)); } else { message.append(oldClassInfo.getNodeTypeName()); message.append(" '"); @@ -153,4 +156,9 @@ return true; } + public SGStateInfo dealWithClassNameConflictAgainstGlobal(SGStateInfo state, ClassInfo classInfo) { + // add log output + return state; + } + } Index: codegen/src/main/java/org/exolab/castor/builder/conflictresolution/ClassNameCRStrategy.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/conflictresolution/ClassNameCRStrategy.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/conflictresolution/ClassNameCRStrategy.java (Arbeitskopie) @@ -15,6 +15,8 @@ */ package org.exolab.castor.builder.conflictresolution; +import java.util.Map; + import org.exolab.castor.builder.SGStateInfo; import org.exolab.castor.builder.SingleClassGenerator; import org.exolab.castor.builder.info.ClassInfo; @@ -36,10 +38,11 @@ * @param state The current source generator state. * @param newClassInfo The {@link CLassInfo} for the new class to be generated. * @param conflict The {@link JClass} instance representing the potential conflict. + * @param knownGlobalElements TODO * @return the source generator state, as modified by the decision. */ SGStateInfo dealWithClassNameConflict(final SGStateInfo state, - final ClassInfo newClassInfo, final JClass conflict); + final ClassInfo newClassInfo, final JClass conflict, Map knownGlobalElements); /** * Implements a specific strategy for dealing with the fact that -- for a @@ -71,4 +74,13 @@ */ void setSingleClassGenerator(SingleClassGenerator generator); + /** + * Implements a specific strategy for dealing with class name conflicts against + * global element definitions. + * @param state The current source generator state. + * @param classInfo The {@link CLassInfo} for the new class to be generated. + * @return the source generator state, as modified by the decision. + */ + SGStateInfo dealWithClassNameConflictAgainstGlobal(SGStateInfo state, ClassInfo classInfo); + } Index: codegen/src/main/java/org/exolab/castor/builder/SourceGenerator.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/SourceGenerator.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/SourceGenerator.java (Arbeitskopie) @@ -56,7 +56,12 @@ import java.io.IOException; import java.io.Reader; import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; import java.util.Properties; +import java.util.Set; import java.util.Vector; import org.apache.commons.logging.Log; @@ -65,6 +70,7 @@ import org.exolab.castor.builder.binding.BindingLoader; import org.exolab.castor.builder.binding.ExtendedBinding; import org.exolab.castor.builder.binding.XMLBindingComponent; +import org.exolab.castor.builder.binding.XPathHelper; import org.exolab.castor.builder.binding.xml.PackageType; import org.exolab.castor.builder.binding.xml.PackageTypeChoice; import org.exolab.castor.builder.binding.xml.types.BindingType; @@ -80,6 +86,7 @@ import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.ValidationException; import org.exolab.castor.xml.XMLException; +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; @@ -145,6 +152,9 @@ private final ConsoleDialog _dialog; /** A vector that keeps track of all the schemas processed. */ private final Vector _schemasProcessed = new Vector(7); + + /** A set that keeps track of global element names */ + private final Map _knownGlobalElements = new HashMap(); /** True if we should suppress non-fatal warnings. */ private boolean _suppressNonFatalWarnings = false; @@ -180,6 +190,9 @@ private GroupNaming _groupNaming = null; /** Strategy for name conflict resolution. */ private String _nameConflictStrategy = WarningViaDialogClassNameCRStrategy.NAME; + + // TODO: think about correct initialization/cleanup + private JClassRegistry _xmlInfoRegistry; /** * Creates a SourceGenerator using the default FieldInfo factory. @@ -220,6 +233,9 @@ _singleClassGenerator = new SingleClassGenerator(_dialog, this, _nameConflictStrategy); _bindingComponent = new XMLBindingComponent(this, _groupNaming); setBinding(binding); + + _xmlInfoRegistry = new JClassRegistry(); + } //-- SourceGenerator /** @@ -630,7 +646,7 @@ // has been fully parsed, create our SourceFactory. (See CASTOR-1346.) // We will reuse this SourceFactory if we are invoked multiple times. if (_sourceFactory == null) { - _sourceFactory = new SourceFactory(this, _infoFactory, _groupNaming); + _sourceFactory = new SourceFactory(this, _infoFactory, _groupNaming, this); _sourceFactory.setCreateMarshalMethods(_createMarshalMethods); _sourceFactory.setTestable(_testable); _sourceFactory.setSAX1(_sax1); @@ -684,6 +700,14 @@ Enumeration structures; + //-- register all gloabl element names for name conflict resolution + for (structures = schema.getElementDecls(); structures.hasMoreElements(); ) { + ElementDecl element = (ElementDecl) structures.nextElement(); + _knownGlobalElements.put(element.getName(), element); + _xmlInfoRegistry.prebindGlobalElement(XPathHelper.getSchemaLocation(element)); + //preBindNonGlobalElements(element, _xmlInfoRegistry); + } + //-- handle all top-level element declarations for (structures = schema.getElementDecls(); structures.hasMoreElements(); ) { createClasses((ElementDecl) structures.nextElement(), sInfo); @@ -716,6 +740,8 @@ fileOutputStream.close(); } } //-- createClasses + + /** * Look at each schema imported by the given schema. Either warn that the @@ -1087,6 +1113,14 @@ } /** + * Returns the collection of already 'processed' = known global elements. + * @return the collection of already 'processed' global elements + */ + public Map getKnownGlobalElements() { + return _knownGlobalElements; + } + + /** * For backwards compability, when we are called as the main() routine, * delegate the command-line usage to the proper class. * @@ -1100,4 +1134,12 @@ SourceGeneratorMain.main(args); } + /** + * Returns the {@link JClassRegistry} instance associated with this source generator. + * @return the {@link JClassRegistry} instance currently in use. + */ + public JClassRegistry getXMLInfoRegistry() { + return _xmlInfoRegistry; + } + } //-- SourceGenerator Index: codegen/src/main/java/org/exolab/castor/builder/JClassRegistry.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/JClassRegistry.java (Revision 0) +++ codegen/src/main/java/org/exolab/castor/builder/JClassRegistry.java (Revision 0) @@ -0,0 +1,264 @@ +/* + * Copyright 2007 Werner Guttmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.exolab.castor.builder; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.exolab.castor.builder.binding.ExtendedBinding; +import org.exolab.castor.builder.binding.XMLBindingComponent; +import org.exolab.castor.builder.binding.XPathHelper; +import org.exolab.castor.xml.JavaNaming; +import org.exolab.castor.xml.schema.Annotated; +import org.exolab.castor.xml.schema.ElementDecl; +import org.exolab.castor.xml.schema.XMLType; +import org.exolab.javasource.JClass; + +/** + * A registry for maintaing information about {@link JClass} instances already + * processed. + * + * @author Werner Guttmann + * @since 1.1 + * + */ +public class JClassRegistry { + + /** + * Logger instance used for all logging functionality. + */ + private static final Log LOG = LogFactory.getLog(JClassRegistry.class); + + /** + * Registry for holding a set of global element definitions. + */ + private Set _globalElements = new HashSet(); + + /** + * Registry for mapping an XPATH location to a {@link JClass} instance + * generated for the XML artefact uniquely identified by the XPATH. + */ + private Map _xpathToJClass = new HashMap(); + + /** + * Registry for recording naming collisions, keyed by the local part of an + * otherwise rooted XPATH. + */ + private Map _localNames = new HashMap(); + + /** + * Registers the XPATH identifier for a global element definition for + * further use. + * + * @param xpath + * The XPATH identifier of a global element. + */ + public void prebindGlobalElement(final String xpath) { + _globalElements.add(xpath); + } + + /** + * Registers a {@link JClass} instance for a given XPATH. + * + * @param jClass + * The {@link JClass} instance to register. + * @param component + * Container for the {@link Annotated} instance referred to by the XPATH. + * @param mode Whether we register JClass instances in 'field' or 'class'mode. + */ + public void bind(final JClass jClass, final XMLBindingComponent component, + final String mode) { + + Annotated annotated = component.getAnnotated(); + + String xPath = XPathHelper.getSchemaLocation(annotated); + + // TODO: it could happen that we silently ignore a custom package as defined in a binding - FIX ! + + String jClassLocalName = jClass.getLocalName(); + String expectedClassNameDerivedFromXPath = JavaNaming.toJavaClassName(getLocalName(xPath)); + if (!jClassLocalName.equals(expectedClassNameDerivedFromXPath)) { + if (component.createGroupItem()) { + xPath += "/#item"; + } + _xpathToJClass.put(xPath, jClass); + return; + } + + if (mode.equals("field")) { + if (annotated instanceof ElementDecl) { + ElementDecl element = (ElementDecl) annotated; + + final boolean isReference = element.isReference(); + if (isReference) { + ElementDecl referredElement = element.getReference(); + // if that global element definition is a substitution head, + // we now + // need to do work out the global element's type, and use + // its + // JClass instance to defer the type of the member currently + // processed + Enumeration possibleSubstitutes = referredElement + .getSubstitutionGroupMembers(); + if (possibleSubstitutes.hasMoreElements()) { + XMLType referredType = referredElement.getType(); + String xPathType = XPathHelper.getSchemaLocation(referredType); + JClass typeJClass = (JClass) _xpathToJClass + .get(xPathType); + jClass.changeLocalName(typeJClass.getLocalName()); +// String typeXPath = XPathHelper +// .getSchemaLocation(referredElement); +// JClass referredJClass = (JClass) _xpathToJClass +// .get(typeXPath + "_class"); +// jClass.changeLocalName(referredJClass.getSuperClass() +// .getLocalName()); + } + return; + } + } + } + + final boolean alreadyProcessed = _xpathToJClass.containsKey(xPath); + + // if already processed, change the JClass instance accordingly + if (alreadyProcessed) { + JClass jClassAlreadyProcessed = (JClass) _xpathToJClass.get(xPath); + jClass.changeLocalName(jClassAlreadyProcessed.getLocalName()); + return; + } + + // register JClass instance for XPATH + _xpathToJClass.put(xPath, jClass); + + LOG.warn("Binding JClass[" + jClass.getName() + "] for XML schema structure " + xPath); + + // global elements don't need to change + final boolean isGlobalElement = _globalElements.contains(xPath); + if (isGlobalElement) { + return; + } + + // get local name + String localName = getLocalName(xPath); + + // resolve references to global elements + if (mode.equals("field") && annotated instanceof ElementDecl) { + ElementDecl element = (ElementDecl) annotated; + final boolean isReference = element.isReference(); + if (isReference) { + ElementDecl referredElement = element.getReference(); + // if that global element definition is a substitution head, we + // now + // need to do work out the global element's type, and use its + // JClass instance to defer the type of the member currently + // processed + Enumeration possibleSubstitutes = referredElement + .getSubstitutionGroupMembers(); + if (possibleSubstitutes.hasMoreElements()) { + String typeXPath = XPathHelper + .getSchemaLocation(referredElement); + JClass referredJClass = (JClass) _xpathToJClass + .get(typeXPath + "_class"); + jClass.changeLocalName(referredJClass.getSuperClass() + .getLocalName()); + } + return; + } + } + + // resolve conflict with a global element + final boolean conflictExistsWithGlobalElement = _globalElements + .contains("/" + localName); + if (conflictExistsWithGlobalElement) { + LOG.warn("resolving global element conflict for " + xPath); + changeClassInfoAsResultOfConflict(jClass, xPath); + return; + } + + // resolve conflict with another element + List localNamesList = (List) _localNames.get(localName); + if (localNamesList == null) { + // this name never occured before + ArrayList arrayList = new ArrayList(); + arrayList.add(xPath); + _localNames.put(localName, arrayList); + } else { + // this entry should be renamed + changeClassInfoAsResultOfConflict(jClass, xPath); + } + } + + /** + * Returns the local name of rooted XPATH expression. + * + * @param xPath + * An (rooted) XPATH expression + * @return the local name + */ + private String getLocalName(final String xPath) { + String localName = xPath.substring(xPath.lastIndexOf("/") + 1); + if (localName.startsWith(ExtendedBinding.COMPLEXTYPE_ID) + || localName.startsWith(ExtendedBinding.SIMPLETYPE_ID) + || localName.startsWith(ExtendedBinding.ENUMTYPE_ID) + || localName.startsWith(ExtendedBinding.GROUP_ID)) { + localName = localName.substring(localName.indexOf(":") + 1); + } + return localName; + } + + /** + * Changes the JClass' internal class name, as a result of an XPATH + * expression uniquely identifying an XML artefact within an XML schema. + * + * @param jClass + * The {@link JClass} instance whose local name should be + * changed. + * @param xpath + * XPATH expression used to defer the new local class name + */ + private void changeClassInfoAsResultOfConflict(final JClass jClass, + final String xpath) { + StringTokenizer stringTokenizer = new StringTokenizer(xpath, "/."); + String prefix = ""; + while (stringTokenizer.hasMoreTokens()) { + String token = stringTokenizer.nextToken(); + // break on last token + if (!stringTokenizer.hasMoreTokens()) { + break; + } + if (token.startsWith(ExtendedBinding.COMPLEXTYPE_ID) + || token.startsWith(ExtendedBinding.SIMPLETYPE_ID) + || token.startsWith(ExtendedBinding.ENUMTYPE_ID) + || token.startsWith(ExtendedBinding.GROUP_ID)) { + token = token.substring(token.indexOf(":") + 1); + } + prefix += JavaNaming.toJavaClassName(token); + } + + // set new classname + String newClassName = prefix + jClass.getLocalName(); + jClass.changeLocalName(newClassName); + } + +} Index: codegen/src/main/java/org/exolab/castor/builder/FactoryState.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/FactoryState.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/FactoryState.java (Arbeitskopie) @@ -51,6 +51,10 @@ import java.util.Vector; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.exolab.castor.builder.binding.ExtendedBinding; +import org.exolab.castor.builder.binding.XMLBindingComponent; import org.exolab.castor.builder.info.ClassInfo; import org.exolab.castor.builder.info.FieldInfo; import org.exolab.castor.xml.schema.Annotated; @@ -67,6 +71,8 @@ //- Member Variables -/ //--------------------/ + private static final Log LOG = LogFactory.getLog(FactoryState.class); + /** The JClass for which we are currently generating code. */ private final JClass _jClass; @@ -97,6 +103,8 @@ /** Keeps track of the different FactoryState. */ private FactoryState _parent = null; + private JClassRegistry _xmlInfoRegistry = null; + //----------------/ //- Constructors -/ //----------------/ @@ -106,9 +114,12 @@ * @param className Class name of the class currently being generated. * @param sgState Source Generator State object * @param packageName package name for generated code. + * @param component TODO */ - protected FactoryState(final String className, final SGStateInfo sgState, - final String packageName) { + protected FactoryState(final String className, + final SGStateInfo sgState, + final String packageName, + final XMLBindingComponent component) { if (sgState == null) { throw new IllegalArgumentException("SGStateInfo cannot be null."); } @@ -122,14 +133,22 @@ //} _jClass = new JClass(className); + + // if configured, try automatic class name conflict resolution + if (_sgState.getSourceGenerator().isAutomaticConflictResolution()) { + _xmlInfoRegistry = sgState.getSourceGenerator().getXMLInfoRegistry(); + _xmlInfoRegistry.bind(_jClass, component, "class"); + } + _classInfo = new ClassInfo(_jClass); - + _resolver = sgState; _packageName = packageName; //-- boundProperties _bound = sgState.getSourceGenerator().boundPropertiesEnabled(); + } //-- FactoryState //-----------/ Index: codegen/src/main/java/org/exolab/castor/builder/info/ClassInfo.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/info/ClassInfo.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/info/ClassInfo.java (Arbeitskopie) @@ -61,15 +61,11 @@ * @version $Revision$ $Date: 2006-04-13 07:37:49 -0600 (Thu, 13 Apr 2006) $ */ public final class ClassInfo extends XMLInfo { - /** Default initial number of attributes to make room for. */ - private static final int ATTR_VECTOR_LENGTH = 3; - /** Default initial number of elements to make room for. */ - private static final int ELEMENT_VECTOR_LENGTH = 5; - + /** Vector of FieldInfo's for all attributes that are members of this Class. */ - private Vector _atts = null; + private Vector _atts = new Vector(); /** Vector of FieldInfo's for all elements that are members of this Class. */ - private Vector _elements = null; + private Vector _elements = new Vector(); /** if this ClassInfo represents a TextField, this is this TextField's FieldInfo. */ private FieldInfo _textField = null; /** The base class. */ @@ -92,6 +88,9 @@ */ public ClassInfo(final JClass jClass) { super(XMLInfo.ELEMENT_TYPE); + +// LOG.info("Creating ClassInfo for JClass " + jClass.getName()); + if (jClass == null) { String err = "JClass passed to constructor of ClassInfo must not be null."; throw new IllegalArgumentException(err); @@ -119,9 +118,6 @@ switch(fieldInfo.getNodeType()) { case XMLInfo.ATTRIBUTE_TYPE: - if (_atts == null) { - _atts = new Vector(ATTR_VECTOR_LENGTH); - } if (!_atts.contains(fieldInfo)) { _atts.addElement(fieldInfo); } @@ -130,9 +126,6 @@ _textField = fieldInfo; break; default: - if (_elements == null) { - _elements = new Vector(ELEMENT_VECTOR_LENGTH); - } if (!_elements.contains(fieldInfo)) { _elements.addElement(fieldInfo); } Index: codegen/src/main/java/org/exolab/castor/builder/SingleClassGenerator.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/SingleClassGenerator.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/SingleClassGenerator.java (Arbeitskopie) @@ -53,14 +53,19 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.Enumeration; +import java.util.Map; import java.util.Properties; +import java.util.Set; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy; import org.exolab.castor.builder.conflictresolution.ClassNameCRStrategyRegistry; import org.exolab.castor.builder.descriptors.DescriptorSourceFactory; import org.exolab.castor.builder.info.ClassInfo; import org.exolab.castor.mapping.xml.MappingRoot; import org.exolab.castor.util.dialog.ConsoleDialog; +import org.exolab.castor.xml.schema.ElementDecl; import org.exolab.javasource.JClass; import org.exolab.javasource.JComment; import org.exolab.javasource.JNaming; @@ -74,6 +79,8 @@ * @version $Revision: 0000 $ $Date: $ */ public final class SingleClassGenerator { + + private static final Log LOG = LogFactory.getLog(SingleClassGenerator.class); /** * The default code header. Please leave "$" and "Id" separated with "+" so * that the CVS server does not expand it here. */ @@ -116,7 +123,7 @@ * The registry for {@link ClassNameCRStrategy} implementations. */ private ClassNameCRStrategyRegistry _classNameConflictResolutionStrategyRegistry; - + /** * Creates an instance of this class. * @param dialog A ConsoleDialog instance @@ -268,13 +275,34 @@ ClassInfo classInfo = state.resolve(jClass); + SGStateInfo stateAfterResolution = state; + //-- Is there a global element with the same name? + + String elementName = jClass.getLocalName().substring(0,1).toLowerCase() + + jClass.getLocalName().substring(1); + Map knownElements = _sourceGenerator.getKnownGlobalElements(); + if (knownElements.containsKey(elementName)) { + ElementDecl element = (ElementDecl) knownElements.get(elementName); + LOG.fatal("ABout to hit conflict against " + elementName); +// if (element.getParent() != element.getSchema()) { + stateAfterResolution = + _conflictStrategy.dealWithClassNameConflictAgainstGlobal(state, classInfo); +// } + } + + if (stateAfterResolution.getStatusCode() == SGStateInfo.STOP_STATUS) { + return false; + } + //-- Have we already processed a class with this name? JClass conflict = state.getProcessed(jClass.getName()); if (conflict != null && !state.getSuppressNonFatalWarnings()) { - SGStateInfo stateAfterResolution = - _conflictStrategy.dealWithClassNameConflict(state, classInfo, conflict); + stateAfterResolution = + _conflictStrategy.dealWithClassNameConflict(state, classInfo, conflict, + knownElements); return stateAfterResolution.getStatusCode() != SGStateInfo.STOP_STATUS; } + //-- Mark the current class as processed state.markAsProcessed(jClass); @@ -424,7 +452,9 @@ // check for existing .castor.xml file props = new Properties(); if (cdrFile.exists()) { - props.load(new FileInputStream(cdrFile)); + FileInputStream fileInputStream = new FileInputStream(cdrFile); + props.load(fileInputStream); + fileInputStream.close(); } sInfo.setCDRFile(cdrFilename, props); } @@ -452,4 +482,12 @@ this._conflictStrategy.setSingleClassGenerator(this); } + /** + * Returns the {@link SourceGenerator} instance that created this class. + * @return the {@link SourceGenerator} instance that created this class. + */ + public SourceGenerator getSourceGenerator() { + return _sourceGenerator; + } + } Index: codegen/src/main/java/org/exolab/castor/builder/EnumerationFactory.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/EnumerationFactory.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/EnumerationFactory.java (Arbeitskopie) @@ -72,9 +72,12 @@ * Creates a new EnumerationFactory for the builder configuration given. * @param config the current BuilderConfiguration instance. * @param groupNaming The group naming scheme to be used. + * @param sourceGenerator the calling source generator. */ - public EnumerationFactory(final BuilderConfiguration config, final GroupNaming groupNaming) { - super(config, null, groupNaming); + public EnumerationFactory(final BuilderConfiguration config, + final GroupNaming groupNaming, + final SourceGenerator sourceGenerator) { + super(config, null, groupNaming, sourceGenerator); _typeConversion = new TypeConversion(getConfig()); // TODO[WG]: add code to read in max. value from builder property file Index: codegen/src/main/java/org/exolab/castor/builder/BuilderConfiguration.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/BuilderConfiguration.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/BuilderConfiguration.java (Arbeitskopie) @@ -222,6 +222,17 @@ */ public static final String NAME_CONFLICT_STRATEGIES = "org.exolab.castor.builder.nameConflictStrategies"; + + /** + * Property specifying whether automatic class name conflict resolution + * should be used or not; defaults to false. + * + *
+ * automaticConflictResolution + *+ */ + public static final String AUTOMATIC_CONFLICT_RESOLUTION = + "org.exolab.castor.builder.automaticConflictResolution"; } //--Property /** @@ -658,4 +669,15 @@ } } //-- processNamespacePackageMappings + /** + * indicates whether automatic class name conflict resolution during + * XML code generation should take place or not. + * @return True if automatic mode should be used. + */ + public boolean isAutomaticConflictResolution() { + String automaticConflictResolutionProperty = + _localProps.getProperty(Property.AUTOMATIC_CONFLICT_RESOLUTION, "false"); + return "true".equalsIgnoreCase(automaticConflictResolutionProperty); + } + } //-- BuilderProperties Index: codegen/src/main/java/org/exolab/castor/builder/SourceFactory.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/SourceFactory.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/SourceFactory.java (Arbeitskopie) @@ -56,6 +56,7 @@ import org.exolab.castor.builder.binding.ExtendedBinding; import org.exolab.castor.builder.binding.XMLBindingComponent; +import org.exolab.castor.builder.binding.XPathHelper; import org.exolab.castor.builder.info.ClassInfo; import org.exolab.castor.builder.info.FieldInfo; import org.exolab.castor.builder.info.XMLInfo; @@ -146,18 +147,22 @@ * @param config the BuilderConfiguration instance (must not be null). * @param infoFactory the FieldInfoFactory to use * @param groupNaming Group naming scheme to be used. + * @param sourceGenerator the calling source generator. */ public SourceFactory(final BuilderConfiguration config, final FieldInfoFactory infoFactory, - final GroupNaming groupNaming) { - super(config, infoFactory, groupNaming); + final GroupNaming groupNaming, + final SourceGenerator sourceGenerator) { + super(config, infoFactory, groupNaming, sourceGenerator); // set the config into the info factory (CASTOR-1346) infoFactory.setBoundProperties(config.boundPropertiesEnabled()); - this._memberFactory = new MemberFactory(config, infoFactory, getGroupNaming()); - this._typeConversion = new TypeConversion(getConfig()); - this._enumerationFactory = new EnumerationFactory(getConfig(), getGroupNaming()); + this._memberFactory = + new MemberFactory(config, infoFactory, getGroupNaming(), sourceGenerator); + this._typeConversion = new TypeConversion(getConfig()); + this._enumerationFactory = + new EnumerationFactory(getConfig(), getGroupNaming(), sourceGenerator); } //-- SourceFactory /** @@ -296,7 +301,8 @@ } //3-- Create factoryState and chain it to sgState to prevent endless loop - FactoryState state = new FactoryState(className, sgState, packageName); + FactoryState state = new FactoryState(className, sgState, packageName, + component); state.setCreateGroupItem(createGroupItem); if (sgState.getCurrentFactoryState() != null) { state.setParent(sgState.getCurrentFactoryState()); @@ -388,7 +394,7 @@ } fInfo.setContainer(true); String newClassName = className.substring(0, className.length() - 4); - state = new FactoryState(newClassName, sgState, packageName); + state = new FactoryState(newClassName, sgState, packageName, component); classInfo = state.getClassInfo(); jClass = state.getJClass(); initialize(jClass); @@ -754,7 +760,9 @@ className = resolveClassName(className, packageName); - FactoryState state = new FactoryState(className, sgState, packageName); +// FactoryState state = new FactoryState(className, sgState, packageName, simpleType, binding); + FactoryState state = new FactoryState(className, sgState, packageName, comp); + state.setParent(sgState.getCurrentFactoryState()); ClassInfo classInfo = state.getClassInfo(); @@ -1003,7 +1011,7 @@ //-- search for proper base class JClass returnType = findBaseClass(parent, sgState); JMethod jMethod = new JMethod(methodName, returnType, - "the unmarshaled " + returnType.getName()); + "the unmarshaled " + returnType); jMethod.getModifiers().setStatic(true); jMethod.addException(SGTypes.MARSHAL_EXCEPTION, "if object is null or if any SAXException is thrown during marshaling"); Index: codegen/src/main/java/org/exolab/castor/builder/XMLFieldHandlerFactory.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/XMLFieldHandlerFactory.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/XMLFieldHandlerFactory.java (Arbeitskopie) @@ -321,7 +321,8 @@ if (any || forGeneralizedHandler || isEnumerated || xsType.isPrimitive() || xsType.getJType().isArray() - || (xsType.getType() == XSType.STRING_TYPE) || isAbstract) { + || (xsType.getType() == XSType.STRING_TYPE) + || isAbstract) { jsc.append("null;"); } else { jsc.append(xsType.newInstanceCode()); Index: codegen/src/main/java/org/exolab/castor/builder/binding/xml/Binding.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/binding/xml/Binding.java (Revision 6793) +++ codegen/src/main/java/org/exolab/castor/builder/binding/xml/Binding.java (Arbeitskopie) @@ -11,6 +11,7 @@ //- Imported classes and packages -/ //---------------------------------/ +import org.exolab.castor.builder.binding.xml.types.BindingType; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; @@ -103,6 +104,8 @@ this._groupBindingList = new java.util.ArrayList(); this._enumBindingList = new java.util.ArrayList(); this._simpleTypeBindingList = new java.util.ArrayList(); + + this._defaultBindingType = BindingType.ELEMENT; } Index: codegen/src/main/java/org/exolab/castor/builder/binding/XPathHelper.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/binding/XPathHelper.java (Revision 0) +++ codegen/src/main/java/org/exolab/castor/builder/binding/XPathHelper.java (Revision 0) @@ -0,0 +1,181 @@ +/* + * Copyright 2007 Werner Guttmann + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.exolab.castor.builder.binding; + +import org.exolab.castor.xml.schema.AttributeDecl; +import org.exolab.castor.xml.schema.ComplexType; +import org.exolab.castor.xml.schema.ElementDecl; +import org.exolab.castor.xml.schema.Group; +import org.exolab.castor.xml.schema.ModelGroup; +import org.exolab.castor.xml.schema.SimpleType; +import org.exolab.castor.xml.schema.Structure; + +/** + * Helper class to assemble an XPATH expression to qualify the path of + * an XML schema structure from the XML schema root. + * @author Werner Guttmann + * @since 1.1 + */ +public class XPathHelper { + + /** + * Initial size of the {@link StringBuffer} used to asseble the XPATH + * expression. + */ + private static final int INITIAL_XPATH_SIZE = 50; + + /** + * Deduces an XPATH expression qualifying the path from the schema root + * to the given structure in question. + * @param structure AN XML structure. + * @param location The XPATH expression to be created. + */ + public static void getSchemaLocation( + final Structure structure, + final StringBuffer location) { + if (structure == null) { + throw new IllegalArgumentException("Structure cannot be null"); + } + + if (location == null) { + throw new IllegalArgumentException("location cannot be null"); + } + + Structure parent = null; + switch (structure.getStructureType()) { + case Structure.ELEMENT: + parent = ((ElementDecl) structure).getParent(); + if (parent.getStructureType() != Structure.SCHEMA) { + getSchemaLocation(parent, location); + } + location.append(ExtendedBinding.PATH_SEPARATOR); + location.append(((ElementDecl) structure).getName()); + break; + + case Structure.COMPLEX_TYPE: + ComplexType complexType = (ComplexType) structure; + parent = (complexType).getParent(); + if (parent.getStructureType() != Structure.SCHEMA) { + getSchemaLocation(parent, location); + } + if (complexType.getName() != null) { + location.append(ExtendedBinding.PATH_SEPARATOR); + location.append(ExtendedBinding.COMPLEXTYPE_ID); + location.append(((ComplexType) structure).getName()); + } + // else { + // location.append(PATH_SEPARATOR); + // location.append(COMPLEXTYPE_ID); + // location.append("anonymous"); + // } + break; + + case Structure.SIMPLE_TYPE: + SimpleType simpleType = (SimpleType) structure; + parent = simpleType.getParent(); + if (parent != null && parent.getStructureType() != Structure.SCHEMA) { + getSchemaLocation(parent, location); + } + + if (parent != null && simpleType.getName() != null) { + location.append(ExtendedBinding.PATH_SEPARATOR); + location.append(ExtendedBinding.ENUMTYPE_ID); + location.append(((SimpleType) structure).getName()); + } + // else { + // location.append(PATH_SEPARATOR); + // location.append(ENUMTYPE_ID); + // location.append("anonymous"); + // } + break; + + case Structure.MODELGROUP: + ModelGroup group = (ModelGroup) structure; + parent = group.getParent(); + if (parent.getStructureType() != Structure.SCHEMA) { + getSchemaLocation(parent, location); + } + if (group.getName() != null) { + location.append(ExtendedBinding.PATH_SEPARATOR); + location.append(ExtendedBinding.GROUP_ID); + location.append(group.getName()); + } + break; + + case Structure.ATTRIBUTE: + parent = ((AttributeDecl) structure).getParent(); + if (parent.getStructureType() != Structure.SCHEMA) { + getSchemaLocation(parent, location); + } + location.append(ExtendedBinding.PATH_SEPARATOR); + location.append(ExtendedBinding.ATTRIBUTE_PREFIX); + location.append(((AttributeDecl) structure).getName()); + break; + + case Structure.GROUP: + // --we are inside a complexType + getSchemaLocation(((Group) structure).getParent(), location); + break; + + // case Structure.ATTRIBUTE_GROUP: + // //handle the real location + + default: + break; + } + } + + /** + * Returns a string (XPATH) representation of an XML Schema component. This + * representation is directly adapted from XPath and will used as a key to + * store the component bindings. + *
+ * The location of a structure is composed of two parts: + *
+ * The local location is defined by: + *
- * The location of a structure is composed of two parts: - *
- * The local location is defined by: - *