def __init__(self, targetNamespace=None, strict=1):
     self.targetNamespace = targetNamespace or 'urn:this-document.wsdl'
     self.documentation = ''
     self.location = None
     self.document = None
     self.name = None
     self.services = CollectionNS(self)
     self.messages = CollectionNS(self)
     self.portTypes = CollectionNS(self)
     self.bindings = CollectionNS(self)
     #self.imports = Collection(self)
     self.types = Types(self)
     self.extensions = []
     self.strict = strict
 def __init__(self, targetNamespace=None, strict=1):
     self.targetNamespace = targetNamespace or 'urn:this-document.wsdl'
     self.documentation = ''
     self.location = None
     self.document = None
     self.name = None
     self.services = CollectionNS(self)
     self.messages = CollectionNS(self)
     self.portTypes = CollectionNS(self)
     self.bindings = CollectionNS(self)
     #self.imports = Collection(self)
     self.types = Types(self)
     self.extensions = []
     self.strict = strict
class WSDL:
    """A WSDL object models a WSDL service description. WSDL objects
       may be created manually or loaded from an xml representation
       using a WSDLReader instance."""

    def __init__(self, targetNamespace=None, strict=1):
        self.targetNamespace = targetNamespace or 'urn:this-document.wsdl'
        self.documentation = ''
        self.location = None
        self.document = None
        self.name = None
        self.services = CollectionNS(self)
        self.messages = CollectionNS(self)
        self.portTypes = CollectionNS(self)
        self.bindings = CollectionNS(self)
        #self.imports = Collection(self)
        self.types = Types(self)
        self.extensions = []
        self.strict = strict

    def __del__(self):
        if self.document is not None:
            self.document.unlink()

    version = '1.1'

    def addService(self, name, documentation='', targetNamespace=None):
        if self.services.has_key(name):
            raise WSDLError(
                'Duplicate service element: %s' % name
                )
        item = Service(name, documentation)
        if targetNamespace:
            item.targetNamespace = targetNamespace
        self.services[name] = item
        return item

    def addMessage(self, name, documentation='', targetNamespace=None):
        if self.messages.has_key(name):
            raise WSDLError(
                'Duplicate message element: %s.' % name
                )
        item = Message(name, documentation)
        if targetNamespace:
            item.targetNamespace = targetNamespace
        self.messages[name] = item
        return item

    def addPortType(self, name, documentation='', targetNamespace=None):
        if self.portTypes.has_key(name):
            raise WSDLError(
                'Duplicate portType element: name'
                )
        item = PortType(name, documentation)
        if targetNamespace:
            item.targetNamespace = targetNamespace
        self.portTypes[name] = item
        return item

    def addBinding(self, name, type, documentation='', targetNamespace=None):
        if self.bindings.has_key(name):
            raise WSDLError(
                'Duplicate binding element: %s' % name
                )
        item = Binding(name, type, documentation)
        if targetNamespace:
            item.targetNamespace = targetNamespace
        self.bindings[name] = item
        return item

    #def addImport(self, namespace, location):
    #    item = ImportElement(namespace, location)
    #    self.imports[namespace] = item
    #    return item

    def load(self, document):
        # We save a reference to the DOM document to ensure that elements
        # saved as "extensions" will continue to have a meaningful context
        # for things like namespace references. The lifetime of the DOM
        # document is bound to the lifetime of the WSDL instance.
        self.document = document

        definitions = DOM.getElement(document, 'definitions', None, None)
        if definitions is None:
            raise WSDLError(
                'Missing <definitions> element.'
                )
        self.version = DOM.WSDLUriToVersion(definitions.namespaceURI)
        NS_WSDL = DOM.GetWSDLUri(self.version)

        self.targetNamespace = DOM.getAttr(definitions, 'targetNamespace',
                                           None, None)
        self.name = DOM.getAttr(definitions, 'name', None, None)
        self.documentation = GetDocumentation(definitions)

        # Resolve (recursively) any import elements in the document.
        imported = {}
        base_location = self.location
        while 1:
            #XXX
            imports = []
            for element in DOM.getElements(definitions, 'import', NS_WSDL):
                location = DOM.getAttr(element, 'location')
                # Resolve relative location, and save
                location = urllib.basejoin(base_location, location)

                if not imported.has_key(location):
                    imports.append(element)

            if not imports:
                break
            for element in imports:
                location = DOM.getAttr(element, 'location')
                self._import(document, element, base_location)
                location = urllib.basejoin(base_location, location)
                imported[location] = 1
            base_location = ''

        #reader = SchemaReader(base_url=self.location)
        for element in DOM.getElements(definitions, None, None):
            targetNamespace = DOM.getAttr(element, 'targetNamespace')
            localName = element.localName

            if not DOM.nsUriMatch(element.namespaceURI, NS_WSDL):
                if localName == 'schema':
                    reader = SchemaReader(base_url=self.location)
                    schema = reader.loadFromNode(WSDLToolsAdapter(self), element)
                    schema.setBaseUrl(self.location)
                    self.types.addSchema(schema)
                else:
                    self.extensions.append(element)
                continue

            elif localName == 'message':
                name = DOM.getAttr(element, 'name')
                docs = GetDocumentation(element)
                message = self.addMessage(name, docs, targetNamespace)
                parts = DOM.getElements(element, 'part', NS_WSDL)
                message.load(parts)
                continue

            elif localName == 'portType':
                name = DOM.getAttr(element, 'name')
                docs = GetDocumentation(element)
                ptype = self.addPortType(name, docs, targetNamespace)
                #operations = DOM.getElements(element, 'operation', NS_WSDL)
                #ptype.load(operations)
                ptype.load(element)
                continue

            elif localName == 'binding':
                name = DOM.getAttr(element, 'name')
                type = DOM.getAttr(element, 'type', default=None)
                if type is None:
                    raise WSDLError(
                        'Missing type attribute for binding %s.' % name
                        )
                type = ParseQName(type, element)
                docs = GetDocumentation(element)
                binding = self.addBinding(name, type, docs, targetNamespace)
                operations = DOM.getElements(element, 'operation', NS_WSDL)
                binding.load(operations)
                binding.load_ex(GetExtensions(element))
                continue

            elif localName == 'service':
                name = DOM.getAttr(element, 'name')
                docs = GetDocumentation(element)
                service = self.addService(name, docs, targetNamespace)
                ports = DOM.getElements(element, 'port', NS_WSDL)
                service.load(ports)
                service.load_ex(GetExtensions(element))
                continue

            elif localName == 'types':
                self.types.documentation = GetDocumentation(element)
                base_location = DOM.getAttr(element, 'base-location')
                if base_location:
                    element.removeAttribute('base-location')
                base_location = base_location or self.location
                reader = SchemaReader(base_url=base_location)
                for item in DOM.getElements(element, None, None):
                    if item.localName == 'schema':
                        schema = reader.loadFromNode(WSDLToolsAdapter(self), item)
                        # XXX <types> could have been imported
                        #schema.setBaseUrl(self.location)
                        schema.setBaseUrl(base_location)
                        self.types.addSchema(schema)
                    else:
                        self.types.addExtension(item)
                # XXX remove the attribute
                # element.removeAttribute('base-location')
                continue

    def _import(self, document, element, base_location=None):
        '''Algo take <import> element's children, clone them,
        and add them to the main document.  Support for relative 
        locations is a bit complicated.  The orig document context
        is lost, so we need to store base location in DOM elements
        representing <types>, by creating a special temporary 
        "base-location" attribute,  and <import>, by resolving
        the relative "location" and storing it as "location".
        
        document -- document we are loading
        element -- DOM Element representing <import> 
        base_location -- location of document from which this
            <import> was gleaned.
        '''
        namespace = DOM.getAttr(element, 'namespace', default=None)
        location = DOM.getAttr(element, 'location', default=None)
        if namespace is None or location is None:
            raise WSDLError(
                'Invalid import element (missing namespace or location).'
                )
        if base_location:
            location = urllib.basejoin(base_location, location)
            element.setAttributeNS(None, 'location', location)

        #location = urllib.basejoin(self.location, location)
        #obimport = self.addImport(namespace, location)
        #obimport._loaded = 1

        importdoc = DOM.loadFromURL(location)
        try:
            if location.find('#') > -1:
                idref = location.split('#')[-1]
                imported = DOM.getElementById(importdoc, idref)
            else:
                imported = importdoc.documentElement
            if imported is None:
                raise WSDLError(
                    'Import target element not found for: %s' % location
                    )

            imported_tns = DOM.findTargetNS(imported)
            if imported_tns != namespace:
                return

            if imported.localName == 'definitions':
                imported_nodes = imported.childNodes
            else:
                imported_nodes = [imported]
            parent = element.parentNode
            for node in imported_nodes:
                if node.nodeType != node.ELEMENT_NODE:
                    continue
                child = DOM.importNode(document, node, 1)
                parent.appendChild(child)
                child.setAttribute('targetNamespace', namespace)
                attrsNS = imported._attrsNS
                for attrkey in attrsNS.keys():
                    if attrkey[0] == DOM.NS_XMLNS:
                        attr = attrsNS[attrkey].cloneNode(1)
                        child.setAttributeNode(attr)

                #XXX Quick Hack, should be in WSDL Namespace.
                if child.localName == 'import':
                    rlocation = child.getAttributeNS(None, 'location')
                    alocation = urllib.basejoin(location, rlocation)
                    child.setAttribute('location', alocation)
                elif child.localName == 'types':
                    child.setAttribute('base-location', location)

        finally:
            importdoc.unlink()
        return location
class WSDL:
    """A WSDL object models a WSDL service description. WSDL objects
       may be created manually or loaded from an xml representation
       using a WSDLReader instance."""
    def __init__(self, targetNamespace=None, strict=1):
        self.targetNamespace = targetNamespace or 'urn:this-document.wsdl'
        self.documentation = ''
        self.location = None
        self.document = None
        self.name = None
        self.services = CollectionNS(self)
        self.messages = CollectionNS(self)
        self.portTypes = CollectionNS(self)
        self.bindings = CollectionNS(self)
        #self.imports = Collection(self)
        self.types = Types(self)
        self.extensions = []
        self.strict = strict

    def __del__(self):
        if self.document is not None:
            self.document.unlink()

    version = '1.1'

    def addService(self, name, documentation='', targetNamespace=None):
        if self.services.has_key(name):
            raise WSDLError('Duplicate service element: %s' % name)
        item = Service(name, documentation)
        if targetNamespace:
            item.targetNamespace = targetNamespace
        self.services[name] = item
        return item

    def addMessage(self, name, documentation='', targetNamespace=None):
        if self.messages.has_key(name):
            raise WSDLError('Duplicate message element: %s.' % name)
        item = Message(name, documentation)
        if targetNamespace:
            item.targetNamespace = targetNamespace
        self.messages[name] = item
        return item

    def addPortType(self, name, documentation='', targetNamespace=None):
        if self.portTypes.has_key(name):
            raise WSDLError('Duplicate portType element: name')
        item = PortType(name, documentation)
        if targetNamespace:
            item.targetNamespace = targetNamespace
        self.portTypes[name] = item
        return item

    def addBinding(self, name, type, documentation='', targetNamespace=None):
        if self.bindings.has_key(name):
            raise WSDLError('Duplicate binding element: %s' % name)
        item = Binding(name, type, documentation)
        if targetNamespace:
            item.targetNamespace = targetNamespace
        self.bindings[name] = item
        return item

    #def addImport(self, namespace, location):
    #    item = ImportElement(namespace, location)
    #    self.imports[namespace] = item
    #    return item

    def load(self, document):
        # We save a reference to the DOM document to ensure that elements
        # saved as "extensions" will continue to have a meaningful context
        # for things like namespace references. The lifetime of the DOM
        # document is bound to the lifetime of the WSDL instance.
        self.document = document

        definitions = DOM.getElement(document, 'definitions', None, None)
        if definitions is None:
            raise WSDLError('Missing <definitions> element.')
        self.version = DOM.WSDLUriToVersion(definitions.namespaceURI)
        NS_WSDL = DOM.GetWSDLUri(self.version)

        self.targetNamespace = DOM.getAttr(definitions, 'targetNamespace',
                                           None, None)
        self.name = DOM.getAttr(definitions, 'name', None, None)
        self.documentation = GetDocumentation(definitions)

        # Resolve (recursively) any import elements in the document.
        imported = {}
        base_location = self.location
        while 1:
            #XXX
            imports = []
            for element in DOM.getElements(definitions, 'import', NS_WSDL):
                location = DOM.getAttr(element, 'location')
                # Resolve relative location, and save
                location = urllib.basejoin(base_location, location)

                if not imported.has_key(location):
                    imports.append(element)

            if not imports:
                break
            for element in imports:
                location = DOM.getAttr(element, 'location')
                self._import(document, element, base_location)
                location = urllib.basejoin(base_location, location)
                imported[location] = 1
            base_location = ''

        #reader = SchemaReader(base_url=self.location)
        for element in DOM.getElements(definitions, None, None):
            targetNamespace = DOM.getAttr(element, 'targetNamespace')
            localName = element.localName

            if not DOM.nsUriMatch(element.namespaceURI, NS_WSDL):
                if localName == 'schema':
                    reader = SchemaReader(base_url=self.location)
                    schema = reader.loadFromNode(WSDLToolsAdapter(self),
                                                 element)
                    schema.setBaseUrl(self.location)
                    self.types.addSchema(schema)
                else:
                    self.extensions.append(element)
                continue

            elif localName == 'message':
                name = DOM.getAttr(element, 'name')
                docs = GetDocumentation(element)
                message = self.addMessage(name, docs, targetNamespace)
                parts = DOM.getElements(element, 'part', NS_WSDL)
                message.load(parts)
                continue

            elif localName == 'portType':
                name = DOM.getAttr(element, 'name')
                docs = GetDocumentation(element)
                ptype = self.addPortType(name, docs, targetNamespace)
                #operations = DOM.getElements(element, 'operation', NS_WSDL)
                #ptype.load(operations)
                ptype.load(element)
                continue

            elif localName == 'binding':
                name = DOM.getAttr(element, 'name')
                type = DOM.getAttr(element, 'type', default=None)
                if type is None:
                    raise WSDLError('Missing type attribute for binding %s.' %
                                    name)
                type = ParseQName(type, element)
                docs = GetDocumentation(element)
                binding = self.addBinding(name, type, docs, targetNamespace)
                operations = DOM.getElements(element, 'operation', NS_WSDL)
                binding.load(operations)
                binding.load_ex(GetExtensions(element))
                continue

            elif localName == 'service':
                name = DOM.getAttr(element, 'name')
                docs = GetDocumentation(element)
                service = self.addService(name, docs, targetNamespace)
                ports = DOM.getElements(element, 'port', NS_WSDL)
                service.load(ports)
                service.load_ex(GetExtensions(element))
                continue

            elif localName == 'types':
                self.types.documentation = GetDocumentation(element)
                base_location = DOM.getAttr(element, 'base-location')
                if base_location:
                    element.removeAttribute('base-location')
                base_location = base_location or self.location
                reader = SchemaReader(base_url=base_location)
                for item in DOM.getElements(element, None, None):
                    if item.localName == 'schema':
                        schema = reader.loadFromNode(WSDLToolsAdapter(self),
                                                     item)
                        # XXX <types> could have been imported
                        #schema.setBaseUrl(self.location)
                        schema.setBaseUrl(base_location)
                        self.types.addSchema(schema)
                    else:
                        self.types.addExtension(item)
                # XXX remove the attribute
                # element.removeAttribute('base-location')
                continue

    def _import(self, document, element, base_location=None):
        '''Algo take <import> element's children, clone them,
        and add them to the main document.  Support for relative 
        locations is a bit complicated.  The orig document context
        is lost, so we need to store base location in DOM elements
        representing <types>, by creating a special temporary 
        "base-location" attribute,  and <import>, by resolving
        the relative "location" and storing it as "location".
        
        document -- document we are loading
        element -- DOM Element representing <import> 
        base_location -- location of document from which this
            <import> was gleaned.
        '''
        namespace = DOM.getAttr(element, 'namespace', default=None)
        location = DOM.getAttr(element, 'location', default=None)
        if namespace is None or location is None:
            raise WSDLError(
                'Invalid import element (missing namespace or location).')
        if base_location:
            location = urllib.basejoin(base_location, location)
            element.setAttributeNS(None, 'location', location)

        #location = urllib.basejoin(self.location, location)
        #obimport = self.addImport(namespace, location)
        #obimport._loaded = 1

        importdoc = DOM.loadFromURL(location)
        try:
            if location.find('#') > -1:
                idref = location.split('#')[-1]
                imported = DOM.getElementById(importdoc, idref)
            else:
                imported = importdoc.documentElement
            if imported is None:
                raise WSDLError('Import target element not found for: %s' %
                                location)

            imported_tns = DOM.findTargetNS(imported)
            if imported_tns != namespace:
                return

            if imported.localName == 'definitions':
                imported_nodes = imported.childNodes
            else:
                imported_nodes = [imported]
            parent = element.parentNode
            for node in imported_nodes:
                if node.nodeType != node.ELEMENT_NODE:
                    continue
                child = DOM.importNode(document, node, 1)
                parent.appendChild(child)
                child.setAttribute('targetNamespace', namespace)
                attrsNS = imported._attrsNS
                for attrkey in attrsNS.keys():
                    if attrkey[0] == DOM.NS_XMLNS:
                        attr = attrsNS[attrkey].cloneNode(1)
                        child.setAttributeNode(attr)

                #XXX Quick Hack, should be in WSDL Namespace.
                if child.localName == 'import':
                    rlocation = child.getAttributeNS(None, 'location')
                    alocation = urllib.basejoin(location, rlocation)
                    child.setAttribute('location', alocation)
                elif child.localName == 'types':
                    child.setAttribute('base-location', location)

        finally:
            importdoc.unlink()
        return location