View Javadoc

1   package org.codehaus.xfire.wsdl11.builder;
2   
3   import java.io.IOException;
4   import java.io.OutputStream;
5   import java.util.ArrayList;
6   import java.util.HashMap;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Map;
10  import java.util.Set;
11  
12  import javax.wsdl.Definition;
13  import javax.wsdl.WSDLException;
14  import javax.wsdl.factory.WSDLFactory;
15  
16  import org.codehaus.xfire.util.NamespaceHelper;
17  import org.codehaus.xfire.wsdl.SchemaType;
18  import org.codehaus.xfire.wsdl.WSDLWriter;
19  import org.codehaus.xfire.service.Service;
20  import org.codehaus.xfire.soap.SoapConstants;
21  import org.dom4j.Document;
22  import org.dom4j.DocumentFactory;
23  import org.dom4j.Element;
24  import org.dom4j.Namespace;
25  import org.dom4j.Node;
26  import org.dom4j.io.DOMReader;
27  import org.dom4j.io.OutputFormat;
28  import org.dom4j.io.XMLWriter;
29  
30  /***
31   * AbstractWSDL
32   * 
33   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
34   */
35  public abstract class AbstractWSDL
36      implements WSDLWriter
37  {
38      private Definition def;
39      private String targetNamespace;
40      private Service service;
41      private Document wsdlDocument;
42      private Map dependencies;
43      private Element schemaTypes;
44      private Map typeMap;
45  
46      /*-------------------------------------------------
47       * Namespace and QName definitions for easy access.
48       *-------------------------------------------------*/
49  
50      protected Namespace xsdNs = new Namespace( "xsd", SoapConstants.XSD );
51      
52      protected org.dom4j.QName schemaQ = new org.dom4j.QName("schema", xsdNs);
53  
54      protected org.dom4j.QName elementQ = new org.dom4j.QName("element", xsdNs);
55  
56      /*** A QName for elements which hold the schema that a WSDL type writes out. */
57      protected org.dom4j.QName xfireTypeQ = org.dom4j.QName.get( "xfire", "http://xfire.codehaus.org" );
58      
59      public AbstractWSDL( Service service )
60          throws WSDLException
61      {
62          dependencies = new HashMap();
63          this.service = service;
64          
65          setDefinition( WSDLFactory.newInstance().newDefinition() );
66          getDefinition().setTargetNamespace( service.getDefaultNamespace() );
67          
68          Document paramDoc = DocumentFactory.getInstance().createDocument();
69          setSchemaTypes( paramDoc.addElement( "root" ) );
70          getSchemaTypes().add(xsdNs);
71          
72          addNamespace( "soap", service.getSoapVersion().getNamespace() );
73          addNamespace( "soapenc", service.getSoapVersion().getSoapEncodingStyle() );
74          addNamespace( "xsd", SoapConstants.XSD );
75          addNamespace( "wsdl", WSDL11_NS );
76          addNamespace( "wsdlsoap", WSDL11_SOAP_NS );
77          addNamespace( "tns", service.getDefaultNamespace() );
78  
79          typeMap = new HashMap();
80      }
81      
82      protected void writeDocument() 
83          throws WSDLException
84      {
85          org.w3c.dom.Document doc = WSDLFactory.newInstance().newWSDLWriter().getDocument( def );
86          
87          wsdlDocument = new DOMReader().read(doc);
88          wsdlDocument.getRootElement().addNamespace( "tns", service.getDefaultNamespace() );
89          
90          writeComplexTypes();
91      }
92      
93      protected void writeComplexTypes()
94          throws WSDLException
95      {
96          Element rootEl = getDocument().getRootElement();
97          
98          Namespace wsdlNs = rootEl.getNamespaceForURI( WSDL11_NS );
99          org.dom4j.QName typeQ = new org.dom4j.QName("types", wsdlNs);   
100         Element types = rootEl.addElement( typeQ );
101     
102         // put the types as the first thing in the document
103         List list = rootEl.content();
104         list.remove( types );
105         list.set(0, types);
106 
107         for ( Iterator nsItr = typeMap.keySet().iterator(); nsItr.hasNext(); )
108         {
109             String schemaNs = (String) nsItr.next();
110     
111             Element schema = types.addElement( schemaQ );
112             schema.addAttribute( "targetNamespace", schemaNs );
113             schema.addAttribute( "elementFormDefault", "qualified" );
114             schema.addAttribute( "attributeFormDefault", "qualified" );
115             
116             writeSchemaForNamespace( schema, schemaNs );
117         }
118         
119     }
120 
121     public void addDependency(SchemaType type)
122     {
123         if ( !type.isComplex() )
124             return;
125             
126         if ( !dependencies.containsKey( type.getSchemaType() ) )
127         {
128             dependencies.put( type.getSchemaType(), type );
129             
130             Element e = createSchemaType( type.getSchemaType().getNamespaceURI() );
131             type.writeSchema( e );
132         }
133 
134         Set deps = type.getDependencies();
135         
136         if ( deps != null )
137         {
138             for ( Iterator itr = deps.iterator(); itr.hasNext(); )
139             {
140                 addDependency( (SchemaType) itr.next() );
141             }
142         }
143     }
144     
145     /***
146      * Write the schema types for a particular namespace.
147      * 
148      * @param schema The schema definition for this namespace. 
149      * Attach the types to this.
150      * @param schemaNs The namespace to write the types for.
151      */
152 	protected void writeSchemaForNamespace(Element schema, String schemaNs)
153 	{
154         List types = (List) typeMap.get(schemaNs);
155         
156         if ( types != null )
157         {
158         	for ( Iterator itr = types.iterator(); itr.hasNext(); )
159             {
160                 Element el = (Element) itr.next();
161                 
162                 for ( Iterator eitr = el.elements().iterator(); eitr.hasNext(); )
163                 {
164                      Node n = ((Element) eitr.next()).detach();
165                      schema.add(n);
166                 }
167 
168                 Namespace ns = NamespaceHelper.getNamespace(el, schemaNs);
169 
170                 getDocument().getRootElement().add( ns );
171             }
172         }
173 	}
174 
175 	/***
176      * @see org.codehaus.xfire.wsdl.WSDLWriter#write(java.io.OutputStream)
177      */
178     public void write(OutputStream out) throws IOException
179     {
180         XMLWriter writer = new XMLWriter( OutputFormat.createCompactFormat() );
181         writer.setOutputStream( out );
182         writer.write( getDocument() );
183         writer.flush();
184     }
185     
186     public void addNamespace(String prefix, String uri)
187     {
188         def.addNamespace( prefix, uri );
189         schemaTypes.addNamespace( prefix, uri );
190     }
191     
192     public Namespace getNamespace( String uri )
193     {
194         return NamespaceHelper.getNamespace( schemaTypes, uri );
195     }
196     
197     /***
198      * @see org.codehaus.xfire.wsdl.WSDLWriter#getDocument()
199      */
200     public Document getDocument()
201     {
202         return wsdlDocument;
203     }
204 
205     public Definition getDefinition()
206     {
207         return def;
208     }
209     
210     public void setDefinition(Definition definition)
211     {
212         this.def = definition;
213     }
214     
215     public Service getService()
216     {
217         return service;
218     }
219     
220     public void setService(Service service)
221     {
222         this.service = service;
223     }
224     
225     /***
226      * Create a shcema type element and store it to be written later on.
227      * 
228      * @param namespace The namespace to create the type in.
229      * @return
230      */
231     public Element createSchemaType( String namespace )
232     {
233         Element e = getSchemaTypes().addElement( xfireTypeQ );
234         
235         List types = (List) typeMap.get( namespace );
236         if ( types == null )
237         {
238         	types = new ArrayList();
239             typeMap.put( namespace, types );
240         }
241         
242         types.add(e);
243         
244         return e;
245     }
246     
247     protected Element getSchemaTypes()
248     {
249         return schemaTypes;
250     }
251     
252     protected void setSchemaTypes(Element schemaTypes)
253     {
254         this.schemaTypes = schemaTypes;
255     }
256 }