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 Tom Jordahl <to...@macromedia.com> on 2002/05/28 23:48:18 UTC

RE: cvs commit: xml-axis/java/test/wsdl/faults FaultService.wsdl FaultServiceSoapBindingImpl.java FaultServiceTestCase.java

Rich,

Finally had a chance to review this submission in detail and it looks great!

We never implemented the fault data serialization because as far as I know JAX-RPC (nor anyone else) has specified where and HOW the fault data gets sent.  Sure it can go in the details element, but does that mean that ONLY fault data is found there?  What about the other stuff we put there: the exception class name, the stack trace, etc.  This should definitely be on the TODO list, near the top.  I fear that we will only be able to support Axis to Axis fault data to start.  Does anyone know how any other implementations put their fault data on the wire?  The WSDL should give us enough info to fill in the Java exception class if we know exactly where to start looking at the XML...

Two suggestions:
- Your first issue should be cut and pasted in to the TODO list
- The text of the submit should be captured in the architecture docs that Glyn has been working on.

Nice job!

--
Tom Jordahl
Macromedia


-----Original Message-----
From: scheu@apache.org [mailto:scheu@apache.org]
Sent: Tuesday, May 14, 2002 7:47 PM
To: xml-axis-cvs@apache.org
Subject: cvs commit: xml-axis/java/test/wsdl/faults FaultService.wsdl
FaultServiceSoapBindingImpl.java FaultServiceTestCase.java


scheu       02/05/14 16:46:34

  Modified:    java/src/org/apache/axis/description ServiceDesc.java
               java/src/org/apache/axis/encoding/ser BeanSerializer.java
               java/src/org/apache/axis/wsdl/toJava JavaBeanWriter.java
                        JavaDefinitionWriter.java JavaGeneratorFactory.java
                        JavaTypeWriter.java Utils.java
               java/test/wsdl/faults FaultService.wsdl
                        FaultServiceSoapBindingImpl.java
                        FaultServiceTestCase.java
  Added:       java/src/org/apache/axis/wsdl/toJava
                        JavaBeanFaultWriter.java
  Log:
  This change implements the JSR 101 v1.0 mapping for
  Faults <-> Exception, which is defines a special
  "complexType" fault mapping.
  
  A byproduct of this change is an improved structure
  of the JavaBeanWriter.
  
  Here is a summary of the mappings from my axis-dev note:
  ======================================================
  The 1.0 version of JSR 101 describes a significantly different
  XML <-> Java mapping for faults.
  
  There are two different mappings. One for message parts which
  reference a simple type, and one for message parts which
  reference a complex type.
  
  Mapping for a Simple Type Message Part
  --------------------------------------
  
  This mapping is similar to the one currently performed in Axis
  for all faults.
  
  Given the following wsdl:
  
  <message name="FaultSimple" >
     <part name="info" type="xsd:string" />  <!-- type is a simple type-->
  </message>
  
  <portType name="myPortType">
    <operation name="myOperation">
       <input message="tns:myOperationInput"/>
       <output message="tns:myOperationOutput"/>
       <fault name="FaultSimple" message="tns:FaultSimple" />
    </operation>
  </portType>
  
  A java fault class will be built with the name "FaultSimple"
  that extends java.lang.Exception:
  
  package com.example;
  public class FaultSimple extends java.lang.Exception {
      public FaultSimple(String info) {...}
      public String getInfo() {...}
  }
  
  Mapping for a ComplexType Message Part
  --------------------------------------
  
  <complexType name="Base">
    <sequence>
      <element name="A" type="xsd:string" />
      <element name="B" type="xsd:string" />
    </sequence>
  </complexType>
  
  <complexType name="Derived">
    <complexContent>
      <extension base="tns:Base" />
        <sequence>
          <element name="C" type="xsd:string" />
          <element name="D" type="xsd:string" />
        </sequence>
      </extension>
    </complexContent>
  </complexType>
  
  <message name="FaultComplex" >
     <part name="info" type="tns:Derived" />  <!-- type is a simple type-->
  </message>
  
  <portType name="myPortType">
    <operation name="myOperation">
       <input message="tns:myOperationInput"/>
       <output message="tns:myOperationOutput"/>
       <fault name="FaultComplex" message="tns:FaultComplex" />
    </operation>
  </portType>
  
  You would think that the above should produce a java fault class
  named FaultComplex, but v1.0 indicates that a java fault class
  named Derived should be generated that extends Base.
  
  package com.example;
  public class Derived extends Base {
      public Derived(String A, String B,
                     String C, String D) {super(A,B)...}
      public String getB() {...}
      public String getC() {...}
  }
  
  package com.example;
  public class Base extends java.lang.Exception {
      public Base(String A, String B) {...}
      public String getA() {...}
      public String getB() {...}
  }
  
  There are a number of reasons for this mapping:
    1) It establishes an inheritance hierarchy of exceptions.
    2) It allows multiple operations to share the hierarchy.
  
  There are a number of generation implications of this mapping.
    A) It assumes that the complexTypes can only be explicitly
       referenced in a fault or non-fault context.
       (Aside: I implemented the code such that the complexType fault
       mapping 'wins' in this situation.)
  
    B) Any complexType that extends a complexType used in a
       fault context will need to be mapped as above (instead of
       being mapped to a bean class).
  
    C) Any complexType that is the base of a complexType used
       in a fault context will need to be mapped as above (instead of
       being mapped to a bean class).
  
    D) Need to implement the Java2WSDL reverse mapping.
  
    E) I'll assume that a complexType that is explicitly or implicitly
       the restriction of a simpleType will be mapped using the
       simple type mapping.
  
  ===================================================================
  
  Description of Changes
  ----------------------
  
  1) Added more structure to the JavaBeanWriter class to make it easier to extend.
     For example, there are now specific methods to write out the various pieces
     (i.e. writeClassStart(...), writeDefaultConstructor() ...).  There are also
     protected flags that allow derived classes to enable/disable the emission of
     the different methods.
  
  2) The "complexType" fault mapping is very similar to a Bean, and eventually
     the stuff in it will need to be serialized back to the client (see issue 1).
     For this reason, I created a new class JavaBeanFaultWriter which extends
     the JavaBeanWriter.  The emitted exception class automatically gets
     the meta-data/helper information just like a bean.  And it can re-use
     95% of the JavaBeanWriter methods.  (I added a writeFullConstructor() method
     to the JavaBeanWriter so that it can be used by JavaBeanFaultWriter or
     by other extensions.)
  
  3) A new method setFaultContext was added to JavaGenerationFactory.  This method
     sets the dynamic variable "ComplexTypeFault" on each complexType TypeEntry that is
     referenced in a fault message.  The "ComplexTypeFault" variable is also set on
     all the base and derived types of the indicated ComplexTypeFault.  This
     flag is used in subsequent processing to invoke the JavaFaultWriter (for the
     simple mapping) or the JavaBeanFaultWriter (for the complexType mapping).
  
     The dynamic variable "ComplexTypeFault" is also set on the MessageEntry
     to simplify processing of fault Messages.  And the dynamic variable "ExceptionClassName"
     is set on the MessageEntry to simplify the retrieval of the java class name
     for both the simple and complexType cases.
     (Changes were made to Utils.getFullExceptionClass to use the
     "ExceptionClassName" setting to get the class name).
  
  4) The JavaTypeWriter was changed to automatically call JavaBeanFaultWriter for complexTypes
     that have the "ComplexTypeFault" flag set.  Changes were made to JavaDefinitionWriter
     to invoke JavaFaultWriter for only the faults that have the simple mapping.
  
  5) The reverse Java2WSDL mapping is simplified.  The construction of a FaultDesc (in ServiceDesc)
     is always defined with a single part which locates the complexType of the specified Exception.
     This results in the "complexType" fault mapping in all cases, which is preferable.
     This also causes the exception class to pass through BeanSerializer.writeSchema(),
     which is great because any existing meta-data will be queried to properly
     write out the elements and attributes.  A small change was made to writeSchema to
     add java.lang.Exception as a stop-class.
  
  6) Changed the test.wsdl.FaultService test to include an operation, throwFault, which throws a
     complexType.  Three complexTypes were added: baseFault, derivedFault (which extends baseFault),
     and derivedFault2 (which extends derivedFault).  The new throwFault operation indicates
     that derivedFault is thrown...but the implementation actually throws derivedFault2.
     The FaultServiceTestCase was changed to assert that derivedFault2 is returned to the caller.
     This testcase tests the complexType fault mapping and exception hierarchies.
  
     The existing Roundtrip test adequately tests the reverse Java2WSDL mapping.
  
  ===================================================================
  Issues:
  
  1) No one has ever implemented the serialization of the fault contents across the wire!
     This information should be in the <details> section of the fault.
     The complexType mapping should make this a little easier since it is just a modified
     bean.  We may want to consider migrating the "simple" fault mapping to be
     like a SimpleType bean to further simplify the processing.
  
     a) The complexType exception class currently extends org.apache.axis.AxisFault instead
        of Exception.  The emitted class also has a default constructor, which is not
        allowed.  These need to be changed when (1) is addressed.
  
  2) A complexType that is used in a fault context will be mapped as an
     Exception class.  This mapping 'wins' over the default bean mapping.
     The code currently does not check for conflicts, and I am not sure if it should.
     I think that later JSR 101 specs will improve the exception mapping so that
     it becomes even more bean-like.
  
  Enjoy!
  
  Revision  Changes    Path
  1.22      +33 -1     xml-axis/java/src/org/apache/axis/description/ServiceDesc.java
  
  Index: ServiceDesc.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/description/ServiceDesc.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- ServiceDesc.java	3 May 2002 12:30:56 -0000	1.21
  +++ ServiceDesc.java	14 May 2002 23:46:34 -0000	1.22
  @@ -728,6 +728,21 @@
           for (int i=0; i < exceptionTypes.length; i++) {
               // Every remote method declares a java.rmi.RemoteException
               if (exceptionTypes[i] != java.rmi.RemoteException.class) {
  +                
  +                // For JSR 101 v.1.0, there is a simple fault mapping
  +                // and a complexType fault mapping...both mappings
  +                // generate a class that extends (directly or indirectly)
  +                // Exception.  
  +                // When converting java back to wsdl it is not possible 
  +                // to determine which way to do the mapping,
  +                // so it is always mapped back using the complexType
  +                // fault mapping because it is more useful (i.e. it
  +                // establishes a hierarchy of exceptions).  Note that this
  +                // will not cause any roundtripping problems.
  +                // Rich
  +                
  +
  +                /* Old Simple Type Mode                  
                   Field[] f = exceptionTypes[i].getDeclaredFields();
                   ArrayList exceptionParams = new ArrayList();
                   for (int j = 0; j < f.length; j++) {
  @@ -746,7 +761,24 @@
                   String pkgAndClsName = exceptionTypes[i].getName();
                   FaultDesc fault = new FaultDesc();
                   fault.setName(pkgAndClsName);
  -                fault.setParameters(exceptionParams);
  +                fault.setParameters(exceptionParams);                
  +                operation.addFault(fault);
  +                */
  +                
  +                // Create a single part with the dummy name "fault"
  +                // that locates the complexType for this exception.
  +                ParameterDesc param = new ParameterDesc(
  +                     new QName("", "fault"),
  +                     ParameterDesc.IN,
  +                     tm.getTypeQName(exceptionTypes[i]));
  +                param.setJavaType(exceptionTypes[i]);
  +                ArrayList exceptionParams = new ArrayList();
  +                exceptionParams.add(param);
  +
  +                String pkgAndClsName = exceptionTypes[i].getName();
  +                FaultDesc fault = new FaultDesc();
  +                fault.setName(pkgAndClsName);
  +                fault.setParameters(exceptionParams);                
                   operation.addFault(fault);
               }
           }
  
  
  
  1.31      +2 -0      xml-axis/java/src/org/apache/axis/encoding/ser/BeanSerializer.java
  
  Index: BeanSerializer.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/BeanSerializer.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- BeanSerializer.java	7 May 2002 16:08:49 -0000	1.30
  +++ BeanSerializer.java	14 May 2002 23:46:34 -0000	1.31
  @@ -243,6 +243,8 @@
           List stopClasses = types.getStopClasses();
           if (superClass != null &&
                   superClass != java.lang.Object.class &&
  +                superClass != java.lang.Exception.class &&
  +                superClass != org.apache.axis.AxisFault.class &&
                   (stopClasses == null ||
                   !(stopClasses.contains(superClass.getName()))) ) {
               // Write out the super class
  
  
  
  1.14      +365 -106  xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaBeanWriter.java
  
  Index: JavaBeanWriter.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaBeanWriter.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- JavaBeanWriter.java	10 May 2002 13:30:35 -0000	1.13
  +++ JavaBeanWriter.java	14 May 2002 23:46:34 -0000	1.14
  @@ -61,6 +61,7 @@
   import org.apache.axis.utils.JavaUtils;
   
   import org.apache.axis.wsdl.symbolTable.ElementDecl;
  +import org.apache.axis.wsdl.symbolTable.SchemaUtils;
   import org.apache.axis.wsdl.symbolTable.TypeEntry;
   
   import org.w3c.dom.Node;
  @@ -74,7 +75,19 @@
       private Vector attributes;
       private TypeEntry extendType;
       protected JavaWriter helper;
  -    protected Vector names = new Vector();
  +    protected Vector names = new Vector(); // even indices: types, odd: vars
  +    protected String simpleValueType = null;  // name of type of simple value
  +
  +    // The following fields can be set by extended classes
  +    // to control processing
  +    protected boolean enableDefaultConstructor = true;
  +    protected boolean enableFullConstructor = false;
  +    protected boolean enableSimpleConstructors = false;
  +    protected boolean enableToString = false;
  +    protected boolean enableSetters = true;
  +    protected boolean enableGetters = true;
  +    protected boolean enableEquals = true;
  +    protected boolean enableHashCode = true;
   
       /**
        * Constructor.
  @@ -99,67 +112,183 @@
           this.attributes = attributes;
           this.extendType = extendType;
           this.helper = helper;
  +        if (type.isSimpleType()) {
  +            enableSimpleConstructors = true;
  +            enableToString = true;
  +        }
       } // ctor
   
       /**
        * Generate the binding for the given complex type.
  -     * The elements vector contains the Types (even indices) and
  -     * element names (odd indices) of the contained elements
        */
       protected void writeFileBody() throws IOException {
  -        String valueType = null;
  -        Node node = type.getNode();
  +        // Populate Names Vector with the names and types of the members.
  +        // The write methods use the names vector whenever they need to get
  +        // a member name or type.
  +        preprocess();
   
  -        // See if this class extends another class
  -        String extendsText = "";
  -        if (extendType != null && !type.isSimpleType()) {
  -            extendsText = " extends " + extendType.getName() + " ";
  +        // Write the start of the class definition
  +        writeClassStart(getAbstractText(), getExtendsText(), getImplementsText());
  +
  +        // Write Member Fields
  +        writeMemberFields();
  +
  +        // Write the default constructor
  +        if (enableDefaultConstructor) {
  +            writeDefaultConstructor();
  +        }
  +
  +        // Write Full Constructor
  +        if (enableFullConstructor) {
  +            writeFullConstructor();
  +        }
  +
  +        // Write SimpleConstructors
  +        if (enableSimpleConstructors) {
  +            writeSimpleConstructors();
  +        }
  +
  +        // Write ToString method
  +        if (enableToString) {
  +            writeToStringMethod();
  +        }
  +
  +        // Write accessor methods
  +        writeAccessMethods();
  +
  +        // Write general purpose equals and hashCode methods
  +        if (enableEquals) {
  +            writeEqualsMethod();
  +        }
  +        if (enableHashCode) {
  +            writeHashCodeMethod();
  +        }
  +
  +        // Write the meta data into a Helper class or
  +        // embed it in the bean class
  +        if (emitter.isHelperWanted()) {
  +            helper.generate(); // separate Helper Class
  +        } else {
  +            helper.generate(pw); // embed in Bean Class
           }
  +        
  +        // Write end of class definition
  +        writeClassStop();
  +        pw.close();
  +    } // writeFileBody
   
  -        // We are only interested in the java names of the types, so create a names list
  +    /**
  +     * Builds the names String vector.  
  +     * The even indices are the java class names of the 
  +     * member fields.  The odd indices are the member variable
  +     * names.
  +     * Also sets the simpleValueType variable to the 
  +     * java class name of the simple value if this bean represents
  +     * a simple type
  +     */
  +    protected void preprocess() {
  +        // Add element names
           if (elements != null) {
               for (int i = 0; i < elements.size(); i++) {
                   ElementDecl elem = (ElementDecl)elements.get(i);
  -                TypeEntry type = elem.getType();
  +                String typeName = elem.getType().getName();
                   String elemName = elem.getName().getLocalPart();
  -                String javaName = Utils.xmlNameToJava(elemName);
  -                names.add(type.getName());
  -                names.add(javaName);
  +                String variableName = Utils.xmlNameToJava(elemName);
  +                names.add(typeName);
  +                names.add(variableName);
  +                if (type.isSimpleType() &&
  +                    variableName.equals("value")) {
  +                    simpleValueType = typeName;
  +                }
               }
           }
  -        // add the attributes to the names list (which will be bean elements too)
  +        // Add attribute names
           if (attributes != null) {
               for (int i = 0; i < attributes.size(); i += 2) {
  -                names.add(((TypeEntry) attributes.get(i)).getName());
  -                names.add(Utils.xmlNameToJava((String) attributes.get(i + 1)));
  +                String typeName = ((TypeEntry) attributes.get(i)).getName();
  +                String variableName = 
  +                    Utils.xmlNameToJava((String) attributes.get(i + 1));
  +                names.add(typeName);
  +                names.add(variableName);
  +                if (type.isSimpleType() &&
  +                    variableName.equals("value")) {
  +                    simpleValueType = typeName;
  +                }
               }
           }
  +    }        
  +    
  +    /**
  +     * Returns the appropriate extends text
  +     * @return "" or " extends <class> "
  +     */
  +    protected String getExtendsText() {
  +        // See if this class extends another class
  +        String extendsText = "";
  +        if (extendType != null && !type.isSimpleType()) {
  +            extendsText = " extends " + extendType.getName() + " ";
  +        }
  +        return extendsText;
  +    }
  +    
  +    /**
  +     * Returns the appropriate implements text
  +     * @return " implements <classes> "
  +     */
  +    protected String getImplementsText() {
  +        // See if this class extends another class
  +        String implementsText = " implements java.io.Serializable";
  +        if (type.isSimpleType()) {
  +            implementsText += ", org.apache.axis.encoding.SimpleType";
  +        }
  +        implementsText += " ";
  +        return implementsText;
  +    }
   
  -        String implementsText = "";
  -        if (type.isSimpleType())
  -            implementsText = ", org.apache.axis.encoding.SimpleType";
  -
  -        // Support abstract attribute by mapping to an abstract class
  -        String abstractText = "";
  +    /**
  +     * Returns the appropriate extends text
  +     * @return "" or "abstract "
  +     */
  +    protected String getAbstractText() {
  +        Node node = type.getNode();
           if (node != null) {
               String abstractValue = Utils.getAttribute(node, "abstract");
               if (abstractValue != null && 
                   abstractValue.equalsIgnoreCase("true")) {
  -                abstractText = "abstract ";
  +                return "abstract ";
               }
           }
  +        return "";
  +    }
   
  +    /**
  +     * Writes the start of the class definition.
  +     * @param String abstractText is the abstract keyword (or "")
  +     * @param String extendsText is the extends clause (or "")
  +     * @param String implementsText is the implements clause (or "")
  +     */
  +    protected void writeClassStart(String abstractText, 
  +                                   String extendsText,
  +                                   String implementsText) {
           pw.println("public " + abstractText + "class " + className + extendsText +
  -                   " implements java.io.Serializable" + implementsText + " {");
  +                   implementsText + " {");
  +    }
  +
  +    /**
  +     * Writes the end of the class definition.
  +     */
  +    protected void writeClassStop() {
  +        pw.println("}");
  +    }
   
  +    /**
  +     * Writes the member fields.
  +     */
  +    protected void writeMemberFields() {
           // Define the member element of the bean
           for (int i = 0; i < names.size(); i += 2) {
               String typeName = (String) names.get(i);
               String variable = (String) names.get(i + 1);
  -            
  -            if (type.isSimpleType() && variable.equals("value")) {
  -                valueType = typeName;
  -            }
                
               // Declare the bean element
               pw.print("    private " + typeName + " " + variable + ";");
  @@ -170,15 +299,172 @@
               else
                   pw.println();
           }
  +        pw.println();
  +    }
   
  +    /**
  +     * Writes the default constructor.
  +     */
  +    protected void writeDefaultConstructor() {
           // Define the default constructor
  -        pw.println();
           pw.println("    public " + className + "() {");
           pw.println("    }");
  +        pw.println();
  +    }
   
  +    /**
  +     * Writes the full constructor.  
  +     * Note that this class is not recommended for 
  +     * JSR 101 compliant beans, but is provided for
  +     * extended classes which may wish to generate a full
  +     * constructor.
  +     */
  +    protected void writeFullConstructor() {
  +        // The constructor needs to consider all extended types
  +        Vector extendList = new Vector();
  +        extendList.add(type);
  +        TypeEntry parent = extendType;
  +        while(parent != null) {
  +            extendList.add(parent);
  +            parent = SchemaUtils.getComplexElementExtensionBase(
  +                parent.getNode(),
  +                emitter.getSymbolTable());
  +        }
  +        
  +        // Now generate a list of names and types starting with
  +        // the oldest parent.  (Attrs are considered before elements).
  +        Vector paramTypes = new Vector();
  +        Vector paramNames = new Vector();
  +        for (int i=extendList.size()-1; i >= 0; i--) {
  +            TypeEntry te = (TypeEntry) extendList.elementAt(i);
  +
  +            // The names of the inherited parms are mangled
  +            // in case they interfere with local parms.
  +            String mangle = "";
  +            if (i > 0) {
  +                mangle = "_" + 
  +                    Utils.xmlNameToJava(te.getQName().getLocalPart()) +
  +                    "_";
  +            }
  +            // Process the attributes
  +            Vector attributes = SchemaUtils.getContainedAttributeTypes(
  +                te.getNode(), emitter.getSymbolTable());
  +            if (attributes != null) {
  +                for (int j=0; j<attributes.size(); j+=2) {
  +                    paramTypes.add(((TypeEntry) attributes.get(j)).getName());
  +                    paramNames.add(mangle +
  +                        Utils.xmlNameToJava((String) attributes.get(j + 1)));
  +                }
  +            }
  +            // Process the elements
  +            Vector elements = SchemaUtils.getContainedElementDeclarations(
  +                te.getNode(), emitter.getSymbolTable()); 
  +            if (elements != null) {
  +                for (int j=0; j<elements.size(); j++) {
  +                    ElementDecl elem = (ElementDecl)elements.get(j);
  +                    paramTypes.add(elem.getType().getName());
  +                    paramNames.add(mangle +
  +                        Utils.xmlNameToJava(elem.getName().getLocalPart()));
  +                }
  +            }
  +        }
  +        // Set the index where the local params start
  +        int localParams = paramTypes.size() - names.size()/2;
  +
  +        
  +        // Now write the constructor signature
  +        pw.println("    public " + className + "(");
  +        for (int i=0; i<paramTypes.size(); i++) {
  +            pw.print("           " + paramTypes.elementAt(i) + 
  +                     " " + paramNames.elementAt(i));
  +            if ((i+1) < paramTypes.size()) {
  +                pw.println(","); 
  +            } else {
  +                pw.println(") {"); 
  +            }
  +        }
  +
  +        // Call the extended constructor to set inherited fields
  +        if (extendType != null) {
  +            pw.println("        super(");
  +            for (int j=0; j<localParams; j++) {
  +                pw.print("            " + paramNames.elementAt(j));
  +                if ((j+1) < localParams) {
  +                    pw.println(","); 
  +                } else {
  +                    pw.println(");");
  +                }
  +            }            
  +        }
  +        // Set local fields directly
  +        for (int j=localParams; j<paramNames.size(); j++) {
  +            pw.println("        this." + paramNames.elementAt(j) +
  +                       " = " + paramNames.elementAt(j)+ ";");
  +        } 
  +        pw.println("    }");
           pw.println();
  -        int j = 0; 
   
  +    }
  +
  +    /**
  +     * Writes the constructors for SimpleTypes.
  +     * Writes a constructor accepting a string and 
  +     * a constructor accepting the simple java type.
  +     */
  +    protected void writeSimpleConstructors() {
  +        // If this is a simple type,need to emit a string
  +        // constructor and a value construtor.
  +        if (type.isSimpleType() && simpleValueType != null) {
  +            if (!simpleValueType.equals("java.lang.String")) {
  +                pw.println("    public " + className + "(" + 
  +                           simpleValueType + " value) {");
  +                pw.println("        this.value = value;");
  +                pw.println("    }");
  +                pw.println();
  +            }
  +            
  +            pw.println("    // " + JavaUtils.getMessage("needStringCtor"));
  +            pw.println("    public " + className + "(java.lang.String value) {");
  +            // Make sure we wrap base types with its Object type
  +            String wrapper = JavaUtils.getWrapper(simpleValueType);
  +            if (wrapper != null) {
  +                pw.println("        this.value = new " + wrapper +
  +                           "(value)." + simpleValueType + "Value();");
  +            } else {
  +                pw.println("        this.value = new " + 
  +                           simpleValueType + "(value);");
  +            }
  +            pw.println("    }");
  +            pw.println();            
  +        }
  +    }
  +
  +    /**
  +     * Writes the toString method  
  +     * Currently the toString method is only written for  
  +     * simpleTypes.                                 
  +     */
  +    protected void writeToStringMethod() {
  +        // If this is a simple type, emit a toString
  +        if (type.isSimpleType() && simpleValueType != null) {
  +            pw.println("    // " + JavaUtils.getMessage("needToString"));
  +            String wrapper = JavaUtils.getWrapper(simpleValueType);
  +            pw.println("    public String toString() {");
  +            if (wrapper != null) {
  +                pw.println("        return new " + wrapper + "(value).toString();");
  +            } else {
  +                pw.println("        return value == null ? null : value.toString();");
  +            }
  +            pw.println("    }");
  +            pw.println();
  +        }
  +    }
  +
  +    /**
  +     * Writes the setter and getter methods    
  +     */
  +    protected void writeAccessMethods() {
  +        int j = 0; 
           // Define getters and setters for the bean elements
           for (int i = 0; i < names.size(); i += 2, j++) {
               String typeName = (String) names.get(i);
  @@ -189,14 +475,20 @@
               if (typeName.equals("boolean"))
                   get = "is";
   
  -            pw.println("    public " + typeName + " " + get + capName + "() {");
  -            pw.println("        return " + name + ";");
  -            pw.println("    }");
  -            pw.println();
  -            pw.println("    public void set" + capName + "(" + typeName + " " + name + ") {");
  -            pw.println("        this." + name + " = " + name + ";");
  -            pw.println("    }");
  -            pw.println();
  +            if (enableGetters) {
  +                pw.println("    public " + typeName + " " + 
  +                           get + capName + "() {");
  +                pw.println("        return " + name + ";");
  +                pw.println("    }");
  +                pw.println();
  +            }
  +            if (enableSetters) {
  +                pw.println("    public void set" + capName + "(" + 
  +                           typeName + " " + name + ") {");
  +                pw.println("        this." + name + " = " + name + ";");
  +                pw.println("    }");
  +                pw.println();
  +            }
               
               // If this is a special collection type, insert extra 
               // java code so that the serializer/deserializer can recognize
  @@ -215,77 +507,39 @@
                       String newingName = typeName.substring(0, bracketIndex + 1);
                       String newingSuffix = typeName.substring(bracketIndex + 1);
                       
  -                    pw.println("    public " + compName + " " + get + capName + "(int i) {");
  -                    pw.println("        return " + name + "[i];");
  -                    pw.println("    }");
  -                    pw.println();
  -                    pw.println("    public void set" + capName + "(int i, " + compName + " value) {");
  -                    pw.println("        if (this." + name + " == null ||");
  -                    pw.println("            this." + name + ".length <= i) {");
  -                    pw.println("            " + typeName + " a = new " +
  -                               newingName + "i + 1" + newingSuffix + ";");
  -                    pw.println("            if (this." + name + " != null) {");
  -                    pw.println("                for(int j = 0; j < this." + name + ".length; j++)");
  -                    pw.println("                    a[j] = this." + name + "[j];");
  -                    pw.println("            }");
  -                    pw.println("            this." + name + " = a;");
  -                    pw.println("        }");
  -                    pw.println("        this." + name + "[i] = value;");
  -                    pw.println("    }");
  -                    pw.println();
  +                    if (enableGetters) {
  +                        pw.println("    public " + compName + " " + get + capName +
  +                                   "(int i) {");
  +                        pw.println("        return " + name + "[i];");
  +                        pw.println("    }");
  +                        pw.println();
  +                    }
  +                    if (enableSetters) {
  +                        pw.println("    public void set" + capName + "(int i, " +
  +                                   compName + " value) {");
  +                        pw.println("        if (this." + name + " == null ||");
  +                        pw.println("            this." + name + ".length <= i) {");
  +                        pw.println("            " + typeName + " a = new " +
  +                                   newingName + "i + 1" + newingSuffix + ";");
  +                        pw.println("            if (this." + name + " != null) {");
  +                        pw.println("                for(int j = 0; j < this." + name +
  +                                   ".length; j++)");
  +                        pw.println("                    a[j] = this." + name + "[j];");
  +                        pw.println("            }");
  +                        pw.println("            this." + name + " = a;");
  +                        pw.println("        }");
  +                        pw.println("        this." + name + "[i] = value;");
  +                        pw.println("    }");
  +                        pw.println();
  +                    }
                   }
               }
  -        }
  -       
  -        // if this is a simple type, we need to emit a toString and a string
  -        // constructor and throw in a value construtor too.
  -        if (type.isSimpleType() && valueType != null) {
  -            // emit contructors and toString().
  -            if (!valueType.equals("java.lang.String")) {
  -                pw.println("    public " + className + "(" + valueType + " value) {");
  -                pw.println("        this.value = value;");
  -                pw.println("    }");
  -                pw.println();
  -            }
  -            
  -            pw.println("    // " + JavaUtils.getMessage("needStringCtor"));
  -            pw.println("    public " + className + "(java.lang.String value) {");
  -            // Make sure we wrap base types with its Object type
  -            String wrapper = JavaUtils.getWrapper(valueType);
  -            if (wrapper != null) {
  -                pw.println("        this.value = new " + wrapper + "(value)." + valueType + "Value();");
  -            } else {
  -                pw.println("        this.value = new " + valueType + "(value);");
  -            }
  -            pw.println("    }");
  -            pw.println();            
  -            pw.println("    // " + JavaUtils.getMessage("needToString"));
  -            pw.println("    public String toString() {");
  -            if (wrapper != null) {
  -                pw.println("        return new " + wrapper + "(value).toString();");
  -            } else {
  -                pw.println("        return value == null ? null : value.toString();");
  -            }
  -            pw.println("    }");
  -            pw.println();
  -        }
  -        writeEqualsMethod();
  -        writeHashCodeMethod();
  -
  -        // Write the meta data into a Helper class or
  -        // embed it in the bean class
  -        if (emitter.isHelperWanted()) {
  -            helper.generate(); // separate Helper Class
  -        } else {
  -            helper.generate(pw); // embed in Bean Class
  -        }
  -        pw.println("}");
  -        pw.close();
  -    } // writeFileBody
  +        }        
  +    }
   
       /**
  -     * Generate an equals method.
  -     **/
  +     * Writes a general purpose equals method
  +     */
       protected void writeEqualsMethod() {
        
           // The __equalsCalc field and synchronized method are necessary
  @@ -360,8 +614,12 @@
           pw.println("        __equalsCalc = null;");
           pw.println("        return _equals;");
           pw.println("    }");
  +        pw.println("");
       }
   
  +    /**
  +     * Writes a general purpose hashCode method.
  +     */
       protected void writeHashCodeMethod() {
           // The __hashCodeCalc field and synchronized method are necessary
           // in case the object has direct or indirect references to itself.
  @@ -434,5 +692,6 @@
           pw.println("        __hashCodeCalc = false;");
           pw.println("        return _hashCode;");
           pw.println("    }");
  +        pw.println("");
       }
   } // class JavaBeanWriter
  
  
  
  1.8       +22 -2     xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaDefinitionWriter.java
  
  Index: JavaDefinitionWriter.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaDefinitionWriter.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- JavaDefinitionWriter.java	9 May 2002 13:14:28 -0000	1.7
  +++ JavaDefinitionWriter.java	14 May 2002 23:46:34 -0000	1.8
  @@ -73,6 +73,7 @@
   import org.apache.axis.wsdl.gen.Generator;
   
   import org.apache.axis.wsdl.symbolTable.SymbolTable;
  +import org.apache.axis.wsdl.symbolTable.MessageEntry;
   
   /**
    * This is Wsdl2java's Definition Writer.  
  @@ -129,8 +130,27 @@
           while (fi.hasNext()) {
               Map.Entry entry = (Map.Entry) fi.next();
               Fault fault = (Fault) entry.getKey();
  -            QName faultQName = (QName) entry.getValue();
  -            new JavaFaultWriter(emitter, faultQName, fault, symbolTable).generate();
  +
  +            // Generate the 'Simple' Faults.
  +            // The complexType Faults are automatically handled
  +            // by JavaTypeWriter.
  +            MessageEntry me = symbolTable.getMessageEntry(
  +                fault.getMessage().getQName());
  +            boolean emitSimpleFault = true;
  +            if (me != null) {
  +                Boolean complexTypeFault = (Boolean)
  +                    me.getDynamicVar(
  +                        JavaGeneratorFactory.COMPLEX_TYPE_FAULT);
  +                if (complexTypeFault != null &&
  +                    complexTypeFault.booleanValue()) {
  +                    emitSimpleFault = false;
  +                }
  +            }
  +            if (emitSimpleFault) {
  +                QName faultQName = (QName) entry.getValue();
  +                new JavaFaultWriter(emitter, faultQName, fault,
  +                                    symbolTable).generate();
  +            }
           }
       } // writeFaults
   
  
  
  
  1.4       +152 -0    xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaGeneratorFactory.java
  
  Index: JavaGeneratorFactory.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaGeneratorFactory.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- JavaGeneratorFactory.java	14 May 2002 18:59:24 -0000	1.3
  +++ JavaGeneratorFactory.java	14 May 2002 23:46:34 -0000	1.4
  @@ -59,6 +59,7 @@
   import java.io.IOException;
   
   import java.util.HashMap;
  +import java.util.HashSet;
   import java.util.Iterator;
   import java.util.Vector;
   
  @@ -103,6 +104,9 @@
   public class JavaGeneratorFactory implements GeneratorFactory {
       protected Emitter     emitter;
       protected SymbolTable symbolTable;
  +    
  +    public static String COMPLEX_TYPE_FAULT = "ComplexTypeFault";
  +    public static String EXCEPTION_CLASS_NAME = "ExceptionClassName";
   
       /**
        * Default constructor.  Note that this class is unusable until setEmitter
  @@ -171,6 +175,7 @@
       public void generatorPass(Definition def, SymbolTable symbolTable) {
           this.symbolTable = symbolTable;
           javifyNames(symbolTable);
  +        setFaultContext(symbolTable);
           resolveNameClashes(symbolTable);
           determineSEINames(symbolTable);
           if (emitter.isAllWanted()) {
  @@ -390,6 +395,142 @@
           }
       } // javifyNames
   
  +    /**
  +     * setFaultContext:
  +     * Processes the symbol table and sets the COMPLEX_TYPE_FAULT
  +     * on each TypeEntry that is a complexType and is referenced in
  +     * a fault message.  TypeEntries that are the base or derived
  +     * from such a TypeEntry are also marked with COMPLEX_TYPE_FAULT.
  +     * The containing MessageEntry is marked with cOMPLEX_TYPE_FAULT, and
  +     * all MessageEntries for faults are tagged with the
  +     * EXCEPTION_CLASS_NAME variable, which indicates the java exception
  +     * class name.
  +     * @param SymbolTable
  +     */
  +    private void setFaultContext(SymbolTable symbolTable) {
  +        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);
  +                // Inspect each BindingEntry in the Symbol Table
  +                if (entry instanceof BindingEntry) {
  +                    BindingEntry bEntry = (BindingEntry) entry;
  +                    Binding binding = bEntry.getBinding();
  +                    // Get the associated PortType
  +                    PortTypeEntry ptEntry = 
  +                        symbolTable.getPortTypeEntry(
  +                            binding.getPortType().getQName());
  +                    PortType portType = ptEntry.getPortType();
  +                    Iterator operations = portType.getOperations().iterator();
  +                    // Inspect the Operations of the PortType
  +                    while(operations.hasNext()) {
  +                        Operation operation = (Operation) operations.next();
  +                        OperationType type = operation.getStyle();
  +                        // Get the associated parameters of the operation.
  +                        String name = operation.getName();
  +                        Parameters parameters = bEntry.getParameters(operation);
  +
  +                        // Inspect the faults of the operation
  +                        Iterator iFault = parameters.faults.values().iterator();
  +                        while(iFault.hasNext()) {
  +                            Fault fault = (Fault) iFault.next();
  +                            setFaultContext(fault, symbolTable);
  +                        }
  +                    }
  +                }
  +            }
  +        }
  +    } // setFaultContext
  +
  +    /**
  +     * setFaultContext:
  +     * Helper routine for the setFaultContext method above.
  +     * Examines the indicated fault and sets COMPLEX_TYPE_FAULT
  +     * and EXCEPTION_CLASS_NAME as appropriate.
  +     * @param Fault to analyze
  +     * @param SymbolTable 
  +     */
  +    private void setFaultContext(Fault fault,
  +                                 SymbolTable symbolTable) {
  +        Vector parts = new Vector();
  +        // Get the parts of the fault's message.
  +        // An IOException is thrown if the parts cannot be
  +        // processed.  Skip such parts for this analysis
  +        try {
  +            symbolTable.getParametersFromParts(
  +                parts, 
  +                fault.getMessage().getOrderedParts(null),
  +                false,
  +                fault.getName(),
  +                "unknown");
  +        } catch (IOException e) {}
  +        
  +        // Inspect each TypeEntry referenced in a Fault Message Part
  +        String exceptionClassName = null;
  +        for(int j=0; j < parts.size(); j++) {
  +            TypeEntry te = ((Parameter)(parts.elementAt(j))).getType();
  +            if (te.getBaseType() != null ||
  +                te.isSimpleType()) {
  +                // Simple Type Exception
  +            } else {
  +                // Complex Type Exception
  +                Boolean isComplexFault = (Boolean) te.getDynamicVar(
  +                    JavaGeneratorFactory.COMPLEX_TYPE_FAULT);
  +                if (isComplexFault == null ||
  +                    !isComplexFault.booleanValue()) {
  +                    te.setDynamicVar(
  +                        JavaGeneratorFactory.COMPLEX_TYPE_FAULT, 
  +                        new Boolean(true));
  +                    // Mark all derived types as Complex Faults
  +                    HashSet derivedSet =
  +                        org.apache.axis.wsdl.symbolTable.Utils.getDerivedTypes(
  +                            te, symbolTable);
  +                    Iterator derivedI = derivedSet.iterator();
  +                    while(derivedI.hasNext()) {
  +                        TypeEntry derivedTE = (TypeEntry)
  +                            derivedI.next();
  +                        derivedTE.setDynamicVar(
  +                            JavaGeneratorFactory.COMPLEX_TYPE_FAULT, 
  +                            new Boolean(true));
  +                    }
  +                    // Mark all base types as Complex Faults
  +                    TypeEntry base = SchemaUtils.getComplexElementExtensionBase(
  +                        te.getNode(),
  +                        symbolTable);
  +                    while (base != null) {
  +                        base.setDynamicVar(
  +                            JavaGeneratorFactory.COMPLEX_TYPE_FAULT, 
  +                            new Boolean(true));
  +                        base = SchemaUtils.getComplexElementExtensionBase(
  +                            base.getNode(),
  +                            symbolTable);
  +                    }
  +                }
  +                exceptionClassName = emitter.getJavaName(te.getQName());
  +            }
  +        }
  +        // Set the name of the exception and
  +        // whether the exception is a complex type
  +        MessageEntry me = symbolTable.getMessageEntry(
  +            fault.getMessage().getQName());
  +        if (me != null) {
  +            if (exceptionClassName != null) {
  +                me.setDynamicVar(
  +                                 JavaGeneratorFactory.COMPLEX_TYPE_FAULT, 
  +                                 new Boolean(true));
  +                me.setDynamicVar(
  +                                 JavaGeneratorFactory.EXCEPTION_CLASS_NAME, 
  +                                 exceptionClassName);
  +            } else {
  +                me.setDynamicVar(
  +                                 JavaGeneratorFactory.EXCEPTION_CLASS_NAME, 
  +                                 emitter.getJavaName(me.getQName()));
  +            }
  +            
  +        }
  +    }
  +
       protected void determineSEINames(SymbolTable symbolTable) {
           Iterator it = symbolTable.getHashMap().values().iterator();
           while (it.hasNext()) {
  @@ -423,6 +564,17 @@
           Iterator it = symbolTable.getHashMap().values().iterator();
           while (it.hasNext()) {
               Vector v = new Vector((Vector) it.next());  // New vector we can temporarily add to it
  +
  +            // Remove MessageEntries since they are not mapped
  +            int index = 0;
  +            while (index < v.size()) {
  +                if (v.elementAt(index) instanceof MessageEntry) {
  +                    v.removeElementAt(index);
  +                } else {
  +                    index++;
  +                }
  +            }
  +
               if (v.size() > 1) {
                   boolean resolve = true;
                   // Common Special Case:
  
  
  
  1.12      +15 -1     xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaTypeWriter.java
  
  Index: JavaTypeWriter.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaTypeWriter.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- JavaTypeWriter.java	9 May 2002 13:14:28 -0000	1.11
  +++ JavaTypeWriter.java	14 May 2002 23:46:34 -0000	1.12
  @@ -88,6 +88,7 @@
               Emitter emitter,
               TypeEntry type,
               SymbolTable symbolTable) {
  +
           if (type.isReferenced() && !type.isOnlyLiteralReferenced()) {
   
               // Determine what sort of type this is and instantiate 
  @@ -171,7 +172,20 @@
                                      Vector attributes) {
           JavaWriter helperWriter = getBeanHelperWriter(emitter, type, elements, base,
                                                     attributes);
  -        return new JavaBeanWriter(emitter, type, elements, base, attributes, 
  +        // If this complexType is referenced in a
  +        // fault context, emit a bean-like exception 
  +        // class
  +        Boolean isComplexFault = (Boolean)
  +            type.getDynamicVar(
  +                               JavaGeneratorFactory.COMPLEX_TYPE_FAULT);
  +        if (isComplexFault != null && 
  +            isComplexFault.booleanValue()) {
  +            return new JavaBeanFaultWriter(emitter, type, 
  +                                           elements, base, attributes, 
  +                                           helperWriter);
  +        }
  +        return new JavaBeanWriter(emitter, type, 
  +                                  elements, base, attributes, 
                                     helperWriter);
       }
   
  
  
  
  1.30      +4 -3      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.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- Utils.java	9 May 2002 13:14:29 -0000	1.29
  +++ Utils.java	14 May 2002 23:46:34 -0000	1.30
  @@ -70,6 +70,7 @@
   
   import org.apache.axis.wsdl.symbolTable.SymbolTable;
   import org.apache.axis.wsdl.symbolTable.TypeEntry;
  +import org.apache.axis.wsdl.symbolTable.MessageEntry;
   
   import org.w3c.dom.Node;
   import org.w3c.dom.NodeList;
  @@ -164,12 +165,12 @@
       public static String getFullExceptionName(
               Fault fault, Emitter emitter) {
   
  -        // Upgraded to JSR 101 version 0.8
  -
           // Get the Message referenced in the message attribute of the
           // fault.
           Message faultMessage = fault.getMessage();
  -        return emitter.getJavaName(faultMessage.getQName());
  +        MessageEntry me = emitter.getSymbolTable().getMessageEntry(
  +            faultMessage.getQName()); 
  +        return (String) me.getDynamicVar(JavaGeneratorFactory.EXCEPTION_CLASS_NAME);
       } // getFullExceptionName
   
       /**
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaBeanFaultWriter.java
  
  Index: JavaBeanFaultWriter.java
  ===================================================================
   /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.axis.wsdl.toJava;
  
  import java.io.IOException;
  
  import java.util.Vector;
  
  import org.apache.axis.utils.JavaUtils;
  
  import org.apache.axis.wsdl.symbolTable.ElementDecl;
  import org.apache.axis.wsdl.symbolTable.SchemaUtils;
  import org.apache.axis.wsdl.symbolTable.TypeEntry;
  
  import org.w3c.dom.Node;
  
  /**
   * This is Wsdl2java's Complex Faylt Writer.
   * It generates bean-like class for complexTypes used
   * in a operation fault message.
   */
  public class JavaBeanFaultWriter extends JavaBeanWriter {
      /**
       * Constructor.
       * @param emitter   
       * @param type        The type representing this class
       * @param elements    Vector containing the Type and name of each property
       * @param extendType  The type representing the extended class (or null)
       * @param attributes  Vector containing the attribute types and names    
       * @param helper      Helper class writer                                
       */
      protected JavaBeanFaultWriter(
              Emitter emitter,
              TypeEntry type,
              Vector elements,
              TypeEntry extendType,
              Vector attributes,
              JavaWriter helper) {
          super(emitter, type, elements, 
                extendType, attributes, helper);
  
          // The Default Constructor is not JSR 101 v1.0 compliant, but
          // is the only way that Axis can get something back over the wire.
          // This will need to be changed when fault contents are supported
          // over the wire.
          enableDefaultConstructor = true;
  
          // JSR 101 v1.0 requires a full constructor
          enableFullConstructor = true;
  
          // JSR 101 v1.0 does not support write access methods
          enableSetters = false;
      } // ctor
      
      /**
       * Returns the appropriate extends text
       * @return "" or " extends <class> "
       */
      protected String getExtendsText() {
          // See if this class extends another class
          String extendsText = super.getExtendsText();
          if (extendsText.equals("")) {
              // JSR 101 compliant code should extend java.lang.Exception!
              //extendsText = " extends java.lang.Exception ";
              extendsText = " extends org.apache.axis.AxisFault ";
          }
          return extendsText;
      }
  
  } // class JavaBeanFaultWriter
  
  
  
  1.2       +71 -3     xml-axis/java/test/wsdl/faults/FaultService.wsdl
  
  Index: FaultService.wsdl
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/faults/FaultService.wsdl,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- FaultService.wsdl	7 Jan 2002 15:54:20 -0000	1.1
  +++ FaultService.wsdl	14 May 2002 23:46:34 -0000	1.2
  @@ -1,5 +1,43 @@
   <?xml version="1.0" encoding="UTF-8"?>
  -<definitions targetNamespace="http://test.com/wsdl/faults" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:serviceNS="http://test.com/wsdl/faults" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/">
  +<definitions targetNamespace="http://test.com/wsdl/faults" 
  +     xmlns:tns="http://test.com/wsdl/faults"
  +     xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  +     xmlns:serviceNS="http://test.com/wsdl/faults"
  +     xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
  +     xmlns="http://schemas.xmlsoap.org/wsdl/">
  +
  +  <types>
  +    <xsd:schema 
  +        targetNamespace="http://test.com/wsdl/faults">
  +      <xsd:complexType name="baseFault">
  +        <xsd:sequence>
  +          <xsd:element name="a" type="xsd:int"/>
  +        </xsd:sequence>
  +      </xsd:complexType>
  +
  +      <xsd:complexType name="derivedFault">
  +        <xsd:complexContent>
  +          <xsd:extension base="tns:baseFault">
  +            <xsd:sequence>
  +              <xsd:element name="b" type="xsd:string"/>
  +            </xsd:sequence>
  +          </xsd:extension>
  +        </xsd:complexContent>
  +      </xsd:complexType>
  +
  +     <xsd:complexType name="derivedFault2">
  +        <xsd:complexContent>
  +          <xsd:extension base="tns:derivedFault">
  +            <xsd:sequence>
  +              <xsd:element name="c" type="xsd:float"/>
  +            </xsd:sequence>
  +          </xsd:extension>
  +        </xsd:complexContent>
  +      </xsd:complexType>
  +
  +    </xsd:schema>
  +  </types>
  +
     <message name="getQuoteResponse">
       <part name="getQuoteResult" type="xsd:float"/>
     </message>
  @@ -9,11 +47,29 @@
     <message name="InvalidTickerFaultMessage">
       <part name="tickerSymbol" type="xsd:string"/>
     </message>
  +
  +  <message name="throwFaultResponse">
  +    <part name="return" type="xsd:int"/>
  +  </message>
  +  <message name="throwFaultRequest">
  +    <part name="a" type="xsd:int"/>
  +    <part name="b" type="xsd:string"/>
  +    <part name="c" type="xsd:float"/>
  +  </message>
  +  <message name="throwFaultFault">
  +    <part name="theFault" type="tns:derivedFault" />
  +  </message>
  +
     <portType name="FaultServicePortType">
       <operation name="getQuote">
         <input message="serviceNS:getQuoteRequest"/>
         <output message="serviceNS:getQuoteResponse"/>
  -      <fault name="InvalidTickerFault" message="serviceNS:InvalidTickerFaultMessage"/>
  +      <fault name="InvalidTickerFaultMessage" message="serviceNS:InvalidTickerFaultMessage"/>
  +    </operation>
  +    <operation name="throwFault">
  +      <input message="serviceNS:throwFaultRequest"/>
  +      <output message="serviceNS:throwFaultResponse"/>
  +      <fault name="throwFaultFault" message="serviceNS:throwFaultFault"/>
       </operation>
     </portType>
     <binding name="FaultServiceSoapBinding" type="serviceNS:FaultServicePortType">
  @@ -27,7 +83,19 @@
           <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace=""/>
         </output>
         <fault>
  -        <soap:fault name="InvalidTickerFault" use="encoded"/>
  +        <soap:fault name="InvalidTickerFaultMessage" use="encoded"/>
  +      </fault>
  +    </operation>
  +    <operation name="throwFault">
  +      <soap:operation soapAction="" style="rpc"/>
  +      <input>
  +        <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace=""/>
  +      </input>
  +      <output>
  +        <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace=""/>
  +      </output>
  +      <fault>
  +        <soap:fault name="throwFaultFault" use="encoded"/>
         </fault>
       </operation>
     </binding>
  
  
  
  1.2       +4 -0      xml-axis/java/test/wsdl/faults/FaultServiceSoapBindingImpl.java
  
  Index: FaultServiceSoapBindingImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/faults/FaultServiceSoapBindingImpl.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- FaultServiceSoapBindingImpl.java	7 Jan 2002 15:54:20 -0000	1.1
  +++ FaultServiceSoapBindingImpl.java	14 May 2002 23:46:34 -0000	1.2
  @@ -12,4 +12,8 @@
       public float getQuote(java.lang.String tickerSymbol) throws java.rmi.RemoteException, InvalidTickerFaultMessage {
           throw new InvalidTickerFaultMessage(tickerSymbol);
       }
  +
  +    public int throwFault(int a, java.lang.String b, float c) throws java.rmi.RemoteException, test.wsdl.faults.DerivedFault {
  +        throw new DerivedFault2(a, b, c);
  +    }
   }
  
  
  
  1.4       +52 -2     xml-axis/java/test/wsdl/faults/FaultServiceTestCase.java
  
  Index: FaultServiceTestCase.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/faults/FaultServiceTestCase.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- FaultServiceTestCase.java	5 Feb 2002 16:22:40 -0000	1.3
  +++ FaultServiceTestCase.java	14 May 2002 23:46:34 -0000	1.4
  @@ -19,10 +19,11 @@
   
       public static void main(String[] args) throws Exception {
           FaultServiceTestCase tester = new FaultServiceTestCase("tester");
  -        tester.testFaultService();
  +        tester.testFaultServiceGetQuote();
  +        tester.testFaultServiceThrowFault();
       }
       
  -    public void testFaultService() {
  +    public void testFaultServiceGetQuote() {
           test.wsdl.faults.FaultServicePortType binding;
           try {
               binding = new FaultServiceLocator().getFaultService();
  @@ -42,6 +43,55 @@
               // We don't support fault data yet!
               //assertEquals("Ticker Symbol in Fault doesn't match original argument", 
               //        symbol, tickerFault.getTickerSymbol());
  +        }
  +        catch (org.apache.axis.AxisFault e) {
  +            throw new junit.framework.
  +                    AssertionFailedError("AxisFault caught: " + e);            
  +        }
  +        catch (java.rmi.RemoteException re) {
  +            throw new junit.framework.
  +                    AssertionFailedError("Remote Exception caught: " + re );
  +        }
  +    }
  +
  +    public void testFaultServiceThrowFault() {
  +        test.wsdl.faults.FaultServicePortType binding;
  +        try {
  +            binding = new FaultServiceLocator().getFaultService();
  +        }
  +        catch (javax.xml.rpc.ServiceException jre) {
  +            throw new junit.framework.
  +                    AssertionFailedError("JAX-RPC ServiceException caught: " + jre);            
  +        }
  +        assertTrue("binding is null", binding != null);
  +        int a = 7;
  +        String b = "test";
  +        float c = 3.14F;
  +            
  +        try {
  +            float value = 0;
  +            value = binding.throwFault(a,b,c);
  +            fail("Should raise a DerivedFault"); 
  +        } 
  +        // We are expecting DerivedFault2 (the operation indicates
  +        // that it throws a DerivedFault, but we know the impl actually
  +        // throws DerivedFault2 which extends DerivedFault)
  +        catch (DerivedFault2 e) {
  +            // We don't support fault data yet!
  +            //assertEquals("Param A in DerivedFault2 doesn't match original", 
  +            //        a, tickerFault.getA());
  +            //assertEquals("Param B in DerivedFault2 doesn't match original", 
  +            //        b, tickerFault.getB());
  +            //assertEquals("Param C in DerivedFault2 doesn't match original", 
  +            //        c, tickerFault.getC());
  +        }
  +        catch (DerivedFault e) {
  +            throw new junit.framework.
  +                    AssertionFailedError("DerivedFault caught: " + e);            
  +        }
  +        catch (BaseFault e) {
  +            throw new junit.framework.
  +                    AssertionFailedError("BaseFault caught: " + e);            
           }
           catch (org.apache.axis.AxisFault e) {
               throw new junit.framework.