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