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
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
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 }