Index: codegen/src/main/java/org/exolab/javasource/JClass.java =================================================================== --- codegen/src/main/java/org/exolab/javasource/JClass.java (Revision 6806) +++ 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 6806) +++ 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 6806) +++ 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,17 @@ if (xsType == null) { String className = component.getQualifiedName(); JClass jClass = new JClass(className); + if (component.isAbstract()) { + jClass.getModifiers().setAbstract(true); + } + 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 6806) +++ 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 6806) +++ codegen/src/main/java/org/exolab/castor/builder/conflictresolution/WarningViaDialogClassNameCRStrategy.java (Arbeitskopie) @@ -18,7 +18,7 @@ import java.util.Enumeration; 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; @@ -102,7 +102,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 +112,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(" '"); Index: codegen/src/main/java/org/exolab/castor/builder/conflictresolution/InformViaLogClassNameCRStrategy.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/conflictresolution/InformViaLogClassNameCRStrategy.java (Revision 6806) +++ codegen/src/main/java/org/exolab/castor/builder/conflictresolution/InformViaLogClassNameCRStrategy.java (Arbeitskopie) @@ -20,7 +20,7 @@ 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; @@ -97,7 +97,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 +107,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(" '"); Index: codegen/src/main/java/org/exolab/castor/builder/SourceGenerator.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/SourceGenerator.java (Revision 6806) +++ codegen/src/main/java/org/exolab/castor/builder/SourceGenerator.java (Arbeitskopie) @@ -65,6 +65,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; @@ -145,7 +146,7 @@ private final ConsoleDialog _dialog; /** A vector that keeps track of all the schemas processed. */ private final Vector _schemasProcessed = new Vector(7); - + /** True if we should suppress non-fatal warnings. */ private boolean _suppressNonFatalWarnings = false; /** Determines whether or not to print extra messages. */ @@ -180,6 +181,8 @@ private GroupNaming _groupNaming = null; /** Strategy for name conflict resolution. */ private String _nameConflictStrategy = WarningViaDialogClassNameCRStrategy.NAME; + /** JClass to XPATH registry; used for class name conflict resolution. */ + private JClassRegistry _xmlInfoRegistry; /** * Creates a SourceGenerator using the default FieldInfo factory. @@ -220,6 +223,9 @@ _singleClassGenerator = new SingleClassGenerator(_dialog, this, _nameConflictStrategy); _bindingComponent = new XMLBindingComponent(this, _groupNaming); setBinding(binding); + + _xmlInfoRegistry = new JClassRegistry(); + } //-- SourceGenerator /** @@ -535,7 +541,7 @@ * @throws IOException if an IOException occurs writing the new source files */ public void generateSource(final InputSource source, final String packageName) - throws IOException { + throws IOException { // -- get default parser from Configuration Parser parser = null; try { @@ -630,7 +636,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 +690,16 @@ Enumeration structures; + //-- register all global element names for name conflict resolution + for (structures = schema.getElementDecls(); structures.hasMoreElements(); ) { + ElementDecl element = (ElementDecl) structures.nextElement(); + _xmlInfoRegistry.prebindGlobalElement(XPathHelper.getSchemaLocation(element)); + } + for (structures = schema.getModelGroups(); structures.hasMoreElements(); ) { + ModelGroup modelGroup = (ModelGroup) structures.nextElement(); + _xmlInfoRegistry.prebindGlobalElement(XPathHelper.getSchemaLocation(modelGroup)); + } + //-- handle all top-level element declarations for (structures = schema.getElementDecls(); structures.hasMoreElements(); ) { createClasses((ElementDecl) structures.nextElement(), sInfo); @@ -1100,4 +1116,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,298 @@ +/* + * 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.ModelGroup; +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); + String localXPath = getLocalXPath(xPath); + String untypedXPath = xPath; + + // TODO: it could happen that we silently ignore a custom package as defined in a binding - FIX ! + + // get local name + String localName = getLocalName(xPath); + + if (annotated instanceof ElementDecl) { + ElementDecl element = (ElementDecl) annotated; + String typexPath = XPathHelper.getSchemaLocation(element.getType()); + xPath += "[" + typexPath + "]"; + } + + String jClassLocalName = jClass.getLocalName(); + String expectedClassNameDerivedFromXPath = JavaNaming.toJavaClassName(localName); + if (!jClassLocalName.equals(expectedClassNameDerivedFromXPath)) { + if (component.createGroupItem()) { + xPath += "/#item"; + } + _xpathToJClass.put(xPath, jClass); + return; + } + + if (mode.equals("field")) { + if (annotated instanceof ModelGroup) { + ModelGroup group = (ModelGroup) annotated; + final boolean isReference = group.isReference(); + if (isReference) { + return; + } + } + + 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); + if (typeJClass != null) { + jClass.changeLocalName(typeJClass.getLocalName()); + } else { + // manually deriving class name for referenced type + XMLBindingComponent temp = component; + temp.setView(referredType); + jClass.changeLocalName(temp.getJavaClassName()); + } +// 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; + } + + // 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("/" + localXPath); + if (conflictExistsWithGlobalElement) { + LOG.warn("resolving global element conflict for " + xPath); + changeClassInfoAsResultOfConflict(jClass, untypedXPath); + 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, untypedXPath); + } + } + + /** + * 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; + } + + /** + * Returns the local part of rooted XPATH expression. + * + * @param xPath + * An (rooted) XPATH expression + * @return the local part + */ + private String getLocalXPath(final String xPath) { + return xPath.substring(xPath.lastIndexOf("/") + 1); + } + + /** + * 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 6806) +++ codegen/src/main/java/org/exolab/castor/builder/FactoryState.java (Arbeitskopie) @@ -51,6 +51,7 @@ import java.util.Vector; +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; @@ -97,6 +98,11 @@ /** Keeps track of the different FactoryState. */ private FactoryState _parent = null; + /** + * {@link JClassRegistry} instance used for automatic class name conflict resolution. + */ + private JClassRegistry _xmlInfoRegistry = null; + //----------------/ //- Constructors -/ //----------------/ @@ -106,9 +112,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 +131,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 6806) +++ codegen/src/main/java/org/exolab/castor/builder/info/ClassInfo.java (Arbeitskopie) @@ -61,15 +61,10 @@ * @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. */ @@ -119,9 +114,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 +122,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 6806) +++ codegen/src/main/java/org/exolab/castor/builder/SingleClassGenerator.java (Arbeitskopie) @@ -116,7 +116,7 @@ * The registry for {@link ClassNameCRStrategy} implementations. */ private ClassNameCRStrategyRegistry _classNameConflictResolutionStrategyRegistry; - + /** * Creates an instance of this class. * @param dialog A ConsoleDialog instance @@ -452,4 +452,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 6806) +++ 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 @@ -84,7 +87,7 @@ /** * Creates all the necessary enumeration code for a given SimpleType. * - * @param binding + * @param binding Extended binding instance * @param simpleType the SimpleType we are processing an enumeration for * @param state our current state * @see #processEnumerationAsBaseType @@ -457,7 +460,7 @@ * public {type} valueOf(String strValue); * } * - * @param binding + * @param binding Extended binding instance * @param simpleType the SimpleType we are processing an enumeration for * @param state our current state */ Index: codegen/src/main/java/org/exolab/castor/builder/BuilderConfiguration.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/BuilderConfiguration.java (Revision 6806) +++ 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 6806) +++ 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,8 @@ className = resolveClassName(className, packageName); - FactoryState state = new FactoryState(className, sgState, packageName); + FactoryState state = new FactoryState(className, sgState, packageName, comp); + state.setParent(sgState.getCurrentFactoryState()); ClassInfo classInfo = state.getClassInfo(); @@ -1003,7 +1010,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 6806) +++ 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 6806) +++ 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: + *

    + *
  1. the location of the parent structure
  2. + *
  3. the local location of the structure itself
  4. + *
+ *

+ * The local location is defined by: + *

+ * Note that only top-level groups and complexTypes are named and thus will + * + * @param structure the structure for which to return a representation. + * @return a string representation of an XML Schema component. + */ + public static String getSchemaLocation(final Structure structure) { + if (structure == null) { + return null; + } + StringBuffer buffer = new StringBuffer(INITIAL_XPATH_SIZE); + getSchemaLocation(structure, buffer); + return buffer.toString(); + } + +} Index: codegen/src/main/java/org/exolab/castor/builder/binding/ExtendedBinding.java =================================================================== --- codegen/src/main/java/org/exolab/castor/builder/binding/ExtendedBinding.java (Revision 6806) +++ codegen/src/main/java/org/exolab/castor/builder/binding/ExtendedBinding.java (Arbeitskopie) @@ -51,11 +51,7 @@ import org.exolab.castor.builder.binding.xml.ComponentBindingType; 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.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; /** @@ -94,11 +90,26 @@ * Constants needed to create the XPath. */ protected static final String PATH_SEPARATOR = "/"; + /** + * Prefix used to identify an attribute. + */ protected static final String ATTRIBUTE_PREFIX = "@"; - protected static final String COMPLEXTYPE_ID = "complexType:"; - protected static final String SIMPLETYPE_ID = "simpleType:"; - protected static final String ENUMTYPE_ID = "enumType:"; - protected static final String GROUP_ID = "group:"; + /** + * Prefix used to identify a complexType. + */ + public static final String COMPLEXTYPE_ID = "complexType:"; + /** + * Prefix used to identity a simplyType. + */ + public static final String SIMPLETYPE_ID = "simpleType:"; + /** + * Prefix used to identify an enumeration. + */ + public static final String ENUMTYPE_ID = "enumType:"; + /** + * Prefix used to identify a model group. + */ + public static final String GROUP_ID = "group:"; private static final short ATTRIBUTE = 10; private static final short ELEMENT = 11; @@ -152,7 +163,7 @@ processBindingComponents(); } - String xPath = getSchemaLocation(annotated); + String xPath = XPathHelper.getSchemaLocation(annotated); ComponentBindingType result = lookupComponentBindingType(xPath); if (result == null) { //--handle reference @@ -164,7 +175,7 @@ if (result == null) { ElementDecl element = (ElementDecl) annotated; if (element.isReference()) { - xPath = getSchemaLocation(element.getReference()); + xPath = XPathHelper.getSchemaLocation(element.getReference()); result = lookupComponentBindingType(xPath); } //--discard the element @@ -178,7 +189,7 @@ //--global element then we use the global binding AttributeDecl attribute = (AttributeDecl) annotated; if (attribute.isReference()) { - xPath = getSchemaLocation(attribute.getReference()); + xPath = XPathHelper.getSchemaLocation(attribute.getReference()); result = lookupComponentBindingType(xPath); } attribute = null; @@ -203,7 +214,7 @@ * @return The ComponentBindingType that correspond to the given Schema * Location XPath, Null is returned when no ComponentBindingType is * found. - * @see org.exolab.castor.builder.binding.ExtendedBinding#getSchemaLocation(Structure) + * @see org.exolab.castor.builder.binding.XPathHelper#getSchemaLocation(Structure) */ private ComponentBindingType lookupComponentBindingType(final String xPath) { if (xPath == null) { @@ -277,7 +288,7 @@ * * @param binding the ComponentBindingType for which we want to process the * children. - * @param currentPath the current XPath location that points to the parent of the + * @param xPath the current XPath location that points to the parent of the * given ComponentBindingType. * @param type an integer that indicates the type of the given * ComponentBindingType @@ -407,136 +418,4 @@ tempBindings = null; } - /** - * Returns a string 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: - *

    - *
  1. the location of the parent structure
  2. - *
  3. the local location of the structure itself
  4. - *
- *

- * The local location is defined by: - *

- * Note that only top-level groups and complexTypes are named and thus will - * - * @param structure the structure for which to return a representation. - * @return a string representation of an XML Schema Component. - */ - public static String getSchemaLocation(final Structure structure) { - if (structure == null) { - return null; - } - StringBuffer buffer = new StringBuffer(30); - getSchemaLocation(structure, buffer); - return buffer.toString(); - } - - private 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(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(PATH_SEPARATOR); - location.append(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(PATH_SEPARATOR); - location.append(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(GROUP_ID); - location.append(group.getName()); - } - break; - - case Structure.ATTRIBUTE: - parent = ((AttributeDecl) structure).getParent(); - if (parent.getStructureType() != Structure.SCHEMA) { - getSchemaLocation(parent, location); - } - location.append(PATH_SEPARATOR); - location.append(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; - } - } - } Index: codegen/src/main/resources/org/exolab/castor/builder/binding/binding.xsd =================================================================== --- codegen/src/main/resources/org/exolab/castor/builder/binding/binding.xsd (Revision 6806) +++ codegen/src/main/resources/org/exolab/castor/builder/binding/binding.xsd (Arbeitskopie) @@ -42,7 +42,7 @@ - + Index: codegen/src/main/resources/org/exolab/castor/builder/castorbuilder.properties =================================================================== --- codegen/src/main/resources/org/exolab/castor/builder/castorbuilder.properties (Revision 6806) +++ codegen/src/main/resources/org/exolab/castor/builder/castorbuilder.properties (Arbeitskopie) @@ -96,3 +96,8 @@ org.exolab.castor.builder.nameConflictStrategies=\ org.exolab.castor.builder.conflictresolution.WarningViaDialogClassNameCRStrategy,\ org.exolab.castor.builder.conflictresolution.InformViaLogClassNameCRStrategy + +# Specifies whether automatic class name conflict resolution +# should be used or not; defaults to false. +# +org.exolab.castor.builder.automaticConflictResolution=false Index: src/main/java/org/exolab/castor/xml/schema/ElementDecl.java =================================================================== --- src/main/java/org/exolab/castor/xml/schema/ElementDecl.java (Revision 6806) +++ src/main/java/org/exolab/castor/xml/schema/ElementDecl.java (Arbeitskopie) @@ -452,6 +452,9 @@ * @return true if this element definition is abstract **/ public boolean isAbstract() { + if (isReference()) { + return _referencedElement.isAbstract(); + } return _isAbstract; } //-- isAbstract Index: src/main/java/org/exolab/castor/xml/schema/TypeReference.java =================================================================== --- src/main/java/org/exolab/castor/xml/schema/TypeReference.java (Revision 6806) +++ src/main/java/org/exolab/castor/xml/schema/TypeReference.java (Arbeitskopie) @@ -53,7 +53,7 @@ * @author Arnaud Berry * @version $Revision: **/ -class TypeReference extends XMLType { +public class TypeReference extends XMLType { /** SerialVersionUID */ private static final long serialVersionUID = -8707313918028332092L; Index: src/main/java/org/exolab/castor/xml/schema/reader/ElementUnmarshaller.java =================================================================== --- src/main/java/org/exolab/castor/xml/schema/reader/ElementUnmarshaller.java (Revision 6806) +++ src/main/java/org/exolab/castor/xml/schema/reader/ElementUnmarshaller.java (Arbeitskopie) @@ -160,7 +160,13 @@ //-- @final _element.setFinal(atts.getValue(SchemaNames.FINAL_ATTR)); - + + //-- @abstract + final boolean isAbstract = new Boolean(atts.getValue(SchemaNames.ABSTRACT)).booleanValue(); + if (isAbstract) { + _element.setAbstract(isAbstract); + } + //-- @fixed attValue = atts.getValue(SchemaNames.FIXED_ATTR); if (attValue != null) { Index: src/main/java/org/exolab/castor/xml/UnmarshalState.java =================================================================== --- src/main/java/org/exolab/castor/xml/UnmarshalState.java (Revision 6806) +++ src/main/java/org/exolab/castor/xml/UnmarshalState.java (Arbeitskopie) @@ -139,10 +139,18 @@ boolean trailingWhitespaceRemoved = false; - /* For sequence validation */ + /** + * Index of next expected sequence element; used during validation + */ public int expectedIndex = 0; /** + * Indicates (during validation) whether the current field descriptor + * points to a multi-valued element. + */ + public boolean withinMultivaluedElement = false; + + /** * The UnmarshalState which contains information * about the parent object for object containted * within this state. Used when handling Index: src/main/java/org/exolab/castor/xml/util/XMLClassDescriptorImpl.java =================================================================== --- src/main/java/org/exolab/castor/xml/util/XMLClassDescriptorImpl.java (Revision 6806) +++ src/main/java/org/exolab/castor/xml/util/XMLClassDescriptorImpl.java (Arbeitskopie) @@ -370,14 +370,14 @@ } // multi valued flag - if (expectedElementDescriptor.isMultivalued() && !withinMultivaluedElement) { - withinMultivaluedElement = true; + if (expectedElementDescriptor.isMultivalued() && !parentState.withinMultivaluedElement) { + parentState.withinMultivaluedElement = true; } if (!anyNode && !(expectedElementName).equals(elementName)) { // handle multi-valued fields if (expectedElementDescriptor.isMultivalued()) { - withinMultivaluedElement = false; + parentState.withinMultivaluedElement = false; parentState.expectedIndex++; checkDescriptorForCorrectOrderWithinSequence(elementDescriptor, parentState, xmlName); return; @@ -394,7 +394,7 @@ } - if (!withinMultivaluedElement) { + if (!parentState.withinMultivaluedElement) { parentState.expectedIndex++; } } Index: xmlctf/tests/MasterTestSuite/sourcegenerator/Binding/Invoice/bindingInvoice.xml =================================================================== --- xmlctf/tests/MasterTestSuite/sourcegenerator/Binding/Invoice/bindingInvoice.xml (Revision 6806) +++ xmlctf/tests/MasterTestSuite/sourcegenerator/Binding/Invoice/bindingInvoice.xml (Arbeitskopie) @@ -9,12 +9,12 @@ - + - + @@ -29,7 +29,7 @@ - +