scheu       02/02/07 15:23:12

  Modified:    java/samples/echo EchoService.java TestClient.java
               java/src/org/apache/axis/encoding
                        DeserializationContextImpl.java
                        SerializationContextImpl.java
               java/src/org/apache/axis/encoding/ser ArrayDeserializer.java
               java/src/org/apache/axis/utils JavaUtils.java
               java/test/encoding TestDeser.java
               java/test/functional TestEchoSample.java
  Log:
  The following changes are made to improve interoperability.
  
   - The ArrayDeserializer has been upgraded to use the
     specific type= information if passed.  For example
     if a specific type is set (not soapenc:Array) and
     the arrayType attribute is missing, the deserializer
     has enough information to continue.  See the comment
     in the code.
  
   - The ArrayDeserializer also sets a destinatation class
     "hint" in the ArrayListExtension object.  This "hint"
     can be used by the JavaUtils:convert() routine to
     instantiate a more specific array.
  
   - Added 12 more tests to test.encoding.TestDeser to
     make sure Axis correctly deserializes xml array
     messages that have missing attributes, etc.
     Also included a test which deserializes an Object array
     which has mixed elements (String and Integer).
  
   - The getTypeFromAttributes routine in DeserializationContextImpl
     has been extended to attempt to use the name qname as the
     type if the type attribute is missing
     (it already did this for soapenc primitives).
     The .Net services sometimes don't set the type= attribute,
     but the name of the
     element is the name of the type.
  
   - minor changes to the test client to more accurately reflect
     the expected return types for arrays of xsd:int and xsd:float.
  
  I ran the interop tests and we are still just as interoperable
  (HP site was down). (I also ran the interop tests with Axis
   passing the specific array type.  In these
  tests Axis was slightly better than the last time.)
  
  Revision  Changes    Path
  1.14      +2 -2      xml-axis/java/samples/echo/EchoService.java
  
  Index: EchoService.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/samples/echo/EchoService.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- EchoService.java  20 Nov 2001 15:07:58 -0000      1.13
  +++ EchoService.java  7 Feb 2002 23:23:11 -0000       1.14
  @@ -96,7 +96,7 @@
        * This method accepts an array of integers and echoes it back to the 
        * client.
        */
  -    public Integer[] echoIntegerArray(Integer[] input) {
  +    public int[] echoIntegerArray(int[] input) {
           return input;
       }
   
  @@ -110,7 +110,7 @@
       /**
        * This method accepts an array of floats and echoes it back to the client.
        */
  -    public Float[] echoFloatArray(Float[] input) {
  +    public float[] echoFloatArray(float[] input) {
           return input;
       }
   
  
  
  
  1.47      +4 -3      xml-axis/java/samples/echo/TestClient.java
  
  Index: TestClient.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/samples/echo/TestClient.java,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- TestClient.java   31 Jan 2002 03:26:08 -0000      1.46
  +++ TestClient.java   7 Feb 2002 23:23:11 -0000       1.47
  @@ -237,9 +237,9 @@
           test("String      ", "abcdefg");
           test("StringArray ", new String[] {"abc", "def"});
           test("Integer     ", new Integer(42));
  -        test("IntegerArray", new Integer[] {new Integer(42)});
  +        test("IntegerArray", new int[] {42});
           test("Float       ", new Float(3.7F));
  -        test("FloatArray  ", new Float[] {new Float(3.7F), new Float(7F)});
  +        test("FloatArray  ", new float[] {3.7F, 7F});
           test("Struct      ", new SOAPStruct(5, "Hello", 10.3F));
           test("StructArray ", new SOAPStruct[] {
             new SOAPStruct(1, "one", 1.1F),
  @@ -305,7 +305,8 @@
                               ((Exception)gotBack).printStackTrace();
                           }
                       }
  -                    System.out.println(method + "\t " + message + gotBack);
  +                    System.out.println(method + "\t " + message +
  +                                       gotBack + " expected " + sent);
                   }
               }
           };
  
  
  
  1.5       +9 -9      
xml-axis/java/src/org/apache/axis/encoding/DeserializationContextImpl.java
  
  Index: DeserializationContextImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/DeserializationContextImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DeserializationContextImpl.java   31 Jan 2002 03:26:09 -0000      1.4
  +++ DeserializationContextImpl.java   7 Feb 2002 23:23:11 -0000       1.5
  @@ -349,18 +349,18 @@
           if (typeQName != null)
               return typeQName;
           
  -        // If no attribute information, can't continue
  -        if (attrs == null)
  -            return null;
  -        
           // Check for type
           String type = Constants.getValue(attrs, Constants.URI_CURRENT_SCHEMA_XSI, 
"type");
  -        
  -        if (type == null)
  -            return null;
  +        if (type != null) {
  +            // Return the type attribute value converted to a QName
  +            return getQNameFromString(type);
  +        }
   
  -        // Return the type attribute value converted to a QName
  -        return getQNameFromString(type);
  +        // If all else fails see if the name is a known type
  +        typeQName = new QName(namespace, localName);
  +        if (getTypeMapping().getClassForQName(typeQName) != null)
  +            return typeQName;
  +        return null;
       }
   
       /**
  
  
  
  1.5       +9 -2      
xml-axis/java/src/org/apache/axis/encoding/SerializationContextImpl.java
  
  Index: SerializationContextImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/SerializationContextImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SerializationContextImpl.java     1 Feb 2002 04:12:28 -0000       1.4
  +++ SerializationContextImpl.java     7 Feb 2002 23:23:11 -0000       1.5
  @@ -107,7 +107,7 @@
       private int lastPrefixIndex = 1;
       private MessageContext msgContext;
       private boolean pretty = false;
  -
  +    private static QName multirefQName = new QName("","multiRef");
   
       /**
        * Should I write out objects as multi-refs?
  @@ -557,7 +557,7 @@
                   // set the javaType argument using value.getClass() because 
                   // values that represent primitives will never get to this point
                   // because they cannot be multi-ref'ed
  -                serialize(new QName("","multiRef"), attrs, val, val.getClass());
  +                serialize(multirefQName, attrs, val, val.getClass());
               }
   
               if (secondLevelObjects != null) {
  @@ -869,6 +869,13 @@
               if ( pair != null ) {
                   QName type = tm.getTypeQName(pair.javaType);
                   attributes = setTypeAttribute(attributes, type);
  +
  +                // The multiref QName is our own fake name.
  +                // It may be beneficial to set the name to the 
  +                // type name, but I didn't see any improvements
  +                // in the interop tests.
  +                //if (name.equals(multirefQName) && type != null)
  +                //    name = type;
                   pair.ser.serialize(name, attributes, value, this);
                   return;
               }
  
  
  
  1.2       +159 -69   
xml-axis/java/src/org/apache/axis/encoding/ser/ArrayDeserializer.java
  
  Index: ArrayDeserializer.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/ArrayDeserializer.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ArrayDeserializer.java    26 Jan 2002 02:40:34 -0000      1.1
  +++ ArrayDeserializer.java    7 Feb 2002 23:23:11 -0000       1.2
  @@ -103,8 +103,9 @@
   
       public QName arrayType = null;
       public int curIndex = 0;
  -    QName arrayItemType;
  +    QName defaultItemType;
       int length;
  +    Class arrayClass = null;
       ArrayList mDimLength = null;  // If set, array of multi-dim lengths 
       ArrayList mDimFactor = null;  // If set, array of factors for multi-dim arrays
       HashSet waiting = new HashSet();  // List of indices waiting for completion
  @@ -126,54 +127,120 @@
                                DeserializationContext context)
           throws SAXException
       {
  +        // Deserializing the xml array requires processing the
  +        // xsi:type= attribute, the soapenc:arrayType attribute,
  +        // and the xsi:type attributes of the individual elements.
  +        //
  +        // The xsi:type=<qName> attribute is used to determine the java
  +        // type of the array to instantiate.  Axis expects it
  +        // to be set to the generic "soapenc:Array" or to
  +        // a specific qName.  If the generic "soapenc:Array"
  +        // specification is used, Axis determines the array
  +        // type by examining the soapenc:arrayType attribute.
  +        //
  +        // The soapenc:arrayType=<qname><dims> is used to determine
  +        // i) the number of dimensions, 
  +        // ii) the length of each dimension,
  +        // iii) the default xsi:type of each of the elements.
  +        //
  +        // If the arrayType attribute is missing, Axis assumes
  +        // a single dimension array with length equal to the number
  +        // of nested elements.  In such cases, the default xsi:type of 
  +        // the elements is determined using the array xsi:type.
  +        //
  +        // The xsi:type attributes of the individual elements of the
  +        // array are used to determine the java type of the element.
  +        // If the xsi:type attribute is missing for an element, the 
  +        // default xsi:type value is used.
  +
           if (category.isDebugEnabled()) {
               category.debug(JavaUtils.getMessage("enter00", 
"ArrayDeserializer.startElement()"));
           }
   
  +        // Get the qname for the array type=, set it to null if
  +        // the generic type is used.
  +        QName typeQName = context.getTypeFromAttributes(namespace,
  +                                                        localName,
  +                                                        attributes);
  +        if (typeQName != null && 
  +            Constants.isSOAP_ENC(typeQName.getNamespaceURI()) &&
  +            typeQName.getLocalPart().equals("Array"))
  +            typeQName = null;
  +
  +        // Now get the arrayType value 
           QName arrayTypeValue = context.getQNameFromString(
                         Constants.getValue(attributes,
                                            Constants.URI_CURRENT_SOAP_ENC,
                                            Constants.ATTR_ARRAY_TYPE));
  -        if (arrayTypeValue == null)
  -            throw new SAXException(JavaUtils.getMessage("noArrayType00"));
  -        
  -        String arrayTypeValueNamespaceURI = arrayTypeValue.getNamespaceURI();
  -        String arrayTypeValueLocalPart = arrayTypeValue.getLocalPart();
  -        int leftBracketIndex = arrayTypeValueLocalPart.lastIndexOf('[');
  -        int rightBracketIndex = arrayTypeValueLocalPart.lastIndexOf(']');
  -
  -        if (leftBracketIndex == -1
  -            || rightBracketIndex == -1
  -            || rightBracketIndex < leftBracketIndex)
  -        {
  -            throw new IllegalArgumentException(
  -                    JavaUtils.getMessage("badArrayType00", "" + arrayTypeValue));
  -        }
  -
  -        Class componentType = null;
  -        String componentTypeName =
  -                        arrayTypeValueLocalPart.substring(0, leftBracketIndex);
  +
  +        // The first part of the arrayType expression is the default item type 
qname.
  +        // The second part is the dimension information
  +        String dimString = null;
  +        if (arrayTypeValue != null) {
  +            String arrayTypeValueNamespaceURI = arrayTypeValue.getNamespaceURI();
  +            String arrayTypeValueLocalPart = arrayTypeValue.getLocalPart();
  +            int leftBracketIndex = arrayTypeValueLocalPart.lastIndexOf('[');
  +            int rightBracketIndex = arrayTypeValueLocalPart.lastIndexOf(']');
  +            if (leftBracketIndex == -1
  +                || rightBracketIndex == -1
  +                || rightBracketIndex < leftBracketIndex)
  +                {
  +                    throw new IllegalArgumentException(
  +                      JavaUtils.getMessage("badArrayType00", "" + arrayTypeValue));
  +                }
  +            
  +            dimString = 
  +                arrayTypeValueLocalPart.substring(leftBracketIndex + 1,
  +                                                  rightBracketIndex);
  +            arrayTypeValueLocalPart = 
  +                arrayTypeValueLocalPart.substring(0, leftBracketIndex);
  +            
  +            // If multi-dim array set to soapenc:Array
  +            if (arrayTypeValueLocalPart.endsWith("]")) {
  +                defaultItemType = new QName(Constants.URI_CURRENT_SOAP_ENC, 
"Array");
  +            } else {
  +                defaultItemType = new QName(arrayTypeValueNamespaceURI,
  +                                            arrayTypeValueLocalPart);
  +            }
  +        }
  +
  +        // If no type QName and no defaultItemType qname, use xsd:anyType
  +        if (defaultItemType == null && typeQName == null)
  +            defaultItemType = new QName(Constants.URI_CURRENT_SCHEMA_XSD, 
"anyType");
           
  -        if (componentTypeName.endsWith("]"))
  -        {
  -            // If the componentTypeName is an array, use soap_enc:Array
  -            // with a componentType of ArrayList.class
  -            arrayItemType = new QName(Constants.URI_CURRENT_SOAP_ENC, "Array");
  -            componentType = ArrayList.class;
  -        }
  -        else
  -            arrayItemType = new QName(arrayTypeValueNamespaceURI,
  -                                      componentTypeName);
  -
  -        String lengthStr =
  -                       arrayTypeValueLocalPart.substring(leftBracketIndex + 1,
  -                                                         rightBracketIndex);
           
  -        if (lengthStr.length() > 0)
  -        {
  +        // Determine the class type for the array.
  +        arrayClass = null;
  +        if (typeQName != null) {
  +            arrayClass = context.getTypeMapping().
  +                getClassForQName(typeQName);
  +        } else {
  +            Class arrayItemClass = context.getTypeMapping().
  +                getClassForQName(defaultItemType);
  +            if (arrayItemClass != null) {
  +                try {
  +                    arrayClass = Class.forName(JavaUtils.getLoadableClassName(
  +                      arrayItemClass.getName() + "[]"));   
  +                } catch (Exception e) {
  +                    throw new SAXException(
  +                       JavaUtils.getMessage("noComponent00",  "" + 
defaultItemType));
  +                }
  +            }
  +        }
  +
  +        if (arrayClass == null) {
  +            throw new SAXException(
  +               JavaUtils.getMessage("noComponent00",  "" + defaultItemType));
  +        }
  +
  +        if (dimString == null || dimString.length() == 0) {
  +            // Size determined using length of the members
  +            value = new ArrayListExtension(arrayClass);
  +        }
  +        else {
               try
               {
  -                StringTokenizer tokenizer = new StringTokenizer(lengthStr, "[],");
  +                StringTokenizer tokenizer = new StringTokenizer(dimString, "[],");
   
                   length = Integer.parseInt(tokenizer.nextToken());
   
  @@ -191,21 +258,9 @@
                           }
                       }
   
  -
  -                // If the componentType was not already determined to be an 
  -                // array, go and get it.
  -                if (componentType == null)
  -                    componentType = context.getTypeMapping().
  -                                              getClassForQName(arrayItemType);
  -
  -                if (componentType == null)
  -                    throw new SAXException(
  -                            JavaUtils.getMessage("noComponent00",  "" + 
arrayItemType));
  -                
  -                
                   // Create an ArrayListExtension class to store the ArrayList
                   // plus converted objects.
  -                ArrayList list = new ArrayListExtension(length);
  +                ArrayList list = new ArrayListExtension(arrayClass, length);
                   // ArrayList lacks a setSize(), so...
                   for (int i = 0; i < length; i++) {
                       list.add(null);
  @@ -216,22 +271,17 @@
               catch (NumberFormatException e)
               {
                   throw new IllegalArgumentException(
  -                        JavaUtils.getMessage("badInteger00", lengthStr));
  +                        JavaUtils.getMessage("badInteger00", dimString));
               }
           }
  -        else
  -        {
  -            // asize with no integers: size must be determined by inspection
  -            // of the actual members.
  -            value = new ArrayListExtension();
  -        }
  -        
  +
  +        // If soapenc:offset specified, set the current index accordingly
           String offset = Constants.getValue(attributes,
                                            Constants.URI_CURRENT_SOAP_ENC,
                                            Constants.ATTR_OFFSET);
           if (offset != null) {
  -            leftBracketIndex = offset.lastIndexOf('[');
  -            rightBracketIndex = offset.lastIndexOf(']');
  +            int leftBracketIndex = offset.lastIndexOf('[');
  +            int rightBracketIndex = offset.lastIndexOf(']');
   
               if (leftBracketIndex == -1
                   || rightBracketIndex == -1
  @@ -272,7 +322,8 @@
           if (category.isDebugEnabled()) {
               category.debug(JavaUtils.getMessage("enter00", 
"ArrayDeserializer.onStartChild()"));
           }
  -        
  +
  +        // If the position attribute is set, use it to update the current index
           if (attributes != null) {
               String pos =
                   Constants.getValue(attributes,
  @@ -301,14 +352,32 @@
                   return null;
               }
           }
  -        
  +
  +        // Use the xsi:type setting on the attribute if it exists.
           QName itemType = context.getTypeFromAttributes(namespace,
                                                          localName,
                                                          attributes);
  -        if (itemType == null)
  -            itemType = arrayItemType;
  -        
  -        Deserializer dSer = context.getDeserializerForType(itemType);
  +
  +        // If xsi:type is not set, use the default.
  +        if (itemType == null) {
  +            itemType = defaultItemType;
  +        }
  +
  +        // If xsi:type is still not set, try using the arrayClass info
  +        if (itemType == null &&
  +            arrayClass != null &&
  +            arrayClass.isArray()) {
  +            itemType = context.getTypeMapping().
  +                getTypeQName(arrayClass.getComponentType());
  +        }
  +
  +        // Get the deserializer for the type.  If no deserializer is 
  +        // found, the deserializer is set to DeserializerImpl() which
  +        // will properly issue any errors.
  +        Deserializer dSer = null;
  +        if (itemType != null) {
  +            dSer = context.getDeserializerForType(itemType);
  +        }
           if (dSer == null) {
               dSer = new DeserializerImpl();  
           }
  @@ -518,15 +587,29 @@
        **/
       public class ArrayListExtension extends ArrayList implements 
JavaUtils.ConvertCache {
           private HashMap table = null;
  -        
  +        private Class arrayClass = null;  // The array class.
           /**
            * Constructors
            */
  -        ArrayListExtension() {
  +        ArrayListExtension(Class arrayClass) {
               super();
  +            this.arrayClass = arrayClass;
  +            // Don't use the array class as a hint if it can't be instantiated
  +            if (arrayClass == null ||
  +                arrayClass.isInterface() ||
  +                java.lang.reflect.Modifier.isAbstract(arrayClass.getModifiers())) {
  +                arrayClass = null;
  +            }                
           }
  -        ArrayListExtension(int length) {
  +        ArrayListExtension(Class arrayClass, int length) {
               super(length);
  +            this.arrayClass = arrayClass;
  +            // Don't use the array class as a hint if it can't be instantiated
  +            if (arrayClass == null ||
  +                arrayClass.isInterface() ||
  +                java.lang.reflect.Modifier.isAbstract(arrayClass.getModifiers())) {
  +                arrayClass = null;
  +            } 
           }
           /**
            * Store converted value
  @@ -543,6 +626,13 @@
               if (table == null)
                   return null;
               return table.get(cls);
  +        }
  +
  +        /**
  +         * Get the destination array class described by the xml
  +         **/         
  +        public Class getDestClass() {
  +            return arrayClass;
           }
       }
      
  
  
  
  1.25      +21 -1     xml-axis/java/src/org/apache/axis/utils/JavaUtils.java
  
  Index: JavaUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/JavaUtils.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- JavaUtils.java    1 Feb 2002 04:38:18 -0000       1.24
  +++ JavaUtils.java    7 Feb 2002 23:23:11 -0000       1.25
  @@ -92,6 +92,10 @@
            **/
           public void setConvertedValue(Class cls, Object value);
           public Object getConvertedValue(Class cls);
  +        /**
  +         * Get the destination array class described by the xml
  +         **/         
  +        public Class getDestClass();
       }
   
       /** Utility function to convert an Object to some desired Class.
  @@ -153,8 +157,24 @@
                   return arg;
               }
           }
  -            
  +
           // Flow to here indicates that neither arg or destClass is a Holder
  +        
  +        // Check to see if the argument has a prefered destination class.
  +        if (arg instanceof ConvertCache &&
  +            (( ConvertCache) arg).getDestClass() != destClass) {
  +            Class hintClass = ((ConvertCache) arg).getDestClass();
  +            if (hintClass != null &&
  +                hintClass.isArray() &&
  +                destClass.isArray() &&
  +                destClass.isAssignableFrom(hintClass)) {
  +                destClass = hintClass;
  +                destValue = ((ConvertCache) arg).getConvertedValue(destClass);
  +                if (destValue != null)
  +                    return destValue;
  +            }
  +        }
  +            
           List list = (List)arg;
           int length = list.size();
           
  
  
  
  1.25      +207 -2    xml-axis/java/test/encoding/TestDeser.java
  
  Index: TestDeser.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/encoding/TestDeser.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- TestDeser.java    6 Feb 2002 14:42:54 -0000       1.24
  +++ TestDeser.java    7 Feb 2002 23:23:12 -0000       1.25
  @@ -8,7 +8,15 @@
   import org.apache.axis.message.RPCParam;
   import org.apache.axis.message.SOAPEnvelope;
   import org.apache.axis.server.AxisServer;
  -
  +import org.apache.axis.utils.JavaUtils;
  +import org.apache.axis.encoding.TypeMapping;
  +import org.apache.axis.encoding.TypeMappingRegistry;
  +import org.apache.axis.encoding.TypeMappingRegistryImpl;
  +import org.apache.axis.encoding.ser.ArraySerializerFactory;
  +import org.apache.axis.encoding.ser.ArrayDeserializerFactory;
  +import org.apache.axis.encoding.ser.BeanSerializerFactory;
  +import org.apache.axis.encoding.ser.BeanDeserializerFactory;
  +import javax.xml.rpc.namespace.QName;
   import java.lang.reflect.Array;
   import java.util.ArrayList;
   import java.util.HashMap;
  @@ -40,6 +48,7 @@
               "<soap:Envelope " +
                 "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"; " +
                 "xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"; " +
  +              "xmlns:me=\"urn:me\" " +
                 "xmlns:xsi=\"" + NS_XSI + "\" " +
                 "xmlns:xsd=\"" + NS_XSD + "\">\n" +
                 "<soap:Body>\n" +
  @@ -49,6 +58,31 @@
                   "</methodResult>\n" +
                 "</soap:Body>\n" +
               "</soap:Envelope>\n";
  +
  +        TypeMappingRegistry tmr = server.getTypeMappingRegistry();
  +        TypeMapping tm = (TypeMapping) tmr.createTypeMapping();
  +        tm.setSupportedNamespaces(new String[] {Constants.URI_CURRENT_SOAP_ENC});
  +        tmr.register(Constants.URI_CURRENT_SOAP_ENC, tm);
  +        tm.register(java.lang.String[].class, 
  +                    new QName("urn:me", "ArrayOfString"),
  +                    new org.apache.axis.encoding.ser.ArraySerializerFactory(),
  +                    new org.apache.axis.encoding.ser.ArrayDeserializerFactory());
  +        tm.register(java.lang.Object[].class, 
  +                    new QName("urn:me", "ArrayOfObject"),
  +                    new org.apache.axis.encoding.ser.ArraySerializerFactory(),
  +                    new org.apache.axis.encoding.ser.ArrayDeserializerFactory());
  +        tm.register(samples.echo.SOAPStruct.class, 
  +                    new QName("urn:me", "SOAPStruct"),
  +                    new org.apache.axis.encoding.ser.BeanSerializerFactory(
  +                          samples.echo.SOAPStruct.class,
  +                          new QName("urn:me", "SOAPStruct")),
  +                    new org.apache.axis.encoding.ser.BeanDeserializerFactory(
  +                          samples.echo.SOAPStruct.class,
  +                          new QName("urn:me", "SOAPStruct")));
  +        tm.register(samples.echo.SOAPStruct[].class, 
  +                    new QName("urn:me", "ArrayOfSOAPStruct"),
  +                    new org.apache.axis.encoding.ser.ArraySerializerFactory(),
  +                    new org.apache.axis.encoding.ser.ArrayDeserializerFactory());
       }
   
       /**
  @@ -94,6 +128,10 @@
        * Verify that a given XML deserialized produces the expected result
        */
       protected void deserialize(String data, Object expected)
  +        throws Exception {
  +        deserialize(data, expected, false);
  +    }
  +    protected void deserialize(String data, Object expected, boolean tryConvert)
          throws Exception
       {
          Message message = new Message(header + data + footer);
  @@ -113,7 +151,17 @@
          assertNotNull("SOAP param should not be null", param);
   
          Object result = param.getValue();
  -       if (!equals(result, expected)) assertEquals("The result is not what is 
expected.", expected, result);
  +       if (!equals(result, expected)) {
  +           // Try to convert to the expected class
  +           if (tryConvert) {
  +               Object result2 = JavaUtils.convert(result, expected.getClass());
  +               if (!equals(result2, expected)) {
  +                   assertEquals("The result is not what is expected.", expected, 
result);
  +               }
  +           } else {
  +               assertEquals("The result is not what is expected.", expected, 
result);
  +           }
  +       }
       }
   
       public void testString() throws Exception {
  @@ -291,5 +339,162 @@
       {
           TestDeser tester = new TestDeser("test");
           tester.testString();
  +    }
  +
  +    // Complicated array tests
  +
  +    // type=soapenc:Array
  +    public void testArrayA() throws Exception {
  +        String[] s = new String[] {"abc", "def"};
  +        deserialize("<result xsi:type=\"soapenc:Array\" " +
  +                            "soapenc:arrayType=\"xsd:string[2]\"> " +
  +                       "<item xsi:type=\"xsd:string\">abc</item>" +
  +                       "<item xsi:type=\"xsd:string\">def</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // Like above but missing [2] dimension
  +    public void testArrayB() throws Exception {
  +        String[] s = new String[] {"abc", "def"};
  +        deserialize("<result xsi:type=\"soapenc:Array\" " +
  +                            "soapenc:arrayType=\"xsd:string[]\"> " +
  +                       "<item xsi:type=\"xsd:string\">abc</item>" +
  +                       "<item xsi:type=\"xsd:string\">def</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +
  +    // Like above but no xsi:type on elements
  +    public void testArrayC() throws Exception {
  +        String[] s = new String[] {"abc", "def"};
  +        deserialize("<result xsi:type=\"soapenc:Array\" " +
  +                            "soapenc:arrayType=\"xsd:string[]\"> " +
  +                       "<item>abc</item>" +
  +                       "<item>def</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // Now try with arrayType=xsd:anyType
  +    public void testArrayD() throws Exception {
  +        String[] s = new String[] {"abc", "def"};
  +        deserialize("<result xsi:type=\"soapenc:Array\" " +
  +                       "soapenc:arrayType=\"xsd:anyType[]\"> " +
  +                       "<item xsi:type=\"xsd:string\">abc</item>" +
  +                       "<item xsi:type=\"xsd:string\">def</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // Now try without arrayType
  +    public void testArrayE() throws Exception {
  +        String[] s = new String[] {"abc", "def"};
  +        deserialize("<result xsi:type=\"soapenc:Array\" " +
  +                       "> " +
  +                       "<item xsi:type=\"xsd:string\">abc</item>" +
  +                       "<item xsi:type=\"xsd:string\">def</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // Use a specific array type, not soapenc:Array
  +    public void testArrayF() throws Exception {
  +        String[] s = new String[] {"abc", "def"};
  +        deserialize("<result xsi:type=\"me:ArrayOfString\" " +
  +                       "> " +
  +                       "<item xsi:type=\"xsd:string\">abc</item>" +
  +                       "<item xsi:type=\"xsd:string\">def</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // Same as above without individual item types
  +    public void testArrayG() throws Exception {
  +        String[] s = new String[] {"abc", "def"};
  +        deserialize("<result xsi:type=\"me:ArrayOfString\" " +
  +                       "> " +
  +                       "<item>abc</item>" +
  +                       "<item>def</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // Same as above except result is an Object[]
  +    public void testArrayH() throws Exception {
  +        Object[] s = new Object[] {new String("abc"), new String("def")};
  +        deserialize("<result xsi:type=\"me:ArrayOfString\" " +
  +                       "> " +
  +                       "<item>abc</item>" +
  +                       "<item>def</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // Ooh La La
  +    // Array of Object containing a String and an Integer
  +    public void testArrayI() throws Exception {
  +        Object[] s = new Object[] {new String("abc"), new Integer(123)};
  +        deserialize("<result xsi:type=\"me:ArrayOfObject\" " +
  +                       "> " +
  +                       "<item xsi:type=\"xsd:string\">abc</item>" +
  +                       "<item xsi:type=\"soapenc:int\">123</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // Same as above using arrayType=xsd:anyType
  +    public void testArrayJ() throws Exception {
  +        Object[] s = new Object[] {new String("abc"), new Integer(123)};
  +        deserialize("<result xsi:type=\"me:ArrayOfObject\" " +
  +                       "soapenc:arrayType=\"xsd:anyType[]\"> " +
  +                       "<item xsi:type=\"xsd:string\">abc</item>" +
  +                       "<item xsi:type=\"soapenc:int\">123</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // Same as above using type=soapenc:Array and no arrayType...bare bones
  +    public void testArrayK() throws Exception {
  +        Object[] s = new Object[] {new String("abc"), new Integer(123)};
  +        deserialize("<result xsi:type=\"soapenc:Array\" " +
  +                       "> " +
  +                       "<item xsi:type=\"xsd:string\">abc</item>" +
  +                       "<item xsi:type=\"soapenc:int\">123</item>" +
  +                    "</result>",
  +                    s, true);
  +    }
  +
  +    // This was created from a return received from a .NET service
  +    public void testArrayL() throws Exception {
  +        samples.echo.SOAPStruct[] s = new samples.echo.SOAPStruct[]
  +            {new samples.echo.SOAPStruct(1, "one",   1.1F),
  +             new samples.echo.SOAPStruct(2, "two",   2.2F),
  +             new samples.echo.SOAPStruct(3, "three", 3.3F)};
  +        deserialize("<soapenc:Array id=\"ref-7\" 
soapenc:arrayType=\"me:SOAPStruct[3]\">" +
  +                    "<item href=\"#ref-8\"/>" + 
  +                    "<item href=\"#ref-9\"/>" +
  +                    "<item href=\"#ref-10\"/>" + 
  +                    "</soapenc:Array>" +
  +
  +                    "<me:SOAPStruct id=\"ref-8\">" +
  +                    "<varString xsi:type=\"xsd:string\">one</varString>" +
  +                    "<varInt xsi:type=\"xsd:int\">1</varInt>" +
  +                    "<varFloat xsi:type=\"xsd:float\">1.1</varFloat>" +
  +                    "</me:SOAPStruct>" +
  +
  +                    "<me:SOAPStruct id=\"ref-9\">" +
  +                    "<varString xsi:type=\"xsd:string\">two</varString>" +
  +                    "<varInt xsi:type=\"xsd:int\">2</varInt>" +
  +                    "<varFloat xsi:type=\"xsd:float\">2.2</varFloat>" +
  +                    "</me:SOAPStruct>" +
  +
  +                    "<me:SOAPStruct id=\"ref-10\">" +
  +                    "<varString xsi:type=\"xsd:string\">three</varString>" +
  +                    "<varInt xsi:type=\"xsd:int\">3</varInt>" +
  +                    "<varFloat xsi:type=\"xsd:float\">3.3</varFloat>" +
  +                    "</me:SOAPStruct>",
  +                    s, true);
       }
   }
  
  
  
  1.10      +1 -1      xml-axis/java/test/functional/TestEchoSample.java
  
  Index: TestEchoSample.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/functional/TestEchoSample.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- TestEchoSample.java       26 Nov 2001 01:09:52 -0000      1.9
  +++ TestEchoSample.java       7 Feb 2002 23:23:12 -0000       1.10
  @@ -87,7 +87,7 @@
           // define the tests using JUnit assert facilities
           TestClient client = new TestClient() {
               public void verify(String method, Object sent, Object gotBack) {
  -                assertTrue("What was sent was not recieved--" + method + ": " + 
gotBack, equals(sent, gotBack));
  +                assertTrue("What was sent was not received--" + method + ": " + 
gotBack, equals(sent, gotBack));
               }
           };
   
  
  
  


Reply via email to