[GRASS-SVN] r54368 - grass-addons/grass7/raster/r.in.wms2

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Dec 22 15:27:15 PST 2012


Author: turek
Date: 2012-12-22 15:27:15 -0800 (Sat, 22 Dec 2012)
New Revision: 54368

Modified:
   grass-addons/grass7/raster/r.in.wms2/r.in.wms2.py
   grass-addons/grass7/raster/r.in.wms2/wms_base.py
   grass-addons/grass7/raster/r.in.wms2/wms_cap_parsers.py
   grass-addons/grass7/raster/r.in.wms2/wms_drv.py
Log:
r.in.wms2: improved wms capabilities check, other minor improvements

Modified: grass-addons/grass7/raster/r.in.wms2/r.in.wms2.py
===================================================================
--- grass-addons/grass7/raster/r.in.wms2/r.in.wms2.py	2012-12-22 15:38:11 UTC (rev 54367)
+++ grass-addons/grass7/raster/r.in.wms2/r.in.wms2.py	2012-12-22 23:27:15 UTC (rev 54368)
@@ -154,14 +154,14 @@
 #%end
 
 #%option G_OPT_F_INPUT
-#% key: cfile
+#% key: capfile
 #% required: no
 #% gisprompt: old,file,bin_input
 #% description: Capabilities file 
 #%end
 
 #%option G_OPT_F_OUTPUT
-#% key: csfile
+#% key: capfile_output
 #% required: no
 #% gisprompt: old,file,bin_input
 #% description: File where capabilities will be saved (only with 'c' flag).

Modified: grass-addons/grass7/raster/r.in.wms2/wms_base.py
===================================================================
--- grass-addons/grass7/raster/r.in.wms2/wms_base.py	2012-12-22 15:38:11 UTC (rev 54367)
+++ grass-addons/grass7/raster/r.in.wms2/wms_base.py	2012-12-22 23:27:15 UTC (rev 54368)
@@ -5,21 +5,20 @@
  - wms_base::WMSBase
  - wms_base::GRASSImporter
  - wms_base::WMSDriversInfo
- 
+
 (C) 2012 by the GRASS Development Team
 
 This program is free software under the GNU General Public License
 (>=v2). Read the file COPYING that comes with GRASS for details.
 
- at TODO use username and password for getting capabilities
-
 @author Stepan Turek <stepan.turek seznam.cz> (Mentor: Martin Landa)
 """
 
 import os
 from   math import ceil
 
-from urllib2 import urlopen, HTTPError, URLError
+import base64
+import urllib2
 from httplib import HTTPException
 
 import grass.script as grass
@@ -57,7 +56,7 @@
         driver_props = drv_info.GetDrvProperties(options['driver'])
         self._checkIgnoeredParams(options, flags, driver_props)
 
-        self.params['cfile'] = options['cfile'].strip()
+        self.params['capfile'] = options['capfile'].strip()
 
         for key in ['url', 'layers', 'styles', 'method']:
             self.params[key] = options[key].strip()
@@ -164,8 +163,7 @@
                             (','.join(not_relevant_flags), options['driver'])))
 
     def GetMap(self, options, flags):
-        """!Download data from WMS server and import data
-        (using GDAL library) into GRASS as a raster map."""
+        """!Download data from WMS server."""
 
         self._initializeParameters(options, flags)  
 
@@ -183,7 +181,7 @@
     def _fetchCapabilities(self, options): 
         """!Download capabilities from WMS server
         """
-        # download capabilities file
+        grass.debug('Fetching capabilities file.')
         cap_url = options['url']
 
         if 'WMTS' in options['driver']:
@@ -194,22 +192,34 @@
             cap_url += "?SERVICE=WMS&REQUEST=GetCapabilities&VERSION=" + options['wms_version'] 
             
         try:
-            cap = urlopen(cap_url)
-        except (IOError, HTTPError, HTTPException):
-            grass.fatal(_("Unable to get capabilities from '%s'") % options['url'])
+            cap = self._fetchDataFromServer(cap_url, options['username'], options['password'])
+        except (IOError, HTTPException), e:
+            if urllib2.HTTPError == type(e) and e.code == 401:
+                grass.fatal(_("Authorization failed to '%s' when fetching capabilities.") % options['url'])
+            else:
+                grass.fatal(_("Unable to fetch capabilities from: '%s'") % options['url'])
         
         return cap
 
+    def _fetchDataFromServer(self, url, username = None, password = None):
+        """!Fetch data from server
+        """      
+        request = urllib2.Request(url)
+        if username and password:
+                    base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
+                    request.add_header("Authorization", "Basic %s" % base64string)
+        return urllib2.urlopen(request)
+
     def GetCapabilities(self, options): 
         """!Get capabilities from WMS server
         """
         cap  = self._fetchCapabilities(options)
-        csfile = options['csfile'].strip()
+        capfile_output = options['capfile_output'].strip()
 
         # save to file
-        if csfile:
+        if capfile_output:
             try:
-                temp = open(csfile, "w")
+                temp = open(capfile_output, "w")
                 temp.write(cap.read())
                 temp.close()
                 return
@@ -505,7 +515,7 @@
 
         props = {}
         props['ignored_flags'] = ['o']
-        props['ignored_params'] = ['bgcolor', 'styles', 'csfile', 
+        props['ignored_params'] = ['bgcolor', 'styles', 'capfile_output', 
                                    'format', 'srs', 'wms_version']
         props['req_multiple_layers'] = False
 
@@ -514,7 +524,7 @@
     def _WMSProperties(self):
 
         props = {}
-        props['ignored_params'] = ['cfile']
+        props['ignored_params'] = ['capfile']
         props['ignored_flags'] = []
         props['req_multiple_layers'] = True
 
@@ -533,7 +543,7 @@
 
         props = {}
         props['ignored_flags'] = []
-        props['ignored_params'] = ['urlparams', 'bgcolor', 'cfile', 'csfile',
+        props['ignored_params'] = ['urlparams', 'bgcolor', 'capfile', 'capfile_output',
                                     'username', 'password']
         props['req_multiple_layers'] = True
 

Modified: grass-addons/grass7/raster/r.in.wms2/wms_cap_parsers.py
===================================================================
--- grass-addons/grass7/raster/r.in.wms2/wms_cap_parsers.py	2012-12-22 15:38:11 UTC (rev 54367)
+++ grass-addons/grass7/raster/r.in.wms2/wms_cap_parsers.py	2012-12-22 23:27:15 UTC (rev 54368)
@@ -1,5 +1,5 @@
 """!
- at brief Parsers for WMS capabilities files.
+ at brief Parsers for WMS/WMTS/NASA OnEarth capabilities files.
 
 List of classes:
  - wms_cap_parsers::BaseCapabilitiesTree
@@ -22,7 +22,7 @@
 
 class BaseCapabilitiesTree(etree.ElementTree):
     def __init__(self, cap_file):
-        """!Initializes xml.etree.ElementTree
+        """!Initialize xml.etree.ElementTree
         """
         try:
             etree.ElementTree.__init__(self, file = cap_file)
@@ -94,14 +94,14 @@
         self._checkFormats(capability)
         self._checkLayerTree(root_layer)
 
-        grass.debug('Checking of WMS capabilities tree was finished.', 4)
+        grass.debug('Check of WMS capabilities tree was finished.', 4)
 
     def _checkFormats(self, capability):
         """!Check if format element is defined.
         """        
         request = self._find(capability, "Request")
         get_map = self._find(request, "GetMap")
-        self._find(get_map, "Format")
+        formats = self._findall(get_map, "Format")
  
     def _checkLayerTree(self, parent_layer, first = True):
         """!Recursively check layer tree and manage inheritance in the tree
@@ -145,7 +145,7 @@
             self._inhNotSame(self.proj_tag, "element_content", layer, parent_layer)
             self._inhNotSame("BoundingBox", "attribute", layer, parent_layer, self.proj_tag)
 
-            #remove invalid Styles 
+            # remove invalid Styles 
             styles = layer.findall(self.xml_ns.Ns('Style'))
             for s in styles:
                 s_name = s.find(self.xml_ns.Ns('Name'))
@@ -160,9 +160,9 @@
         """Inherit elements which have unique values.
 
         @param element_name - name of inherited element
-        @param cmp_type - 'element_content' - the value is text of <Layer> element
-        @param cmp_type - 'child_element_content' - the value is text of a child of the <Layer> element
-        @param cmp_type - 'attribute' - the value is text of the <Layer> element attribute
+        @param cmp_type - 'element_content' - compared value is text of <Layer> element
+        @param cmp_type - 'child_element_content' - compared value is text of a child of the <Layer> element
+        @param cmp_type - 'attribute' - compared value is text of the <Layer> element attribute
         @param layer - <Layer> element which inherits
         @param parent_layer - <Layer> element which is inherited from 
         @param add_arg - name of child element or attribute
@@ -174,7 +174,7 @@
             parent_elems = parent_layer.findall(self.xml_ns.Ns(element_name))
         
         for par_elem in parent_elems:
-            parent_cmp_text = ""
+            parent_cmp_text = None
             if cmp_type == "attribute":
                 if add_arg in par_elem.attrib:
                     parent_cmp_text = par_elem.attrib[add_arg];
@@ -183,9 +183,11 @@
                 parent_cmp_text = par_elem.text
                 
             elif cmp_type == "child_element_content":
-                parent_cmp_text = par_elem.find(self.xml_ns.Ns(add_arg)).text
+                parent_cmp = par_elem.find(self.xml_ns.Ns(add_arg))
+                if parent_cmp is not None:
+                    parent_cmp_text = parent_cmp.text
             
-            if parent_cmp_text == "":
+            if parent_cmp_text is None:
                 continue
             
             is_there = False
@@ -199,9 +201,12 @@
                     cmp_text = elem.text
                 
                 elif cmp_type == "child_element_content":
-                    cmp_text = elem.find(self.xml_ns.Ns(add_arg)).text
+                    cmp = elem.find(self.xml_ns.Ns(add_arg))
+                    if cmp is not None:
+                        cmp_text = cmp.text
                 
-                if cmp_text.lower() == parent_cmp_text.lower():
+                if cmpt_text is None or \
+                   cmp_text.lower() == parent_cmp_text.lower():
                     is_there = True
                     break
             
@@ -283,7 +288,6 @@
         self._findall(contents, 'TileMatrixSet', self.xml_ns.NsWmts)
 
         layers = self._findall(contents, 'Layer', self.xml_ns.NsWmts)
-
         for l in layers:
             if not self._checkLayer(l):
                 grass.debug('Removed invalid <Layer> element.', 4)
@@ -292,7 +296,7 @@
         # are there any <Layer> elements after the check
         self._findall(contents, 'Layer', self.xml_ns.NsWmts)
 
-        grass.debug('Checking WMTS capabilities tree was finished.', 4)
+        grass.debug('Check of WMTS capabilities tree was finished.', 4)
 
     def _checkMatSet(self, mat_set):
         """!Check <TileMatrixSet>.
@@ -303,16 +307,9 @@
 
         mat_set_srs = mat_set.find(self.xml_ns.NsOws('SupportedCRS'))
         if mat_set_srs is None or \
-           not mat_set_srs.text or \
-               len(mat_set_srs.text) < 6 or \
-           not mat_set_srs.text.lower()[:5] == ("epsg:"):
+           not mat_set_srs.text:
             return False
 
-        try:
-            int(mat_set_srs.text[5:])
-        except ValueError:
-            return False
-
         tile_mats = mat_set.findall(self.xml_ns.NsWmts('TileMatrix'))
         if not tile_mats:
             return False
@@ -373,7 +370,6 @@
     def _checkLayer(self, layer):
         """!Check <Layer> element.
         """
-        contents = self.getroot().find(self.xml_ns.NsWmts('Contents'))
         layer_id = layer.find(self.xml_ns.NsOws('Identifier'))
         if layer_id is None or not layer_id.text:
             return False
@@ -392,42 +388,51 @@
                 grass.debug('Removed invalid <Style> element.', 4)
                 layer.remove(s_name)
 
-        tileMatrixSets = contents.findall(self.xml_ns.NsWmts('TileMatrixSet'))
+        contents = self.getroot().find(self.xml_ns.NsWmts('Contents'))
+        mat_sets = contents.findall(self.xml_ns.NsWmts('TileMatrixSet'))
 
         for link in  mat_set_links:
-            found = False
-            mat_set_link_id = link.find(self.xml_ns.NsWmts('TileMatrixSet')).text
+            # <TileMatrixSetLink> does not point to existing  <TileMatrixSet>
+            if not self._checkMatSetLink(link, mat_sets):
+                grass.debug('Removed invalid <TileMatrixSetLink> element.', 4)
+                layer.remove(link)
 
-            for mat_set in tileMatrixSets:
-                mat_set_id = mat_set.find(self.xml_ns.NsOws('Identifier')).text
+        return True
 
-                if mat_set_id != mat_set_link_id:
-                    continue
+    def _checkMatSetLink(self, link, mat_sets):
+        """!Check <TileMatrixSetLink> element.
+        """
+        mat_set_link_id = link.find(self.xml_ns.NsWmts('TileMatrixSet')).text
+        found = False
 
-                # the link points to existing <TileMatrixSet>
-                found = True
+        for mat_set in mat_sets:
+            mat_set_id = mat_set.find(self.xml_ns.NsOws('Identifier')).text
 
-                tile_mat_set_limits = link.find(self.xml_ns.NsWmts('TileMatrixSetLimits'))
-                if tile_mat_set_limits is None:
-                    continue
+            if mat_set_id != mat_set_link_id:
+                continue
 
-                tile_mat_limits = tile_mat_set_limits.findall(self.xml_ns.NsWmts('TileMatrixLimits'))
-                for limit in tile_mat_limits:
-                    if not self._checkMatSetLimit(limit):
-                        grass.debug('Removed invalid <TileMatrixLimits> element.', 4)
-                        tile_mat_limits.remove(limit)
+            # the link points to existing <TileMatrixSet>
+            found = True
 
-                # are there any <TileMatrixLimits> elements after the check
-                tile_mat_limits = tile_mat_set_limits.findall(self.xml_ns.NsWmts('TileMatrixLimits'))
-                if not tile_mat_limits:
-                    grass.debug('Removed invalid <TileMatrixSetLimits> element.', 4)
-                    link.remove(tile_mat_set_limits)
+            tile_mat_set_limits = link.find(self.xml_ns.NsWmts('TileMatrixSetLimits'))
+            if tile_mat_set_limits is None:
+                continue
 
-            # TileMatrixSetLink does not point to existing  <TileMatrixSet>
-            if not found:
-                grass.debug('Removed invalid <Layer> element.', 4)
-                layer.remove(link)
+            tile_mat_limits = tile_mat_set_limits.findall(self.xml_ns.NsWmts('TileMatrixLimits'))
+            for limit in tile_mat_limits:
+                if not self._checkMatSetLimit(limit):
+                    grass.debug('Removed invalid <TileMatrixLimits> element.', 4)
+                    tile_mat_limits.remove(limit)
 
+            # are there any <TileMatrixLimits> elements after the check
+            tile_mat_limits = tile_mat_set_limits.findall(self.xml_ns.NsWmts('TileMatrixLimits'))
+            if not tile_mat_limits:
+                grass.debug('Removed invalid <TileMatrixSetLimits> element.', 4)
+                link.remove(tile_mat_set_limits)
+          
+        if not found:
+            return False
+
         return True
 
     def _checkMatSetLimit(self, limit):
@@ -484,7 +489,7 @@
 
 class OnEarthCapabilitiesTree(BaseCapabilitiesTree):
     def __init__(self, cap_file):
-        """!Parses NASA OnEarth tile service file.
+        """!Parse NASA OnEarth tile service file.
             If the file cannot be parsed it raises xml.etree.ElementTree.ParseError.
 
         The class also removes elements which are in invalid form and are needed 
@@ -492,20 +497,19 @@
 
         @param cap_file - capabilities file        
         """
-        #TODO check also TilePattern urls
         BaseCapabilitiesTree.__init__(self, cap_file)
 
         grass.debug('Checking OnEarth capabilities tree.', 4)
 
         self._checkLayerTree(self.getroot())
 
-        grass.debug('Checking OnEarth capabilities tree was finished.', 4)
+        grass.debug('Check if OnEarth capabilities tree was finished.', 4)
 
     def _checkLayerTree(self, parent_layer, first = True):
         """!Recursively check layer tree.
         """
         if first:
-            tiled_patterns = self.find(parent_layer, 'TiledPatterns')
+            tiled_patterns = self._find(parent_layer, 'TiledPatterns')
             layers = tiled_patterns.findall('TiledGroup')
             layers += tiled_patterns.findall('TiledGroups')
             parent_layer = tiled_patterns
@@ -520,7 +524,7 @@
             if l.tag == 'TiledGroups':
                self._checkLayerTree(l, False)
 
-    def find(self, etreeElement, tag):
+    def _find(self, etreeElement, tag):
         """!Find child element.
             If the element is not found it raises xml.etree.ElementTree.ParseError.  
         """
@@ -532,18 +536,6 @@
 
         return res
 
-    def findall(self, etreeElement, tag):
-        """!Find all children element.
-            If no element is found it raises xml.etree.ElementTree.ParseError.  
-        """
-        res = etreeElement.findall(tag)
-        
-        if not res:
-            raise  etree.ParseError(_("Unable to parse tile service file. \n\
-                                       Tag <%s> was not found.") % tag)
-
-        return res
-
     def _checkLayer(self, layer):
         """!Check <TiledGroup>/<TiledGroups> elements.
         """
@@ -556,9 +548,88 @@
 
         t_patts = layer.findall('TilePattern')
 
+        for patt in t_patts:
+            urls = self._getUrls(patt)
+            for url in urls:
+                if not self.gettilepatternurldata(url):
+                    urls.remove(url)
+
+            # check if there are any vaild urls
+            if not urls:
+                grass.debug('<TilePattern>  was removed. It has no valid url.', 4)
+                layer.remove(patt)
+            patt.text = '\n'.join(urls)
+
+        t_patts = layer.findall('TilePattern')
         if not t_patts:
             return False
 
         return True
 
+    def _getUrls(self, tile_pattern):
+        """!Get all urls from tile pattern.
+        """
+        urls = []
+        if  tile_pattern.text is not None:
+            tile_patt_lines = tile_pattern.text.split('\n')
 
+            for line in tile_patt_lines:
+                if 'request=GetMap' in line:
+                    urls.append(line.strip())
+        return urls
+
+    def gettilepatternurldata(self, url):
+        """!Parse url string in Tile Pattern.
+        """
+        par_url = bbox = width = height = None 
+
+        bbox_idxs = self.geturlparamidxs(url, "bbox=")
+        if bbox_idxs is None:
+            return None
+
+        par_url = [url[:bbox_idxs[0] - 1], url[bbox_idxs[1]:]]
+
+        bbox = url[bbox_idxs[0] + len('bbox=') : bbox_idxs[1]]
+        bbox_list = bbox.split(',')
+        if len(bbox_list) < 4:
+            return None
+
+        try:
+            bbox = map(float, bbox.split(','))
+        except ValueError:
+            return None
+
+        width_idxs = self.geturlparamidxs(url, "width=")
+        if width_idxs is None:
+            return None
+
+        try:
+            width = int(url[width_idxs[0] + len('width=') : width_idxs[1]])
+        except  ValueError:
+            return None
+
+        height_idxs = self.geturlparamidxs(url, "height=")
+        if height_idxs is None:
+            return None
+
+        try:
+            height = int(url[height_idxs[0] + len('height=') : height_idxs[1]])
+        except  ValueError:
+            return None
+
+        if height < 0 or width < 0:
+            return None
+
+        return par_url, bbox, width, height
+
+    def geturlparamidxs(self, params_str, param_key):
+        """!Find start and end index of parameter and it's value in url string
+        """
+        start_i = params_str.lower().find(param_key)
+        if start_i < 0: 
+            return None
+        end_i = params_str.find("&", start_i)
+        if end_i < 0:
+            end_i = len(params_str)
+
+        return (start_i, end_i) 
\ No newline at end of file

Modified: grass-addons/grass7/raster/r.in.wms2/wms_drv.py
===================================================================
--- grass-addons/grass7/raster/r.in.wms2/wms_drv.py	2012-12-22 15:38:11 UTC (rev 54367)
+++ grass-addons/grass7/raster/r.in.wms2/wms_drv.py	2012-12-22 23:27:15 UTC (rev 54368)
@@ -17,9 +17,6 @@
 """
 
 import grass.script as grass 
-import base64
-from urllib2 import urlopen, HTTPError
-from httplib import HTTPException
 
 try:
     from osgeo import gdal
@@ -27,13 +24,14 @@
 except:
     grass.fatal(_("Unable to load GDAL python bindings"))
 
-import urllib2
-from xml.etree.ElementTree import ParseError
-
 import numpy as Numeric
 Numeric.arrayrange = Numeric.arange
 
 from math import pi, floor
+from urllib2 import HTTPError
+from httplib import HTTPException
+from xml.etree.ElementTree import ParseError
+
 from wms_base import WMSBase
 
 from wms_cap_parsers import WMTSCapabilitiesTree, OnEarthCapabilitiesTree
@@ -46,10 +44,10 @@
         """ 
         grass.message(_("Downloading data from WMS server..."))
 
-        if not self.params['cfile']:
+        if not self.params['capfile']:
             self.cap_file = self._fetchCapabilities(self.params)
         else:
-            self.cap_file = self.params['cfile']
+            self.cap_file = self.params['capfile']
 
         # initialize correct manager according to chosen OGC service
         if self.params['driver'] == 'WMTS_GRASS':
@@ -80,18 +78,14 @@
 
             # the tile size and offset in pixels for placing it into raster where tiles are joined
             tile_ref = tile[1]
-            grass.debug(query_url)
+            grass.debug(query_url, 2)
             try: 
-                request = urllib2.Request(query_url)
-                if self.params['username']:
-                    base64string = base64.encodestring('%s:%s' % (self.params['username'], self.params['password'])).replace('\n', '')
-                    request.add_header("Authorization", "Basic %s" % base64string) 
-                wms_data = urllib2.urlopen(request)
+                wms_data = self._fetchDataFromServer(query_url, self.params['username'], self.params['password'])
             except (IOError, HTTPException), e:
                 if HTTPError == type(e) and e.code == 401:
-                    grass.fatal(_("Authorization failed"))           
+                    grass.fatal(_("Authorization failed to '%s' when fetching data.") % self.params['url'])
                 else:
-                    grass.fatal(_("Unable to fetch data from server")) 
+                    grass.fatal(_("Unable to fetch data from: '%s'") % self.params['url'])
 
             temp_tile = self._tempfile()
                 
@@ -441,6 +435,8 @@
 
         # parse capabilities file
         try:
+            # checks all elements needed by this class,
+            # invalid elements are removed
             cap_tree = WMTSCapabilitiesTree(cap_file)
         except ParseError as error:
             grass.fatal(_("Unable to parse tile service file.\n%s\n") % str(error))
@@ -649,11 +645,13 @@
         """!Initializes data needed for iteration through tiles.
         """
         try:
-            cap_tree = OnEarthCapabilitiesTree(tile_service)
+            # checks all elements needed by this class,
+            # invalid elements are removed
+            self.cap_tree = OnEarthCapabilitiesTree(tile_service)
         except ParseError as error:
             grass.fatal(_("Unable to parse tile service file.\n%s\n") % str(error))
 
-        root = cap_tree.getroot()
+        root = self.cap_tree.getroot()
 
         # parse tile service file and get needed data for making tile requests
         url, self.tile_span, t_patt_bbox, self.tile_size = self._parseTileService(root, bbox, region, params)
@@ -688,10 +686,7 @@
         group_t_patts = req_group.findall('TilePattern')
         best_patt = self._parseTilePattern(group_t_patts, bbox, region)
 
-        if best_patt is None:
-            grass.fatal("Unable to parse any url in '%s' of %s '%s'" % ('TilePattern', params['layers'], 'TiledGroup'))
-
-        urls = self._getUrls(best_patt)
+        urls = best_patt.text.split('\n')
         if params['urlparams']:
             url = self._insTimeToTilePatternUrl(params['urlparams'], urls)
         else:
@@ -700,7 +695,7 @@
                 if not 'time=${' in u:
                     url = u
 
-        url, t_bbox, width, height = self._parseUrl(url)
+        url, t_bbox, width, height = self.cap_tree.gettilepatternurldata(url)
         tile_span = {}
         tile_span['x'] = abs(t_bbox[0] - t_bbox[2])
         tile_span['y'] = abs(t_bbox[1] - t_bbox[3])
@@ -745,16 +740,8 @@
         t_res = {}
         best_patt = None
         for pattern in group_t_patts:
-            urls = self._getUrls(pattern)
-            if not urls:
-                continue
+            url, t_bbox, width, height = self.cap_tree.gettilepatternurldata(pattern.text.split('\n')[0])
 
-            ret = self._parseUrl(urls[0])
-
-            if not ret:
-                continue
-            url, t_bbox, width, height = ret
-
             t_res['x'] = abs(t_bbox[0] - t_bbox[2]) / width
             t_res['y'] = abs(t_bbox[1] - t_bbox[3]) / height
 
@@ -775,44 +762,6 @@
 
         return best_patt
 
-    def _getUrls(self, tile_pattern):
-        """!Get all urls from tile pattern.
-        """
-        urls = []
-        if  tile_pattern.text is not None:
-            tile_patt_lines = tile_pattern.text.split('\n')
-
-            for line in tile_patt_lines:
-                if 'request=GetMap' in line:
-                    urls.append(line.strip())
-        return urls
-
-    def _parseUrl(self, url):
-        """!Parse url string in Tile Pattern.
-        """
-        par_url = bbox = width = height = None 
-
-        bbox_idxs = self._getParameterIdxs(url, "bbox=")
-        if bbox_idxs is None:
-            return None
-
-        par_url = [url[:bbox_idxs[0] - 1], url[bbox_idxs[1]:]]
-
-        bbox = url[bbox_idxs[0] + len('bbox=') : bbox_idxs[1]]
-        bbox = map(float, bbox.split(','))
-
-        width_idxs = self._getParameterIdxs(url, "width=")
-        if width_idxs is None:
-            return None
-        width = int(url[width_idxs[0] + len('width=') : width_idxs[1]])
-
-        height_idxs = self._getParameterIdxs(url, "height=")
-        if height_idxs is None:
-            return None
-        height = int(url[height_idxs[0] + len('height=') : height_idxs[1]])
-
-        return par_url, bbox, width, height
-
     def _insTimeToTilePatternUrl(self, url_params, urls):
         """!Time can be variable in some urls in OnEarth TMS. 
             Insert requested time from 'urlparams' into the variable if any url of urls contains the variable.
@@ -834,7 +783,7 @@
 
             has_time_var = False
             for url in urls: 
-                url_p_idxs = self._getParameterIdxs(url, k)
+                url_p_idxs = self.geturlparamidxs(url, k)
                 if not url_p_idxs:
                     continue
 
@@ -855,18 +804,6 @@
 
         return url
 
-    def _getParameterIdxs(self, params_str, param_key):
-        """!Find start and end index of parameter and it's value in url string
-        """
-        start_i = params_str.lower().find(param_key)
-        if start_i < 0: 
-            return None
-        end_i = params_str.find("&", start_i)
-        if end_i < 0:
-            end_i = len(params_str)
-
-        return (start_i, end_i) 
-
     def _computeRequestData(self, bbox, t_patt_bbox, tile_span, tile_size):
         """!Initialize data needed for iteration through tiles.
         """  



More information about the grass-commit mailing list