• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/opal/ZSI/ZSI/wstools/WSDLTools.py

00001 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00002 #
00003 # This software is subject to the provisions of the Zope Public License,
00004 # Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
00005 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00006 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00007 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00008 # FOR A PARTICULAR PURPOSE.
00009 
00010 ident = "$Id: WSDLTools.py 1122 2006-02-04 01:24:50Z boverhof $"
00011 
00012 import weakref
00013 from cStringIO import StringIO
00014 from Namespaces import OASIS, XMLNS, WSA, WSA_LIST, WSRF_V1_2, WSRF
00015 from Utility import Collection, CollectionNS, DOM, ElementProxy, basejoin
00016 from XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter
00017 
00018 
00019 class WSDLReader:
00020     """A WSDLReader creates WSDL instances from urls and xml data."""
00021 
00022     # Custom subclasses of WSDLReader may wish to implement a caching
00023     # strategy or other optimizations. Because application needs vary 
00024     # so widely, we don't try to provide any caching by default.
00025 
00026     def loadFromStream(self, stream, name=None):
00027         """Return a WSDL instance loaded from a stream object."""
00028         document = DOM.loadDocument(stream)
00029         wsdl = WSDL()
00030         if name:
00031             wsdl.location = name
00032         elif hasattr(stream, 'name'):
00033             wsdl.location = stream.name
00034         wsdl.load(document)
00035         return wsdl
00036 
00037     def loadFromURL(self, url):
00038         """Return a WSDL instance loaded from the given url."""
00039         document = DOM.loadFromURL(url)
00040         wsdl = WSDL()
00041         wsdl.location = url
00042         wsdl.load(document)
00043         return wsdl
00044 
00045     def loadFromString(self, data):
00046         """Return a WSDL instance loaded from an xml string."""
00047         return self.loadFromStream(StringIO(data))
00048 
00049     def loadFromFile(self, filename):
00050         """Return a WSDL instance loaded from the given file."""
00051         file = open(filename, 'rb')
00052         try:
00053             wsdl = self.loadFromStream(file)
00054         finally:
00055             file.close()
00056         return wsdl
00057 
00058 class WSDL:
00059     """A WSDL object models a WSDL service description. WSDL objects
00060        may be created manually or loaded from an xml representation
00061        using a WSDLReader instance."""
00062 
00063     def __init__(self, targetNamespace=None, strict=1):
00064         self.targetNamespace = targetNamespace or 'urn:this-document.wsdl'
00065         self.documentation = ''
00066         self.location = None
00067         self.document = None
00068         self.name = None
00069         self.services = CollectionNS(self)
00070         self.messages = CollectionNS(self)
00071         self.portTypes = CollectionNS(self)
00072         self.bindings = CollectionNS(self)
00073         self.imports = Collection(self)
00074         self.types = Types(self)
00075         self.extensions = []
00076         self.strict = strict
00077 
00078     def __del__(self):
00079         if self.document is not None:
00080             self.document.unlink()
00081 
00082     version = '1.1'
00083 
00084     def addService(self, name, documentation='', targetNamespace=None):
00085         if self.services.has_key(name):
00086             raise WSDLError(
00087                 'Duplicate service element: %s' % name
00088                 )
00089         item = Service(name, documentation)
00090         if targetNamespace:
00091             item.targetNamespace = targetNamespace
00092         self.services[name] = item
00093         return item
00094 
00095     def addMessage(self, name, documentation='', targetNamespace=None):
00096         if self.messages.has_key(name):
00097             raise WSDLError(
00098                 'Duplicate message element: %s.' % name
00099                 )
00100         item = Message(name, documentation)
00101         if targetNamespace:
00102             item.targetNamespace = targetNamespace
00103         self.messages[name] = item
00104         return item
00105 
00106     def addPortType(self, name, documentation='', targetNamespace=None):
00107         if self.portTypes.has_key(name):
00108             raise WSDLError(
00109                 'Duplicate portType element: name'
00110                 )
00111         item = PortType(name, documentation)
00112         if targetNamespace:
00113             item.targetNamespace = targetNamespace
00114         self.portTypes[name] = item
00115         return item
00116 
00117     def addBinding(self, name, type, documentation='', targetNamespace=None):
00118         if self.bindings.has_key(name):
00119             raise WSDLError(
00120                 'Duplicate binding element: %s' % name
00121                 )
00122         item = Binding(name, type, documentation)
00123         if targetNamespace:
00124             item.targetNamespace = targetNamespace
00125         self.bindings[name] = item
00126         return item
00127 
00128     def addImport(self, namespace, location):
00129         item = ImportElement(namespace, location)
00130         self.imports[namespace] = item
00131         return item
00132 
00133     def toDom(self):
00134         """ Generate a DOM representation of the WSDL instance.
00135         Not dealing with generating XML Schema, thus the targetNamespace
00136         of all XML Schema elements or types used by WSDL message parts 
00137         needs to be specified via import information items.
00138         """
00139         namespaceURI = DOM.GetWSDLUri(self.version)
00140         self.document = DOM.createDocument(namespaceURI ,'wsdl:definitions')
00141 
00142         # Set up a couple prefixes for easy reading.
00143         child = DOM.getElement(self.document, None)
00144         child.setAttributeNS(None, 'targetNamespace', self.targetNamespace)
00145         child.setAttributeNS(XMLNS.BASE, 'xmlns:wsdl', namespaceURI)
00146         child.setAttributeNS(XMLNS.BASE, 'xmlns:xsd', 'http://www.w3.org/1999/XMLSchema')
00147         child.setAttributeNS(XMLNS.BASE, 'xmlns:soap', 'http://schemas.xmlsoap.org/wsdl/soap/')
00148         child.setAttributeNS(XMLNS.BASE, 'xmlns:tns', self.targetNamespace)
00149         
00150         if self.name:
00151             child.setAttributeNS(None, 'name', self.name)
00152 
00153         # wsdl:import
00154         for item in self.imports: 
00155             item.toDom()
00156         # wsdl:message
00157         for item in self.messages:
00158             item.toDom()
00159         # wsdl:portType
00160         for item in self.portTypes:
00161             item.toDom()
00162         # wsdl:binding
00163         for item in self.bindings:
00164             item.toDom()
00165         # wsdl:service
00166         for item in self.services:
00167             item.toDom()
00168 
00169     def load(self, document):
00170         # We save a reference to the DOM document to ensure that elements
00171         # saved as "extensions" will continue to have a meaningful context
00172         # for things like namespace references. The lifetime of the DOM
00173         # document is bound to the lifetime of the WSDL instance.
00174         self.document = document
00175 
00176         definitions = DOM.getElement(document, 'definitions', None, None)
00177         if definitions is None:
00178             raise WSDLError(
00179                 'Missing <definitions> element.'
00180                 )
00181         self.version = DOM.WSDLUriToVersion(definitions.namespaceURI)
00182         NS_WSDL = DOM.GetWSDLUri(self.version)
00183 
00184         self.targetNamespace = DOM.getAttr(definitions, 'targetNamespace',
00185                                            None, None)
00186         self.name = DOM.getAttr(definitions, 'name', None, None)
00187         self.documentation = GetDocumentation(definitions)
00188 
00189         # 
00190         # Retrieve all <wsdl:import>'s, append all children of imported
00191         # document to main document.  First iteration grab all original 
00192         # <wsdl:import>'s from document, second iteration grab all 
00193         # "imported" <wsdl:imports> from document, etc break out when 
00194         # no more <wsdl:import>'s.
00195         # 
00196         imported = []
00197         base_location = self.location
00198         do_it = True
00199         while do_it:
00200             do_it = False
00201             for element in DOM.getElements(definitions, 'import', NS_WSDL):
00202                 location = DOM.getAttr(element, 'location')
00203 
00204                 if base_location is not None:
00205                     location = basejoin(base_location, location)
00206                     
00207                 if location not in imported:
00208                     do_it = True
00209                     self._import(document, element, base_location)
00210                     imported.append(location)
00211                 else:
00212                     definitions.removeChild(element)
00213 
00214             base_location = None
00215 
00216         # 
00217         # No more <wsdl:import>'s, now load up all other 
00218         # WSDL information items.
00219         # 
00220         for element in DOM.getElements(definitions, None, None):
00221             targetNamespace = DOM.getAttr(element, 'targetNamespace')
00222             localName = element.localName
00223 
00224             if not DOM.nsUriMatch(element.namespaceURI, NS_WSDL):
00225                 if localName == 'schema':
00226                     tns = DOM.getAttr(element, 'targetNamespace')
00227                     reader = SchemaReader(base_url=self.imports[tns].location)
00228                     schema = reader.loadFromNode(WSDLToolsAdapter(self),
00229                                                  element)
00230 #                    schema.setBaseUrl(self.location)
00231                     self.types.addSchema(schema)
00232                 else:
00233                     self.extensions.append(element)
00234                 continue
00235 
00236             elif localName == 'message':
00237                 name = DOM.getAttr(element, 'name')
00238                 docs = GetDocumentation(element)
00239                 message = self.addMessage(name, docs, targetNamespace)
00240                 parts = DOM.getElements(element, 'part', NS_WSDL)
00241                 message.load(parts)
00242                 continue
00243 
00244             elif localName == 'portType':
00245                 name = DOM.getAttr(element, 'name')
00246                 docs = GetDocumentation(element)
00247                 ptype = self.addPortType(name, docs, targetNamespace)
00248                 #operations = DOM.getElements(element, 'operation', NS_WSDL)
00249                 #ptype.load(operations)
00250                 ptype.load(element)
00251                 continue
00252 
00253             elif localName == 'binding':
00254                 name = DOM.getAttr(element, 'name')
00255                 type = DOM.getAttr(element, 'type', default=None)
00256                 if type is None:
00257                     raise WSDLError(
00258                         'Missing type attribute for binding %s.' % name
00259                         )
00260                 type = ParseQName(type, element)
00261                 docs = GetDocumentation(element)
00262                 binding = self.addBinding(name, type, docs, targetNamespace)
00263                 operations = DOM.getElements(element, 'operation', NS_WSDL)
00264                 binding.load(operations)
00265                 binding.load_ex(GetExtensions(element))
00266                 continue
00267 
00268             elif localName == 'service':
00269                 name = DOM.getAttr(element, 'name')
00270                 docs = GetDocumentation(element)
00271                 service = self.addService(name, docs, targetNamespace)
00272                 ports = DOM.getElements(element, 'port', NS_WSDL)
00273                 service.load(ports)
00274                 service.load_ex(GetExtensions(element))
00275                 continue
00276 
00277             elif localName == 'types':
00278                 self.types.documentation = GetDocumentation(element)
00279                 base_location = DOM.getAttr(element, 'base-location')
00280                 if base_location:
00281                     element.removeAttribute('base-location')
00282                 base_location = base_location or self.location
00283                 reader = SchemaReader(base_url=base_location)
00284                 for item in DOM.getElements(element, None, None):
00285                     if item.localName == 'schema':
00286                         schema = reader.loadFromNode(WSDLToolsAdapter(self), item)
00287                         # XXX <types> could have been imported
00288                         #schema.setBaseUrl(self.location)
00289                         schema.setBaseUrl(base_location)
00290                         self.types.addSchema(schema)
00291                     else:
00292                         self.types.addExtension(item)
00293                 # XXX remove the attribute
00294                 # element.removeAttribute('base-location')
00295                 continue
00296 
00297     def _import(self, document, element, base_location=None):
00298         '''Algo take <import> element's children, clone them,
00299         and add them to the main document.  Support for relative 
00300         locations is a bit complicated.  The orig document context
00301         is lost, so we need to store base location in DOM elements
00302         representing <types>, by creating a special temporary 
00303         "base-location" attribute,  and <import>, by resolving
00304         the relative "location" and storing it as "location".
00305         
00306         document -- document we are loading
00307         element -- DOM Element representing <import> 
00308         base_location -- location of document from which this
00309             <import> was gleaned.
00310         '''
00311         namespace = DOM.getAttr(element, 'namespace', default=None)
00312         location = DOM.getAttr(element, 'location', default=None)
00313         if namespace is None or location is None:
00314             raise WSDLError(
00315                 'Invalid import element (missing namespace or location).'
00316                 )
00317         if base_location:
00318             location = basejoin(base_location, location)
00319             element.setAttributeNS(None, 'location', location)
00320 
00321         obimport = self.addImport(namespace, location)
00322         obimport._loaded = 1
00323 
00324         importdoc = DOM.loadFromURL(location)
00325         try:
00326             if location.find('#') > -1:
00327                 idref = location.split('#')[-1]
00328                 imported = DOM.getElementById(importdoc, idref)
00329             else:
00330                 imported = importdoc.documentElement
00331             if imported is None:
00332                 raise WSDLError(
00333                     'Import target element not found for: %s' % location
00334                     )
00335 
00336             imported_tns = DOM.findTargetNS(imported)
00337             if imported_tns != namespace:
00338                 return
00339 
00340             if imported.localName == 'definitions':
00341                 imported_nodes = imported.childNodes
00342             else:
00343                 imported_nodes = [imported]
00344             parent = element.parentNode
00345 
00346             parent.removeChild(element)
00347             
00348             for node in imported_nodes:
00349                 if node.nodeType != node.ELEMENT_NODE:
00350                     continue
00351                 child = DOM.importNode(document, node, 1)
00352                 parent.appendChild(child)
00353                 child.setAttribute('targetNamespace', namespace)
00354                 attrsNS = imported._attrsNS
00355                 for attrkey in attrsNS.keys():
00356                     if attrkey[0] == DOM.NS_XMLNS:
00357                         attr = attrsNS[attrkey].cloneNode(1)
00358                         child.setAttributeNode(attr)
00359 
00360                 #XXX Quick Hack, should be in WSDL Namespace.
00361                 if child.localName == 'import':
00362                     rlocation = child.getAttributeNS(None, 'location')
00363                     alocation = basejoin(location, rlocation)
00364                     child.setAttribute('location', alocation)
00365                 elif child.localName == 'types':
00366                     child.setAttribute('base-location', location)
00367 
00368         finally:
00369             importdoc.unlink()
00370         return location
00371 
00372 class Element:
00373     """A class that provides common functions for WSDL element classes."""
00374     def __init__(self, name=None, documentation=''):
00375         self.name = name
00376         self.documentation = documentation
00377         self.extensions = []
00378 
00379     def addExtension(self, item):
00380         item.parent = weakref.ref(self)
00381         self.extensions.append(item)
00382         
00383     def getWSDL(self):
00384         """Return the WSDL object that contains this information item."""
00385         parent = self
00386         while 1:
00387             # skip any collections
00388             if isinstance(parent, WSDL):
00389                 return parent
00390             try: parent = parent.parent()
00391             except: break
00392             
00393         return None
00394 
00395 
00396 class ImportElement(Element):
00397     def __init__(self, namespace, location):
00398         self.namespace = namespace
00399         self.location = location
00400 
00401 #    def getWSDL(self):
00402 #        """Return the WSDL object that contains this Message Part."""
00403 #        return self.parent().parent()
00404 
00405     def toDom(self):
00406         wsdl = self.getWSDL()
00407         ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
00408         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'import')
00409         epc.setAttributeNS(None, 'namespace', self.namespace)
00410         epc.setAttributeNS(None, 'location', self.location)
00411 
00412     _loaded = None
00413 
00414 
00415 class Types(Collection):
00416     default = lambda self,k: k.targetNamespace
00417     def __init__(self, parent):
00418         Collection.__init__(self, parent)
00419         self.documentation = ''
00420         self.extensions = []
00421 
00422     def addSchema(self, schema):
00423         name = schema.targetNamespace
00424         self[name] = schema
00425         return schema
00426 
00427     def addExtension(self, item):
00428         self.extensions.append(item)
00429 
00430 
00431 class Message(Element):
00432     def __init__(self, name, documentation=''):
00433         Element.__init__(self, name, documentation)
00434         self.parts = Collection(self)
00435 
00436     def addPart(self, name, type=None, element=None):
00437         if self.parts.has_key(name):
00438             raise WSDLError(
00439                 'Duplicate message part element: %s' % name
00440                 )
00441         if type is None and element is None:
00442             raise WSDLError(
00443                 'Missing type or element attribute for part: %s' % name
00444                 )
00445         item = MessagePart(name)
00446         item.element = element
00447         item.type = type
00448         self.parts[name] = item
00449         return item
00450 
00451     def load(self, elements):
00452         for element in elements:
00453             name = DOM.getAttr(element, 'name')
00454             part = MessagePart(name)
00455             self.parts[name] = part
00456             elemref = DOM.getAttr(element, 'element', default=None)
00457             typeref = DOM.getAttr(element, 'type', default=None)
00458             if typeref is None and elemref is None:
00459                 raise WSDLError(
00460                     'No type or element attribute for part: %s' % name
00461                     )
00462             if typeref is not None:
00463                 part.type = ParseTypeRef(typeref, element)
00464             if elemref is not None:
00465                 part.element = ParseTypeRef(elemref, element)
00466 
00467 #    def getElementDeclaration(self):
00468 #        """Return the XMLSchema.ElementDeclaration instance or None"""
00469 #        element = None
00470 #        if self.element:
00471 #            nsuri,name = self.element
00472 #            wsdl = self.getWSDL()
00473 #            if wsdl.types.has_key(nsuri) and wsdl.types[nsuri].elements.has_key(name):
00474 #                element = wsdl.types[nsuri].elements[name]
00475 #        return element
00476 #
00477 #    def getTypeDefinition(self):
00478 #        """Return the XMLSchema.TypeDefinition instance or None"""
00479 #        type = None
00480 #        if self.type:
00481 #            nsuri,name = self.type
00482 #            wsdl = self.getWSDL()
00483 #            if wsdl.types.has_key(nsuri) and wsdl.types[nsuri].types.has_key(name):
00484 #                type = wsdl.types[nsuri].types[name]
00485 #        return type
00486 
00487 #    def getWSDL(self):
00488 #        """Return the WSDL object that contains this Message Part."""
00489 #        return self.parent().parent()
00490 
00491     def toDom(self):
00492         wsdl = self.getWSDL()
00493         ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
00494         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'message')
00495         epc.setAttributeNS(None, 'name', self.name)
00496 
00497         for part in self.parts:
00498             part.toDom(epc._getNode())
00499 
00500 
00501 class MessagePart(Element):
00502     def __init__(self, name):
00503         Element.__init__(self, name, '')
00504         self.element = None
00505         self.type = None
00506 
00507 #    def getWSDL(self):
00508 #        """Return the WSDL object that contains this Message Part."""
00509 #        return self.parent().parent().parent().parent()
00510 
00511     def getTypeDefinition(self):
00512         wsdl = self.getWSDL()
00513         nsuri,name = self.type
00514         schema = wsdl.types.get(nsuri, {})
00515         return schema.get(name)
00516 
00517     def getElementDeclaration(self):
00518         wsdl = self.getWSDL()
00519         nsuri,name = self.element
00520         schema = wsdl.types.get(nsuri, {})
00521         return schema.get(name)
00522 
00523     def toDom(self, node):
00524         """node -- node representing message"""
00525         wsdl = self.getWSDL()
00526         ep = ElementProxy(None, node)
00527         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'part')
00528         epc.setAttributeNS(None, 'name', self.name)
00529 
00530         if self.element is not None:
00531             ns,name = self.element
00532             prefix = epc.getPrefix(ns)
00533             epc.setAttributeNS(None, 'element', '%s:%s'%(prefix,name))
00534         elif self.type is not None:
00535             ns,name = self.type
00536             prefix = epc.getPrefix(ns)
00537             epc.setAttributeNS(None, 'type', '%s:%s'%(prefix,name))
00538 
00539 
00540 class PortType(Element):
00541     '''PortType has a anyAttribute, thus must provide for an extensible
00542        mechanism for supporting such attributes.  ResourceProperties is
00543        specified in WS-ResourceProperties.   wsa:Action is specified in
00544        WS-Address.
00545 
00546        Instance Data:
00547            name -- name attribute
00548            resourceProperties -- optional. wsr:ResourceProperties attribute,
00549               value is a QName this is Parsed into a (namespaceURI, name)
00550               that represents a Global Element Declaration.
00551            operations
00552     '''
00553 
00554     def __init__(self, name, documentation=''):
00555         Element.__init__(self, name, documentation)
00556         self.operations = Collection(self)
00557         self.resourceProperties = None
00558 
00559 #    def getWSDL(self):
00560 #        return self.parent().parent()
00561 
00562     def getTargetNamespace(self):
00563         return self.targetNamespace or self.getWSDL().targetNamespace
00564 
00565     def getResourceProperties(self):
00566         return self.resourceProperties
00567 
00568     def addOperation(self, name, documentation='', parameterOrder=None):
00569         item = Operation(name, documentation, parameterOrder)
00570         self.operations[name] = item
00571         return item
00572 
00573     def load(self, element):
00574         self.name = DOM.getAttr(element, 'name')
00575         self.documentation = GetDocumentation(element)
00576         self.targetNamespace = DOM.getAttr(element, 'targetNamespace')
00577 
00578         for nsuri in WSRF_V1_2.PROPERTIES.XSD_LIST:
00579             if DOM.hasAttr(element, 'ResourceProperties', nsuri):
00580                 rpref = DOM.getAttr(element, 'ResourceProperties', nsuri)
00581                 self.resourceProperties = ParseQName(rpref, element)
00582 
00583         NS_WSDL = DOM.GetWSDLUri(self.getWSDL().version)
00584         elements = DOM.getElements(element, 'operation', NS_WSDL)
00585         for element in elements:
00586             name = DOM.getAttr(element, 'name')
00587             docs = GetDocumentation(element)
00588             param_order = DOM.getAttr(element, 'parameterOrder', default=None)
00589             if param_order is not None:
00590                 param_order = param_order.split(' ')
00591             operation = self.addOperation(name, docs, param_order)
00592 
00593             item = DOM.getElement(element, 'input', None, None)
00594             if item is not None:
00595                 name = DOM.getAttr(item, 'name')
00596                 docs = GetDocumentation(item)
00597                 msgref = DOM.getAttr(item, 'message')
00598                 message = ParseQName(msgref, item)
00599                 for WSA in WSA_LIST:
00600                     action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None)
00601                     if action: break
00602                 operation.setInput(message, name, docs, action)
00603 
00604             item = DOM.getElement(element, 'output', None, None)
00605             if item is not None:
00606                 name = DOM.getAttr(item, 'name')
00607                 docs = GetDocumentation(item)
00608                 msgref = DOM.getAttr(item, 'message')
00609                 message = ParseQName(msgref, item)
00610                 for WSA in WSA_LIST:
00611                     action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None)
00612                     if action: break
00613                 operation.setOutput(message, name, docs, action)
00614 
00615             for item in DOM.getElements(element, 'fault', None):
00616                 name = DOM.getAttr(item, 'name')
00617                 docs = GetDocumentation(item)
00618                 msgref = DOM.getAttr(item, 'message')
00619                 message = ParseQName(msgref, item)
00620                 for WSA in WSA_LIST:
00621                     action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None)
00622                     if action: break
00623                 operation.addFault(message, name, docs, action)
00624                 
00625     def toDom(self):
00626         wsdl = self.getWSDL()
00627 
00628         ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
00629         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'portType')
00630         epc.setAttributeNS(None, 'name', self.name)
00631         if self.resourceProperties:
00632             ns,name = self.resourceProperties
00633             prefix = epc.getPrefix(ns)
00634             epc.setAttributeNS(WSRF.PROPERTIES.LATEST, 'ResourceProperties', 
00635                                 '%s:%s'%(prefix,name))
00636 
00637         for op in self.operations:
00638             op.toDom(epc._getNode())
00639 
00640 
00641 
00642 class Operation(Element):
00643     def __init__(self, name, documentation='', parameterOrder=None):
00644         Element.__init__(self, name, documentation)
00645         self.parameterOrder = parameterOrder
00646         self.faults = Collection(self)
00647         self.input = None
00648         self.output = None
00649 
00650     def getWSDL(self):
00651         """Return the WSDL object that contains this Operation."""
00652         return self.parent().parent().parent().parent()
00653 
00654     def getPortType(self):
00655         return self.parent().parent()
00656 
00657     def getInputAction(self):
00658         """wsa:Action attribute"""
00659         return GetWSAActionInput(self)
00660 
00661     def getInputMessage(self):
00662         if self.input is None:
00663             return None
00664         wsdl = self.getPortType().getWSDL()
00665         return wsdl.messages[self.input.message]
00666 
00667     def getOutputAction(self):
00668         """wsa:Action attribute"""
00669         return GetWSAActionOutput(self)
00670 
00671     def getOutputMessage(self):
00672         if self.output is None:
00673             return None
00674         wsdl = self.getPortType().getWSDL()
00675         return wsdl.messages[self.output.message]
00676 
00677     def getFaultAction(self, name):
00678         """wsa:Action attribute"""
00679         return GetWSAActionFault(self, name)
00680 
00681     def getFaultMessage(self, name):
00682         wsdl = self.getPortType().getWSDL()
00683         return wsdl.messages[self.faults[name].message]
00684 
00685     def addFault(self, message, name, documentation='', action=None):
00686         if self.faults.has_key(name):
00687             raise WSDLError(
00688                 'Duplicate fault element: %s' % name
00689                 )
00690         item = MessageRole('fault', message, name, documentation, action)
00691         self.faults[name] = item
00692         return item
00693 
00694     def setInput(self, message, name='', documentation='', action=None):
00695         self.input = MessageRole('input', message, name, documentation, action)
00696         self.input.parent = weakref.ref(self)
00697         return self.input
00698 
00699     def setOutput(self, message, name='', documentation='', action=None):
00700         self.output = MessageRole('output', message, name, documentation, action)
00701         self.output.parent = weakref.ref(self)
00702         return self.output
00703 
00704     def toDom(self, node):
00705         wsdl = self.getWSDL()
00706 
00707         ep = ElementProxy(None, node)
00708         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'operation')
00709         epc.setAttributeNS(None, 'name', self.name)
00710         node = epc._getNode()
00711         if self.input:
00712            self.input.toDom(node)
00713         if self.output:
00714            self.output.toDom(node)
00715         for fault in self.faults:
00716            fault.toDom(node)
00717 
00718 
00719 class MessageRole(Element):
00720     def __init__(self, type, message, name='', documentation='', action=None):
00721         Element.__init__(self, name, documentation)
00722         self.message = message
00723         self.type = type
00724         self.action = action
00725         
00726     def getWSDL(self):
00727         """Return the WSDL object that contains this information item."""
00728         parent = self
00729         while 1:
00730             # skip any collections
00731             if isinstance(parent, WSDL):
00732                 return parent
00733             try: parent = parent.parent()
00734             except: break
00735             
00736         return None
00737 
00738     def getMessage(self):
00739         """Return the WSDL object that represents the attribute message 
00740         (namespaceURI, name) tuple
00741         """
00742         wsdl = self.getWSDL()
00743         return wsdl.messages[self.message]
00744 
00745     def toDom(self, node):
00746         wsdl = self.getWSDL()
00747 
00748         ep = ElementProxy(None, node)
00749         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), self.type)
00750         if not isinstance(self.message, basestring) and len(self.message) == 2:
00751             ns,name = self.message
00752             prefix = epc.getPrefix(ns)
00753             epc.setAttributeNS(None, 'message', '%s:%s' %(prefix,name))
00754         else:
00755             epc.setAttributeNS(None, 'message', self.message)
00756 
00757         if self.action:
00758             epc.setAttributeNS(WSA.ADDRESS, 'Action', self.action)
00759             
00760         if self.name:
00761             epc.setAttributeNS(None, 'name', self.name)
00762         
00763 
00764 class Binding(Element):
00765     def __init__(self, name, type, documentation=''):
00766         Element.__init__(self, name, documentation)
00767         self.operations = Collection(self)
00768         self.type = type
00769 
00770 #    def getWSDL(self):
00771 #        """Return the WSDL object that contains this binding."""
00772 #        return self.parent().parent()
00773 
00774     def getPortType(self):
00775         """Return the PortType object associated with this binding."""
00776         return self.getWSDL().portTypes[self.type]
00777 
00778     def findBinding(self, kind):
00779         for item in self.extensions:
00780             if isinstance(item, kind):
00781                 return item
00782         return None
00783 
00784     def findBindings(self, kind):
00785         return [ item for item in self.extensions if isinstance(item, kind) ]
00786 
00787     def addOperationBinding(self, name, documentation=''):
00788         item = OperationBinding(name, documentation)
00789         self.operations[name] = item
00790         return item
00791 
00792     def load(self, elements):
00793         for element in elements:
00794             name = DOM.getAttr(element, 'name')
00795             docs = GetDocumentation(element)
00796             opbinding = self.addOperationBinding(name, docs)
00797             opbinding.load_ex(GetExtensions(element))
00798 
00799             item = DOM.getElement(element, 'input', None, None)
00800             if item is not None:
00801                 #TODO: addInputBinding?
00802                 mbinding = MessageRoleBinding('input')
00803                 mbinding.documentation = GetDocumentation(item)
00804                 opbinding.input = mbinding
00805                 mbinding.load_ex(GetExtensions(item))
00806                 mbinding.parent = weakref.ref(opbinding)
00807 
00808             item = DOM.getElement(element, 'output', None, None)
00809             if item is not None:
00810                 mbinding = MessageRoleBinding('output')
00811                 mbinding.documentation = GetDocumentation(item)
00812                 opbinding.output = mbinding
00813                 mbinding.load_ex(GetExtensions(item))
00814                 mbinding.parent = weakref.ref(opbinding)
00815 
00816             for item in DOM.getElements(element, 'fault', None):
00817                 name = DOM.getAttr(item, 'name')
00818                 mbinding = MessageRoleBinding('fault', name)
00819                 mbinding.documentation = GetDocumentation(item)
00820                 opbinding.faults[name] = mbinding
00821                 mbinding.load_ex(GetExtensions(item))
00822                 mbinding.parent = weakref.ref(opbinding)
00823 
00824     def load_ex(self, elements):
00825         for e in elements:
00826             ns, name = e.namespaceURI, e.localName
00827             if ns in DOM.NS_SOAP_BINDING_ALL and name == 'binding':
00828                 transport = DOM.getAttr(e, 'transport', default=None)
00829                 style = DOM.getAttr(e, 'style', default='document')
00830                 ob = SoapBinding(transport, style)
00831                 self.addExtension(ob)
00832                 continue
00833             elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'binding':
00834                 verb = DOM.getAttr(e, 'verb')
00835                 ob = HttpBinding(verb)
00836                 self.addExtension(ob)
00837                 continue
00838             else:
00839                 self.addExtension(e)
00840 
00841     def toDom(self):
00842         wsdl = self.getWSDL()
00843         ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
00844         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'binding')
00845         epc.setAttributeNS(None, 'name', self.name)
00846 
00847         ns,name = self.type
00848         prefix = epc.getPrefix(ns)
00849         epc.setAttributeNS(None, 'type', '%s:%s' %(prefix,name))
00850 
00851         node = epc._getNode()
00852         for ext in self.extensions:
00853             ext.toDom(node)
00854         for op_binding in self.operations:
00855             op_binding.toDom(node)
00856 
00857 
00858 class OperationBinding(Element):
00859     def __init__(self, name, documentation=''):
00860         Element.__init__(self, name, documentation)
00861         self.input = None
00862         self.output = None
00863         self.faults = Collection(self)
00864 
00865 #    def getWSDL(self):
00866 #        """Return the WSDL object that contains this binding."""
00867 #        return self.parent().parent().parent().parent()
00868 
00869 
00870     def getBinding(self):
00871         """Return the parent Binding object of the operation binding."""
00872         return self.parent().parent()
00873 
00874     def getOperation(self):
00875         """Return the abstract Operation associated with this binding."""
00876         return self.getBinding().getPortType().operations[self.name]
00877         
00878     def findBinding(self, kind):
00879         for item in self.extensions:
00880             if isinstance(item, kind):
00881                 return item
00882         return None
00883 
00884     def findBindings(self, kind):
00885         return [ item for item in self.extensions if isinstance(item, kind) ]
00886 
00887     def addInputBinding(self, binding):
00888         if self.input is None:
00889             self.input = MessageRoleBinding('input')
00890             self.input.parent = weakref.ref(self)
00891         self.input.addExtension(binding)
00892         return binding
00893 
00894     def addOutputBinding(self, binding):
00895         if self.output is None:
00896             self.output = MessageRoleBinding('output')
00897             self.output.parent = weakref.ref(self)
00898         self.output.addExtension(binding)
00899         return binding
00900 
00901     def addFaultBinding(self, name, binding):
00902         fault = self.get(name, None)
00903         if fault is None:
00904             fault = MessageRoleBinding('fault', name)
00905         fault.addExtension(binding)
00906         return binding
00907 
00908     def load_ex(self, elements):
00909         for e in elements:
00910             ns, name = e.namespaceURI, e.localName
00911             if ns in DOM.NS_SOAP_BINDING_ALL and name == 'operation':
00912                 soapaction = DOM.getAttr(e, 'soapAction', default=None)
00913                 style = DOM.getAttr(e, 'style', default=None)
00914                 ob = SoapOperationBinding(soapaction, style)
00915                 self.addExtension(ob)
00916                 continue
00917             elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'operation':
00918                 location = DOM.getAttr(e, 'location')
00919                 ob = HttpOperationBinding(location)
00920                 self.addExtension(ob)
00921                 continue
00922             else:
00923                 self.addExtension(e)
00924 
00925     def toDom(self, node):
00926         wsdl = self.getWSDL()
00927         ep = ElementProxy(None, node)
00928         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'operation')
00929         epc.setAttributeNS(None, 'name', self.name)
00930 
00931         node = epc._getNode()
00932         for ext in self.extensions:
00933             ext.toDom(node)
00934         if self.input:
00935             self.input.toDom(node)
00936         if self.output:
00937             self.output.toDom(node)
00938         for fault in self.faults:
00939             fault.toDom(node)
00940 
00941 
00942 class MessageRoleBinding(Element):
00943     def __init__(self, type, name='', documentation=''):
00944         Element.__init__(self, name, documentation)
00945         self.type = type
00946 
00947     def findBinding(self, kind):
00948         for item in self.extensions:
00949             if isinstance(item, kind):
00950                 return item
00951         return None
00952 
00953     def findBindings(self, kind):
00954         return [ item for item in self.extensions if isinstance(item, kind) ]
00955 
00956     def load_ex(self, elements):
00957         for e in elements:
00958             ns, name = e.namespaceURI, e.localName
00959             if ns in DOM.NS_SOAP_BINDING_ALL and name == 'body':
00960                 encstyle = DOM.getAttr(e, 'encodingStyle', default=None)
00961                 namespace = DOM.getAttr(e, 'namespace', default=None)
00962                 parts = DOM.getAttr(e, 'parts', default=None)
00963                 use = DOM.getAttr(e, 'use', default=None)
00964                 if use is None:
00965                     raise WSDLError(
00966                         'Invalid soap:body binding element.'
00967                         )
00968                 ob = SoapBodyBinding(use, namespace, encstyle, parts)
00969                 self.addExtension(ob)
00970                 continue
00971 
00972             elif ns in DOM.NS_SOAP_BINDING_ALL and name == 'fault':
00973                 encstyle = DOM.getAttr(e, 'encodingStyle', default=None)
00974                 namespace = DOM.getAttr(e, 'namespace', default=None)
00975                 name = DOM.getAttr(e, 'name', default=None)
00976                 use = DOM.getAttr(e, 'use', default=None)
00977                 if use is None or name is None:
00978                     raise WSDLError(
00979                         'Invalid soap:fault binding element.'
00980                         )
00981                 ob = SoapFaultBinding(name, use, namespace, encstyle)
00982                 self.addExtension(ob)
00983                 continue
00984 
00985             elif ns in DOM.NS_SOAP_BINDING_ALL and name in (
00986                 'header', 'headerfault'
00987                 ):
00988                 encstyle = DOM.getAttr(e, 'encodingStyle', default=None)
00989                 namespace = DOM.getAttr(e, 'namespace', default=None)
00990                 message = DOM.getAttr(e, 'message')
00991                 part = DOM.getAttr(e, 'part')
00992                 use = DOM.getAttr(e, 'use')
00993                 if name == 'header':
00994                     _class = SoapHeaderBinding
00995                 else:
00996                     _class = SoapHeaderFaultBinding
00997                 message = ParseQName(message, e)
00998                 ob = _class(message, part, use, namespace, encstyle)
00999                 self.addExtension(ob)
01000                 continue
01001 
01002             elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'urlReplacement':
01003                 ob = HttpUrlReplacementBinding()
01004                 self.addExtension(ob)
01005                 continue
01006 
01007             elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'urlEncoded':
01008                 ob = HttpUrlEncodedBinding()
01009                 self.addExtension(ob)
01010                 continue
01011 
01012             elif ns in DOM.NS_MIME_BINDING_ALL and name == 'multipartRelated':
01013                 ob = MimeMultipartRelatedBinding()
01014                 self.addExtension(ob)
01015                 ob.load_ex(GetExtensions(e))
01016                 continue
01017 
01018             elif ns in DOM.NS_MIME_BINDING_ALL and name == 'content':
01019                 part = DOM.getAttr(e, 'part', default=None)
01020                 type = DOM.getAttr(e, 'type', default=None)
01021                 ob = MimeContentBinding(part, type)
01022                 self.addExtension(ob)
01023                 continue
01024 
01025             elif ns in DOM.NS_MIME_BINDING_ALL and name == 'mimeXml':
01026                 part = DOM.getAttr(e, 'part', default=None)
01027                 ob = MimeXmlBinding(part)
01028                 self.addExtension(ob)
01029                 continue
01030 
01031             else:
01032                 self.addExtension(e)
01033 
01034     def toDom(self, node):
01035         wsdl = self.getWSDL()
01036         ep = ElementProxy(None, node)
01037         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), self.type)
01038 
01039         node = epc._getNode()
01040         for item in self.extensions:
01041             if item: item.toDom(node)
01042 
01043 
01044 class Service(Element):
01045     def __init__(self, name, documentation=''):
01046         Element.__init__(self, name, documentation)
01047         self.ports = Collection(self)
01048 
01049     def getWSDL(self):
01050         return self.parent().parent()
01051 
01052     def addPort(self, name, binding, documentation=''):
01053         item = Port(name, binding, documentation)
01054         self.ports[name] = item
01055         return item
01056 
01057     def load(self, elements):
01058         for element in elements:
01059             name = DOM.getAttr(element, 'name', default=None)
01060             docs = GetDocumentation(element)
01061             binding = DOM.getAttr(element, 'binding', default=None)
01062             if name is None or binding is None:
01063                 raise WSDLError(
01064                     'Invalid port element.'
01065                     )
01066             binding = ParseQName(binding, element)
01067             port = self.addPort(name, binding, docs)
01068             port.load_ex(GetExtensions(element))
01069 
01070     def load_ex(self, elements):
01071         for e in elements:
01072             self.addExtension(e)
01073 
01074     def toDom(self):
01075         wsdl = self.getWSDL()
01076         ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
01077         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), "service")
01078         epc.setAttributeNS(None, "name", self.name)
01079 
01080         node = epc._getNode()
01081         for port in self.ports:
01082             port.toDom(node)
01083 
01084 
01085 class Port(Element):
01086     def __init__(self, name, binding, documentation=''):
01087         Element.__init__(self, name, documentation)
01088         self.binding = binding
01089 
01090 #    def getWSDL(self):
01091 #        return self.parent().parent().getWSDL()
01092 
01093     def getService(self):
01094         """Return the Service object associated with this port."""
01095         return self.parent().parent()
01096 
01097     def getBinding(self):
01098         """Return the Binding object that is referenced by this port."""
01099         wsdl = self.getService().getWSDL()
01100         return wsdl.bindings[self.binding]
01101 
01102     def getPortType(self):
01103         """Return the PortType object that is referenced by this port."""
01104         wsdl = self.getService().getWSDL()
01105         binding = wsdl.bindings[self.binding]
01106         return wsdl.portTypes[binding.type]
01107 
01108     def getAddressBinding(self):
01109         """A convenience method to obtain the extension element used
01110            as the address binding for the port."""
01111         for item in self.extensions:
01112             if isinstance(item, SoapAddressBinding) or \
01113                isinstance(item, HttpAddressBinding):
01114                 return item
01115         raise WSDLError(
01116             'No address binding found in port.'
01117             )
01118 
01119     def load_ex(self, elements):
01120         for e in elements:
01121             ns, name = e.namespaceURI, e.localName
01122             if ns in DOM.NS_SOAP_BINDING_ALL and name == 'address':
01123                 location = DOM.getAttr(e, 'location', default=None)
01124                 ob = SoapAddressBinding(location)
01125                 self.addExtension(ob)
01126                 continue
01127             elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'address':
01128                 location = DOM.getAttr(e, 'location', default=None)
01129                 ob = HttpAddressBinding(location)
01130                 self.addExtension(ob)
01131                 continue
01132             else:
01133                 self.addExtension(e)
01134 
01135     def toDom(self, node):
01136         wsdl = self.getWSDL()
01137         ep = ElementProxy(None, node)
01138         epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), "port")
01139         epc.setAttributeNS(None, "name", self.name)
01140 
01141         ns,name = self.binding
01142         prefix = epc.getPrefix(ns)
01143         epc.setAttributeNS(None, "binding", "%s:%s" %(prefix,name))
01144 
01145         node = epc._getNode()
01146         for ext in self.extensions:
01147             ext.toDom(node)
01148 
01149 
01150 class SoapBinding:
01151     def __init__(self, transport, style='rpc'):
01152         self.transport = transport
01153         self.style = style
01154 
01155     def getWSDL(self):
01156         return self.parent().getWSDL()
01157 
01158     def toDom(self, node):
01159         wsdl = self.getWSDL()
01160         ep = ElementProxy(None, node)
01161         epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'binding')
01162         if self.transport:
01163             epc.setAttributeNS(None, "transport", self.transport)
01164         if self.style:
01165             epc.setAttributeNS(None, "style", self.style)
01166 
01167 class SoapAddressBinding:
01168     def __init__(self, location):
01169         self.location = location
01170 
01171     def getWSDL(self):
01172         return self.parent().getWSDL()
01173 
01174     def toDom(self, node):
01175         wsdl = self.getWSDL()
01176         ep = ElementProxy(None, node)
01177         epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'address')
01178         epc.setAttributeNS(None, "location", self.location)
01179 
01180 
01181 class SoapOperationBinding:
01182     def __init__(self, soapAction=None, style=None):
01183         self.soapAction = soapAction
01184         self.style = style
01185 
01186     def getWSDL(self):
01187         return self.parent().getWSDL()
01188 
01189     def toDom(self, node):
01190         wsdl = self.getWSDL()
01191         ep = ElementProxy(None, node)
01192         epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'operation')
01193         if self.soapAction:
01194             epc.setAttributeNS(None, 'soapAction', self.soapAction)
01195         if self.style:
01196             epc.setAttributeNS(None, 'style', self.style)
01197 
01198 
01199 class SoapBodyBinding:
01200     def __init__(self, use, namespace=None, encodingStyle=None, parts=None):
01201         if not use in ('literal', 'encoded'):
01202             raise WSDLError(
01203                 'Invalid use attribute value: %s' % use
01204                 )
01205         self.encodingStyle = encodingStyle
01206         self.namespace = namespace
01207         if type(parts) in (type(''), type(u'')):
01208             parts = parts.split()
01209         self.parts = parts
01210         self.use = use
01211 
01212     def getWSDL(self):
01213         return self.parent().getWSDL()
01214 
01215     def toDom(self, node):
01216         wsdl = self.getWSDL()
01217         ep = ElementProxy(None, node)
01218         epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'body')
01219         epc.setAttributeNS(None, "use", self.use)
01220         epc.setAttributeNS(None, "namespace", self.namespace)
01221 
01222 
01223 class SoapFaultBinding:
01224     def __init__(self, name, use, namespace=None, encodingStyle=None):
01225         if not use in ('literal', 'encoded'):
01226             raise WSDLError(
01227                 'Invalid use attribute value: %s' % use
01228                 )
01229         self.encodingStyle = encodingStyle
01230         self.namespace = namespace
01231         self.name = name
01232         self.use = use
01233         
01234     def getWSDL(self):
01235         return self.parent().getWSDL()
01236     
01237     def toDom(self, node):
01238         wsdl = self.getWSDL()
01239         ep = ElementProxy(None, node)
01240         epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'body')
01241         epc.setAttributeNS(None, "use", self.use)
01242         epc.setAttributeNS(None, "name", self.name)
01243         if self.namespace is not None:
01244             epc.setAttributeNS(None, "namespace", self.namespace)
01245         if self.encodingStyle is not None:
01246             epc.setAttributeNS(None, "encodingStyle", self.encodingStyle)
01247 
01248 
01249 class SoapHeaderBinding:
01250     def __init__(self, message, part, use, namespace=None, encodingStyle=None):
01251         if not use in ('literal', 'encoded'):
01252             raise WSDLError(
01253                 'Invalid use attribute value: %s' % use
01254                 )
01255         self.encodingStyle = encodingStyle
01256         self.namespace = namespace
01257         self.message = message
01258         self.part = part
01259         self.use = use
01260 
01261     tagname = 'header'
01262 
01263 class SoapHeaderFaultBinding(SoapHeaderBinding):
01264     tagname = 'headerfault'
01265 
01266 
01267 class HttpBinding:
01268     def __init__(self, verb):
01269         self.verb = verb
01270 
01271 class HttpAddressBinding:
01272     def __init__(self, location):
01273         self.location = location
01274 
01275 
01276 class HttpOperationBinding:
01277     def __init__(self, location):
01278         self.location = location
01279 
01280 class HttpUrlReplacementBinding:
01281     pass
01282 
01283 
01284 class HttpUrlEncodedBinding:
01285     pass
01286 
01287 
01288 class MimeContentBinding:
01289     def __init__(self, part=None, type=None):
01290         self.part = part
01291         self.type = type
01292 
01293 
01294 class MimeXmlBinding:
01295     def __init__(self, part=None):
01296         self.part = part
01297 
01298 
01299 class MimeMultipartRelatedBinding:
01300     def __init__(self):
01301         self.parts = []
01302 
01303     def load_ex(self, elements):
01304         for e in elements:
01305             ns, name = e.namespaceURI, e.localName
01306             if ns in DOM.NS_MIME_BINDING_ALL and name == 'part':
01307                 self.parts.append(MimePartBinding())
01308                 continue
01309 
01310 
01311 class MimePartBinding:
01312     def __init__(self):
01313         self.items = []
01314 
01315     def load_ex(self, elements):
01316         for e in elements:
01317             ns, name = e.namespaceURI, e.localName
01318             if ns in DOM.NS_MIME_BINDING_ALL and name == 'content':
01319                 part = DOM.getAttr(e, 'part', default=None)
01320                 type = DOM.getAttr(e, 'type', default=None)
01321                 ob = MimeContentBinding(part, type)
01322                 self.items.append(ob)
01323                 continue
01324 
01325             elif ns in DOM.NS_MIME_BINDING_ALL and name == 'mimeXml':
01326                 part = DOM.getAttr(e, 'part', default=None)
01327                 ob = MimeXmlBinding(part)
01328                 self.items.append(ob)
01329                 continue
01330 
01331             elif ns in DOM.NS_SOAP_BINDING_ALL and name == 'body':
01332                 encstyle = DOM.getAttr(e, 'encodingStyle', default=None)
01333                 namespace = DOM.getAttr(e, 'namespace', default=None)
01334                 parts = DOM.getAttr(e, 'parts', default=None)
01335                 use = DOM.getAttr(e, 'use', default=None)
01336                 if use is None:
01337                     raise WSDLError(
01338                         'Invalid soap:body binding element.'
01339                         )
01340                 ob = SoapBodyBinding(use, namespace, encstyle, parts)
01341                 self.items.append(ob)
01342                 continue
01343 
01344 
01345 class WSDLError(Exception):
01346     pass
01347 
01348 
01349 
01350 def DeclareNSPrefix(writer, prefix, nsuri):
01351     if writer.hasNSPrefix(nsuri):
01352         return
01353     writer.declareNSPrefix(prefix, nsuri)
01354 
01355 def ParseTypeRef(value, element):
01356     parts = value.split(':', 1)
01357     if len(parts) == 1:
01358         return (DOM.findTargetNS(element), value)
01359     nsuri = DOM.findNamespaceURI(parts[0], element)
01360     return (nsuri, parts[1])
01361 
01362 def ParseQName(value, element):
01363     nameref = value.split(':', 1)
01364     if len(nameref) == 2:
01365         nsuri = DOM.findNamespaceURI(nameref[0], element)
01366         name = nameref[-1]
01367     else:
01368         nsuri = DOM.findTargetNS(element)
01369         name  = nameref[-1]
01370     return nsuri, name
01371 
01372 def GetDocumentation(element):
01373     docnode = DOM.getElement(element, 'documentation', None, None)
01374     if docnode is not None:
01375         return DOM.getElementText(docnode)
01376     return ''
01377 
01378 def GetExtensions(element):
01379     return [ item for item in DOM.getElements(element, None, None)
01380         if item.namespaceURI != DOM.NS_WSDL ]
01381 
01382 def GetWSAActionFault(operation, name):
01383     """Find wsa:Action attribute, and return value or WSA.FAULT
01384        for the default.
01385     """
01386     attr = operation.faults[name].action
01387     if attr is not None:
01388         return attr
01389     return WSA.FAULT
01390 
01391 def GetWSAActionInput(operation):
01392     """Find wsa:Action attribute, and return value or the default."""
01393     attr = operation.input.action
01394     if attr is not None:
01395         return attr
01396     portType = operation.getPortType()
01397     targetNamespace = portType.getTargetNamespace()
01398     ptName = portType.name
01399     msgName = operation.input.name
01400     if not msgName:
01401         msgName = operation.name + 'Request'
01402     if targetNamespace.endswith('/'):
01403         return '%s%s/%s' %(targetNamespace, ptName, msgName)
01404     return '%s/%s/%s' %(targetNamespace, ptName, msgName)
01405 
01406 def GetWSAActionOutput(operation):
01407     """Find wsa:Action attribute, and return value or the default."""
01408     attr = operation.output.action
01409     if attr is not None:
01410         return attr
01411     targetNamespace = operation.getPortType().getTargetNamespace()
01412     ptName = operation.getPortType().name
01413     msgName = operation.output.name
01414     if not msgName:
01415         msgName = operation.name + 'Response'
01416     if targetNamespace.endswith('/'):
01417         return '%s%s/%s' %(targetNamespace, ptName, msgName)
01418     return '%s/%s/%s' %(targetNamespace, ptName, msgName)
01419 
01420 def FindExtensions(object, kind, t_type=type(())):
01421     if isinstance(kind, t_type):
01422         result = []
01423         namespaceURI, name = kind
01424         return [ item for item in object.extensions
01425                 if hasattr(item, 'nodeType') \
01426                 and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \
01427                 and item.name == name ]
01428     return [ item for item in object.extensions if isinstance(item, kind) ]
01429 
01430 def FindExtension(object, kind, t_type=type(())):
01431     if isinstance(kind, t_type):
01432         namespaceURI, name = kind
01433         for item in object.extensions:
01434             if hasattr(item, 'nodeType') \
01435             and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \
01436             and item.name == name:
01437                 return item
01438     else:
01439         for item in object.extensions:
01440             if isinstance(item, kind):
01441                 return item
01442     return None
01443 
01444 
01445 class SOAPCallInfo:
01446     """SOAPCallInfo captures the important binding information about a 
01447        SOAP operation, in a structure that is easier to work with than
01448        raw WSDL structures."""
01449 
01450     def __init__(self, methodName):
01451         self.methodName = methodName
01452         self.inheaders = []
01453         self.outheaders = []
01454         self.inparams = []
01455         self.outparams = []
01456         self.retval = None
01457 
01458     encodingStyle = DOM.NS_SOAP_ENC
01459     documentation = ''
01460     soapAction = None
01461     transport = None
01462     namespace = None
01463     location = None
01464     use = 'encoded'
01465     style = 'rpc'
01466 
01467     def addInParameter(self, name, type, namespace=None, element_type=0):
01468         """Add an input parameter description to the call info."""
01469         parameter = ParameterInfo(name, type, namespace, element_type)
01470         self.inparams.append(parameter)
01471         return parameter
01472 
01473     def addOutParameter(self, name, type, namespace=None, element_type=0):
01474         """Add an output parameter description to the call info."""
01475         parameter = ParameterInfo(name, type, namespace, element_type)
01476         self.outparams.append(parameter)
01477         return parameter
01478 
01479     def setReturnParameter(self, name, type, namespace=None, element_type=0):
01480         """Set the return parameter description for the call info."""
01481         parameter = ParameterInfo(name, type, namespace, element_type)
01482         self.retval = parameter
01483         return parameter
01484 
01485     def addInHeaderInfo(self, name, type, namespace, element_type=0,
01486                         mustUnderstand=0):
01487         """Add an input SOAP header description to the call info."""
01488         headerinfo = HeaderInfo(name, type, namespace, element_type)
01489         if mustUnderstand:
01490             headerinfo.mustUnderstand = 1
01491         self.inheaders.append(headerinfo)
01492         return headerinfo
01493 
01494     def addOutHeaderInfo(self, name, type, namespace, element_type=0,
01495                          mustUnderstand=0):
01496         """Add an output SOAP header description to the call info."""
01497         headerinfo = HeaderInfo(name, type, namespace, element_type)
01498         if mustUnderstand:
01499             headerinfo.mustUnderstand = 1
01500         self.outheaders.append(headerinfo)
01501         return headerinfo
01502 
01503     def getInParameters(self):
01504         """Return a sequence of the in parameters of the method."""
01505         return self.inparams
01506 
01507     def getOutParameters(self):
01508         """Return a sequence of the out parameters of the method."""
01509         return self.outparams
01510 
01511     def getReturnParameter(self):
01512         """Return param info about the return value of the method."""
01513         return self.retval
01514 
01515     def getInHeaders(self):
01516         """Return a sequence of the in headers of the method."""
01517         return self.inheaders
01518 
01519     def getOutHeaders(self):
01520         """Return a sequence of the out headers of the method."""
01521         return self.outheaders
01522 
01523 
01524 class ParameterInfo:
01525     """A ParameterInfo object captures parameter binding information."""
01526     def __init__(self, name, type, namespace=None, element_type=0):
01527         if element_type:
01528             self.element_type = 1
01529         if namespace is not None:
01530             self.namespace = namespace
01531         self.name = name
01532         self.type = type
01533 
01534     element_type = 0
01535     namespace = None
01536     default = None
01537 
01538 
01539 class HeaderInfo(ParameterInfo):
01540     """A HeaderInfo object captures SOAP header binding information."""
01541     def __init__(self, name, type, namespace, element_type=None):
01542         ParameterInfo.__init__(self, name, type, namespace, element_type)
01543 
01544     mustUnderstand = 0
01545     actor = None
01546 
01547 
01548 def callInfoFromWSDL(port, name):
01549     """Return a SOAPCallInfo given a WSDL port and operation name."""
01550     wsdl = port.getService().getWSDL()
01551     binding = port.getBinding()
01552     portType = binding.getPortType()
01553     operation = portType.operations[name]
01554     opbinding = binding.operations[name]
01555     messages = wsdl.messages
01556     callinfo = SOAPCallInfo(name)
01557 
01558     addrbinding = port.getAddressBinding()
01559     if not isinstance(addrbinding, SoapAddressBinding):
01560         raise ValueError, 'Unsupported binding type.'        
01561     callinfo.location = addrbinding.location
01562 
01563     soapbinding = binding.findBinding(SoapBinding)
01564     if soapbinding is None:
01565         raise ValueError, 'Missing soap:binding element.'
01566     callinfo.transport = soapbinding.transport
01567     callinfo.style = soapbinding.style or 'document'
01568 
01569     soap_op_binding = opbinding.findBinding(SoapOperationBinding)
01570     if soap_op_binding is not None:
01571         callinfo.soapAction = soap_op_binding.soapAction
01572         callinfo.style = soap_op_binding.style or callinfo.style
01573 
01574     parameterOrder = operation.parameterOrder
01575 
01576     if operation.input is not None:
01577         message = messages[operation.input.message]
01578         msgrole = opbinding.input
01579 
01580         mime = msgrole.findBinding(MimeMultipartRelatedBinding)
01581         if mime is not None:
01582             raise ValueError, 'Mime bindings are not supported.'
01583         else:
01584             for item in msgrole.findBindings(SoapHeaderBinding):
01585                 part = messages[item.message].parts[item.part]
01586                 header = callinfo.addInHeaderInfo(
01587                     part.name,
01588                     part.element or part.type,
01589                     item.namespace,
01590                     element_type = part.element and 1 or 0
01591                     )
01592                 header.encodingStyle = item.encodingStyle
01593 
01594             body = msgrole.findBinding(SoapBodyBinding)
01595             if body is None:
01596                 raise ValueError, 'Missing soap:body binding.'
01597             callinfo.encodingStyle = body.encodingStyle
01598             callinfo.namespace = body.namespace
01599             callinfo.use = body.use
01600 
01601             if body.parts is not None:
01602                 parts = []
01603                 for name in body.parts:
01604                     parts.append(message.parts[name])
01605             else:
01606                 parts = message.parts.values()
01607 
01608             for part in parts:
01609                 callinfo.addInParameter(
01610                     part.name,
01611                     part.element or part.type,
01612                     element_type = part.element and 1 or 0
01613                     )
01614 
01615     if operation.output is not None:
01616         try:
01617             message = messages[operation.output.message]
01618         except KeyError:
01619             if self.strict:
01620                 raise RuntimeError(
01621                     "Recieved message not defined in the WSDL schema: %s" %
01622                     operation.output.message)
01623             else:
01624                 message = wsdl.addMessage(operation.output.message)
01625                 print "Warning:", \
01626                       "Recieved message not defined in the WSDL schema.", \
01627                       "Adding it."
01628                 print "Message:", operation.output.message
01629          
01630         msgrole = opbinding.output
01631 
01632         mime = msgrole.findBinding(MimeMultipartRelatedBinding)
01633         if mime is not None:
01634             raise ValueError, 'Mime bindings are not supported.'
01635         else:
01636             for item in msgrole.findBindings(SoapHeaderBinding):
01637                 part = messages[item.message].parts[item.part]
01638                 header = callinfo.addOutHeaderInfo(
01639                     part.name,
01640                     part.element or part.type,
01641                     item.namespace,
01642                     element_type = part.element and 1 or 0
01643                     )
01644                 header.encodingStyle = item.encodingStyle
01645 
01646             body = msgrole.findBinding(SoapBodyBinding)
01647             if body is None:
01648                 raise ValueError, 'Missing soap:body binding.'
01649             callinfo.encodingStyle = body.encodingStyle
01650             callinfo.namespace = body.namespace
01651             callinfo.use = body.use
01652 
01653             if body.parts is not None:
01654                 parts = []
01655                 for name in body.parts:
01656                     parts.append(message.parts[name])
01657             else:
01658                 parts = message.parts.values()
01659 
01660             if parts:
01661                 for part in parts:
01662                     callinfo.addOutParameter(
01663                         part.name,
01664                         part.element or part.type,
01665                         element_type = part.element and 1 or 0
01666                         )
01667 
01668     return callinfo

Generated on Wed Oct 20 2010 11:12:16 for APBS by  doxygen 1.7.2