scheu       02/03/13 07:19:27

  Modified:    java/lib wsdl4j.jar
               java/src/org/apache/axis/wsdl/toJava Emitter.java
                        JavaDeployWriter.java JavaStubWriter.java
                        JavaWriterFactory.java SchemaUtils.java
                        SymbolTable.java Utils.java
               java/test/wsdl/refattr refattr.wsdl
  Log:
  Changes for anonymous type processing in WSDL2Java Symbol Table.
  
  Problem Description:
  --------------------
  An anonymous type is a type (simpleType or complexType) that does not
  have a name.  Here is an example:
  
    ...
      <element name="foo">
      <complexType>
         ....
      </complexType>
  
  The WSDL2Java symbol table uses the QName as the key to access a
  symbol table entry.  Since an anonymous type does not have a qname,
  the qname of the containing element is used.  Unfortunately it is
  possible that the element is not unique, which results in a symbol
  table collision.  (As reported by Tom Jordahl.)
  
  Solution:
  ---------
  
  1) The first change is to give anonymous type elements unique names
     to avoid symbol table collisions.  The unique name must be something
     that can be determined by examining the dom tree.  I chose to use
     the following format for the local name:
        <qname-of-containing-simple/compleType>.<qname-of-element>
     If the anonymous type is used to define a global element, its local name is:
        .<qname-of-element>
  
  2) Change to the SchemaUtils code that queries the qname of an anon type.
  
  3) Change to the JavaWriterFactory.javifyNames method.  This method is
     enhanced to ensure that anonymous java type name collisions don't occur.
     If a name collision is detected, the suffix ANON### is appended to the name
     of the anonymous class java name to prevent the collision (### is a unique 
number).
  
  4) Changed the refattr.wsdl to have a anonymous type collision similar to the
     one submitted to axis-dev by Tom Jordahl.
  
  Phase 2:
  --------
  Anonymous types for root elements are not put into the symbol table.  Instead
  the emitter writer classes use the DefinedElement information when generating code.  
This
  can lead to some fuzzy logic and subtle bugs. (I promised Glen last week that
  I would look at changing this code.)
  
  Solution:
  
  1) Anonymous types for root elements are added to the symbol table just like
  all other anonymous types.
  
  2) The JavaWriterFactory.resolve() method is modified to ensure that
  the java name of the root DefinedElement matches the java name of its anonymous 
DefinedType.
  
  3) Changed Utils.getNested to get the anonymous DefinedType.
  
  4) Changed the emitter writeTypes() method to only process Type entries
     (not Element entries).  This is an improvement, writeTypes only deals with types!
  
  5) Changed the deploy and stub writers to not register type mappings for
     Elements.  (Before the deploy and stub writers had to examine the Element
     to see if it had an anonymous type...)
  
  * There are a number of existing testcases that use anonymous types
  for root elements.  All of the tests passed.
  
  Revision  Changes    Path
  1.10      +553 -414  xml-axis/java/lib/wsdl4j.jar
  
        <<Binary file>>
  
  
  1.25      +3 -1      xml-axis/java/src/org/apache/axis/wsdl/toJava/Emitter.java
  
  Index: Emitter.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/Emitter.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- Emitter.java      5 Mar 2002 14:52:06 -0000       1.24
  +++ Emitter.java      13 Mar 2002 15:19:26 -0000      1.25
  @@ -482,9 +482,11 @@
               //  - we found its definition (getNode())
               //  - it is referenced 
               //  - it is not a base java type
  +            //  - it is a Type (not an Element)
               // (Note that types that are arrays are passed to getWriter
               //  because they may require a Holder)
  -            if (type.getNode() != null &&   
  +            if (type.getNode() != null && 
  +                type instanceof Type &&
                   type.isReferenced() && 
                   type.getBaseType() == null) {
                   Writer writer = writerFactory.getWriter(type, symbolTable);
  
  
  
  1.26      +3 -13     
xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaDeployWriter.java
  
  Index: JavaDeployWriter.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaDeployWriter.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- JavaDeployWriter.java     8 Mar 2002 20:04:45 -0000       1.25
  +++ JavaDeployWriter.java     13 Mar 2002 15:19:26 -0000      1.26
  @@ -157,28 +157,18 @@
               // 1) Don't register types that are base (primitive) types.
               //    If the baseType != null && getRefType() != null this
               //    is a simpleType that must be registered.
  -            // 2) Don't register the special types for collections
  -            //    (indexed properties)
  +            // 2) Don't register the special types for collections 
  +            //    (indexed properties) or element types
               // 3) Don't register types that are not referenced
               //    or only referenced in a literal context.
               if ((type.getBaseType() != null && type.getRefType() == null) ||
                   type instanceof CollectionType ||
  +                type instanceof Element ||
                   !type.isReferenced() ||
                   type.isOnlyLiteralReferenced()) {
                   process = false;
               }
   
  -
  -            // 4) If the type is an element, the typemapping is only generated
  -            // if the element has an anonymous type.  This is a quick fix
  -            // until I add anonymous types as actual symbol table elements. Scheu
  -            if (process && type instanceof Element) {
  -                Node node = symbolTable.getTypeEntry(type.getQName(),
  -                                                     true).getNode();
  -                if (node == null ||
  -                    Utils.getNodeTypeRefQName(node, "type") != null)
  -                    process = false;
  -            }
               if (process) {
                   pw.println("      <typeMapping");
                   pw.println("        xmlns:ns=\"" + 
type.getQName().getNamespaceURI() + "\"");
  
  
  
  1.42      +3 -12     
xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaStubWriter.java
  
  Index: JavaStubWriter.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaStubWriter.java,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -u -r1.41 -r1.42
  --- JavaStubWriter.java       6 Mar 2002 18:50:51 -0000       1.41
  +++ JavaStubWriter.java       13 Mar 2002 15:19:26 -0000      1.42
  @@ -402,27 +402,18 @@
           // 1) Don't register types that are base (primitive) types.
           //    If the baseType != null && getRefType() != null this
           //    is a simpleType that must be registered.
  -        // 2) Don't register the special types for collections
  -        //    (indexed properties)
  +        // 2) Don't register the special types for collections 
  +        //    (indexed properties) or element types
           // 3) Don't register types that are not referenced
           //    or only referenced in a literal context.
           if ((type.getBaseType() != null && type.getRefType() == null) ||
               type instanceof CollectionType ||
  +            type instanceof Element ||
               !type.isReferenced() ||
               type.isOnlyLiteralReferenced()) {
               process = false;
           }
           
  -        // 4) If the type is an element, the typemapping is only generated
  -        // if the element has an anonymous type.  This is a quick fix
  -        // until I add anonymous types as actual symbol table elements. Scheu
  -        if (process && type instanceof Element) {
  -            Node node = symbolTable.getTypeEntry(type.getQName(),
  -                                                 true).getNode();
  -            if (node == null ||
  -                Utils.getNodeTypeRefQName(node, "type") != null)
  -                process = false;
  -        }
           if (!process) {
               return;
           }
  
  
  
  1.17      +51 -4     
xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaWriterFactory.java
  
  Index: JavaWriterFactory.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaWriterFactory.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- JavaWriterFactory.java    27 Feb 2002 13:41:28 -0000      1.16
  +++ JavaWriterFactory.java    13 Mar 2002 15:19:27 -0000      1.17
  @@ -157,17 +157,20 @@
       } // getWriter
   
       /**
  -     * Fill in the names of each SymTabEntry with the javaified name
  +     * Fill in the names of each SymTabEntry with the javaified name.
  +     * Note: This method also ensures that anonymous types are 
  +     * given unique java type names.
        */
       private void javifyNames(SymbolTable symbolTable) {
  +        int uniqueNum = 0;
  +        HashMap anonQNames = new HashMap();
           Iterator it = symbolTable.getHashMap().values().iterator();
           while (it.hasNext()) {
               Vector v = (Vector) it.next();
               for (int i = 0; i < v.size(); ++i) {
                   SymTabEntry entry = (SymTabEntry) v.elementAt(i);
   
  -                // If it's a type, then use the referenced type's QName to generate 
this type's
  -                // name.
  +                // Use the type or the referenced type's QName to generate the java 
name.      
                   if (entry instanceof TypeEntry) {
                       TypeEntry tEntry = (TypeEntry) entry;
                       String dims = tEntry.getDimensions();
  @@ -177,7 +180,28 @@
                           dims += tEntry.getDimensions();
                           refType = tEntry.getRefType();
                       }
  -                    entry.setName(symbolTable.getJavaName(tEntry.getQName()) + 
dims);
  +                    // Get the QName to javify
  +                    QName typeQName = tEntry.getQName();
  +                    if (typeQName.getLocalPart().lastIndexOf('.') >= 0) {
  +                        // This is an anonymous type name.
  +                        // Axis uses '.' as a nesting token to generate
  +                        // unique qnames for anonymous types.
  +                        // Only consider the localName after the last '.' when
  +                        // generating the java name
  +                        String localName = typeQName.getLocalPart();
  +                        localName = 
localName.substring(localName.lastIndexOf('.')+1);
  +                        typeQName = new QName(typeQName.getNamespaceURI(), 
localName);
  +                        // If there is already an existing type, there will be a 
  +                        // collision.  If there is an existing anon type, there 
will be a 
  +                        // collision.  In both cases, the java type name should be 
mangled.
  +                        if (symbolTable.getType(typeQName) != null ||
  +                            anonQNames.get(typeQName) != null) {
  +                            localName += "ANON" + uniqueNum++;
  +                            typeQName = new QName(typeQName.getNamespaceURI(), 
localName);
  +                        } 
  +                        anonQNames.put(typeQName, typeQName);
  +                    }
  +                    entry.setName(symbolTable.getJavaName(typeQName) + dims);
                   }
   
                   // If it is not a type, then use this entry's QName to generate its 
name.
  @@ -245,6 +269,15 @@
                           if (entry instanceof Element) {
                               entry.setName(mangleName(entry.getName(),
                                       "_ElemType"));
  +                            // If this global element was defined using 
  +                            // an anonymous type, then need to change the
  +                            // java name of the anonymous type to match.
  +                            QName anonQName = new 
QName(entry.getQName().getNamespaceURI(),
  +                                                        "." + 
entry.getQName().getLocalPart());
  +                            TypeEntry anonType = symbolTable.getType(anonQName);
  +                            if (anonType != null) {
  +                                anonType.setName(entry.getName());
  +                            }
                           }
                           else if (entry instanceof TypeEntry) {
                               // Search all other types for java names that match 
this one.
  @@ -508,6 +541,20 @@
                                   p.type.setDynamicVar(
                                           JavaTypeWriter.HOLDER_IS_NEEDED,
                                           new Boolean(true));
  +
  +                                // If the type is a DefinedElement, need to 
  +                                // set HOLDER_IS_NEEDED on the anonymous type.
  +                                QName anonQName = SchemaUtils.
  +                                    getElementAnonQName(p.type.getNode());
  +                                if (anonQName != null) {
  +                                    TypeEntry anonType = 
  +                                        symbolTable.getType(anonQName);
  +                                    if (anonType != null) {
  +                                        anonType.setDynamicVar(
  +                                            JavaTypeWriter.HOLDER_IS_NEEDED,
  +                                            new Boolean(true));
  +                                    }                                    
  +                                }
                               }
                           }
                       }
  
  
  
  1.14      +27 -4     xml-axis/java/src/org/apache/axis/wsdl/toJava/SchemaUtils.java
  
  Index: SchemaUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/SchemaUtils.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- SchemaUtils.java  11 Mar 2002 16:25:32 -0000      1.13
  +++ SchemaUtils.java  13 Mar 2002 15:19:27 -0000      1.14
  @@ -324,17 +324,40 @@
           QName nodeName = Utils.getNodeNameQName(elementNode);
           BooleanHolder forElement = new BooleanHolder();
           QName nodeType = Utils.getNodeTypeRefQName(elementNode, forElement);
  -        if (nodeType == null) { // The element may use an anonymous type
  -             nodeType = nodeName;
  -             forElement.value = false;
  +        if (nodeType == null) { // The element may use an anonymous type       
  +            nodeType = getElementAnonQName(elementNode);            
  +            forElement.value = false;
           }
  -
  +        
           TypeEntry type = (TypeEntry) symbolTable.getTypeEntry(nodeType, 
forElement.value);
           if (type != null) {
               v.add(type);
               v.add(nodeName.getLocalPart());
           }
           return v;
  +    }
  +
  +    /**
  +     * Returns the WSDL2Java QName for the anonymous type of the element
  +     * or null.
  +     */
  +    public static QName getElementAnonQName(Node node) {
  +        QName nodeKind = Utils.getNodeQName(node);
  +        if (nodeKind != null &&
  +            nodeKind.getLocalPart().equals("element") &&
  +            Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
  +            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));
  +                }
  +            }
  +        }
  +        return null;
       }
   
       /**
  
  
  
  1.43      +1 -14     xml-axis/java/src/org/apache/axis/wsdl/toJava/SymbolTable.java
  
  Index: SymbolTable.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/SymbolTable.java,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -r1.42 -r1.43
  --- SymbolTable.java  11 Mar 2002 16:25:32 -0000      1.42
  +++ SymbolTable.java  13 Mar 2002 15:19:27 -0000      1.43
  @@ -613,21 +613,8 @@
        */
       private void createTypeFromDef(Node node, boolean isElement,
               boolean belowSchemaLevel) throws IOException {
  -        // See if this is an anonymous complexType for a global element
  -        // If it is, the element in the dictionary is used.
  -        QName qName = null;
  -        TypeEntry anonType = null;
  -        if (!isElement &&
  -            Utils.getAttribute(node, "name") == null) {
  -            qName = Utils.getNodeNameQName(node);
  -            if (qName != null &&
  -                getElement(qName) != null) {  // Element exists in dictionary so 
use it.
  -                return;
  -            }
  -        }
  -
           // Get the QName of the node's name attribute value
  -        qName = Utils.getNodeNameQName(node);
  +        QName qName = Utils.getNodeNameQName(node);
           if (qName != null) {
   
               // If the qname is already registered as a base type,
  
  
  
  1.18      +27 -88    xml-axis/java/src/org/apache/axis/wsdl/toJava/Utils.java
  
  Index: Utils.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/Utils.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- Utils.java        11 Mar 2002 16:25:32 -0000      1.17
  +++ Utils.java        13 Mar 2002 15:19:27 -0000      1.18
  @@ -97,93 +97,6 @@
           return name;
       } // capitalizeFirstChar
   
  -
  -
  -    /**
  -     * Some QNames represent base types.  This routine returns the 
  -     * name of the base java type or null.
  -     * (These mappings based on JSR-101 version 0.6 Public Draft)
  -     * ----------------------------------------------------------
  -     * Note that the Schema simple types map to different java types
  -     * depending on whether the nillable flag is set.  This routine
  -     * assumes nillable is false.
  -     * ----------------------------------------------------------
  -     * @param QName
  -     */
  -    /*
  -    public static String getBaseJavaName(QName qName) {
  -        String localName = qName.getLocalPart();
  -        if (Constants.isSchemaXSD(qName.getNamespaceURI())) {
  -            if (localName.equals("string")) {
  -                return "java.lang.String";
  -            } else if (localName.equals("integer")) {
  -                return "java.math.BigInteger";
  -            } else if (localName.equals("int")) {
  -                return "int";
  -            } else if (localName.equals("long")) {
  -                return "long";
  -            } else if (localName.equals("short")) {
  -                return "short";
  -            } else if (localName.equals("decimal")) {
  -                return "java.math.BigDecimal";
  -            } else if (localName.equals("float")) {
  -                return "float";
  -            } else if (localName.equals("double")) {
  -                return "double";
  -            } else if (localName.equals("boolean")) {
  -                return "boolean";
  -            } else if (localName.equals("byte")) {
  -                return "byte";
  -            } else if (localName.equals("QName")) {
  -                return "javax.xml.rpc.namespace.QName";
  -            } else if (localName.equals("dateTime")) {
  -                return "java.util.Date";             // Should be Calendar, but 
Calendar is abstract!
  -            } else if (localName.equals("base64Binary")) {
  -                return "byte[]";
  -            } else if (localName.equals("hexBinary")) {
  -                return "byte[]";
  -            } else if (localName.equals("date")) {   // Not defined in JSR-101
  -                return "java.util.Date";
  -            } else if (localName.equals("void")) {   // Not defined in JSR-101
  -                return "void";
  -            } else if (localName.equals("anyType")) { 
  -                return "java.lang.Object";
  -            }
  -        }
  -        else if (Constants.isSOAP_ENC(qName.getNamespaceURI())) {
  -            if (localName.equals("string")) {
  -                return "java.lang.String";
  -            } else if (localName.equals("int")) {
  -                return "java.lang.Integer";
  -            } else if (localName.equals("short")) {
  -                return "java.lang.Short";
  -            } else if (localName.equals("decimal")) {
  -                return "java.math.BigDecimal";
  -            } else if (localName.equals("float")) {
  -                return "java.lang.Float";
  -            } else if (localName.equals("double")) {
  -                return "java.lang.Double";
  -            } else if (localName.equals("boolean")) {
  -                return "java.lang.Boolean";
  -            } else if (localName.equals("base64")) {
  -                return "java.lang.Byte[]";
  -            } else if (localName.equals("byte")) {     
  -                return "java.lang.Byte";
  -            } else if (localName.equals("Array")) {    // Support for JAX-RPC Array
  -                return "Object[]";
  -            } else if (localName.equals("Vector")) {   // Not defined in JSR-101
  -                return "java.util.Vector";
  -            }
  -        }
  -        // special "java" namesapce means straight java types
  -        // So "java:void" maps to "void"
  -        else if (qName.getNamespaceURI().equals("java")) {  // Not defined in 
JSR-101
  -            return localName;
  -        }
  -        return null;
  -    }
  -    */
  -
       /**
        * getNillableQName returns the QName to use if the nillable=true
        * attribute is used.                             
  @@ -327,7 +240,23 @@
           // the complexType may be anonymous, which is why the getScopedAttribute
           // method is used.
           if (localName == null) {
  -            localName = getScopedAttribute(node, "name");
  +            localName = "";
  +            Node search = node.getParentNode();
  +            while(search != null) {
  +                QName kind = getNodeQName(search);
  +                if (kind.getLocalPart().equals("schema")) {
  +                    search = null;
  +                } else if (kind.getLocalPart().equals("element")) {
  +                    localName = "." + getNodeNameQName(search).getLocalPart();
  +                    search = search.getParentNode();
  +                } else if (kind.getLocalPart().equals("complexType") ||
  +                           kind.getLocalPart().equals("simpleType")) {
  +                    localName = getNodeNameQName(search).getLocalPart() + localName;
  +                    search = null;
  +                } else {
  +                    search = search.getParentNode();
  +                }
  +            }            
           }
           if (localName == null)
               return null;
  @@ -707,6 +636,16 @@
                   }
               }
           }
  +        
  +        // Get the anonymous type of the element
  +        QName anonQName = SchemaUtils.getElementAnonQName(type);
  +        if (anonQName != null) {
  +            TypeEntry anonType = symbolTable.getType(anonQName);
  +            if (anonType != null && !types.contains(anonType)) {
  +                types.add(anonType);
  +            }
  +        }
  +
           // Process extended types
           TypeEntry extendType = SchemaUtils.getComplexElementExtensionBase(type, 
symbolTable);
           if (extendType != null) {
  
  
  
  1.4       +21 -1     xml-axis/java/test/wsdl/refattr/refattr.wsdl
  
  Index: refattr.wsdl
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/refattr/refattr.wsdl,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- refattr.wsdl      25 Jan 2002 18:31:53 -0000      1.3
  +++ refattr.wsdl      13 Mar 2002 15:19:27 -0000      1.4
  @@ -28,13 +28,33 @@
           <xsd:all>
             <xsd:element name="areaCode" type="xsd:int"/>
             <xsd:element name="exchange" type="xsd:string"/>
  -          <xsd:element name="number" type="xsd:string"/>
  +          <xsd:element name="number">
  +             <xsd:complexType>
  +                <xsd:simpleContent>
  +                   <xsd:extension base = "xsd:string">
  +                      <xsd:attribute name= "length" type="xsd:int" />
  +                   </xsd:extension>
  +                </xsd:simpleContent>
  +             </xsd:complexType>
  +          </xsd:element>
           </xsd:all>
         </xsd:complexType>
   
         <xsd:complexType name="example">
           <xsd:all>
             <xsd:element name="address" type="soapenc:string"/>
  +          <!-- both example and phone contain anonymous types of number elements. 
-->
  +          <!-- This should result in two Number classes...one which has a mangled 
name -->
  +          <xsd:element name="number">
  +             <xsd:complexType>
  +                <xsd:simpleContent>
  +                   <xsd:extension base = "xsd:string">
  +                      <xsd:attribute name= "theLength" type="xsd:int" />
  +                   </xsd:extension>
  +                </xsd:simpleContent>
  +             </xsd:complexType>
  +          </xsd:element>
  +
           </xsd:all>
         </xsd:complexType>
   
  
  
  


Reply via email to