Hi, here's a patch for the situation where the same element can
occur more than once in a complex type (e.g., in different
places within a sequence.)

Also, the default attribute didn't seem to work with attributese of
types NMTOKENS (at least not with -type j2), so I fixed that (for
-type j2).

This is a diff against the latest version in cvs.

Attached is a very simple schema on which the current version of
castor fails, and the patched version succeeds.

Hope this is useful.

Thanks
Bruce Cota
Unicon, Inc.



===================================================================
RCS file: /cvs/castor/castor/src/main/org/exolab/castor/builder/CollectionInfo.java,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 CollectionInfo.java
--- src/main/org/exolab/castor/builder/CollectionInfo.java      3 Mar 2003 07:07:41 
-0000       1.1.1.1
+++ src/main/org/exolab/castor/builder/CollectionInfo.java      18 May 2003 17:52:20 
-0000
@@ -55,6 +55,7 @@
 import org.exolab.castor.xml.JavaNaming;
 import org.exolab.javasource.*;
 
+import java.util.StringTokenizer;
 import java.util.Vector;
 
 /**
@@ -77,6 +78,7 @@
 
     private FieldInfo content   = null;
     private String elementName;
+       protected Vector initValues = null;  //initial values for the collection
 
     /**
      * Creates a new CollectionInfo
@@ -107,6 +109,7 @@
     public String getReadMethodName() {
         StringBuffer sb = new StringBuffer("get");
         sb.append(JavaNaming.toJavaClassName(getElementName()));
+               sb.append(getSuffix());
         // fix for avoiding compilation conflict sb.append("List");
         return sb.toString();
     } //-- getReadMethodName
@@ -115,9 +118,25 @@
         StringBuffer sb = new StringBuffer();
         sb.append("add");
         sb.append(JavaNaming.toJavaClassName(getElementName()));
+               sb.append(getSuffix());
         return sb.toString();
     } //-- getWriteMethodName
 
+       
+       /* Sets the default value for this FieldInfo.  
+        * This must be a WS-separated list of strings.
+     * @param defaultValue the default value
+        **/
+    public void setDefaultValue(String defaultValue) {
+               StringTokenizer tokenizer = new StringTokenizer(defaultValue);
+               int numTokens = tokenizer.countTokens();
+               initValues = new Vector(numTokens);
+               while (tokenizer.hasMoreElements()) {
+                       initValues.add(tokenizer.nextToken());
+               }
+    } //-- setDefaultValue;
+
+
     //------------------/
     //- Public Methods -/
     //------------------/
@@ -143,6 +162,7 @@
         //---------------------/
 
         String cName = JavaNaming.toJavaClassName(getElementName());
+               cName += getSuffix();
         method = new JMethod(null, "add"+cName);
         jClass.addMethod(method);
         method.addException(SGTypes.IndexOutOfBoundsException);
Index: src/main/org/exolab/castor/builder/CollectionInfoJ2.java
===================================================================
RCS file: /cvs/castor/castor/src/main/org/exolab/castor/builder/CollectionInfoJ2.java,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 CollectionInfoJ2.java
--- src/main/org/exolab/castor/builder/CollectionInfoJ2.java    3 Mar 2003 07:07:42 
-0000       1.1.1.1
+++ src/main/org/exolab/castor/builder/CollectionInfoJ2.java    18 May 2003 17:52:20 
-0000
@@ -85,8 +85,26 @@
     **/
     public void generateInitializerCode(JSourceCode jsc) {
         jsc.add(getName());
-        jsc.append(" = new ArrayList();");
-    } //-- generateConstructorCode
+
+               int numValues = -1;
+               if (initValues != null && initValues.size() > 0) {
+                       numValues = initValues.size();
+               }
+               
+        jsc.append(" = new ArrayList(");
+               if (numValues > 0) {
+                       jsc.append("" + initValues.size());
+               }
+        jsc.append(");");
+               
+               for (int i=0; i<numValues; ++i) {
+                       jsc.add(getName());
+                       jsc.append(".add(\"");
+                       jsc.append((String)initValues.get(i));
+                       jsc.append("\");");
+               }
+
+   } //-- generateConstructorCode
 
     //------------------/
     //- Public Methods -/
@@ -109,6 +127,7 @@
         JSourceCode jsc = null;
 
         String cName = JavaNaming.toJavaClassName(getElementName());
+               cName += getSuffix();
 
         //-- add{Name}(Object)
         method = new JMethod(null, "add"+cName);
@@ -180,7 +199,7 @@
             //-- Reference setter (non type-safe)
             String suffix = 
SourceGenerator.getProperty(this.REFERENCE_SUFFIX_PROPERTY, 
                 "AsReference");
-            method = new JMethod(null, "set" + cName + suffix);
+            method = new JMethod(null, "set" + cName);
             method.addParameter(vParam);
             jClass.addMethod(method);
             createSetCollectionReferenceMethod(method);
@@ -514,7 +533,8 @@
     **/
     public void createSetCollectionMethod(JMethod method) {
 
-        String cName = JavaNaming.toJavaMemberName(getElementName());
+        String cName = JavaNaming.toJavaMemberName(getElementName())
+                       + getSuffix();
         
         //-- get param name
         String paramName = method.getParameter(0).getName();
@@ -570,7 +590,8 @@
     **/
     public void createSetCollectionReferenceMethod(JMethod method) {
 
-        String cName = JavaNaming.toJavaMemberName(getElementName());
+        String cName = JavaNaming.toJavaMemberName(getElementName())
+                       + getSuffix();
         
         //-- get param name
         String paramName = method.getParameter(0).getName();
Index: src/main/org/exolab/castor/builder/FieldInfo.java
===================================================================
RCS file: /cvs/castor/castor/src/main/org/exolab/castor/builder/FieldInfo.java,v
retrieving revision 1.2
diff -u -r1.2 FieldInfo.java
--- src/main/org/exolab/castor/builder/FieldInfo.java   8 Mar 2003 07:35:42 -0000      
 1.2
+++ src/main/org/exolab/castor/builder/FieldInfo.java   18 May 2003 17:52:21 -0000
@@ -63,7 +63,9 @@
     /**
      * The Java name for Members described by this FieldInfo
     **/
-    private String name = null;
+       private String _suffix = "";
+
+    private String name = null; //Added to method names to make sure they are unique
 
 
     private ClassInfo declaringClassInfo = null;
@@ -494,6 +496,23 @@
     public String getName() {
         return this.name;
     } //-- getName
+
+       /**
+     * Returns the suffix used to methods unique.
+     * @return the suffix
+        **/
+    public String getSuffix() {
+        return this._suffix;
+    }
+       
+    /**
+     * Sets the suffix used to methods unique.
+        * @param suffix
+        **/
+    public void setSuffix(String suffix) {
+        this._suffix = suffix;
+    }
+
 
     /**
      * Returns true if this FieldInfo represents a bound property
Index: src/main/org/exolab/castor/builder/MemberFactory.java
===================================================================
RCS file: /cvs/castor/castor/src/main/org/exolab/castor/builder/MemberFactory.java,v
retrieving revision 1.2
diff -u -r1.2 MemberFactory.java
--- src/main/org/exolab/castor/builder/MemberFactory.java       3 Mar 2003 09:57:14 
-0000       1.2
+++ src/main/org/exolab/castor/builder/MemberFactory.java       18 May 2003 17:52:21 
-0000
@@ -58,6 +58,7 @@
 
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.HashMap;
 
 /**
  * @author <a href="mailto:[EMAIL PROTECTED]">Keith Visco</a>
@@ -179,16 +180,18 @@
      *
      * @param component the XMLBindingComponent to create the
      * FieldInfo for
+        * @param resolver
+        * @param usedNames HashMap of field names already used (to avoid conflicts)
      * @return the FieldInfo for the given attribute declaration
      */
     public FieldInfo createFieldInfo
-        (XMLBindingComponent component, ClassInfoResolver resolver)
+        (XMLBindingComponent component, ClassInfoResolver resolver, HashMap usedNames)
     {
         
         String xmlName = component.getXMLName();
-        String memberName = component.getJavaMemberName();
-        if (!memberName.startsWith("_"))
-            memberName = "_"+memberName;
+        String memberName = getMemberName(component);
+               String suffix = uniqueSuffix(memberName, usedNames);
+               memberName += suffix;
 
         XMLType xmlType = component.getXMLType();
         ClassInfo classInfo = resolver.resolve(component);
@@ -389,7 +392,8 @@
             }
             //don't generate code for date/time type since the constructor that parses
             //a string is throwing exception
-            else if (!xsType.getJType().isPrimitive() && !xsType.isDateTime()) {
+            else if (!xsType.getJType().isPrimitive() && !xsType.isDateTime() 
+                                        && !(fieldInfo instanceof CollectionInfo)) { 
                  //XXX This works only if a constructor
                  //XXX with String as parameter exists
                  value = "new "+xsType.getJType().toString()+"(\""+value+"\")";
@@ -504,5 +508,40 @@
         }
         return new String(newChars,0,count);
     }
+
+       /**
+        * Factored out of createFieldInfo(XMLBindingComponent, ClassInfoResolver)
+        * Create a member name from an XMLBindingComponent.
+        * @param component
+        * @return the name
+        */
+       public static String getMemberName(XMLBindingComponent component) {
+               String memberName = component.getJavaMemberName();
+        if (!memberName.startsWith("_"))
+            memberName = "_"+memberName;
+               return memberName;
+       }
+
+       /**
+        * Utility for generating a unique name that is not already present in a 
HashMap.
+        * @param name
+        * @param HashMap
+        * @return a suffix that will make the name unique.  The name+suffix is also 
added to the map.
+        */
+       public static String uniqueSuffix(String name, HashMap usedNames) {
+               if (usedNames.get(name) == null) {
+                       usedNames.put(name, "true");
+                       return "";
+               } else {
+                       int namect = 1;
+                       while (usedNames.get(name+"_"+namect) != null) {
+                               namect += 1;
+                       }
+                       String suffix = "_" + namect;
+                       usedNames.put(name+suffix, "true");
+                       return suffix;
+               }
+       }
+
 
 } //-- MemberFactory
Index: src/main/org/exolab/castor/builder/SourceFactory.java
===================================================================
RCS file: /cvs/castor/castor/src/main/org/exolab/castor/builder/SourceFactory.java,v
retrieving revision 1.4
diff -u -r1.4 SourceFactory.java
--- src/main/org/exolab/castor/builder/SourceFactory.java       24 Apr 2003 02:07:49 
-0000      1.4
+++ src/main/org/exolab/castor/builder/SourceFactory.java       18 May 2003 17:52:23 
-0000
@@ -60,6 +60,7 @@
 import org.exolab.javasource.*;
 
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Vector;
 
 /**
@@ -395,6 +396,7 @@
             //-- create main group class
             String fname = component.getJavaClassName() + ITEM_NAME;
             fname  = JavaNaming.toJavaMemberName(fname, false);
+                       fname = jClass.uniqueFieldName(fname);
 
             FieldInfo fInfo = null;
             if (createForGroup) {
@@ -1192,6 +1194,9 @@
         if (complexType == null)
             return;
 
+               //track field names used to avoid conflicts
+               HashMap namesUsed = new HashMap();
+
         Enumeration enum = complexType.getAttributeDecls();
         XMLBindingComponent component = new XMLBindingComponent();
         if (_binding != null) component.setBinding(_binding);
@@ -1210,7 +1215,7 @@
                     createSourceCode(sType, state.getSGStateInfo());
                 }
             }
-            FieldInfo fieldInfo = memberFactory.createFieldInfo(component, state);
+            FieldInfo fieldInfo = memberFactory.createFieldInfo(component, state, 
namesUsed);
             handleField(fieldInfo, state);
         }
         return;
@@ -1322,6 +1327,7 @@
         //------------------------------/
 
         Enumeration enum = contentModel.enumerate();
+               HashMap namesUsed = new HashMap();
 
         FieldInfo fieldInfo = null;
         XMLBindingComponent component = new XMLBindingComponent();
@@ -1336,7 +1342,7 @@
 
                 //-- handle element declarations
                 case Structure.ELEMENT:
-                    fieldInfo = memberFactory.createFieldInfo(component, state);
+                    fieldInfo = memberFactory.createFieldInfo(component, state, 
namesUsed);
                     //-- Fix for element declarations being used in 
                     //-- a group with minOccurs = 0;  
                     //-- (kvisco - 20021007) 
@@ -1367,7 +1373,8 @@
                             (contentModel instanceof ModelGroup)) )
                     {
                         fieldInfo = memberFactory.createFieldInfo(component,
-                                                                   
state.getSGStateInfo());
+                                                                                      
                                           state.getSGStateInfo(),
+                                                                                      
                                           namesUsed);
                         handleField(fieldInfo, state);
                     } else {
                        //--else we just flatten the group
@@ -1385,7 +1392,8 @@
                         //that is referring to a model group in order
                         //not to loose the Particle information
                         fieldInfo = memberFactory.createFieldInfo(component,
-                                                  state.getSGStateInfo());
+                                                                                      
                                           state.getSGStateInfo(),
+                                                                                      
                                           namesUsed);
                         handleField(fieldInfo, state);
                         break;
                     } else {
Index: src/main/org/exolab/castor/xml/schema/ContentModelGroupImpl.java
===================================================================
RCS file: 
/cvs/castor/castor/src/main/org/exolab/castor/xml/schema/ContentModelGroupImpl.java,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 ContentModelGroupImpl.java
--- src/main/org/exolab/castor/xml/schema/ContentModelGroupImpl.java    3 Mar 2003 
07:09:30 -0000       1.1.1.1
+++ src/main/org/exolab/castor/xml/schema/ContentModelGroupImpl.java    18 May 2003 
17:52:24 -0000
@@ -102,11 +102,14 @@
         String key = "element:"+name;
         //-- check for naming collisions
         if (_resolver.resolve(key) != null) {
-            String err = "An element declaration with the given name, ";
-            err += name + ", already exists in this scope.";
-            throw new SchemaException(err);
-        }
-
+                       int namect = 1;
+                       do {
+                               name = elementDecl.getName() + "_" + namect++;
+                               key = "element:"+name;
+                       } while (_resolver.resolve(key) != null);
+                       elementDecl.setName(name);        
+               }
+               
         _resolver.addResolvable(key, elementDecl);
 
         //-- add to content model
@@ -345,4 +348,4 @@
     } //-- getParticleCount
 
 
-} //-- ContentModelGroup
\ No newline at end of file
+} //-- ContentModelGroup
Index: src/main/org/exolab/javasource/JClass.java
===================================================================
RCS file: /cvs/castor/castor/src/main/org/exolab/javasource/JClass.java,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 JClass.java
--- src/main/org/exolab/javasource/JClass.java  3 Mar 2003 07:09:53 -0000       1.1.1.1
+++ src/main/org/exolab/javasource/JClass.java  18 May 2003 17:52:25 -0000
@@ -167,11 +167,12 @@
         }
         
         String name = jField.getName();
-        
-        if (_fields.get(name) != null) {
-            String err = "duplicate name found: " + name;
-            throw new IllegalArgumentException(err);
-        }
+
+               if (_fields.get(name) != null) {
+                       String err = "duplicate name found: " + name;
+                       throw new IllegalArgumentException(err);
+               }
+
         _fields.put(name, jField);
 
         // if member is of a type not imported by this class
@@ -774,7 +775,32 @@
         _superClass = superClass;
     } //-- setSuperClass
 
-
+       /**
+        * Do we already have this field?
+        * @param fieldName
+        * return boolean
+        */
+       public boolean hasField(String fieldName) {
+               return (_fields.get(fieldName) != null);
+       }
+
+
+       /**
+        * Get a unique name that the class does not already have.
+        * @param name
+        * @param hasMapIndex
+        **/
+       public String uniqueFieldName(String name) {
+               if (!hasField(name)) {
+                       return name;
+               } else {
+                       int namect = 1;
+                       while (hasField(name + "_" + namect)) {
+                               namect += 1;
+                       }
+                       return name + "_" + namect;
+               }
+       }
 
 
     /**
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"; elementFormDefault="qualified">
        <xs:element name="redundant" type="xs:string"/>
        <xs:element name="testElement">
                <xs:complexType>
                        <xs:sequence>
                                <xs:element ref="redundant" minOccurs="0"/>
                                <xs:element name="middle" minOccurs="0" 
type="xs:string"/>
                                <xs:element ref="redundant" minOccurs="0"/>
                        </xs:sequence>
                </xs:complexType>
        </xs:element>
</xs:schema>

Reply via email to