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 }