View Javadoc

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          if ( getKey() == null || context.containsKey(getKey()) )
47          {
48              Element typeEl = element.addElement( getQName() );
49      
50              if ( getChildren() != null )
51              {
52                  for ( Iterator itr = getChildren().iterator(); itr.hasNext(); )
53                  {
54                      Type type = (Type) itr.next();
55                      type.write(typeEl, context);
56                  }
57              }
58          }
59      }
60      
61      public void read( Element element, Map context )
62          throws XFireFault 
63      {
64          read( element, 0, context );
65      }
66  
67      /***
68       * @see org.codehaus.xfire.aegis.type.Type#read(org.dom4j.Element, int, java.util.Map)
69       */
70      public void read(Element element, int occurrence, Map context) throws XFireFault
71      {
72          List elements = element.elements( getQName() );
73          if ( elements == null || elements.size() <= occurrence )
74              return;
75          
76          Element typeEl = (Element) elements.get(occurrence);
77          
78          if ( getOgnl() != null )
79          {
80  			try
81  			{
82  				Object value = Ognl.getValue( getOgnl(), context, (Object) null );
83                  
84                  context.put( key, value );
85  			}
86  			catch (OgnlException e)
87  			{
88  				throw new XFireFault( "Couldn't process message.", e, XFireFault.SENDER );
89  			}
90          }
91          
92          if ( getChildren() != null )
93          {
94              for ( Iterator itr = getChildren().iterator(); itr.hasNext(); )
95              {
96                  Type type = (Type) itr.next();
97                  type.read(typeEl, context);
98              }
99          }
100     }
101 
102     public List getChildren()
103     {
104         return children;
105     }
106     
107     public void setChildren( List children )
108     {
109         this.children = children;
110     }
111     
112     public void addChild( Type type )
113     {
114         if ( children == null )
115             children = new ArrayList();
116         
117         children.add( type );
118     }    
119     
120 	public String getKey()
121 	{
122 		return key;
123 	}
124     
125 	public void setKey(String key)
126 	{
127 		this.key = key;
128 	}
129 
130 	public boolean isComplex()
131 	{
132 		return true;
133 	}
134     
135 	/***
136 	 * @see org.codehaus.xfire.aegis.type.Type#writeSchema(org.dom4j.Element)
137 	 */
138 	public void writeSchema(Element root)
139 	{
140         Namespace xsdNs = root.getNamespaceForURI( SOAPConstants.XSD );
141         Namespace beanNs = root.getNamespaceForURI( getSchemaType().getNamespaceURI() );
142         
143         org.dom4j.QName elementQ = new org.dom4j.QName( "element", xsdNs );
144         Element concreteEl = root.addElement( elementQ );
145         concreteEl.addAttribute("name", getName());
146         //concreteEl.addAttribute("type", beanNs.getPrefix() + ":" + getSchemaType().getName());
147         
148         org.dom4j.QName complexQ = new org.dom4j.QName("complexType", xsdNs); 
149         Element complex = concreteEl.addElement( complexQ );
150         // complex.addAttribute( "name", getName() );
151 
152         org.dom4j.QName seqQ = new org.dom4j.QName("sequence", xsdNs); 
153         Element seq = complex.addElement( seqQ );
154 
155         if ( getChildren() == null )
156             return;
157         
158         for ( Iterator itr = getChildren().iterator(); itr.hasNext(); )
159         {
160             Type type = (Type) itr.next();
161 
162             Element element = seq.addElement( elementQ );
163             
164             Namespace typeNS = root.getNamespaceForURI( type.getSchemaType().getNamespaceURI() );
165             if ( type.isComplex() )
166             {
167                  element.addAttribute( "ref",  typeNS.getPrefix() + ":" + type.getSchemaType().getName() );
168             }
169             else
170             {
171                 element.addAttribute( "name", type.getName() );
172                 // TODO: Add config support for nillable
173                 element.addAttribute( "nillable", "true" );
174                 element.addAttribute("type", typeNS.getPrefix() + ":" + type.getSchemaType().getName());
175             }
176         }
177 	}
178 
179 	/***
180 	 * @see org.codehaus.xfire.aegis.type.Type#configure(org.dom4j.Element)
181 	 */
182 	public void configure(Element configuration, AegisService service, TypeRegistry reg )
183 	{
184 		setName( configuration.attributeValue("name") );
185         setOgnl( configuration.attributeValue("ognl") );
186         setKey( configuration.attributeValue("key") );
187         
188         String min = configuration.attributeValue("minOccurs");
189         if (min != null)
190         	setMinOccurs(min);
191         
192         String max = configuration.attributeValue("maxOccurs");
193         if (max != null)
194         	setMaxOccurs(max);
195         
196         setQName( QName.get( getName(), service.getDefaultNamespace() ) );
197         setDocumentation( configuration.getTextTrim() );
198         
199         Attribute xsdAt = configuration.attribute("schemaType");
200         if ( xsdAt != null )
201         {
202             setSchemaType( null );
203         }
204         else
205         {
206             setSchemaType( QName.get(getName(), service.getDefaultNamespace() ) );
207         }
208         
209         List childElements = configuration.elements();
210         for ( Iterator itr = childElements.iterator(); itr.hasNext(); )
211         {
212             Element paramEl = (Element) itr.next();
213             QName typeQ = QName.get(paramEl.getName(), service.getSoapVersion());
214 
215             Type type = reg.createType(typeQ);
216             
217             if ( type == null )
218                 throw new RuntimeException("No such type: " + typeQ.getName());
219             
220             type.configure(paramEl, service, reg);
221             
222             addChild(type);
223         }
224     }
225 
226 	public Set getDependencies()
227 	{
228         if ( children == null )
229             return null;
230         
231 		Set deps = new HashSet();
232         
233         deps.addAll( children );
234         
235         return deps;
236 	}
237 
238 }