1 package org.codehaus.xfire.type.basic;
2
3 import java.beans.BeanInfo;
4 import java.beans.IntrospectionException;
5 import java.beans.Introspector;
6 import java.lang.reflect.Array;
7 import java.util.ArrayList;
8 import java.util.HashSet;
9 import java.util.List;
10 import java.util.Set;
11
12 import org.codehaus.xfire.MessageContext;
13 import org.codehaus.xfire.XFireRuntimeException;
14 import org.codehaus.xfire.fault.XFireFault;
15 import org.codehaus.xfire.message.MessageReader;
16 import org.codehaus.xfire.message.MessageWriter;
17 import org.codehaus.xfire.soap.SoapConstants;
18 import org.codehaus.xfire.type.Type;
19 import org.codehaus.xfire.util.NamespaceHelper;
20 import org.dom4j.DocumentFactory;
21 import org.dom4j.Element;
22 import org.dom4j.Namespace;
23 import org.dom4j.QName;
24
25 /***
26 * An ArrayType.
27 *
28 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
29 */
30 public class ArrayType
31 extends Type
32 {
33 public Object readObject(MessageReader reader, MessageContext context)
34 throws XFireFault
35 {
36 try
37 {
38 Type compType = getComponentType();
39
40 List values = new ArrayList();
41
42 while ( reader.hasMoreChildReaders() )
43 {
44 Type type = getTypeMapping().getType( compType.getTypeClass() );
45
46 values.add( type.readObject(reader.getNextChildReader(), context) );
47 }
48
49 return values.toArray( (Object[]) Array.newInstance( compType.getTypeClass(), values.size()) );
50 }
51 catch (IllegalArgumentException e)
52 {
53 throw new XFireRuntimeException("Illegal argument.", e);
54 }
55 }
56
57 public void writeObject(Object object, MessageWriter writer, MessageContext context)
58 throws XFireFault
59 {
60 if (object == null)
61 return;
62
63 try
64 {
65 Object[] array = (Object[]) object;
66
67 Type type = getComponentType();
68
69 if ( type == null )
70 throw new XFireRuntimeException( "Couldn't find type for " + type.getTypeClass() + "." );
71
72 for ( int i = 0; i < array.length; i++ )
73 {
74 BeanInfo info = Introspector.getBeanInfo( type.getTypeClass(), Object.class );
75
76 MessageWriter cwriter = writer.getChildWriter(type.getSchemaType().getLocalPart());
77 type.writeObject( array[i], writer, context );
78 cwriter.close();
79 }
80 }
81 catch (IntrospectionException e)
82 {
83 throw new XFireRuntimeException("Couldn't introspect.", e);
84 }
85 catch (IllegalArgumentException e)
86 {
87 throw new XFireRuntimeException("Illegal argument.", e);
88 }
89 }
90
91 public void writeSchema( Element root )
92 {
93 try
94 {
95 Namespace xsdNs = root.getNamespaceForURI( SoapConstants.XSD );
96 org.dom4j.QName complexQ = new org.dom4j.QName("complexType", xsdNs);
97
98 Element complex = root.addElement( complexQ );
99
100 complex.addAttribute( "name", getSchemaType().getLocalPart() );
101
102 org.dom4j.QName seqQ = new org.dom4j.QName("sequence", xsdNs);
103 Element seq = complex.addElement( seqQ );
104
105 org.dom4j.QName elementQ = new org.dom4j.QName("element", xsdNs);
106 Element element = seq.addElement( elementQ );
107
108 Type componentType = getComponentType();
109 Namespace ns = NamespaceHelper.getNamespace( root, componentType.getSchemaType().getNamespaceURI() );
110
111 QName typeDom4j = DocumentFactory.getInstance().createQName( componentType.getSchemaType().getLocalPart(),
112 ns );
113
114 String typeName = typeDom4j.getNamespacePrefix() + ":" + componentType.getSchemaType().getLocalPart();
115
116 element.addAttribute("name", componentType.getSchemaType().getLocalPart());
117 element.addAttribute("type", typeName);
118
119 element.addAttribute("nillable", "true");
120
121 element.addAttribute("minOccurs", "0");
122 element.addAttribute("maxOccurs", "unbounded");
123
124 }
125 catch (IllegalArgumentException e)
126 {
127 throw new XFireRuntimeException("Illegal argument.", e);
128 }
129 }
130
131 /***
132 * We need to write a complex type schema for Beans, so return true.
133 *
134 * @see org.codehaus.xfire.type.Type#isComplex()
135 */
136 public boolean isComplex()
137 {
138 return true;
139 }
140
141 /***
142 * @see org.codehaus.xfire.type.Type#getDependencies()
143 */
144 public Set getDependencies()
145 {
146 Set deps = new HashSet();
147
148 deps.add( getTypeMapping().getType( getTypeClass().getComponentType() ) );
149
150 return deps;
151 }
152
153 protected Type getComponentType()
154 {
155 Class compType = getTypeClass().getComponentType();
156
157 return getTypeMapping().getType( compType );
158 }
159 }