1 package org.codehaus.xfire.aegis.type;
2
3 import java.util.ArrayList;
4 import java.util.HashSet;
5 import java.util.Iterator;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Set;
9
10 import ognl.Ognl;
11 import ognl.OgnlException;
12
13 import org.codehaus.xfire.SOAPConstants;
14 import org.codehaus.xfire.aegis.AegisService;
15 import org.codehaus.xfire.aegis.mapping.TypeRegistry;
16 import org.codehaus.xfire.fault.XFireFault;
17 import org.dom4j.Attribute;
18 import org.dom4j.Element;
19 import org.dom4j.Namespace;
20 import org.dom4j.QName;
21
22 /***
23 * <p>
24 * The BeanType takes child types and read/writes each of them.
25 * </p>
26 * <p>
27 * The BeanType can take its own OGNL expression and a key. This is for when
28 * you want to take action when <i>reading</i> in an <code>Element</code>.
29 * For instance, if you specify the OGNL expression as
30 * "new com.company.Bean()" and the key as "bean" it will put a
31 * new Bean object in the context with the key "bean".
32 * </p>
33 *
34 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
35 */
36 public class BeanType
37 extends Type
38 {
39 private List children;
40
41 private String key;
42
43 public void write( Element element, Map context )
44 throws XFireFault
45 {
46 Element typeEl = element.addElement( getQName() );
47
48 if ( getChildren() != null )
49 {
50 for ( Iterator itr = getChildren().iterator(); itr.hasNext(); )
51 {
52 Type type = (Type) itr.next();
53 type.write(typeEl, context);
54 }
55 }
56 }
57
58 public void read( Element element, Map context )
59 throws XFireFault
60 {
61 Element typeEl = element.element( getQName() );
62
63 if ( getOgnl() != null )
64 {
65 try
66 {
67 Object value = Ognl.getValue( getOgnl(), context, (Object) null );
68
69 context.put( key, value );
70 }
71 catch (OgnlException e)
72 {
73 throw new XFireFault( "Couldn't process message.", e, XFireFault.SENDER );
74 }
75
76 }
77
78 if ( getChildren() != null )
79 {
80 for ( Iterator itr = getChildren().iterator(); itr.hasNext(); )
81 {
82 Type type = (Type) itr.next();
83 type.read(typeEl, context);
84 }
85 }
86 }
87
88 public List getChildren()
89 {
90 return children;
91 }
92
93 public void setChildren( List children )
94 {
95 this.children = children;
96 }
97
98 public void addChild( Type type )
99 {
100 if ( children == null )
101 children = new ArrayList();
102
103 children.add( type );
104 }
105
106 public String getKey()
107 {
108 return key;
109 }
110
111 public void setKey(String key)
112 {
113 this.key = key;
114 }
115
116 public boolean isComplex()
117 {
118 return true;
119 }
120
121 /***
122 * @see org.codehaus.xfire.aegis.type.Type#writeSchema(org.dom4j.Element)
123 */
124 public void writeSchema(Element root)
125 {
126 Namespace xsdNs = root.getNamespaceForURI( SOAPConstants.XSD );
127 Namespace beanNs = root.getNamespaceForURI( getSchemaType().getNamespaceURI() );
128
129 org.dom4j.QName elementQ = new org.dom4j.QName( "element", xsdNs );
130 Element concreteEl = root.addElement( elementQ );
131 concreteEl.addAttribute("name", getName());
132
133
134 org.dom4j.QName complexQ = new org.dom4j.QName("complexType", xsdNs);
135 Element complex = concreteEl.addElement( complexQ );
136
137
138 org.dom4j.QName seqQ = new org.dom4j.QName("sequence", xsdNs);
139 Element seq = complex.addElement( seqQ );
140
141 for ( Iterator itr = getChildren().iterator(); itr.hasNext(); )
142 {
143 Type type = (Type) itr.next();
144
145 Element element = seq.addElement( elementQ );
146
147 Namespace typeNS = root.getNamespaceForURI( type.getSchemaType().getNamespaceURI() );
148 if ( type.isComplex() )
149 {
150 element.addAttribute( "ref", typeNS.getPrefix() + ":" + type.getSchemaType().getName() );
151 }
152 else
153 {
154 element.addAttribute( "name", type.getName() );
155
156 element.addAttribute( "nillable", "true" );
157 element.addAttribute("type", typeNS.getPrefix() + ":" + type.getSchemaType().getName());
158 }
159 }
160 }
161
162 /***
163 * @see org.codehaus.xfire.aegis.type.Type#configure(org.dom4j.Element)
164 */
165 public void configure(Element configuration, AegisService service, TypeRegistry reg )
166 {
167 setName( configuration.attributeValue("name") );
168 setOgnl( configuration.attributeValue("ognl") );
169 setKey( configuration.attributeValue("key") );
170
171 String min = configuration.attributeValue("minOccurs");
172 if (min != null)
173 setMinOccurs(min);
174
175 String max = configuration.attributeValue("maxOccurs");
176 if (max != null)
177 setMaxOccurs(max);
178
179 setQName( QName.get( getName(), service.getDefaultNamespace() ) );
180 setDocumentation( configuration.getTextTrim() );
181
182 Attribute xsdAt = configuration.attribute("schemaType");
183 if ( xsdAt != null )
184 {
185 setSchemaType( null );
186 }
187 else
188 {
189 setSchemaType( QName.get(getName(), service.getDefaultNamespace() ) );
190 }
191
192 List childElements = configuration.elements();
193 for ( Iterator itr = childElements.iterator(); itr.hasNext(); )
194 {
195 Element paramEl = (Element) itr.next();
196 QName typeQ = QName.get(paramEl.getName(), service.getSoapVersion());
197
198 Type type = reg.createType(typeQ);
199 type.configure(paramEl, service, reg);
200
201 addChild(type);
202 }
203 }
204
205 public Set getDependencies()
206 {
207 Set deps = new HashSet();
208
209 deps.addAll( getChildren() );
210
211 return deps;
212 }
213 }