Generate WSDL types
[sfa.git] / wsdl / gw2wsdl.py
1 #!/usr/bin/python
2 #
3 # Sapan Bhatia <sapanb@cs.princeton.edu>
4 #
5 # Generates a WSDL for geniwrapper
6 # Current limitations:
7 # - Invalid for the following reasons 
8 # - The types are python types, not WSDL types
9
10 import os, sys
11 import time
12 import pdb
13 import xml.dom.minidom
14 import xml.dom.ext
15 import globals
16 import apistub
17 from types import *
18
19 from geni.util.auth import Auth
20 from geni.util.parameter import Parameter,Mixed
21
22 complex_types = {}
23 services = {}
24
25 num_types = 0
26
27 class SoapError(Exception):
28      def __init__(self, value):
29          self.value = value
30      def __str__(self):
31          return repr(self.value)
32 try:
33     set
34 except NameError:
35     from sets import Set
36     set = Set
37
38
39 def name_vector_type(acc,arg):
40     name = name_complex_type(elt)
41     complex_types[arg]=name
42     acc.append(name)
43     return acc
44
45 def name_complex_type(arg):
46     if (instanceof(arg, Mixed)):
47         inner_types = reduce(name_vector_type, arg)
48     
49         num_types=num_types+1
50         type_name = "Type%d"%num_types
51         complex_type = types.firstChild.appendChild(types.createElement("wsdl:complexType"))
52         complex_type.setAttribute("name", type_name)
53
54         choice = complex_type.appendChild(complex_type.createElement("xsd:choice"))
55         choice.appendChild(choice.createElement("element"))
56         for i in types:
57             choice.setAttribute("name", "Foobar")
58             choice.setAttribute("minOccurs","1")
59             choice.setAttribute("maxOccurs","1")
60             choice.setAttribute("type", "tns:$i")
61
62         return type_name
63     else:
64         return (name_simple_type(arg))
65
66 def name_simple_type(arg):
67     arg_type=arg.type
68     if arg_type == IntType or arg_type == LongType:
69         return "int"
70     elif arg_type == bool:
71         return "boolean"
72     elif arg_type == FloatType:
73         return "double"
74     elif arg_type in StringTypes:
75         return "string"
76     else:
77         pdb.set_trace()
78         raise SoapError, "Cannot handle %s objects" % arg_type
79
80 def param_type(arg):
81     return (name_complex_type(arg))
82
83 def add_wsdl_ports_and_bindings (wsdl):
84     for method in apistub.methods:
85         # Skip system. methods
86         if "system." in method:
87             continue
88
89         function = apistub.callable(method) # Commented documentation
90         #lines = ["// " + line.strip() for line in function.__doc__.strip().split("\n")]
91         #print "\n".join(lines)
92         #print
93
94         
95         in_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:message"))
96         in_el.setAttribute("name", method + "_in")
97
98         for service_name in function.interfaces:
99             if (services.has_key(service_name)):
100                 if (not method in services[service_name]):
101                     services[service_name].append(method)
102             else:
103                 services[service_name]=[method]
104
105         # Arguments
106
107         if (function.accepts):
108             (min_args, max_args, defaults) = function.args()
109             for (argname,argtype) in zip(max_args,function.accepts):
110                 arg_part = in_el.appendChild(wsdl.createElement("wsdl:part"))
111                 arg_part.setAttribute("name", argname)
112                 arg_part.setAttribute("type", param_type(argtype))
113                 
114         # Return type            
115         return_type = function.returns
116         out_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:message"))
117         out_el.setAttribute("name", method + "_out")
118         ret_part = out_el.appendChild(wsdl.createElement("wsdl:part"))
119         ret_part.setAttribute("name", "returnvalue")
120         ret_part.setAttribute("type", param_type(return_type))
121
122         # Port connecting arguments with return type
123
124         port_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:portType"))
125         port_el.setAttribute("name", method + "_port")
126         
127         op_el = port_el.appendChild(wsdl.createElement("wsdl:operation"))
128         op_el.setAttribute("name", method)
129         op_el.appendChild(wsdl.createElement("wsdl:input")).setAttribute("message","tns:" + method + "_in")
130         op_el.appendChild(wsdl.createElement("wsdl:output")).setAttribute("message","tns:" + method + "_out")
131
132         # Bindings
133
134         bind_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:binding"))
135         bind_el.setAttribute("name", method + "_binding")
136         bind_el.setAttribute("type", "tns:" + method + "_port")
137         
138         soap_bind = bind_el.appendChild(wsdl.createElement("soap:binding"))
139         soap_bind.setAttribute("style", "rpc")
140         soap_bind.setAttribute("transport","http://schemas.xmlsoap.org/soap/http")
141
142         
143         wsdl_op = bind_el.appendChild(wsdl.createElement("wsdl:operation"))
144         wsdl_op.setAttribute("name", method)
145         wsdl_op.appendChild(wsdl.createElement("soap:operation")).setAttribute("soapAction",
146                 "urn:" + method)
147
148         
149         wsdl_input = wsdl_op.appendChild(wsdl.createElement("wsdl:input"))
150         input_soap_body = wsdl_input.appendChild(wsdl.createElement("soap:body"))
151         input_soap_body.setAttribute("use", "encoded")
152         input_soap_body.setAttribute("namespace", "urn:" + method)
153         input_soap_body.setAttribute("encodingStyle","http://schemas.xmlsoap.org/soap/encoding/")
154
155         
156         wsdl_output = wsdl_op.appendChild(wsdl.createElement("wsdl:output"))
157         output_soap_body = wsdl_output.appendChild(wsdl.createElement("soap:body"))
158         output_soap_body.setAttribute("use", "encoded")
159         output_soap_body.setAttribute("namespace", "urn:" + method)
160         output_soap_body.setAttribute("encodingStyle","http://schemas.xmlsoap.org/soap/encoding/")
161         
162
163 def add_wsdl_service(wsdl):
164     for service in services.keys():
165         service_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:service"))
166         service_el.setAttribute("name", service)
167
168         for method in services[service]:
169             name=method
170             servport_el = service_el.appendChild(wsdl.createElement("wsdl:port"))
171             servport_el.setAttribute("name", name + "_port")
172             servport_el.setAttribute("binding", "tns:" + name + "_binding")
173
174             soapaddress = servport_el.appendChild(wsdl.createElement("soap:address"))
175             soapaddress.setAttribute("location", "%s/%s" % (globals.plc_ns,service))
176
177
178 def get_wsdl_definitions():
179     wsdl_text_header = """
180         <wsdl:definitions
181         name="auto_generated"
182         targetNamespace="%s"
183         xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
184         xmlns:tns="xmlns:%s"
185         xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
186         xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"/>""" % (globals.plc_ns,globals.plc_ns)
187         
188     wsdl = xml.dom.minidom.parseString(wsdl_text_header)
189     
190     return wsdl
191     
192
193
194 types = get_wsdl_definitions()
195 wsdl = get_wsdl_definitions()
196 add_wsdl_ports_and_bindings(wsdl)
197 add_wsdl_service(wsdl)
198
199
200 xml.dom.ext.PrettyPrint(wsdl)
201