Fix attribute serialization of the form attribute

git-svn-id: https://svn.apache.org/repos/asf/webservices/commons/trunk/modules/XmlSchema@1021748 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/ws/commons/schema/XmlSchemaAttribute.java b/src/main/java/org/apache/ws/commons/schema/XmlSchemaAttribute.java
index 8a26e93..85423b3 100644
--- a/src/main/java/org/apache/ws/commons/schema/XmlSchemaAttribute.java
+++ b/src/main/java/org/apache/ws/commons/schema/XmlSchemaAttribute.java
@@ -27,7 +27,7 @@
 

 /**

  * Class for attribute types. Represents the World Wide Web Consortium (W3C) attribute element.

- * 

+ *

  * ref= attributes are in the parent items collection, not in the map of named items.

  */

 public class XmlSchemaAttribute extends XmlSchemaAttributeOrGroupRef implements XmlSchemaNamedWithForm,

@@ -40,7 +40,7 @@
     private XmlSchemaUse use;

     private XmlSchemaNamedWithFormImpl namedDelegate;

     private XmlSchemaRef<XmlSchemaAttribute> ref;

-    

+

     /**

      * Create a new attribute.

      * @param schema containing scheme.

@@ -98,39 +98,46 @@
     }

 

     public void setUse(XmlSchemaUse use) {

+        if (namedDelegate.isTopLevel() && use != null) {

+            throw new XmlSchemaException("Top-level attributes may not have a 'use'");

+        }

         this.use = use;

     }

 

     public String getName() {

         return namedDelegate.getName();

     }

-    

+

 

     public XmlSchema getParent() {

         return namedDelegate.getParent();

     }

-    

+

 

     public QName getQName() {

         return namedDelegate.getQName();

     }

-    

+

 

     public boolean isAnonymous() {

         return namedDelegate.isAnonymous();

     }

-    

+

 

     public boolean isTopLevel() {

         return namedDelegate.isTopLevel();

     }

 

     public void setName(String name) {

+

         if (namedDelegate.isTopLevel() && namedDelegate.getName() != null) {

             namedDelegate.getParent().getAttributes().remove(getQName());

         }

         namedDelegate.setName(name);

         if (namedDelegate.isTopLevel()) {

+            if (name == null) {

+                throw new XmlSchemaException("Top-level attributes may not be anonymous");

+            }

             namedDelegate.getParent().getAttributes().put(getQName(), this);

         }

     }

@@ -144,6 +151,9 @@
     }

 

     public void setForm(XmlSchemaForm form) {

+        if (namedDelegate.isTopLevel() && form != XmlSchemaForm.NONE) {

+            throw new XmlSchemaException("Top-level attributes may not have a 'form'");

+        }

         namedDelegate.setForm(form);

     }

 

diff --git a/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java b/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java
index a5bc57c..698cb7b 100644
--- a/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java
+++ b/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java
@@ -62,7 +62,7 @@
 
         /**
          * Standard constructor with a message.
-         * 
+         *
          * @param msg the message.
          */
         public XmlSchemaSerializerException(String msg) {
@@ -108,7 +108,7 @@
 
     /**
      * Get the registry of extensions for this serializer.
-     * 
+     *
      * @return the registry.
      */
     public ExtensionRegistry getExtReg() {
@@ -117,7 +117,7 @@
 
     /**
      * Serialize an entire schema, returning an array of DOM Documents, one per XSL file.
-     * 
+     *
      * @param schemaObj The XML Schema.
      * @param serializeIncluded whether to create DOM trees for any included or imported schemas.
      * @return Documents. If serializeIncluded is false, the array with have one entry. The main document is
@@ -131,7 +131,7 @@
 
     /**
      * Set the registry of extensions for this serializer.
-     * 
+     *
      * @param extReg the registry.
      */
     public void setExtReg(ExtensionRegistry extReg) {
@@ -249,11 +249,11 @@
             anyEl.setAttribute("namespace", anyObj.getNamespace());
         }
 
-        if (anyObj.getProcessContent() != null 
+        if (anyObj.getProcessContent() != null
             && anyObj.getProcessContent() != XmlSchemaContentProcessing.NONE) {
             anyEl.setAttribute("processContents", anyObj.getProcessContent().toString());
         }
-        
+
         if (anyObj.getAnnotation() != null) {
             Element annotation = serializeAnnotation(doc, anyObj.getAnnotation(), schema);
             anyEl.appendChild(annotation);
@@ -358,16 +358,21 @@
     Element serializeAttribute(Document doc, XmlSchemaAttribute attributeObj, XmlSchema schema)
         throws XmlSchemaSerializerException {
 
+        boolean refPresent = attributeObj.getRef().getTargetQName() != null;
+
         Element attribute = createNewElement(doc, "attribute", schema.getSchemaNamespacePrefix(),
                                              XmlSchema.SCHEMA_NS);
-        if (attributeObj.getRef().getTargetQName() != null) {
+        if (refPresent) {
             String refName = resolveQName(attributeObj.getRef().getTargetQName(), schema);
             attribute.setAttribute("ref", refName);
         } else if (!attributeObj.isAnonymous()) {
             attribute.setAttribute("name", attributeObj.getName());
         }
 
-        if (attributeObj.getSchemaTypeName() != null) {
+        /*
+         * TODO: should this be caught by refusing to allow both to be true at the same time?
+         */
+        if (attributeObj.getSchemaTypeName() != null && !refPresent) {
             String typeName = resolveQName(attributeObj.getSchemaTypeName(), schema);
             attribute.setAttribute("type", typeName);
         }
@@ -379,10 +384,13 @@
             attribute.setAttribute("fixed", attributeObj.getFixedValue());
         }
 
-        if (attributeObj.getForm() != XmlSchemaForm.NONE) {
+        /*
+         * TODO: should this be caught by refusing to allow both to be true at the same time?
+         */
+        if (attributeObj.isFormSpecified() && !refPresent) {
             attribute.setAttribute("form", attributeObj.getForm().toString());
         }
-        
+
         if (attributeObj.getId() != null) {
             attribute.setAttribute("id", attributeObj.getId());
         }
@@ -390,13 +398,16 @@
         if (attributeObj.getUse() != null && attributeObj.getUse() != XmlSchemaUse.NONE) {
             attribute.setAttribute("use", attributeObj.getUse().toString());
         }
-        
+
         if (attributeObj.getAnnotation() != null) {
             Element annotation = serializeAnnotation(doc, attributeObj.getAnnotation(), schema);
             attribute.appendChild(annotation);
         }
 
-        if (attributeObj.getSchemaType() != null) {
+        /*
+         * TODO: should this be caught by refusing to allow both to be true at the same time?
+         */
+        if (attributeObj.getSchemaType() != null && !refPresent) {
             try {
                 XmlSchemaSimpleType simpleType = attributeObj.getSchemaType();
                 Element simpleTypeEl = serializeSimpleType(doc, simpleType, schema);
@@ -580,7 +591,7 @@
         throws XmlSchemaSerializerException {
         // todo: handle any non schema attri ?
 
-        Element choice = createNewElement(doc, "choice", schema.getSchemaNamespacePrefix(), 
+        Element choice = createNewElement(doc, "choice", schema.getSchemaNamespacePrefix(),
                                           XmlSchema.SCHEMA_NS);
         if (choiceObj.getId() != null && choiceObj.getId().length() > 0) {
             choice.setAttribute("id", choiceObj.getId());
@@ -722,7 +733,7 @@
                                                          schema);
             extension.appendChild(sequenceParticle);
         } else if (extensionObj.getParticle() instanceof XmlSchemaChoice) {
-            Element choiceParticle = serializeChoice(doc, 
+            Element choiceParticle = serializeChoice(doc,
                                                      (XmlSchemaChoice)extensionObj.getParticle(), schema);
             extension.appendChild(choiceParticle);
         } else if (extensionObj.getParticle() instanceof XmlSchemaAll) {
@@ -798,7 +809,7 @@
                                                          schema);
             restriction.appendChild(sequenceParticle);
         } else if (restrictionObj.getParticle() instanceof XmlSchemaChoice) {
-            Element choiceParticle = serializeChoice(doc, 
+            Element choiceParticle = serializeChoice(doc,
                                                      (XmlSchemaChoice)restrictionObj.getParticle(), schema);
             restriction.appendChild(choiceParticle);
         } else if (restrictionObj.getParticle() instanceof XmlSchemaAll) {
@@ -850,7 +861,7 @@
     Element serializeComplexType(Document doc, XmlSchemaComplexType complexTypeObj, XmlSchema schema)
         throws XmlSchemaSerializerException {
 
-        Element serializedComplexType = createNewElement(doc, "complexType", 
+        Element serializedComplexType = createNewElement(doc, "complexType",
                                                          schema.getSchemaNamespacePrefix(),
                                                          XmlSchema.SCHEMA_NS);
 
@@ -895,7 +906,7 @@
         }
 
         if (complexTypeObj.getParticle() instanceof XmlSchemaSequence) {
-            Element sequence = serializeSequence(doc, 
+            Element sequence = serializeSequence(doc,
                                                  (XmlSchemaSequence)complexTypeObj.getParticle(), schema);
             serializedComplexType.appendChild(sequence);
         } else if (complexTypeObj.getParticle() instanceof XmlSchemaChoice) {
@@ -909,12 +920,12 @@
             serializedComplexType.appendChild(group);
         }
 
-        if (complexTypeObj.getBlock() != null 
+        if (complexTypeObj.getBlock() != null
             && complexTypeObj.getBlock() != XmlSchemaDerivationMethod.NONE) {
             serializedComplexType.setAttribute("block", complexTypeObj.toString());
         }
-        
-        if (complexTypeObj.getFinalDerivation() != null 
+
+        if (complexTypeObj.getFinalDerivation() != null
             && complexTypeObj.getFinalDerivation() != XmlSchemaDerivationMethod.NONE) {
             serializedComplexType.setAttribute("final", complexTypeObj.getFinalDerivation().toString());
         }
@@ -1030,7 +1041,7 @@
             serializedEl.setAttribute("default", elementObj.getDefaultValue());
         }
 
-        if (elementObj.getFinalDerivation() != null 
+        if (elementObj.getFinalDerivation() != null
             && elementObj.getFinalDerivation() != XmlSchemaDerivationMethod.NONE) {
             serializedEl.setAttribute("final", elementObj.getFinalDerivation().toString());
         }
@@ -1041,7 +1052,7 @@
         if (elementObj.isFormSpecified()) {
             serializedEl.setAttribute("form", elementObj.getForm().toString());
         }
-        
+
         if (elementObj.getId() != null) {
             serializedEl.setAttribute("id", elementObj.getId());
         }
@@ -1063,8 +1074,8 @@
         if (elementObj.getSchemaType() != null && elementObj.getSchemaTypeName() == null) {
             if (elementObj.getSchemaType() instanceof XmlSchemaComplexType) {
 
-                Element complexType = 
-                    serializeComplexType(doc, 
+                Element complexType =
+                    serializeComplexType(doc,
                                          (XmlSchemaComplexType)elementObj.getSchemaType(),
                                          schema);
                 serializedEl.appendChild(complexType);
@@ -1170,8 +1181,8 @@
     Element serializeField(Document doc, XmlSchemaXPath fieldObj, XmlSchema schema)
         throws XmlSchemaSerializerException {
 
-        Element field = createNewElement(doc, "field", 
-                                         schema.getSchemaNamespacePrefix(), 
+        Element field = createNewElement(doc, "field",
+                                         schema.getSchemaNamespacePrefix(),
                                          XmlSchema.SCHEMA_NS);
 
         if (fieldObj.xpath != null) {
@@ -1207,7 +1218,7 @@
     Element serializeGroup(Document doc, XmlSchemaGroup groupObj, XmlSchema schema)
         throws XmlSchemaSerializerException {
 
-        Element group = createNewElement(doc, "group", schema.getSchemaNamespacePrefix(), 
+        Element group = createNewElement(doc, "group", schema.getSchemaNamespacePrefix(),
                                          XmlSchema.SCHEMA_NS);
 
         if (!groupObj.isAnonymous()) {
@@ -1259,7 +1270,7 @@
     Element serializeGroupRef(Document doc, XmlSchemaGroupRef groupRefObj, XmlSchema schema)
         throws XmlSchemaSerializerException {
 
-        Element groupRef = createNewElement(doc, "group", schema.getSchemaNamespacePrefix(), 
+        Element groupRef = createNewElement(doc, "group", schema.getSchemaNamespacePrefix(),
                                             XmlSchema.SCHEMA_NS);
 
         if (groupRefObj.getRefName() != null) {
@@ -1318,10 +1329,10 @@
             constraint = createNewElement(doc, "unique", schema.getSchemaNamespacePrefix(),
                                           XmlSchema.SCHEMA_NS);
         } else if (constraintObj instanceof XmlSchemaKey) {
-            constraint = createNewElement(doc, "key", schema.getSchemaNamespacePrefix(), 
+            constraint = createNewElement(doc, "key", schema.getSchemaNamespacePrefix(),
                                           XmlSchema.SCHEMA_NS);
         } else if (constraintObj instanceof XmlSchemaKeyref) {
-            constraint = createNewElement(doc, "keyref", schema.getSchemaNamespacePrefix(), 
+            constraint = createNewElement(doc, "keyref", schema.getSchemaNamespacePrefix(),
                                           XmlSchema.SCHEMA_NS);
             XmlSchemaKeyref keyref = (XmlSchemaKeyref)constraintObj;
             if (keyref.refer != null) {
@@ -1375,7 +1386,7 @@
     Element serializeImport(Document doc, XmlSchemaImport importObj, XmlSchema schema,
                             boolean serializeIncluded) throws XmlSchemaSerializerException {
 
-        Element importEl = createNewElement(doc, "import", 
+        Element importEl = createNewElement(doc, "import",
                                             schema.getSchemaNamespacePrefix(), XmlSchema.SCHEMA_NS);
 
         if (importObj.namespace != null) {
@@ -1520,7 +1531,7 @@
 
         return redefine;
     }
-    
+
     Document[] serializeSchemaElement(XmlSchema schemaObj,
                                       boolean serializeIncluded) throws XmlSchemaSerializerException {
 
@@ -1546,7 +1557,7 @@
             String targetNS =
                     (String)schemaNamespace.get(schemaObj.getSyntacticalTargetNamespace());
 
-            //if the namespace is not entered then add 
+            //if the namespace is not entered then add
             //the targetNamespace
             if (targetNS == null) {
                 String prefix = null;
@@ -1554,8 +1565,8 @@
                     prefix = schemaObj.
                         getNamespaceContext().getPrefix(schemaObj.getSyntacticalTargetNamespace());
                 }
-                if (prefix == null 
-                    && schemaObj.getParent() != null 
+                if (prefix == null
+                    && schemaObj.getParent() != null
                     && schemaObj.getParent().getNamespaceContext() != null) {
                     prefix = schemaObj.getParent().
                         getNamespaceContext().getPrefix(schemaObj.getSyntacticalTargetNamespace());
@@ -1569,7 +1580,7 @@
                     String ns = serializedSchema.getAttribute("xmlns:" + prefix);
                     if (ns != null && !"".equals(ns)) {
                         prefix = null;
-                    }                    
+                    }
                 }
                 if (prefix == null) {
                     //find a usable prefix
@@ -1581,13 +1592,13 @@
                         prefix = "tns" + count;
                         ns = serializedSchema.getAttribute("xmlns:" + prefix);
                     }
-                } 
+                }
                 if ("".equals(prefix)) {
                     serializedSchema.setAttributeNS(XMLNS_NAMESPACE_URI,
                                                     "xmlns", schemaObj.getSyntacticalTargetNamespace());
                 } else {
                     serializedSchema.setAttributeNS(XMLNS_NAMESPACE_URI,
-                                                    "xmlns:" 
+                                                    "xmlns:"
                                                     + prefix, schemaObj.getSyntacticalTargetNamespace());
                 }
                 schemaNamespace.put(schemaObj.getSyntacticalTargetNamespace(), prefix);
@@ -1595,7 +1606,7 @@
         }
 
 
-        //todo: implement xml:lang, 
+        //todo: implement xml:lang,
         if (schemaObj.getAttributeFormDefault() != null) {
             String formQualified = schemaObj.getAttributeFormDefault().toString();
 
@@ -1626,7 +1637,7 @@
             String blockDefault = schemaObj.getBlockDefault().toString();
             serializedSchema.setAttribute("blockDefault", blockDefault);
         }
-        
+
         if (schemaObj.getFinalDefault() != XmlSchemaDerivationMethod.NONE) {
             String finalDefault = schemaObj.getFinalDefault().toString();
             serializedSchema.setAttribute("finalDefault", finalDefault);
@@ -1637,7 +1648,7 @@
         }
 
         //after serialize the schema add into documentation
-        //and add to document collection array  which at the end 
+        //and add to document collection array  which at the end
         //returned
         serializeSchemaChild(items, serializedSchema, serializedSchemaDocs,
                 schemaObj, serializeIncluded);
@@ -1949,7 +1960,7 @@
         Element serializedSimpleType = createNewElement(doc, "simpleType", schema.getSchemaNamespacePrefix(),
                                                         XmlSchema.SCHEMA_NS);
 
-        if (simpleTypeObj.getFinalDerivation() != null 
+        if (simpleTypeObj.getFinalDerivation() != null
             && simpleTypeObj.getFinalDerivation() != XmlSchemaDerivationMethod.NONE) {
             serializedSimpleType.setAttribute("final", simpleTypeObj.getFinalDerivation().toString());
         }
@@ -2114,7 +2125,7 @@
     Element serializeSimpleTypeUnion(Document doc, XmlSchemaSimpleTypeUnion unionObj, XmlSchema schema)
         throws XmlSchemaSerializerException {
 
-        Element union = createNewElement(doc, "union", schema.getSchemaNamespacePrefix(), 
+        Element union = createNewElement(doc, "union", schema.getSchemaNamespacePrefix(),
                                          XmlSchema.SCHEMA_NS);
         if (unionObj.getId() != null) {
             union.setAttribute("id", unionObj.getId());
@@ -2150,7 +2161,7 @@
 
     // for each collection if it is an attribute serialize attribute and
     // append that child to container element.
-    void setupAttr(Document doc, List<XmlSchemaAttributeOrGroupRef> attrColl, 
+    void setupAttr(Document doc, List<XmlSchemaAttributeOrGroupRef> attrColl,
                    XmlSchema schema, Element container)
         throws XmlSchemaSerializerException {
         int collectionLength = attrColl.size();
@@ -2207,7 +2218,7 @@
 
     private Element constructFacet(XmlSchemaFacet facetObj, Document doc, XmlSchema schema, String tagName) {
 
-        Element facetEl = createNewElement(doc, tagName, schema.getSchemaNamespacePrefix(), 
+        Element facetEl = createNewElement(doc, tagName, schema.getSchemaNamespacePrefix(),
                                            XmlSchema.SCHEMA_NS);
 
         facetEl.setAttribute("value", facetObj.value.toString());
@@ -2236,7 +2247,7 @@
      * A generic method to process the extra attributes and the extra elements present within the schema. What
      * are considered extensions are child elements with non schema namespace and child attributes with any
      * namespace.
-     * 
+     *
      * @param schemaObject
      * @param parentElement
      */
@@ -2263,7 +2274,7 @@
      * will search whether the prefix is available in global hash table, if it is there than append the prefix
      * to the element name. If not then it will create new prefix corresponding to that namespace and store
      * that in hash table. Finally add the new prefix and namespace to <schema> element
-     * 
+     *
      * @param names
      * @param schemaObj
      * @return resolved QName of the string
@@ -2304,12 +2315,12 @@
 
     /**
      * A common method to serialize the max/min occurs
-     * 
+     *
      * @param particle
      * @param element
      */
     private void serializeMaxMinOccurs(XmlSchemaParticle particle, Element element) {
-        if (particle.getMaxOccurs() < Long.MAX_VALUE 
+        if (particle.getMaxOccurs() < Long.MAX_VALUE
             && (particle.getMaxOccurs() > 1 || particle.getMaxOccurs() == 0)) {
             element.setAttribute("maxOccurs", particle.getMaxOccurs() + "");
         } else if (particle.getMaxOccurs() == Long.MAX_VALUE) {
@@ -2419,7 +2430,7 @@
                     if ("".equals(prefix) || !schemaNamespace.containsKey(uri)) {
                         schemaNamespace.put(uri, prefix);
                     }
-                    prefix = (prefix.length() > 0) ? "xmlns:" + prefix : "xmlns";                
+                    prefix = (prefix.length() > 0) ? "xmlns:" + prefix : "xmlns";
                     schemaEl.setAttributeNS(XMLNS_NAMESPACE_URI,
                                             prefix, uri);
                 }
@@ -2433,7 +2444,7 @@
                                         "xmlns", XSD_NAMESPACE);
             } else {
                 schemaEl.setAttributeNS(XMLNS_NAMESPACE_URI,
-                                        "xmlns:" + xsdPrefix, XSD_NAMESPACE);                
+                                        "xmlns:" + xsdPrefix, XSD_NAMESPACE);
             }
             schemaObj.setSchemaNamespacePrefix(xsdPrefix);
         }
diff --git a/src/main/java/org/apache/ws/commons/schema/utils/XmlSchemaNamedWithFormImpl.java b/src/main/java/org/apache/ws/commons/schema/utils/XmlSchemaNamedWithFormImpl.java
index 58b0e27..cda243f 100644
--- a/src/main/java/org/apache/ws/commons/schema/utils/XmlSchemaNamedWithFormImpl.java
+++ b/src/main/java/org/apache/ws/commons/schema/utils/XmlSchemaNamedWithFormImpl.java
@@ -26,7 +26,7 @@
 import org.apache.ws.commons.schema.XmlSchemaForm;
 
 /**
- * 
+ *
  */
 public class XmlSchemaNamedWithFormImpl extends XmlSchemaNamedImpl implements XmlSchemaNamedWithForm {
     private XmlSchemaForm form = XmlSchemaForm.NONE;
@@ -44,7 +44,12 @@
         this.element = element;
     }
 
-    /** {@inheritDoc}*/
+    /**
+     * Return the <strong>effective</strong> 'form' for this item. If the item
+     * has an explicit form declaration, this returns that declared form. If not,
+     * it returns the appropriate default form from the containing schema.
+     * @return {@link XmlSchemaForm#QUALIFIED} or {@link XmlSchemaForm#UNQUALIFIED}.
+     */
     public XmlSchemaForm getForm() {
         if (form != XmlSchemaForm.NONE) {
             return form;
diff --git a/src/main/java/org/apache/ws/commons/schema/utils/XmlSchemaRef.java b/src/main/java/org/apache/ws/commons/schema/utils/XmlSchemaRef.java
index a9b83ca..f3b7b86 100644
--- a/src/main/java/org/apache/ws/commons/schema/utils/XmlSchemaRef.java
+++ b/src/main/java/org/apache/ws/commons/schema/utils/XmlSchemaRef.java
@@ -35,18 +35,19 @@
 public class XmlSchemaRef<T extends XmlSchemaNamed> extends XmlSchemaRefBase {
     private Class<? extends T> targetClass;
     private T targetObject;
-    
+
     public XmlSchemaRef(XmlSchema parent, Class<T> targetClass) {
         this.parent = parent;
         this.targetClass = targetClass;
     }
-    
+
     protected void forgetTargetObject() {
         targetObject = null;
     }
-    
+
+
     public T getTarget() {
-        
+
         if (targetObject == null) {
             Class<?> cls = targetClass;
             XmlSchemaCollection parentCollection = parent.getParent();
@@ -66,4 +67,9 @@
         }
         return targetObject;
     }
+
+    @Override
+    public String toString() {
+        return "XmlSchemaRef: " + targetClass.getName() + " " + targetQName;
+    }
 }