You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by di...@apache.org on 2003/01/03 14:56:09 UTC

cvs commit: xml-axis/java/test/wsdl/qualify2 attribute-qualify.wsdl

dims        2003/01/03 05:56:09

  Modified:    java/src/org/apache/axis/wsdl/symbolTable SchemaUtils.java
                        DefinedType.java SymbolTable.java Utils.java
               java/test/wsdl/qualify2 attribute-qualify.wsdl
  Log:
  Fixes for Bug 15724 - WSDL2Java takes hours on large files
  from Eric.D.Friedman@wellsfargo.com (Eric Friedman)
  
  Notes:
  - attribute-qualify.wsdl had a small bug it was not using xsd:attribute for phone complextype
  
  Revision  Changes    Path
  1.22      +182 -287  xml-axis/java/src/org/apache/axis/wsdl/symbolTable/SchemaUtils.java
  
  Index: SchemaUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/symbolTable/SchemaUtils.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- SchemaUtils.java	31 Dec 2002 22:46:51 -0000	1.21
  +++ SchemaUtils.java	3 Jan 2003 13:56:08 -0000	1.22
  @@ -61,6 +61,9 @@
   import javax.xml.namespace.QName;
   import javax.xml.rpc.holders.BooleanHolder;
   import javax.xml.rpc.holders.IntHolder;
  +import java.util.Arrays;
  +import java.util.HashSet;
  +import java.util.Set;
   import java.util.Vector;
   
   /**
  @@ -70,6 +73,8 @@
    */
   public class SchemaUtils {
   
  +    static final QName VALUE_QNAME = Utils.findQName("", "value");
  +    
       /**
        * If the specified node represents a supported JAX-RPC complexType or 
        * simpleType, a Vector is returned which contains ElementDecls for the 
  @@ -89,53 +94,41 @@
           }
   
           // If the node kind is an element, dive into it.
  -        QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("element") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "element")) {
               NodeList children = node.getChildNodes();
  -            Node complexNode = null;
  -            for (int j = 0; j < children.getLength() && complexNode == null; j++) {
  -                QName complexKind = Utils.getNodeQName(children.item(j));
  -                if (complexKind != null &&
  -                    complexKind.getLocalPart().equals("complexType") &&
  -                    Constants.isSchemaXSD(complexKind.getNamespaceURI())) {
  -                    complexNode = children.item(j);
  -                    node = complexNode;
  +            for (int j = 0; j < children.getLength(); j++) {
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexType")) {
  +                    node = kid;
  +                    break;
                   }
               }
           }
   
           // Expecting a schema complexType or simpleType
  -        nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("complexType") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  -
  +        if (isXSDNode(node, "complexType")) {
               // Under the complexType there could be complexContent/simpleContent
               // and extension elements if this is a derived type.  Skip over these.
               NodeList children = node.getChildNodes();
               Node complexContent = null;
               Node simpleContent = null;
               Node extension = null;
  -            for (int j = 0; j < children.getLength() && complexContent == null; j++) {
  -                QName complexContentKind = Utils.getNodeQName(children.item(j));
  -                if (complexContentKind != null &&
  -                    Constants.isSchemaXSD(complexContentKind.getNamespaceURI())) {
  -                    if (complexContentKind.getLocalPart().equals("complexContent") )
  -                        complexContent = children.item(j);
  -                    else if (complexContentKind.getLocalPart().equals("simpleContent"))
  -                        simpleContent = children.item(j);
  +            for (int j = 0; j < children.getLength(); j++) {
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexContent")) {
  +                    complexContent = kid;
  +                    break;      // REMIND: should this be here or on either branch?
  +                } else if (isXSDNode(kid, "simpleContent")) {
  +                    simpleContent = kid;
                   }
               }
               if (complexContent != null) {
                   children = complexContent.getChildNodes();
                   for (int j = 0; j < children.getLength() && extension == null; j++) {
  -                    QName extensionKind = Utils.getNodeQName(children.item(j));
  -                    if (extensionKind != null &&
  -                        extensionKind.getLocalPart().equals("extension") &&
  -                        Constants.isSchemaXSD(extensionKind.getNamespaceURI()))
  -                        extension = children.item(j);
  +                    Node kid = children.item(j);
  +                    if (isXSDNode(kid, "extension")) { 
  +                        extension = kid;
  +                    }
                   }
               }
               if (simpleContent != null) {
  @@ -156,11 +149,10 @@
                           Vector v = new Vector();
                           ElementDecl elem = new ElementDecl();
                           elem.setType(symbolTable.getTypeEntry(extendsOrRestrictsType, false));
  -                        elem.setName(new javax.xml.namespace.QName("", "value"));
  +                        elem.setName(VALUE_QNAME);
                           v.add(elem);
                           return v;
                       }
  -                        
                   }
               }
   
  @@ -260,7 +252,7 @@
                       // serializer.
                       TypeEntry type = symbolTable.getType(Constants.XSD_ANY);
                       ElementDecl elem = 
  -                        new ElementDecl(type, new QName("","any"));
  +                        new ElementDecl(type, Utils.findQName("","any"));
                       elem.setAnyElement(true);
                       v.add(elem);
                   } else if (subNodeKind.getLocalPart().equals("element")) {
  @@ -308,15 +300,11 @@
           Vector v = new Vector();
           NodeList children = allNode.getChildNodes();
           for (int j = 0; j < children.getLength(); j++) {
  -            QName subNodeKind = Utils.getNodeQName(children.item(j));
  -            if (subNodeKind != null &&
  -                Constants.isSchemaXSD(subNodeKind.getNamespaceURI())) {
  -                if (subNodeKind.getLocalPart().equals("element")) {
  -                    ElementDecl elem = 
  -                            processChildElementNode(children.item(j), 
  -                                                    symbolTable);
  -                    if (elem != null)
  -                        v.add(elem);
  +            Node kid = children.item(j);
  +            if (isXSDNode(kid, "element")) {
  +                ElementDecl elem = processChildElementNode(kid,symbolTable);
  +                if (elem != null) {
  +                    v.add(elem);
                   }
               }
           }
  @@ -354,14 +342,14 @@
               String form = Utils.getAttribute(elementNode, "form");
               if (form != null && form.equals("unqualified")) {
                   // Unqualified nodeName
  -                nodeName = new QName("", nodeName.getLocalPart());            
  +                nodeName = Utils.findQName("", nodeName.getLocalPart());            
               } else if (form == null) {
                   // check elementForDefault on schema element
                   String def = Utils.getScopedAttribute(elementNode, 
                                                         "elementFormDefault");
                   if (def == null || def.equals("unqualified")) {
                       // Unqualified nodeName
  -                    nodeName = new QName("", nodeName.getLocalPart());            
  +                    nodeName = Utils.findQName("", nodeName.getLocalPart());            
                   }
               }
           }
  @@ -383,18 +371,12 @@
        * or null.
        */
       public static QName getElementAnonQName(Node node) {
  -        QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("element") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "element")) {
               NodeList children = node.getChildNodes();
               for (int j = 0; j < children.getLength(); j++) {
  -                QName kind = Utils.getNodeQName(children.item(j));
  -                if (kind != null &&
  -                    (kind.getLocalPart().equals("complexType") ||
  -                     kind.getLocalPart().equals("simpleType")) &&
  -                    Constants.isSchemaXSD(kind.getNamespaceURI())) {
  -                    return Utils.getNodeNameQName(children.item(j));
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexType") || isXSDNode(kid, "simpleType")) {
  +                    return Utils.getNodeNameQName(kid);
                   }
               }
           }
  @@ -406,18 +388,12 @@
        * or null.
        */
       public static QName getAttributeAnonQName(Node node) {
  -        QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("attribute") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "attribute")) {
               NodeList children = node.getChildNodes();
               for (int j = 0; j < children.getLength(); j++) {
  -                QName kind = Utils.getNodeQName(children.item(j));
  -                if (kind != null &&
  -                    (kind.getLocalPart().equals("complexType") ||
  -                     kind.getLocalPart().equals("simpleType")) &&
  -                    Constants.isSchemaXSD(kind.getNamespaceURI())) {
  -                    return Utils.getNodeNameQName(children.item(j));
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexType") || isXSDNode(kid, "simpleType")) {
  +                    return Utils.getNodeNameQName(kid);
                   }
               }
           }
  @@ -433,53 +409,37 @@
           }
   
           // If the node kind is an element, dive into it.
  -        QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("element") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "element")) {
               NodeList children = node.getChildNodes();
  -            Node complexNode = null;
  -            for (int j = 0; j < children.getLength() && complexNode == null; j++) {
  -                QName kind = Utils.getNodeQName(children.item(j));
  -                if (kind != null &&
  -                    kind.getLocalPart().equals("complexType") &&
  -                    Constants.isSchemaXSD(kind.getNamespaceURI())) {
  -                    complexNode = children.item(j);
  -                    node = complexNode;
  -                }
  -                if (kind != null &&
  -                    kind.getLocalPart().equals("simpleType") &&
  -                    Constants.isSchemaXSD(kind.getNamespaceURI())) {
  +            for (int j = 0; j < children.getLength(); j++) {
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexType")) {
  +                    node = kid;
  +                    break;
  +                } else if (isXSDNode(kid, "simpleType")) { 
                       return true;
                   }
               }
           }
   
           // Expecting a schema complexType or simpleType
  -        nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("simpleType") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "simpleType")) {
               return true;
           }
   
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("complexType") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  -
  +        if (isXSDNode(node, "complexType")) {
               // Under the complexType there could be complexContent/simpleContent
               // and extension elements if this is a derived type.  Skip over these.
               NodeList children = node.getChildNodes();
               Node complexContent = null;
               Node simpleContent = null;
  -            for (int j = 0; j < children.getLength() && complexContent == null; j++) {
  -                QName complexContentKind = Utils.getNodeQName(children.item(j));
  -                if (complexContentKind != null &&
  -                    Constants.isSchemaXSD(complexContentKind.getNamespaceURI())) {
  -                    if (complexContentKind.getLocalPart().equals("complexContent") )
  -                        complexContent = children.item(j);
  -                    else if (complexContentKind.getLocalPart().equals("simpleContent"))
  -                        simpleContent = children.item(j);
  +            for (int j = 0; j < children.getLength(); j++) {
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexContent")) {
  +                    complexContent = kid;
  +                    break;
  +                } else if (isXSDNode(kid, "simpleContent")) {
  +                    simpleContent = kid;
                   }
               }
               if (complexContent != null) {
  @@ -493,6 +453,26 @@
       }
   
       /**
  +     * Test whether <tt>node</tt> is not null, belongs to the XML
  +     * Schema namespace, and has a localName that matches
  +     * <tt>schemaLocalName</tt>
  +     *
  +     * This can be used to determine that a given Node defines a
  +     * schema "complexType" "element" and so forth.
  +     *
  +     * @param node a <code>Node</code> value
  +     * @param schemaLocalName a <code>String</code> value
  +     * @return true if the node is matches the name in the schema namespace.
  +     */
  +    private static boolean isXSDNode(Node node, String schemaLocalName) {
  +        if ((node != null) && Constants.isSchemaXSD(node.getNamespaceURI())) {
  +            String localName = node.getLocalName();
  +            return ((localName != null) && localName.equals(schemaLocalName));
  +        }
  +        return false;
  +    }
  +
  +    /**
        * If the specified node represents a supported JAX-RPC complexType/element
        * which extends another complexType.  The Type of the base is returned.
        */
  @@ -501,18 +481,17 @@
               return null;
           }
   
  +        TypeEntry cached = (TypeEntry)symbolTable.node2ExtensionBase.get(node);
  +        if (cached != null) {
  +            return cached;      // cache hit
  +        }
  +
           // If the node kind is an element, dive into it.
  -        QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("element") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "element")) {
               NodeList children = node.getChildNodes();
               Node complexNode = null;
               for (int j = 0; j < children.getLength() && complexNode == null; j++) {
  -                QName complexKind = Utils.getNodeQName(children.item(j));
  -                if (complexKind != null &&
  -                    complexKind.getLocalPart().equals("complexType") &&
  -                    Constants.isSchemaXSD(complexKind.getNamespaceURI())) {
  +                if (isXSDNode(children.item(j), "complexType")) {
                       complexNode = children.item(j);
                       node = complexNode;
                   }
  @@ -520,10 +499,7 @@
           }
   
           // Expecting a schema complexType
  -        nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("complexType") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "complexType")) {
   
               // Under the complexType there could be should be a complexContent &
               // extension elements if this is a derived type. 
  @@ -531,39 +507,35 @@
               Node content = null;
               Node extension = null;
               for (int j = 0; j < children.getLength() && content == null; j++) {
  -                QName contentKind = Utils.getNodeQName(children.item(j));
  -                if (contentKind != null &&
  -                    contentKind.getLocalPart().equals("complexContent") &&
  -                    Constants.isSchemaXSD(contentKind.getNamespaceURI()))
  -                    content = children.item(j);
  -                if (contentKind != null &&
  -                    contentKind.getLocalPart().equals("simpleContent") &&
  -                    Constants.isSchemaXSD(contentKind.getNamespaceURI()))
  -                    content = children.item(j);
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) {
  +                    content = kid;
  +                }
               }
               if (content != null) {
                   children = content.getChildNodes();
                   for (int j = 0; j < children.getLength() && extension == null; j++) {
  -                    QName extensionKind = Utils.getNodeQName(children.item(j));
  -                    if (extensionKind != null &&
  -                        extensionKind.getLocalPart().equals("extension") &&
  -                        Constants.isSchemaXSD(extensionKind.getNamespaceURI()))
  -                        extension = children.item(j);
  +                    Node kid = children.item(j);
  +                    if (isXSDNode(kid, "extension")) {
  +                        extension = kid;
  +                    }
                   }
               }
               if (extension == null) {
  -                return null;  // No extension                               
  -            }
  -
  -            // Get the QName of the extension base
  -            QName extendsType = Utils.getTypeQName(extension, new BooleanHolder(), false);
  -            if (extendsType == null) {
  -                return null; // No extension base
  +                cached = null;
  +            } else {
  +                // Get the QName of the extension base
  +                QName extendsType = Utils.getTypeQName(extension, new BooleanHolder(), false);
  +                if (extendsType == null) {
  +                    cached = null;
  +                } else {
  +                    // Return associated Type
  +                    cached = symbolTable.getType(extendsType);
  +                }
               }
  -            // Return associated Type
  -            return symbolTable.getType(extendsType);
           }
  -        return null;
  +        symbolTable.node2ExtensionBase.put(node, cached);
  +        return cached;
       }
   
       /**
  @@ -579,37 +551,25 @@
   
           // If the node kind is an element, dive into it.
           QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("element") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "element")) {
               NodeList children = node.getChildNodes();
  -            Node simpleNode = null;
  -            for (int j = 0; j < children.getLength() && simpleNode == null; j++) {
  -                QName simpleKind = Utils.getNodeQName(children.item(j));
  -                if (simpleKind != null &&
  -                    simpleKind.getLocalPart().equals("simpleType") &&
  -                    Constants.isSchemaXSD(simpleKind.getNamespaceURI())) {
  -                    simpleNode = children.item(j);
  -                    node = simpleNode;
  +            for (int j = 0; j < children.getLength(); j++) {
  +                if (isXSDNode(children.item(j), "simpleType")) {
  +                    node = children.item(j);
  +                    break;
                   }
               }
           }
           // Get the node kind, expecting a schema simpleType
  -        nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("simpleType") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  -
  +        if (isXSDNode(node, "simpleType")) {
               // Under the simpleType there should be a restriction.
               // (There may be other #text nodes, which we will ignore).
               NodeList children = node.getChildNodes();
               Node restrictionNode = null;
               for (int j = 0; j < children.getLength() && restrictionNode == null; j++) {
  -                QName restrictionKind = Utils.getNodeQName(children.item(j));
  -                if (restrictionKind != null &&
  -                    restrictionKind.getLocalPart().equals("restriction") &&
  -                    Constants.isSchemaXSD(restrictionKind.getNamespaceURI()))
  +                if (isXSDNode(children.item(j), "restriction")) {
                       restrictionNode = children.item(j);
  +                }
               }
   
               // The restriction node indicates the type being restricted
  @@ -623,11 +583,7 @@
               if (baseQName != null && restrictionNode != null) {
                   NodeList enums = restrictionNode.getChildNodes();
                   for (int i=0; i < enums.getLength(); i++) {
  -                    QName enumKind = Utils.getNodeQName(enums.item(i));
  -                    if (enumKind != null &&
  -                        enumKind.getLocalPart().equals("enumeration") &&
  -                        Constants.isSchemaXSD(enumKind.getNamespaceURI())) {
  -                        
  +                    if (isXSDNode(enums.item(i), "enumeration")) {
                           // Found an enumeration, this isn't a 
                           // 'normal' simple type.
                           return null;
  @@ -649,42 +605,28 @@
           }
   
           // If the node kind is an element, dive into it.
  -        QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("element") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "element")) {
               NodeList children = node.getChildNodes();
               Node node2 = null;
  -            for (int j = 0; j < children.getLength() && node2 == null; j++) {
  -                QName kind2 = Utils.getNodeQName(children.item(j));
  -                if (kind2 != null &&
  -                    (kind2.getLocalPart().equals("simpleType") ||
  -                     kind2.getLocalPart().equals("complexType") ||
  -                     kind2.getLocalPart().equals("simpleContent")) &&
  -                    Constants.isSchemaXSD(kind2.getNamespaceURI())) {
  -                    node2 = children.item(j);
  -                    node = node2;
  +            for (int j = 0; j < children.getLength(); j++) {
  +                Node n = children.item(j);
  +                if (isXSDNode(n, "simpleType") || isXSDNode(n, "complexType") || isXSDNode(n, "simpleContent")) {
  +                    node = n;
  +                    break;
                   }
               }
           }
           // Get the node kind, expecting a schema simpleType
  -        nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            (nodeKind.getLocalPart().equals("simpleType") ||
  -             nodeKind.getLocalPart().equals("complexType")) &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  -
  +        if (isXSDNode(node, "simpleType") || isXSDNode(node, "complexType")) {
               // Under the complexType there could be a complexContent.
               NodeList children = node.getChildNodes();
               Node complexContent = null;
  -            if (nodeKind.getLocalPart().equals("complexType")) {
  +            if (node.getLocalName().equals("complexType")) {
                   for (int j = 0; j < children.getLength() && complexContent == null; j++) {
  -                    QName complexContentKind = Utils.getNodeQName(children.item(j));
  -                    if (complexContentKind != null &&
  -                        (complexContentKind.getLocalPart().equals("complexContent") ||
  -                         complexContentKind.getLocalPart().equals("simpleContent"))&&
  -                        Constants.isSchemaXSD(complexContentKind.getNamespaceURI()))
  -                        complexContent = children.item(j);
  +                    Node kid = children.item(j);
  +                    if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) {
  +                        complexContent = kid;
  +                    }
                   }
                   node = complexContent;
               }
  @@ -692,12 +634,10 @@
               if (node != null) {
                   children = node.getChildNodes();
                   for (int j = 0; j < children.getLength() && re == null; j++) {
  -                    QName reKind = Utils.getNodeQName(children.item(j));
  -                    if (reKind != null &&
  -                        (reKind.getLocalPart().equals("extension") ||
  -                         reKind.getLocalPart().equals("restriction")) &&
  -                        Constants.isSchemaXSD(reKind.getNamespaceURI()))
  -                        re = children.item(j);
  +                    Node kid = children.item(j);
  +                    if (isXSDNode(kid, "extension") || isXSDNode(kid, "restriction")) {
  +                        re = kid;
  +                    }
                   }
               }
           }
  @@ -738,11 +678,7 @@
           }
   
           // If the node kind is an element, dive get its type.
  -        QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("element") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  -
  +        if (isXSDNode(node, "element")) {
               // Compare the componentQName with the name of the
               // full name.  If different, return componentQName
               BooleanHolder forElement = new BooleanHolder();
  @@ -793,39 +729,29 @@
           }
   
           // If the node kind is an element, dive into it.
  -        QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("element") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "element")) {
               NodeList children = node.getChildNodes();
  -            Node complexNode = null;
  -            for (int j = 0; j < children.getLength() && complexNode == null; j++) {
  -                QName complexKind = Utils.getNodeQName(children.item(j));
  -                if (complexKind != null &&
  -                    complexKind.getLocalPart().equals("complexType") &&
  -                    Constants.isSchemaXSD(complexKind.getNamespaceURI())) {
  -                    complexNode = children.item(j);
  -                    node = complexNode;
  +            for (int j = 0; j < children.getLength(); j++) {
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexType")) {
  +                    node = kid;
  +                    break;
                   }
               }
           }
  -        // Get the node kind, expecting a schema complexType
  -        nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("complexType") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
   
  +        // Get the node kind, expecting a schema complexType
  +        if (isXSDNode(node, "complexType")) {
               // Under the complexType there should be a complexContent.
               // (There may be other #text nodes, which we will ignore).
               NodeList children = node.getChildNodes();
               Node complexContentNode = null;
  -            for (int j = 0; j < children.getLength() && complexContentNode == null; j++) {
  -                QName complexContentKind = Utils.getNodeQName(children.item(j));
  -                if (complexContentKind != null &&
  -                    (complexContentKind.getLocalPart().equals("complexContent") ||
  -                    complexContentKind.getLocalPart().equals("simpleContent")) &&
  -                    Constants.isSchemaXSD(complexContentKind.getNamespaceURI()))
  -                    complexContentNode = children.item(j);
  +            for (int j = 0; j < children.getLength(); j++) {
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) {
  +                    complexContentNode = kid;
  +                    break;
  +                }
               }
   
               // Under the complexContent there should be a restriction.
  @@ -833,12 +759,12 @@
               Node restrictionNode = null;
               if (complexContentNode != null) {
                   children = complexContentNode.getChildNodes();
  -                for (int j = 0; j < children.getLength() && restrictionNode == null; j++) {
  -                    QName restrictionKind = Utils.getNodeQName(children.item(j));
  -                    if (restrictionKind != null &&
  -                        restrictionKind.getLocalPart().equals("restriction") &&
  -                        Constants.isSchemaXSD(restrictionKind.getNamespaceURI()))
  -                        restrictionNode = children.item(j);
  +                for (int j = 0; j < children.getLength(); j++) {
  +                    Node kid = children.item(j);
  +                    if (isXSDNode(kid, "restriction")) {
  +                        restrictionNode = kid;
  +                        break;
  +                    }
                   }
               }
   
  @@ -864,12 +790,9 @@
                   for (int j = 0;
                        j < children.getLength() && groupNode == null && attributeNode == null;
                        j++) {
  -                    QName kind = Utils.getNodeQName(children.item(j));
  -                    if (kind != null &&
  -                        (kind.getLocalPart().equals("sequence") ||
  -                         kind.getLocalPart().equals("all")) &&
  -                        Constants.isSchemaXSD(kind.getNamespaceURI())) {
  -                        groupNode = children.item(j);
  +                    Node kid = children.item(j);
  +                    if (isXSDNode(kid, "sequence") || isXSDNode(kid, "all")) {
  +                        groupNode = kid;
                           if (groupNode.getChildNodes().getLength() == 0) {
                               // This covers the rather odd but legal empty sequence.
                               // <complexType name="ArrayOfString">
  @@ -883,18 +806,16 @@
                               groupNode = null;
                           }
                       }
  -                    if (kind != null &&
  -                        kind.getLocalPart().equals("attribute") &&
  -                        Constants.isSchemaXSD(kind.getNamespaceURI())) {
  +                    if (isXSDNode(kid, "attribute")) {
                           // If the attribute node does not have ref="soapenc:arrayType"
                           // then keep looking.
                           BooleanHolder isRef = new BooleanHolder();
  -                        QName refQName = Utils.getTypeQName(children.item(j), isRef, false);
  +                        QName refQName = Utils.getTypeQName(kid, isRef, false);
                           if (refQName != null &&
                               isRef.value &&
                               refQName.getLocalPart().equals("arrayType") &&
                               Constants.isSOAP_ENC(refQName.getNamespaceURI())) {
  -                            attributeNode = children.item(j);
  +                            attributeNode = kid;
                           }
                       }
                   }
  @@ -938,11 +859,10 @@
                   NodeList elements = groupNode.getChildNodes();
                   Node elementNode = null;
                   for (int i=0; i < elements.getLength() && elementNode == null; i++) {
  -                    QName elementKind = Utils.getNodeQName(elements.item(i));
  -                    if (elementKind != null &&
  -                        elementKind.getLocalPart().equals("element") &&
  -                        Constants.isSchemaXSD(elementKind.getNamespaceURI())) {
  +                    Node kid = elements.item(i);
  +                    if (isXSDNode(kid, "element")) {
                           elementNode = elements.item(i);
  +                        break;
                       }
                   }
                    
  @@ -989,70 +909,49 @@
           }
           // Check for SimpleContent
           // If the node kind is an element, dive into it.
  -        QName nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("element") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +        if (isXSDNode(node, "element")) {
               NodeList children = node.getChildNodes();
  -            Node complexNode = null;
  -            for (int j = 0; j < children.getLength() && complexNode == null; j++) {
  -                QName complexKind = Utils.getNodeQName(children.item(j));
  -                if (complexKind != null &&
  -                    complexKind.getLocalPart().equals("complexType") &&
  -                    Constants.isSchemaXSD(complexKind.getNamespaceURI())) {
  -                    complexNode = children.item(j);
  -                    node = complexNode;
  +            for (int j = 0; j < children.getLength(); j++) {
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexType")) {
  +                    node = kid;
  +                    break;
                   }
               }
           }
   
           // Expecting a schema complexType
  -        nodeKind = Utils.getNodeQName(node);
  -        if (nodeKind != null &&
  -            nodeKind.getLocalPart().equals("complexType") &&
  -            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  -
  +        if (isXSDNode(node, "complexType")) {
               // Under the complexType there could be complexContent/simpleContent
               // and extension elements if this is a derived type.  Skip over these.
               NodeList children = node.getChildNodes();
               Node content = null;
  -            Node extension = null;
  -            for (int j = 0; j < children.getLength() && content == null; j++) {
  -                QName complexContentKind = Utils.getNodeQName(children.item(j));
  -                if (complexContentKind != null &&
  -                    Constants.isSchemaXSD(complexContentKind.getNamespaceURI())) {
  -                    if (complexContentKind.getLocalPart().equals("complexContent") ||
  -                        complexContentKind.getLocalPart().equals("simpleContent")) {
  -                        content = children.item(j);
  -                    }
  +            for (int j = 0; j < children.getLength(); j++) {
  +                Node kid = children.item(j);
  +                if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent")) {
  +                    content = kid;
  +                    break;
                   }
               }
               // Check for extensions
               if (content != null) {
                   children = content.getChildNodes();
                   for (int j = 0; j < children.getLength(); j++) {
  -                    QName extensionKind = Utils.getNodeQName(children.item(j));
  -                    if (extensionKind != null &&
  -                            extensionKind.getLocalPart().equals("extension") &&
  -                            Constants.isSchemaXSD(extensionKind.getNamespaceURI())) {
  -                        extension = children.item(j);
  +                    Node kid = children.item(j);
  +                    if (isXSDNode(kid, "extension")) {
  +                        node = kid;
                           break;
                       }
                   }
               }
               
  -            if (extension != null) {
  -                node = extension;
  -            }
  -            
               // examine children of the node for <attribute> elements
               children = node.getChildNodes();
               for (int i = 0; i < children.getLength(); i++) {
                   Node child = children.item(i);
  -                nodeKind = Utils.getNodeQName(child);
  -                if (nodeKind == null ||
  -                        ! nodeKind.getLocalPart().equals("attribute"))
  +                if (! isXSDNode(child, "attribute")) {
                       continue;
  +                }
                   
                   // we have an attribute node
                   if (v == null)
  @@ -1076,14 +975,14 @@
                       String form = Utils.getAttribute(child, "form");
                       if (form != null && form.equals("unqualified")) {
                           // Unqualified nodeName
  -                        attributeName = new QName("", attributeName.getLocalPart());            
  +                        attributeName = Utils.findQName("", attributeName.getLocalPart());            
                       } else if (form == null) {
                           // check attributeFormDefault on schema element
                           String def = Utils.getScopedAttribute(child, 
                                                                 "attributeFormDefault");
                           if (def == null || def.equals("unqualified")) {
                               // Unqualified nodeName
  -                            attributeName = new QName("", attributeName.getLocalPart());            
  +                            attributeName = Utils.findQName("", attributeName.getLocalPart());            
                           }
                       }
                   } else {
  @@ -1152,6 +1051,8 @@
           "NMTOKEN",
           "NMTOKENS"
       };
  +
  +    private static final Set schemaTypeSet = new HashSet(Arrays.asList(schemaTypes));
       
       /**
        * Determine if a string is a simple XML Schema type 
  @@ -1159,14 +1060,8 @@
       private static boolean isSimpleSchemaType(String s) {
           if (s == null)
               return false;
  -        
  -        // This is rather expensive.  Probably should be
  -        // a hash lookup.  
  -        for (int i = 0; i < schemaTypes.length; i++) {
  -            if (schemaTypes[i].equals(s))
  -                return true;
  -        }
  -        return false;
  +
  +        return schemaTypeSet.contains(s);
       }
       /**
        * Determine if a QName is a simple XML Schema type 
  
  
  
  1.3       +16 -0     xml-axis/java/src/org/apache/axis/wsdl/symbolTable/DefinedType.java
  
  Index: DefinedType.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/symbolTable/DefinedType.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DefinedType.java	20 Jun 2002 20:35:47 -0000	1.2
  +++ DefinedType.java	3 Jan 2003 13:56:08 -0000	1.3
  @@ -62,11 +62,27 @@
    * always emitted.
    */
   public class DefinedType extends Type {
  +    // cache lookups for our base type
  +    protected TypeEntry extensionBase;
  +    
       public DefinedType(QName pqName, Node pNode) {
           super(pqName, pNode);
       }
       public DefinedType(QName pqName, TypeEntry refType, Node pNode, String dims) {
           super(pqName, refType, pNode, dims);
  +    }
  +
  +    /**
  +     * Get a TypeEntry for the base type of this type, if one exists.
  +     *
  +     * @param symbolTable a <code>SymbolTable</code> value
  +     * @return a <code>TypeEntry</code> value
  +     */
  +    public TypeEntry getComplexTypeExtensionBase(SymbolTable symbolTable) {
  +        if (null == extensionBase) {
  +            extensionBase = SchemaUtils.getComplexElementExtensionBase(getNode(), symbolTable);
  +        }
  +        return extensionBase;
       }
   };
   
  
  
  
  1.67      +73 -37    xml-axis/java/src/org/apache/axis/wsdl/symbolTable/SymbolTable.java
  
  Index: SymbolTable.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/symbolTable/SymbolTable.java,v
  retrieving revision 1.66
  retrieving revision 1.67
  diff -u -r1.66 -r1.67
  --- SymbolTable.java	2 Jan 2003 00:02:42 -0000	1.66
  +++ SymbolTable.java	3 Jan 2003 13:56:08 -0000	1.67
  @@ -106,6 +106,7 @@
   import java.net.URL;
   import java.util.ArrayList;
   import java.util.Collection;
  +import java.util.Collections;
   import java.util.HashMap;
   import java.util.HashSet;
   import java.util.Iterator;
  @@ -139,8 +140,20 @@
   
       private HashMap symbolTable = new HashMap();
   
  -    // A list of the TypeEntry elements in the symbol table
  -    private Vector types = new Vector();
  +    // a map of qnames -> Elements in the symbol table
  +    private final Map elementTypeEntries = new HashMap();
  +    // an unmodifiable wrapper so that we can share the index with others, safely
  +    private final Map elementIndex = Collections.unmodifiableMap(elementTypeEntries);
  +    // a map of qnames -> Types in the symbol table
  +    private final Map typeTypeEntries = new HashMap();
  +    // an unmodifiable wrapper so that we can share the index with others, safely
  +    private final Map typeIndex = Collections.unmodifiableMap(typeTypeEntries);
  +
  +    /** cache of nodes -> base types for complexTypes.  The cache is
  +     * built on nodes because multiple TypeEntry objects may use the
  +     * same node.
  +     */
  +    protected final Map node2ExtensionBase = new HashMap(); // allow friendly access
   
       private boolean verbose;
   
  @@ -215,30 +228,19 @@
       } // getTypeEntry
   
       /**
  -     * Get the Type TypeEntry with the given QName.  If it doesn't exist, return null.
  +     * Get the Type TypeEntry with the given QName.  If it doesn't
  +     * exist, return null.
        */
       public Type getType(QName qname) {
  -        for (int i = 0; i < types.size(); ++i) {
  -            TypeEntry type = (TypeEntry) types.get(i);
  -            if (type.getQName().equals(qname)
  -                    && (type instanceof Type)) {
  -                return (Type) type;
  -            }
  -        }
  -        return null;
  +        return (Type)typeTypeEntries.get(qname);
       } // getType
   
       /**
  -     * Get the Element TypeEntry with the given QName.  If it doesn't exist, return null.
  +     * Get the Element TypeEntry with the given QName.  If it doesn't
  +     * exist, return null.
        */
       public Element getElement(QName qname) {
  -        for (int i = 0; i < types.size(); ++i) {
  -            TypeEntry type = (TypeEntry) types.get(i);
  -            if (type.getQName().equals(qname) && type instanceof Element) {
  -                return (Element) type;
  -            }
  -        }
  -        return null;
  +        return (Element)elementTypeEntries.get(qname);
       } // getElement
   
       /**
  @@ -272,12 +274,46 @@
       /**
        * Get the list of all the XML schema types in the symbol table.  In other words, all entries
        * that are instances of TypeEntry.
  +     *
  +     * @deprecated use specialized get{Element,Type}Index() methods instead
        */
       public Vector getTypes() {
  -        return types;
  +        Vector v = new Vector();
  +        v.addAll(elementTypeEntries.values());
  +        v.addAll(typeTypeEntries.values());
  +        return v;
       } // getTypes
   
       /**
  +     * Return an unmodifiable map of qnames -> Elements in the symbol
  +     * table.
  +     *
  +     * @return an unmodifiable <code>Map</code> value
  +     */
  +    public Map getElementIndex() {
  +        return elementIndex;
  +    }
  +
  +    /**
  +     * Return an unmodifiable map of qnames -> Elements in the symbol
  +     * table.
  +     *
  +     * @return an unmodifiable <code>Map</code> value
  +     */
  +    public Map getTypeIndex() {
  +        return typeIndex;
  +    }
  +
  +    /**
  +     * Return the count of TypeEntries in the symbol table.
  +     *
  +     * @return an <code>int</code> value
  +     */
  +    public int getTypeEntryCount() {
  +        return elementTypeEntries.size() + typeTypeEntries.size();
  +    }
  +    
  +    /**
        * Get the Definition.  The definition is null until
        * populate is called.
        */
  @@ -1931,9 +1967,13 @@
                   if (stuff.isEmpty()) {
                       stuff = def.getMessages();
                       if (stuff.isEmpty()) {
  -                        for (int i = 0; i < types.size(); ++i) {
  -                            TypeEntry type = (TypeEntry) types.get(i);
  -                            setTypeReferences(type, doc, false);
  +                        for (Iterator i = elementTypeEntries.values().iterator();
  +                             i.hasNext();) {
  +                            setTypeReferences((TypeEntry)i.next(), doc, false);
  +                        }
  +                        for (Iterator i = typeTypeEntries.values().iterator();
  +                             i.hasNext();) {
  +                            setTypeReferences((TypeEntry)i.next(), doc, false);
                           }
                       }
                       else {
  @@ -2264,12 +2304,8 @@
                           // Replace it in the symbol table
                           v.setElementAt(entry, i);
   
  -                        // Replace it in the types Vector
  -                        for (int j = 0; j < types.size(); ++j) {
  -                            if (types.elementAt(j) == oldEntry) {
  -                                types.setElementAt(entry, j);
  -                            }
  -                        }
  +                        // Replace it in the types index
  +                        typeTypeEntries.put(name, entry);
   
                           // Update all of the entries that refer to the unknown type
                           ((UndefinedType)oldEntry).update((Type)entry);
  @@ -2289,12 +2325,8 @@
                           // Replace it in the symbol table
                           v.setElementAt(entry, i);
   
  -                        // Replace it in the types Vector
  -                        for (int j = 0; j < types.size(); ++j) {
  -                            if (types.elementAt(j) == oldEntry) {
  -                                types.setElementAt(entry, j);
  -                            }
  -                        }
  +                        // Replace it in the elements index
  +                        elementTypeEntries.put(name, entry);
   
                           // Update all of the entries that refer to the unknown type
                           ((Undefined)oldEntry).update((Element)entry);
  @@ -2309,8 +2341,12 @@
                       symbolTable.put(name, v);
                   }
                   v.add(entry);
  -                if (entry instanceof TypeEntry) {
  -                    types.add(entry);
  +                // add TypeEntries to specialized indices for
  +                // fast lookups during reference resolution.
  +                if (entry instanceof Element) {
  +                    elementTypeEntries.put(name, entry);
  +                } else if (entry instanceof Type) {
  +                    typeTypeEntries.put(name, entry);
                   }
               }
           }
  
  
  
  1.24      +52 -24    xml-axis/java/src/org/apache/axis/wsdl/symbolTable/Utils.java
  
  Index: Utils.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/symbolTable/Utils.java,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- Utils.java	2 Jan 2003 15:37:47 -0000	1.23
  +++ Utils.java	3 Jan 2003 13:56:08 -0000	1.24
  @@ -61,8 +61,10 @@
   
   import javax.xml.namespace.QName;
   import javax.xml.rpc.holders.BooleanHolder;
  +import java.util.HashMap;
   import java.util.HashSet;
   import java.util.Iterator;
  +import java.util.Map;
   import java.util.Vector;
   
   /**
  @@ -72,8 +74,39 @@
    * @author Tom Jordahl (tomj@macromedia.com)
    */
   public class Utils {
  +    /** cache of namespaces -> maps of localNames -> QNames */
  +    static final Map nsmap = new HashMap();
   
       /**
  +     * Find or create a QName with the specified namespace/localName.
  +     *
  +     * @param namespace
  +     * @param localName
  +     */
  +    static QName findQName(String namespace, String localName) {
  +        QName qname = null;
  +
  +        // get the inner map, using the namespace as a key
  +        Map ln2qn = (Map)nsmap.get(namespace);
  +        if (null == ln2qn) {    // cache miss
  +            ln2qn = new HashMap();
  +            nsmap.put(namespace, ln2qn);
  +
  +            qname = new QName(namespace, localName);
  +            ln2qn.put(localName, qname);
  +        } else {                // cache hit
  +            qname = (QName)ln2qn.get(localName);
  +            if (null == qname) { // cache miss
  +                qname = new QName(namespace, localName);
  +                ln2qn.put(localName, qname);
  +            } else {
  +                                // cache hit
  +            }
  +        }
  +        return qname;
  +    }
  +    
  +    /**
        * getNillableQName returns the QName to use if the nillable=true
        * attribute is used.                             
        * For example, in JAX-RPC:
  @@ -95,13 +128,13 @@
                   localName.equals("double") ||
                   localName.equals("boolean") ||
                   localName.equals("byte")) {
  -                rc = new QName(Constants.URI_DEFAULT_SOAP_ENC, 
  +                rc = findQName(Constants.URI_DEFAULT_SOAP_ENC, 
                                  qName.getLocalPart());
               }
               else if (localName.equals("base64Binary")) {
  -                rc = new QName(Constants.URI_DEFAULT_SOAP_ENC, "base64");
  +                rc = findQName(Constants.URI_DEFAULT_SOAP_ENC, "base64");
               } else if (localName.equals("hexBinary")) {
  -                rc = new QName(Constants.URI_DEFAULT_SCHEMA_XSD, "hexBinary");
  +                rc = findQName(Constants.URI_DEFAULT_SCHEMA_XSD, "hexBinary");
               }
           }
          return rc;
  @@ -186,7 +219,7 @@
           }
           String namespace = node.getNamespaceURI();
   
  -        return (new QName(namespace, localName));
  +        return (findQName(namespace, localName));
       }
   
       /**
  @@ -244,7 +277,7 @@
           if (namespace == null) {
               namespace = getScopedAttribute(node, "targetNamespace");
           }
  -        return (new QName(namespace, localName));
  +        return (findQName(namespace, localName));
       }
   
       /**
  @@ -308,7 +341,7 @@
                   } else if (!maxOccursValue.equals("1") || !minOccursValue.equals("1")) {
                       String localPart = qName.getLocalPart();
                       localPart += "[" + maxOccursValue + "]";
  -                    qName = new QName(qName.getNamespaceURI(), localPart);
  +                    qName = findQName(qName.getNamespaceURI(), localPart);
                   }
               }
           }
  @@ -412,7 +445,7 @@
           else {
              namespace = getScopedAttribute(node, "xmlns:" + prefixedName.substring(0, prefixedName.lastIndexOf(":")));
           }
  -        return (new QName(namespace, localName));
  +        return (findQName(namespace, localName));
       }
   
       /**
  @@ -427,32 +460,27 @@
                      (type.getQName().getLocalPart().equals("anyType")||
                       type.getQName().getLocalPart().equals("any"))) {
               // All types are derived from anyType
  -            types.addAll(symbolTable.getTypes());
  +            types.addAll(symbolTable.getTypeIndex().values());
           }
           return types;
       } // getNestedTypes
   
  -    private static void getDerivedTypes(
  -            TypeEntry type, HashSet types, SymbolTable symbolTable) {
  +    private static void getDerivedTypes(TypeEntry type, HashSet types, SymbolTable symbolTable) {
   
           // If all types are in the set, return
  -        if (types.size() == symbolTable.getTypes().size()) {
  +        if (types.size() == symbolTable.getTypeEntryCount()) {
               return;
           }
   
           // Search the dictionary for derived types of type
  -        Vector allTypes = symbolTable.getTypes();
  -        Iterator it = allTypes.iterator();
  -        while(it.hasNext()) {
  -            TypeEntry derivedType = (TypeEntry) it.next();
  -            if (derivedType instanceof DefinedType &&
  -                derivedType.getNode() != null &&
  -                !types.contains(derivedType) &&
  -                SchemaUtils.getComplexElementExtensionBase(
  -                   derivedType.getNode(),
  -                   symbolTable) == type) {
  -                types.add(derivedType);
  -                getDerivedTypes(derivedType, types, symbolTable);
  +        for (Iterator it = symbolTable.getTypeIndex().values().iterator(); it.hasNext();) {
  +            Type t = (Type)it.next();
  +            if (t instanceof DefinedType &&
  +                t.getNode() != null &&
  +                !types.contains(t) &&
  +                (((DefinedType)t).getComplexTypeExtensionBase(symbolTable) == type)) {
  +                types.add(t);
  +                getDerivedTypes(t, types, symbolTable);
               }
           }
       } // getDerivedTypes
  @@ -483,7 +511,7 @@
           }
           
           // If all types are in the set, return
  -        if (types.size() == symbolTable.getTypes().size()) {
  +        if (types.size() == symbolTable.getTypeEntryCount()) {
               return;
           }
           
  
  
  
  1.2       +3 -3      xml-axis/java/test/wsdl/qualify2/attribute-qualify.wsdl
  
  Index: attribute-qualify.wsdl
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/qualify2/attribute-qualify.wsdl,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- attribute-qualify.wsdl	1 Jul 2002 16:09:39 -0000	1.1
  +++ attribute-qualify.wsdl	3 Jan 2003 13:56:09 -0000	1.2
  @@ -19,10 +19,10 @@
               <xsd:element name="number" type="xsd:string"/>
           </xsd:all>
           <!-- These attributes should be qualified -->
  -        <attribute name="color" type="xsd:string"/>
  -        <attribute name="hair" type="xsd:string" form="qualified"/>
  +        <xsd:attribute name="color" type="xsd:string"/>
  +        <xsd:attribute name="hair" type="xsd:string" form="qualified"/>
           <!-- This attribute should not -->
  -        <attribute name="age" type="xsd:int" form="unqualified"/>
  +        <xsd:attribute name="age" type="xsd:int" form="unqualified"/>
         </xsd:complexType>
   
         <xsd:element name="phone" type="s0:phone"/>