View Javadoc

    1   package org.codehaus.xfire.aegis.type.basic;
    2
    3   import java.lang.reflect.Array;
    4   import java.util.ArrayList;
    5   import java.util.HashSet;
    6   import java.util.List;
    7   import java.util.Set;
    8
    9   import javax.xml.namespace.QName;
    10
    11  import org.apache.commons.logging.Log;
    12  import org.apache.commons.logging.LogFactory;
    13  import org.codehaus.xfire.MessageContext;
    14  import org.codehaus.xfire.XFireRuntimeException;
    15  import org.codehaus.xfire.aegis.MessageReader;
    16  import org.codehaus.xfire.aegis.MessageWriter;
    17  import org.codehaus.xfire.aegis.type.Type;
    18  import org.codehaus.xfire.fault.XFireFault;
    19  import org.codehaus.xfire.soap.SoapConstants;
    20  import org.codehaus.xfire.util.NamespaceHelper;
    21  import org.codehaus.yom.Attribute;
    22  import org.codehaus.yom.Element;
    23
    24  /***
    25   * An ArrayType.
    26   *
    27   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
    28   */
    29  public class ArrayType
    30      extends Type
    31  {
    32      private QName componentName;
    33      private static final Log logger = LogFactory.getLog(ArrayType.class);
    34
    35      public ArrayType()
    36      {
    37          setNillable(true);
    38      }
    39
    40      public Object readObject(MessageReader reader, MessageContext context)
    41          throws XFireFault
    42      {
    43          try
    44          {
    45              Type compType = getComponentType();
    46
    47              List values = new ArrayList();
    48
    49              while ( reader.hasMoreElementReaders() )
    50              {
    51                  values.add( compType.readObject(reader.getNextElementReader(), context) );
    52              }
    53
    54              return makeArray(getComponentType().getTypeClass(), values);
    55          }
    56          catch (IllegalArgumentException e)
    57          {
    58              throw new XFireRuntimeException("Illegal argument.", e);
    59          }
    60      }
    61
    62      protected Object makeArray(Class arrayType, List values)
    63      {
    64          if (Integer.TYPE.equals(arrayType))
    65          {
    66              Object[] objects = values.toArray();
    67              Object array = Array.newInstance(Integer.TYPE, objects.length);
    68              for (int i = 0, n = objects.length; i < n; i++)
    69              {
    70                  Array.set(array, i, objects[i]);
    71              }
    72              return array;
    73          }
    74          else if (Long.TYPE.equals(arrayType))
    75          {
    76              Object[] objects = values.toArray();
    77              Object array = Array.newInstance(Long.TYPE, objects.length);
    78              for (int i = 0, n = objects.length; i < n; i++)
    79              {
    80                  Array.set(array, i, objects[i]);
    81              }
    82              return array;
    83          }
    84          else if (Short.TYPE.equals(arrayType))
    85          {
    86              Object[] objects = values.toArray();
    87              Object array = Array.newInstance(Short.TYPE, objects.length);
    88              for (int i = 0, n = objects.length; i < n; i++)
    89              {
    90                  Array.set(array, i, objects[i]);
    91              }
    92              return array;
    93          }
    94          else if (Double.TYPE.equals(arrayType))
    95          {
    96              Object[] objects = values.toArray();
    97              Object array = Array.newInstance(Double.TYPE, objects.length);
    98              for (int i = 0, n = objects.length; i < n; i++)
    99              {
    100                 Array.set(array, i, objects[i]);
    101             }
    102             return array;
    103         }
    104         else if (Float.TYPE.equals(arrayType))
    105         {
    106             Object[] objects = values.toArray();
    107             Object array = Array.newInstance(Float.TYPE, objects.length);
    108             for (int i = 0, n = objects.length; i < n; i++)
    109             {
    110                 Array.set(array, i, objects[i]);
    111             }
    112             return array;
    113         }
    114         else if (Byte.TYPE.equals(arrayType))
    115         {
    116             Object[] objects = values.toArray();
    117             Object array = Array.newInstance(Byte.TYPE, objects.length);
    118             for (int i = 0, n = objects.length; i < n; i++)
    119             {
    120                 Array.set(array, i, objects[i]);
    121             }
    122             return array;
    123         }
    124         else if (Boolean.TYPE.equals(arrayType))
    125         {
    126             Object[] objects = values.toArray();
    127             Object array = Array.newInstance(Boolean.TYPE, objects.length);
    128             for (int i = 0, n = objects.length; i < n; i++)
    129             {
    130                 Array.set(array, i, objects[i]);
    131             }
    132             return array;
    133         }
    134
    135         return values.toArray( (Object[]) Array.newInstance( getComponentType().getTypeClass(),
    136                                                              values.size()) );
    137     }
    138
    139     public void writeObject(Object values, MessageWriter writer, MessageContext context)
    140         throws XFireFault
    141     {
    142         if (values == null)
    143             return;
    144
    145         Type type = getComponentType();
    146
    147         String ns = null;
    148         if (type.isAbstract())
    149             ns = getSchemaType().getNamespaceURI();
    150         else
    151             ns = type.getSchemaType().getNamespaceURI();
    152
    153         String name = type.getSchemaType().getLocalPart();
    154
    155         if ( type == null )
    156             throw new XFireRuntimeException( "Couldn't find type for " + type.getTypeClass() + "." );
    157
    158         Class arrayType = type.getTypeClass();
    159
    160         if (Object.class.isAssignableFrom(arrayType))
    161         {
    162             Object[] objects = (Object[]) values;
    163             for (int i = 0, n = objects.length; i < n; i++)
    164             {
    165                 writeValue(objects[i], writer, context, type, name, ns);
    166             }
    167         }
    168         else if (Integer.TYPE.equals(arrayType))
    169         {
    170             int[] objects = (int[]) values;
    171             for (int i = 0, n = objects.length; i < n; i++)
    172             {
    173                 writeValue(new Integer(objects[i]), writer, context, type, name, ns);
    174             }
    175         }
    176         else if (Long.TYPE.equals(arrayType))
    177         {
    178             long[] objects = (long[]) values;
    179             for (int i = 0, n = objects.length; i < n; i++)
    180             {
    181                 writeValue(new Long(objects[i]), writer, context, type, name, ns);
    182             }
    183         }
    184         else if (Short.TYPE.equals(arrayType))
    185         {
    186             short[] objects = (short[]) values;
    187             for (int i = 0, n = objects.length; i < n; i++)
    188             {
    189                 writeValue(new Short(objects[i]), writer, context, type, name, ns);
    190             }
    191         }
    192         else if (Double.TYPE.equals(arrayType))
    193         {
    194             double[] objects = (double[]) values;
    195             for (int i = 0, n = objects.length; i < n; i++)
    196             {
    197                 writeValue(new Double(objects[i]), writer, context, type, name, ns);
    198             }
    199         }
    200         else if (Float.TYPE.equals(arrayType))
    201         {
    202             float[] objects = (float[]) values;
    203             for (int i = 0, n = objects.length; i < n; i++)
    204             {
    205                 writeValue(new Float(objects[i]), writer, context, type, name, ns);
    206             }
    207         }
    208         else if (Byte.TYPE.equals(arrayType))
    209         {
    210             byte[] objects = (byte[]) values;
    211             for (int i = 0, n = objects.length; i < n; i++)
    212             {
    213                 writeValue(new Byte(objects[i]), writer, context, type, name, ns);
    214             }
    215         }
    216         else if (Boolean.TYPE.equals(arrayType))
    217         {
    218             boolean[] objects = (boolean[]) values;
    219             for (int i = 0, n = objects.length; i < n; i++)
    220             {
    221                 writeValue(new Boolean(objects[i]), writer, context, type, name, ns);
    222             }
    223         }
    224     }
    225
    226     protected void writeValue(Object value,
    227                               MessageWriter writer,
    228                               MessageContext context,
    229                               Type type,
    230                               String name,
    231                               String ns)
    232         throws XFireFault
    233     {
    234         MessageWriter cwriter = writer.getElementWriter(name, ns);
    235
    236         type.writeObject( value, cwriter, context );
    237
    238         cwriter.close();
    239     }
    240
    241     public void writeSchema(Element root)
    242     {
    243         try
    244         {
    245             Element complex = new Element(SoapConstants.XSD_PREFIX + ":complexType",
    246                                           SoapConstants.XSD);
    247             complex.addAttribute(new Attribute("name", getSchemaType().getLocalPart()));
    248             root.appendChild(complex);
    249
    250             Element seq = new Element(SoapConstants.XSD_PREFIX + ":sequence",
    251                                       SoapConstants.XSD);
    252             complex.appendChild(seq);
    253
    254             Element element = new Element(SoapConstants.XSD_PREFIX + ":element",
    255                                       SoapConstants.XSD);
    256             seq.appendChild(element);
    257
    258             Type componentType = getComponentType();
    259             String prefix = NamespaceHelper.getUniquePrefix((Element) root.getParent(),
    260                                                             componentType.getSchemaType().getNamespaceURI());
    261
    262             String typeName = prefix + ":"
    263                     + componentType.getSchemaType().getLocalPart();
    264
    265             element.addAttribute(new Attribute("name", componentType.getSchemaType().getLocalPart()));
    266             element.addAttribute(new Attribute("type", typeName));
    267
    268             if (componentType.isNillable())
    269             {
    270                 element.addAttribute(new Attribute("nillable", "true"));
    271             }
    272
    273             element.addAttribute(new Attribute("minOccurs", "0"));
    274             element.addAttribute(new Attribute("maxOccurs", "unbounded"));
    275
    276         }
    277         catch (IllegalArgumentException e)
    278         {
    279             throw new XFireRuntimeException("Illegal argument.", e);
    280         }
    281     }
    282
    283     /***
    284      * We need to write a complex type schema for Beans, so return true.
    285      *
    286      * @see org.codehaus.xfire.aegis.type.Type#isComplex()
    287      */
    288     public boolean isComplex()
    289     {
    290         return true;
    291     }
    292
    293     public QName getComponentName()
    294     {
    295         return componentName;
    296     }
    297
    298     public void setComponentName(QName componentName)
    299     {
    300         this.componentName = componentName;
    301     }
    302
    303     /***
    304      * @see org.codehaus.xfire.aegis.type.Type#getDependencies()
    305      */
    306     public Set getDependencies()
    307     {
    308         Set deps = new HashSet();
    309
    310         deps.add( getComponentType() );
    311
    312         return deps;
    313     }
    314
    315     /***
    316      * Get the <code>Type</code> of the elements in the array.
    317      *
    318      * @return
    319      */
    320     public Type getComponentType()
    321     {
    322         Class compType = getTypeClass().getComponentType();
    323
    324         Type type;
    325
    326         if (componentName == null)
    327         {
    328             type = getTypeMapping().getType(compType);
    329         }
    330         else
    331         {
    332             type = getTypeMapping().getType(componentName);
    333
    334             // We couldn't find the type the user specified. One is created below instead.
    335             if (type == null)
    336             {
    337                 logger.debug("Couldn't find array component type "
    338                              + componentName + ". Creating one instead.");
    339             }
    340         }
    341
    342         if (type == null)
    343         {
    344             type = getTypeMapping().getTypeCreator().createType(compType);
    345             getTypeMapping().register(type);
    346         }
    347
    348         return type;
    349     }
    350 }