def handleLayer(self, ns, layerEl, nodes, endpoint, parentId, commonData, antecedentKeywordData, idMap):
        """Processes a layer.
        Determines whether the layer has sublayers, in which case this method is called recursively,
        or if it is a leaf, in which case a node is added to the node list.
        """
        subLayers = xml_util.getChildrenByNameNS(layerEl, ns, 'Layer')
        isLeaf = len(subLayers) == 0
        layer = WmsLayer()
        layer.populateFromLayerElement(ns, layerEl, commonData)
        log.debug("Layer %s %s" % (layer.name, layer.title))

        self.setLayerId(layer, parentId, isLeaf)

        # Merge all keyword data applicable to the layer.
        keywordData = self.getLayerDataFromEndpoint(endpoint, layer)
        if antecedentKeywordData:
            mergedKeywordData = antecedentKeywordData.copy()
            mergedKeywordData.update(keywordData)
        else:
            mergedKeywordData = keywordData

        log.debug("keywordData: %s" % mergedKeywordData)
        layer.generateDimensionDisplayValues(mergedKeywordData.get('dimension_format', None),
                                             mergedKeywordData.get('dimension_reverse', None))

        treeInfo = self.makeTreeInfo(endpoint, layer, isLeaf, keywordData)


        # Look for sublayers - if there any any, call this method recursively to add them to the tree,
        # otherwise just add a leaf node.
        children = []
        node = Node(layer.id, layer, children, treeInfo, keywordData)
        #idMap[layer.id] = node
        nodes.append(node)
        if isLeaf:
            log.debug("Found layer: title '%s' (ID=%s)", layer.title, layer.id)
        else:
            for lyr in subLayers:
                self.handleLayer(ns, lyr, children, endpoint, layer.id, commonData, antecedentKeywordData, idMap)
    def getLayers(self, endpoint, parentId, idMap, keywordData, forceRefresh):
        """Returns a list of 'endpoint_hierarchy_builder.Node's for the layers of an endpoint in a WMC document.
        Also, adds nodes to a map from node ID to node.
        """
        log.debug("getLayers called for %s", endpoint['wmsurl'])
        log.debug("  keywordData: %s" % keywordData)
        wmsUrl = self.makeProxiedUrl(endpoint['wmsurl'])
        wmcDoc = self.wmsCapabilityCache.getWmsCapabilities(wmsUrl, True)

        dom = xml.dom.minidom.parseString(wmcDoc)
        # Get the namespace URI for the document root element.
        ns = dom.documentElement.namespaceURI

        # Get the version the WMS server responded with.
        wmsVersion = dom.documentElement.getAttribute('version')

        nodes = []
        capability = xml_util.getSingleChildByNameNS(dom.documentElement, ns, 'Capability')
        if capability == None:
            return None

        getCapabilitiesUrlEl = xml_util.getSingleChildByPathNS(capability,
                                                               [(ns, 'Request'), (ns, 'GetCapabilities'), (ns, 'DCPType'),
                                                                (ns, 'HTTP'), (ns, 'Get'), (ns, 'OnlineResource')])
        getCapabilitiesUrl = getCapabilitiesUrlEl.getAttributeNS(XLINK_URI, 'href')
        if not getCapabilitiesUrl:
            getCapabilitiesUrl = xml_util.getAttributeByLocalName(getCapabilitiesUrlEl, 'href')
        log.debug("GetCapabilities URL: %s", getCapabilitiesUrl)
        getCapabilitiesUrl = parseEndpointString(getCapabilitiesUrl, {'REQUEST':'GetCapabilities', 'SERVICE':'WMS'})

        getFeatureInfoOnlineResourceEl = xml_util.getSingleChildByPathNS(capability,
                                                                         [(ns, 'Request'), (ns, 'GetFeatureInfo'),
                                                                          (ns, 'DCPType'), (ns, 'HTTP'),
                                                                          (ns, 'Get'), (ns, 'OnlineResource')])
        if getFeatureInfoOnlineResourceEl:
            getFeatureInfoUrl = getFeatureInfoOnlineResourceEl.getAttributeNS(XLINK_URI, 'href')
            if not getFeatureInfoUrl:
                getFeatureInfoUrl = xml_util.getAttributeByLocalName(getFeatureInfoOnlineResourceEl, 'href')
            log.debug("GetFeatureInfo URL: %s", getFeatureInfoUrl)
            getFeatureInfoUrl = getFeatureInfoUrl.rstrip('?&')
        else:
            getFeatureInfoUrl = None

        getMapOnlineResourceEl = xml_util.getSingleChildByPathNS(capability,
                                                               [(ns, 'Request'), (ns, 'GetMap'), (ns, 'DCPType'), (ns, 'HTTP'),
                                                                (ns, 'Get'), (ns, 'OnlineResource')])
        getMapUrl = getMapOnlineResourceEl.getAttributeNS(XLINK_URI, 'href')
        if not getMapUrl:
            getMapUrl = xml_util.getAttributeByLocalName(getMapOnlineResourceEl, 'href')
        log.debug("GetMap URL: %s", getMapUrl)
        getMapUrl = getMapUrl.rstrip('?&')
        getMapUrl = self.makeProxiedUrl(getMapUrl)

        commonData = {
            'getCapabilitiesUrl': getCapabilitiesUrl,
            'getFeatureInfoUrl': getFeatureInfoUrl,
            'getMapUrl': getMapUrl,
            'wmsVersion': wmsVersion
            }
        if 'wcsurl' in endpoint:
            commonData['getCoverageUrl'] = endpoint['wcsurl']
        for layer in xml_util.getChildrenByNameNS(capability, ns, 'Layer'):
            self.handleLayer(ns, layer, nodes, endpoint, parentId, commonData, keywordData, idMap)

        # Break internal references to facilitate garbage collection.
        dom.unlink()

        return nodes
Exemple #3
0
    def populateFromLayerElement(self, ns, layerEl, commonData):
        """Populates a WmsLayer instance from a WMS capabilities Layer element
        @param ns: namespace in capabilities document
        @param layerEl: Layer element
        @param commonData: dict of capabilities data that is not specific to the layer
        """
        self.title = xml_util.getSingleChildTextByNameNS(layerEl, ns, 'Title')
        self.name = xml_util.getSingleChildTextByNameNS(layerEl, ns, 'Name')
        self.abstract = xml_util.getSingleChildTextByNameNS(layerEl, ns, 'Abstract')
        self.getMapUrl = commonData['getMapUrl']
        self.getCapabilitiesUrl = commonData['getCapabilitiesUrl']
        self.getFeatureInfoUrl = commonData['getFeatureInfoUrl']
        self.wmsVersion = commonData['wmsVersion']
        self.getCoverageUrl = commonData['getCoverageUrl']

        # Parse Dimension element into attributes and list of values.
        # First look for pre-WMS 1.3.0 Extent elements.
        extents = {}
        for extentEl in xml_util.getChildrenByNameNS(layerEl, ns, 'Extent'):
            name = extentEl.getAttribute('name')
            extentData = extentEl.firstChild
            if extentData != None:
                extentStr = extentEl.firstChild.data.strip()
                extentValues = extentStr.split(',')
                extents[name] = extentValues

        # Find the Dimension elements.
        self.dimensions = []
        for dimensionEl in xml_util.getChildrenByNameNS(layerEl, ns, 'Dimension'):
            name = dimensionEl.getAttribute('name')
            units = dimensionEl.getAttribute('units')
            unitSymbol = dimensionEl.getAttribute('unitSymbol')
            default = dimensionEl.getAttribute('default')
            dimensionData = dimensionEl.firstChild
            if dimensionData != None:
                dimensionStr = dimensionEl.firstChild.data.strip()
                dimensionValues = dimensionStr.split(',')
            elif name in extents:
                dimensionValues = extents[name]
            else:
                dimensionValues = None
            if dimensionValues:
                dimension = {
                    'name': name,
                    'units': units,
                    'unitSymbol': unitSymbol,
                    'default': default,
                    'dimensionValues': dimensionValues
                    }
                self.dimensions.append(dimension)

        # Parse Style element into list of values.
        self.styles = []
        for styleEl in xml_util.getChildrenByNameNS(layerEl, ns, 'Style'):
            name = xml_util.getSingleChildTextByNameNS(styleEl, ns, 'Name')
            title = xml_util.getSingleChildTextByNameNS(styleEl, ns, 'Title')
            style = {
                'name': name,
                'title': title,
                }
            legendUrlEl = xml_util.getSingleChildByNameNS(styleEl, ns, 'LegendURL')
            if legendUrlEl != None:
                width = legendUrlEl.getAttribute('width')
                height = legendUrlEl.getAttribute('height')
                onlineResourceEl = xml_util.getSingleChildByNameNS(legendUrlEl, ns, 'OnlineResource')
                legendURL = onlineResourceEl.getAttributeNS(XLINK_URI, 'href')

                style['legendURL'] = {
                    'width': width,
                    'height': height,
                    'onlineResource': legendURL
                    }
            self.styles.append(style)

        self.getDisplayOptionsUrl = None
        for metadataUrlEl in xml_util.getChildrenByNameNS(layerEl, ns, 'MetadataURL'):
            metadataUrlType = metadataUrlEl.getAttribute('type')
            if metadataUrlType and (metadataUrlType == 'display_options') :
                if xml_util.getSingleChildTextByNameNS(metadataUrlEl, ns, 'Format') == 'application/json':
                    onlineResourceEl = xml_util.getSingleChildByNameNS(metadataUrlEl, ns, 'OnlineResource')
                    if onlineResourceEl:
                        self.getDisplayOptionsUrl = onlineResourceEl.getAttributeNS(XLINK_URI, 'href')