Added the possibility of genearting sm, am and registry separately
[sfa.git] / wsdl / gw2wsdl.py
index b95ab39..558ad1f 100755 (executable)
@@ -3,21 +3,23 @@
 # Sapan Bhatia <sapanb@cs.princeton.edu>
 #
 # Generates a WSDL for geniwrapper
-# Current limitations:
-# - Invalid for the following reasons 
-# - The types are python types, not WSDL types
+
 
 import os, sys
 import time
 import pdb
 import xml.dom.minidom
 import xml.dom.ext
-import globals
 import apistub
+import inspect
+
 from types import *
+from optparse import OptionParser
 
-from geni.util.auth import Auth
-from geni.util.parameter import Parameter,Mixed
+from sfa.trust.auth import Auth
+from sfa.util.parameter import Parameter,Mixed
+
+import globals
 
 complex_types = {}
 services = {}
@@ -44,7 +46,6 @@ def fold_complex_type_names(acc, arg):
         acc = [python_is_braindead,name]
     return acc
 
-
 def fold_complex_type(acc, arg):
     global complex_types
     name = name_complex_type(arg)
@@ -60,11 +61,9 @@ def name_complex_type(arg):
     global num_types
     global types
 
-    #if (complex_types.has_key(arg)):
-    #    return complex_types[arg]
-
-    types_section = types.firstChild.firstChild
+    types_section = types.getElementsByTagName("xsd:schema")[0]
 
+    #pdb.set_trace()
     if (isinstance(arg, Mixed)):
         inner_types = reduce(fold_complex_type, arg)
         inner_names = reduce(fold_complex_type_names, arg)
@@ -76,30 +75,52 @@ def name_complex_type(arg):
     
         num_types=num_types+1
         type_name = "Type%d"%num_types
-        complex_type = types_section.appendChild(types.createElement("wsdl:complexType"))
+        complex_type = types_section.appendChild(types.createElement("xsd:complexType"))
         complex_type.setAttribute("name", type_name)
 
         choice = complex_type.appendChild(types.createElement("xsd:choice"))
         for n,t in zip(inner_names,inner_types):
             element = choice.appendChild(types.createElement("element"))
             element.setAttribute("name", n)
-            element.setAttribute("type", "tns:%s"%t)
+            element.setAttribute("type", "%s"%t)
             element.setAttribute("minOccurs","%d"%min_args)
-        return "tns:%s"%type_name
+        return "xsdl:%s"%type_name
     elif (isinstance(arg, Parameter)):
         return (name_simple_type(arg.type))
     elif type(arg) == ListType or type(arg) == TupleType:
-        return "sequence"
-    elif type(arg) == DictType or arg == DictType:
-        return "dict"
+        inner_type = name_complex_type(arg[0]) 
+        num_types=num_types+1
+        type_name = "Type%d"%num_types
+        complex_type = types_section.appendChild(types.createElement("xsd:simpleType"))
+        complex_type.setAttribute("name", type_name)
+        complex_content = complex_type.appendChild(types.createElement("xsd:list"))
+        complex_content.setAttribute("itemType",inner_type)
+        return "xsdl:%s"%type_name
+    elif type(arg) == DictType or arg == DictType or (inspect.isclass(arg) and issubclass(arg, dict)):
+        num_types=num_types+1
+        type_name = "Type%d"%num_types
+        complex_type = types_section.appendChild(types.createElement("xsd:complexType"))
+        complex_type.setAttribute("name", type_name)
+        complex_content = complex_type.appendChild(types.createElement("xsd:sequence"))
+        for k in arg.fields:
+            inner_type = name_complex_type(arg.fields[k]) 
+            element=complex_content.appendChild(types.createElement("xsd:element"))
+            element.setAttribute("name",k)
+            element.setAttribute("type",inner_type)
+
+        return "xsdl:%s"%type_name 
     else:
         return (name_simple_type(arg))
 
 def name_simple_type(arg_type):
+    # A Parameter is reported as an instance, even though it is serialized as a type <>
+    if type(arg_type) == InstanceType:
+        return (name_simple_type(arg_type.type))
     if arg_type == None:
         return "none"
     if arg_type == DictType:
-        return "xsd:dict"
+        return "xsd:anyType"
     elif arg_type == IntType or arg_type == LongType:
         return "xsd:int"
     elif arg_type == bool:
@@ -109,14 +130,15 @@ def name_simple_type(arg_type):
     elif arg_type in StringTypes:
         return "xsd:string"
     else:
-       #pdb.set_trace()
-        raise SoapError, "Cannot handle %s objects" % arg_type
+       pdb.set_trace()
+       raise SoapError, "Cannot handle %s objects" % arg_type
 
 def param_type(arg):
     return (name_complex_type(arg))
 
 def add_wsdl_ports_and_bindings (wsdl):
     for method in apistub.methods:
+
         # Skip system. methods
         if "system." in method:
             continue
@@ -127,7 +149,7 @@ def add_wsdl_ports_and_bindings (wsdl):
         #print
 
         
-        in_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:message"))
+        in_el = wsdl.firstChild.appendChild(wsdl.createElement("message"))
         in_el.setAttribute("name", method + "_in")
 
         for service_name in function.interfaces:
@@ -142,35 +164,37 @@ def add_wsdl_ports_and_bindings (wsdl):
         if (function.accepts):
             (min_args, max_args, defaults) = function.args()
             for (argname,argtype) in zip(max_args,function.accepts):
-                arg_part = in_el.appendChild(wsdl.createElement("wsdl:part"))
+                arg_part = in_el.appendChild(wsdl.createElement("part"))
                 arg_part.setAttribute("name", argname)
                 arg_part.setAttribute("type", param_type(argtype))
                 
         # Return type            
         return_type = function.returns
-        out_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:message"))
+        out_el = wsdl.firstChild.appendChild(wsdl.createElement("message"))
         out_el.setAttribute("name", method + "_out")
-        ret_part = out_el.appendChild(wsdl.createElement("wsdl:part"))
+        ret_part = out_el.appendChild(wsdl.createElement("part"))
         ret_part.setAttribute("name", "returnvalue")
         ret_part.setAttribute("type", param_type(return_type))
 
         # Port connecting arguments with return type
 
-        port_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:portType"))
+        port_el = wsdl.firstChild.appendChild(wsdl.createElement("portType"))
         port_el.setAttribute("name", method + "_port")
         
-        op_el = port_el.appendChild(wsdl.createElement("wsdl:operation"))
+        op_el = port_el.appendChild(wsdl.createElement("operation"))
         op_el.setAttribute("name", method)
-        inp_el=wsdl.createElement("wsdl:input").setAttribute("message","tns:" + method + "_in"
+        inp_el=wsdl.createElement("input")
+        inp_el.setAttribute("message","tns:" + method + "_in")
         inp_el.setAttribute("name",method+"_request")
         op_el.appendChild(inp_el)
-        out_el = wsdl.createElement("wsdl:output").setAttribute("message","tns:" + method + "_out")
+        out_el = wsdl.createElement("output")
+        out_el.setAttribute("message","tns:" + method + "_out")
         out_el.setAttribute("name",method+"_response")
         op_el.appendChild(out_el)
 
         # Bindings
 
-        bind_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:binding"))
+        bind_el = wsdl.firstChild.appendChild(wsdl.createElement("binding"))
         bind_el.setAttribute("name", method + "_binding")
         bind_el.setAttribute("type", "tns:" + method + "_port")
         
@@ -179,20 +203,20 @@ def add_wsdl_ports_and_bindings (wsdl):
         soap_bind.setAttribute("transport","http://schemas.xmlsoap.org/soap/http")
 
         
-        wsdl_op = bind_el.appendChild(wsdl.createElement("wsdl:operation"))
+        wsdl_op = bind_el.appendChild(wsdl.createElement("operation"))
         wsdl_op.setAttribute("name", method)
         wsdl_op.appendChild(wsdl.createElement("soap:operation")).setAttribute("soapAction",
                 "urn:" + method)
 
         
-        wsdl_input = wsdl_op.appendChild(wsdl.createElement("wsdl:input"))
+        wsdl_input = wsdl_op.appendChild(wsdl.createElement("input"))
         input_soap_body = wsdl_input.appendChild(wsdl.createElement("soap:body"))
         input_soap_body.setAttribute("use", "encoded")
         input_soap_body.setAttribute("namespace", "urn:" + method)
         input_soap_body.setAttribute("encodingStyle","http://schemas.xmlsoap.org/soap/encoding/")
 
         
-        wsdl_output = wsdl_op.appendChild(wsdl.createElement("wsdl:output"))
+        wsdl_output = wsdl_op.appendChild(wsdl.createElement("output"))
         output_soap_body = wsdl_output.appendChild(wsdl.createElement("soap:body"))
         output_soap_body.setAttribute("use", "encoded")
         output_soap_body.setAttribute("namespace", "urn:" + method)
@@ -201,41 +225,80 @@ def add_wsdl_ports_and_bindings (wsdl):
 
 def add_wsdl_service(wsdl):
     for service in services.keys():
-        service_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:service"))
-        service_el.setAttribute("name", service)
+        global interface_options
+        if (getattr(interface_options,service)):
+            service_el = wsdl.firstChild.appendChild(wsdl.createElement("service"))
+            service_el.setAttribute("name", service)
 
-        for method in services[service]:
-            name=method
-            servport_el = service_el.appendChild(wsdl.createElement("wsdl:port"))
-            servport_el.setAttribute("name", name + "_port")
-            servport_el.setAttribute("binding", "tns:" + name + "_binding")
+            for method in services[service]:
+                    name=method
+                    servport_el = service_el.appendChild(wsdl.createElement("port"))
+                    servport_el.setAttribute("name", name + "_port")
+                    servport_el.setAttribute("binding", "tns:" + name + "_binding")
 
-            soapaddress = servport_el.appendChild(wsdl.createElement("soap:address"))
-            soapaddress.setAttribute("location", "%s/%s" % (globals.plc_ns,service))
+                    soapaddress = servport_el.appendChild(wsdl.createElement("soap:address"))
+                    soapaddress.setAttribute("location", "%s/%s" % (globals.plc_ns,service))
 
 
 def get_wsdl_definitions():
     wsdl_text_header = """
         <wsdl:definitions
-        name="auto_generated"
-        targetNamespace="%s"
-        xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
-        xmlns:tns="xmlns:%s"
+        name="geniwrapper_autogenerated"
+        targetNamespace="%s/2009/07/sfa.wsdl"
+        xmlns="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        xmlns:xsdl="%s/2009/07/schema"
+        xmlns:tns="%s/2009/07/sfa.wsdl"
         xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+        xmlns:soapenc="http://schemas.xmlsoap.org/wsdl/soap/encoding"
         xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"/>
-        """ % (globals.plc_ns,globals.plc_ns)
+        """ % (globals.plc_ns,globals.plc_ns,globals.plc_ns)
         
     wsdl = xml.dom.minidom.parseString(wsdl_text_header)
     
     return wsdl
-    
 
-types = get_wsdl_definitions()
-types.firstChild.appendChild(types.createElement("wsdl:types"))
-wsdl = get_wsdl_definitions()
-add_wsdl_ports_and_bindings(wsdl)
-wsdl_types = wsdl.importNode(types.firstChild.firstChild, True)
-wsdl.firstChild.appendChild(wsdl_types)
-add_wsdl_service(wsdl)
+def get_wsdl_definitions_and_types():
+    wsdl_text_header = """
+    <wsdl:definitions
+        name="geniwrapper_autogenerated"
+        targetNamespace="%s/2009/07/sfa.wsdl"
+        xmlns="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        xmlns:xsdl="%s/2009/07/schema"
+        xmlns:tns="%s/2009/07/sfa.wsdl"
+        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+        xmlns:soapenc="http://schemas.xmlsoap.org/wsdl/soap/encoding"
+        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
+        <types>
+            <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="%s/2009/07/schema"/>
+        </types>
+    </wsdl:definitions> """ % (globals.plc_ns, globals.plc_ns, globals.plc_ns, globals.plc_ns)
+    wsdl = xml.dom.minidom.parseString(wsdl_text_header)
+    return wsdl
 
-xml.dom.ext.PrettyPrint(wsdl)
+def main():
+    global types
+    global interface_options
+
+    parser = OptionParser()
+    parser.add_option("-r", "--registry", dest="registry", action="store_true", 
+                              help="Generate registry.wsdl", metavar="FILE")
+    parser.add_option("-s", "--slice-manager",
+                              action="store_true", dest="slicemgr", 
+                              help="Generate sm.wsdl")
+    parser.add_option("-a", "--aggregate", action="store_true", dest="aggregate",
+                              help="Generate am.wsdl")
+
+    (interface_options, args) = parser.parse_args()
+    types = get_wsdl_definitions_and_types()
+    wsdl = get_wsdl_definitions()
+    add_wsdl_ports_and_bindings(wsdl)
+    wsdl_types = wsdl.importNode(types.getElementsByTagName("types")[0], True)
+    wsdl.firstChild.appendChild(wsdl_types)
+    add_wsdl_service(wsdl)
+
+    xml.dom.ext.PrettyPrint(wsdl)
+
+if __name__ == "__main__":
+        main()