package com.cdmtech.proj.spider.encoding;


import org.apache.axis.encoding.SerializationContext;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.Attributes;
import javax.xml.rpc.namespace.QName;

import java.io.IOException;
import java.lang.reflect.Array;

/******************************************************************************
* Serializes one and multi dimensional Object arrays, ArrayLists and Vectors.
* Works with com.cdmtech.proj.spider.encoding.ArrayDeserializer.
*
* Type Mapping:
*
*    <typeMapping
*    qname="SOAP-ENC:Array(YyYyYyYyYyYyYyYyYyYyYyYyYyYyYy)"
*    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
*    languageSpecificType="java:XxXxXxXxXxXxXxXxXxXxXxXxXxXx"
*    serializer="com.cdmtech.proj.spider.encoding.ArraySerializer"
*    deserializer="com.cdmtech.proj.spider.encoding.ArrayDeserializer$Factory"
*    />
*
* Where XxXxXxXxXxXxXxXxXxXxXxXxXxXx is one of these Java Classes:
*    java.util.Vector
*    java.util.ArrayList
*    [Ljava.lang.Object;
*    [[Ljava.lang.Object;
*    [[[Ljava.lang.Object;
*    [[[[Ljava.lang.Object;
*    ...
*
* And where (YyYyYyYyYyYyYyYyYyYyYyYyYyYyYy) is one of the following
*    (Vector)
*    (ArrayList)
*    (1D)
*    (2D)
*    (3D)
*    (4D)
*    ...
*
******************************************************************************/
public class ArraySerializer extends org.apache.axis.encoding.ArraySerializer
{

   /***************************************************************************
   * Overides the serialize method in the AXIS array serializer so that
   * array type can be correctly set according to the SOAP specification.
   *
   ***************************************************************************/
   public void serialize(QName name, Attributes attributes,
                         Object value, SerializationContext context)
      throws IOException
   {
      if (value.getClass().isArray())
      {
         String uri = "http://schemas.xmlsoap.org/soap/encoding/";
         String type = getArrayType(value);

         AttributesImpl att = (AttributesImpl)attributes;
         att.addAttribute(uri, "arrayType", uri + ":" + type, "CDATA", type);
      }

      super.serialize(name, attributes, value, context);
   }

   /***************************************************************************
   * Generates a String holding the array type information for an array.
   * It will include the comma delimited dimensions of the array.
   *
   ***************************************************************************/
   private static String getArrayType(Object array)
   {
      StringBuffer type = new StringBuffer("xsd:anyType[");
      int dimensions = array.getClass().getName().indexOf("java") - 1;
      type.append(Array.getLength(array));

      while (0 <--dimensions)
      {
         array = Array.get(array, 0);
         type.append(',');
         type.append(Array.getLength(array));
      }

      type.append(']');

      return type.toString();
   }
}
