1 package org.codehaus.xfire.wsdl11.builder;
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.util.HashMap;
6 import java.util.Iterator;
7 import java.util.Map;
8 import java.util.Set;
9
10 import javax.wsdl.Definition;
11 import javax.wsdl.WSDLException;
12 import javax.wsdl.factory.WSDLFactory;
13
14 import org.codehaus.xfire.XFireRuntimeException;
15 import org.codehaus.xfire.service.Service;
16 import org.codehaus.xfire.soap.SoapConstants;
17 import org.codehaus.xfire.util.NamespaceHelper;
18 import org.codehaus.xfire.wsdl.SchemaType;
19 import org.codehaus.xfire.wsdl.WSDLWriter;
20 import org.codehaus.yom.Attribute;
21 import org.codehaus.yom.Document;
22 import org.codehaus.yom.Element;
23 import org.codehaus.yom.Serializer;
24 import org.codehaus.yom.converters.DOMConverter;
25
26 /***
27 * AbstractWSDL
28 *
29 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
30 */
31 public abstract class AbstractWSDL
32 implements WSDLWriter
33 {
34 private Definition def;
35
36 private String targetNamespace;
37
38 private Service service;
39
40 private Document wsdlDocument;
41
42 private Map dependencies;
43
44 private Element schemaTypes;
45
46 private Map typeMap;
47
48 private WSDLBuilderInfo info;
49
50
51
52
53
54 public final static String schemaQ = SoapConstants.XSD_PREFIX + ":" + "schema";
55
56 public final static String elementQ = SoapConstants.XSD_PREFIX + ":" + "element";
57
58 public final static String complexQ = SoapConstants.XSD_PREFIX + ":" + "complexType";
59
60 public final static String sequenceQ = SoapConstants.XSD_PREFIX + ":" + "sequence";
61
62 public AbstractWSDL(Service service) throws WSDLException
63 {
64 dependencies = new HashMap();
65 this.service = service;
66 this.info = (WSDLBuilderInfo) service.getProperty(WSDLBuilderInfo.KEY);
67
68 if (info == null)
69 info = new WSDLBuilderInfo(service);
70
71 setDefinition(WSDLFactory.newInstance().newDefinition());
72 getDefinition().setTargetNamespace(info.getTargetNamespace());
73
74 Element root = new Element("wsdl:types", WSDL11_NS);
75 Document paramDoc = new Document(root);
76 setSchemaTypes(root);
77 root.addNamespaceDeclaration(SoapConstants.XSD_PREFIX, SoapConstants.XSD);
78
79 addNamespace("soap", service.getSoapVersion().getNamespace());
80 addNamespace("soapenc", service.getSoapVersion().getSoapEncodingStyle());
81 addNamespace("xsd", SoapConstants.XSD);
82 addNamespace("wsdl", WSDL11_NS);
83 addNamespace("wsdlsoap", WSDL11_SOAP_NS);
84 addNamespace("tns", info.getTargetNamespace());
85
86 typeMap = new HashMap();
87 }
88
89 protected void writeDocument()
90 throws WSDLException
91 {
92 org.w3c.dom.Document doc = WSDLFactory.newInstance().newWSDLWriter().getDocument(def);
93
94 wsdlDocument = DOMConverter.convert(doc);
95
96 writeComplexTypes();
97 }
98
99 protected void writeComplexTypes()
100 throws WSDLException
101 {
102 Element rootEl = getDocument().getRootElement();
103
104 if (schemaTypes.getChildCount() > 0)
105 {
106 schemaTypes.detach();
107 rootEl.insertChild(schemaTypes, 0);
108 }
109
110 }
111
112 public void addDependency(SchemaType type)
113 {
114 if (!type.isComplex())
115 {
116 return;
117 }
118
119 if (!hasDependency(type))
120 {
121 dependencies.put(type.getSchemaType(), type);
122
123 Element e = createSchemaType(type.getSchemaType().getNamespaceURI());
124 type.writeSchema(e);
125
126 Set deps = type.getDependencies();
127
128 if (deps != null)
129 {
130 for (Iterator itr = deps.iterator(); itr.hasNext();)
131 {
132 addDependency((SchemaType) itr.next());
133 }
134 }
135 }
136 }
137
138 protected boolean hasDependency(SchemaType type)
139 {
140 return dependencies.containsKey(type.getSchemaType());
141 }
142
143 /***
144 * @see org.codehaus.xfire.wsdl.WSDLWriter#write(java.io.OutputStream)
145 */
146 public void write(OutputStream out)
147 throws IOException
148 {
149 Serializer writer = new Serializer(out);
150 writer.write(getDocument());
151 writer.flush();
152 }
153
154 public void addNamespace(String prefix, String uri)
155 {
156 def.addNamespace(prefix, uri);
157
158 String declaredUri = schemaTypes.getNamespaceURI(prefix);
159 if (declaredUri == null)
160 {
161 schemaTypes.addNamespaceDeclaration(prefix, uri);
162 }
163 else if (!declaredUri.equals(uri))
164 {
165 throw new XFireRuntimeException("Namespace conflict: " + declaredUri
166 + " was declared but " + uri + " was attempted.");
167 }
168 }
169
170 public String getNamespacePrefix(String uri)
171 {
172 return NamespaceHelper.getUniquePrefix(schemaTypes, uri);
173 }
174
175 public WSDLBuilderInfo getInfo()
176 {
177 return info;
178 }
179
180 /***
181 * @see org.codehaus.xfire.wsdl.WSDLWriter#getDocument()
182 */
183 public Document getDocument()
184 {
185 return wsdlDocument;
186 }
187
188 public Definition getDefinition()
189 {
190 return def;
191 }
192
193 public void setDefinition(Definition definition)
194 {
195 this.def = definition;
196 }
197
198 public Service getService()
199 {
200 return service;
201 }
202
203 public void setService(Service service)
204 {
205 this.service = service;
206 }
207
208 /***
209 * Create a shcema type element and store it to be written later on.
210 *
211 * @param namespace
212 * The namespace to create the type in.
213 * @return
214 */
215 public Element createSchemaType(String namespace)
216 {
217 Element e = (Element) typeMap.get(namespace);
218
219 if (e == null)
220 {
221 e = new Element(schemaQ, SoapConstants.XSD);
222
223 e.addAttribute(new Attribute("targetNamespace", namespace));
224 e.addAttribute(new Attribute("elementFormDefault", "qualified"));
225 e.addAttribute(new Attribute("attributeFormDefault", "qualified"));
226
227 setSchema(namespace, e);
228 }
229
230 return e;
231 }
232
233 protected boolean hasSchema(String namespace)
234 {
235 return typeMap.containsKey(namespace);
236 }
237
238 protected void setSchema(String namespace, Element schema)
239 {
240 typeMap.put(namespace, schema);
241 getSchemaTypes().appendChild(schema);
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 }