00f16cd9efee12b88edc05efeaac90676ee08b2e
[plcapi.git] / wsdl / api2wsdl.py
1 #!/usr/bin/python
2 #
3 # Sapan Bhatia <sapanb@cs.princeton.edu>
4 #
5 # Generates a WSDL for plcapi
6 # Current limitations:
7 # - Invalid for the following reasons 
8 # - The types are python types, not WSDL types
9 # - I'm not sure of what to do with the auth structure 
10
11 import os, sys
12 import time
13 import pdb
14 import xml.dom.minidom
15 import inspect
16 import globals
17
18 from PLC.API import PLCAPI
19 from PLC.Method import *
20 from PLC.Auth import Auth
21 from PLC.Parameter import Parameter, Mixed, python_type, xmlrpc_type
22
23
24 api = PLCAPI(None)
25
26 try:
27     set
28 except NameError:
29     from sets import Set
30     set = Set
31
32 # Class functions
33
34 def param_type(param):
35     if isinstance(param, Mixed) and len(param):
36         subtypes = [param_type(subparam) for subparam in param]
37         return " or ".join(subtypes)
38     elif isinstance(param, (list, tuple, set)) and len(param):
39         return "array of " + " or ".join([param_type(subparam) for subparam in param])
40     else:
41         return xmlrpc_type(python_type(param))
42
43
44 def add_wsdl_ports_and_bindings (wsdl):
45     api.all_methods.sort()
46     for method in api.all_methods:
47         # Skip system. methods
48         if "system." in method:
49             continue
50
51         function = api.callable(method)
52
53         # Commented documentation
54         #lines = ["// " + line.strip() for line in function.__doc__.strip().split("\n")]
55         #print "\n".join(lines)
56         #print
57
58         
59         in_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:message"))
60         in_el.setAttribute("name", function.name + "_in")
61
62         # Arguments
63
64         if (function.accepts):
65             (min_args, max_args, defaults) = function.args()
66             for (argname,argtype) in zip(max_args,function.accepts):
67                 arg_part = in_el.appendChild(wsdl.createElement("wsdl:part"))
68                 arg_part.setAttribute("name", argname)
69                 arg_part.setAttribute("type", param_type(argtype))
70                 
71         # Return type            
72         return_type = function.returns
73         out_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:message"))
74         out_el.setAttribute("name", function.name + "_out")
75         ret_part = out_el.appendChild(wsdl.createElement("wsdl:part"))
76         ret_part.setAttribute("name", "returnvalue")
77         ret_part.setAttribute("type", param_type(return_type))
78
79         # Port connecting arguments with return type
80
81         port_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:portType"))
82         port_el.setAttribute("name", function.name + "_port")
83         
84         op_el = port_el.appendChild(wsdl.createElement("wsdl:operation"))
85         op_el.setAttribute("name", function.name)
86         op_el.appendChild(wsdl.createElement("wsdl:input")).setAttribute("message","tns:" + function.name + "_in")
87         op_el.appendChild(wsdl.createElement("wsdl:output")).setAttribute("message","tns:" + function.name + "_out")
88
89         # Bindings
90
91         bind_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:binding"))
92         bind_el.setAttribute("name", function.name + "_binding")
93         bind_el.setAttribute("type", "tns:" + function.name + "_port")
94         
95         soap_bind = bind_el.appendChild(wsdl.createElement("soap:binding"))
96         soap_bind.setAttribute("style", "rpc")
97         soap_bind.setAttribute("transport","http://schemas.xmlsoap.org/soap/http")
98
99         
100         wsdl_op = bind_el.appendChild(wsdl.createElement("wsdl:operation"))
101         wsdl_op.setAttribute("name", function.name)
102         wsdl_op.appendChild(wsdl.createElement("soap:operation")).setAttribute("soapAction",
103                 "urn:" + function.name)
104
105         
106         wsdl_input = wsdl_op.appendChild(wsdl.createElement("wsdl:input"))
107         input_soap_body = wsdl_input.appendChild(wsdl.createElement("soap:body"))
108         input_soap_body.setAttribute("use", "encoded")
109         input_soap_body.setAttribute("namespace", "urn:" + function.name)
110         input_soap_body.setAttribute("encodingStyle","http://schemas.xmlsoap.org/soap/encoding/")
111
112         
113         wsdl_output = wsdl_op.appendChild(wsdl.createElement("wsdl:output"))
114         output_soap_body = wsdl_output.appendChild(wsdl.createElement("soap:body"))
115         output_soap_body.setAttribute("use", "encoded")
116         output_soap_body.setAttribute("namespace", "urn:" + function.name)
117         output_soap_body.setAttribute("encodingStyle","http://schemas.xmlsoap.org/soap/encoding/")
118         
119
120 def add_wsdl_service(wsdl):
121     service_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:service"))
122     service_el.setAttribute("name", "plc_api_service")
123
124     for method in api.all_methods:
125         name=api.callable(method).name
126         servport_el = service_el.appendChild(wsdl.createElement("wsdl:port"))
127         servport_el.setAttribute("name", name + "_port")
128         servport_el.setAttribute("binding", "tns:" + name + "_binding")
129
130     soapaddress = servport_el.appendChild(wsdl.createElement("soap:address"))
131     soapaddress.setAttribute("location", "%s" % globals.plc_ns)
132
133
134 def get_wsdl_definitions():
135     wsdl_text_header = """
136         <wsdl:definitions
137         name="auto_generated"
138         targetNamespace="%s"
139         xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
140         xmlns:tns="xmlns:%s"
141         xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
142         xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"/>""" % (globals.plc_ns,globals.plc_ns)
143         
144     wsdl = xml.dom.minidom.parseString(wsdl_text_header)
145
146     return wsdl
147     
148
149 wsdl = get_wsdl_definitions()
150 add_wsdl_ports_and_bindings(wsdl)
151 add_wsdl_service(wsdl)
152
153
154 print wsdl.toprettyxml()
155