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