Bläddra i källkod

wfs works + we are using owslib now

Jachym Cepicky 14 år sedan
förälder
incheckning
9dd37df466
3 ändrade filer med 83 tillägg och 121 borttagningar
  1. 5 59
      OWS.py
  2. 2 1
      config.cfg-template
  3. 76 61
      wfs/__init__.py

+ 5 - 59
OWS.py

@@ -12,6 +12,8 @@ import md5
 import mapscript
 from string import Template
 
+from owslib.wfs import WebFeatureService
+
 class OWS:
 
     capabilities = None
@@ -50,68 +52,12 @@ class OWS:
         self.config = ConfigParser.ConfigParser()
         self.config.read(configFiles)
 
-        logging.debug("Creating cachedir for %s in %s" % (self.url,self.config.get("OWSViewer","cachedir")))
+        logging.debug("Creating cachedir for %s in %s" % (self.url,self.config.get("OWSProxy","cachedir")))
         logging.debug("%s initialized"%self.service)
 
     def __getCapabilities(self):
         self.parsedUrl = urlparse.urlparse(self.url)
-        params = urlparse.parse_qs(self.parsedUrl.query,keep_blank_values=True)
-        if "request" in params:
-            params["request"] = "GetCapabilities"
-        else:
-            params["REQUEST"] = "GetCapabilities"
-
-        if "service" in params:
-            params["service"] = self.service
-        else:
-            params["SERVICE"] = self.service
-
-        # HACK HACK HACK
-        # 1.0.0 works
-        # 1.1.0 reverses axes, while OGR is requesting the FeatureType
-        # using BBOX FILTER
-        if self.service == "WFS":
-            if "version" in params:
-                params["version"] = "1.0.0"
-            else:
-                params["VERSION"] = "1.0.0"
-
-
-        url = urlparse.urlunparse((self.parsedUrl[0],
-                                    self.parsedUrl[1],
-                                    self.parsedUrl[2],
-                                    self.parsedUrl[3],
-                                    urllib.unquote(urllib.urlencode(params,True)),
-                                    self.parsedUrl[5]))
-        e = objectify.parse(urllib.urlopen(url))
-        self.capabilities = e.getroot()
-
-        try:
-            params.pop("service")
-        except:
-            pass
-
-        try:
-            params.pop("request")
-        except:
-            pass
-
-        try:
-            params.pop("SERVICE")
-        except:
-            pass
-
-        try:
-            params.pop("REQUEST")
-        except:
-            pass
-
-        self.url = urlparse.urlunparse((self.parsedUrl[0],
-                                        self.parsedUrl[1],
-                                        self.parsedUrl[2],
-                                        self.parsedUrl[3],
-                                        urllib.urlencode(params,True),
-                                        self.parsedUrl[5]))
+        self.capabilities = WebFeatureService(url=self.url)
 
     def getParams(self):
         return urlparse.parse_qs(self.qstring)
@@ -150,7 +96,7 @@ class OWS:
         
         self.cachedir = tempfile.mkdtemp(prefix="%s-%s"%(self.service,
                                         md5.new(self.url).hexdigest()),
-                                        dir=self.config.get("OWSViewer","cachedir"))
+                                        dir=self.config.get("OWSProxy","cachedir"))
         os.chmod(self.cachedir,  0777)
         logging.debug("Cachedir %s created" % self.cachedir)
         open(os.path.join(self.cachedir,"url.txt"),"w").write(self.url)

+ 2 - 1
config.cfg-template

@@ -1,6 +1,7 @@
-[OWSViewer]
+[OWSProxy]
 cachedir=/tmp/
 logging=DEBUG
+owslib=/home/jachym/usr/src/owslib/OWSLib/
 
 [MapServer]
 name=owsproxy

+ 76 - 61
wfs/__init__.py

@@ -9,9 +9,9 @@ import urllib
 import urlparse
 import logging
 from osgeo import ogr
+from osgeo import osr
 import os
 
-
 class WFS(OWS):
 
     service = "WFS"
@@ -25,6 +25,7 @@ class WFS(OWS):
 
         mapobj = self.getMapObj(mapfilename)
 
+
         self.layerDefFile = self.createLayerDefinitionFile("wfs",
                 os.path.join( os.path.dirname(__file__), "templates",'wfs.xml'))
 
@@ -32,59 +33,40 @@ class WFS(OWS):
 
         self.setMapName(mapobj)
 
-        for layer in self.capabilities.FeatureTypeList.getchildren():
-            if layer.tag != "{http://www.opengis.net/wfs}FeatureType":
-                continue
+        logging.debug(self.capabilities.contents)
+
+        for name in self.capabilities.contents:
+            layer = self.capabilities.contents[name]
 
-            name = layer.Name.text
             logging.debug("Creating layer %s" % name)
 
             lyrobj = mapscript.layerObj(mapobj)
             lyrobj.name = name
-            lyrobj.title = layer.Title.text
-            lyrobj.setMetaData("wms_title",layer.Title.text)
-            try:
-                lyrobj.setMetaData("ows_abstract",  layer["{%s}%s" % ("http://www.opengis.net/wfs","Abstract")].text)
-            except: 
-                pass
-            lyrobj.setMetaData("wfs_typename",layer.Name.text)
-            lyrobj.setMetaData("wfs_version",self.capabilities.attrib["version"])
+            lyrobj.title = layer.title
+            if layer.title:
+                lyrobj.setMetaData("wms_title",layer.title)
+            #if layer.abstract:
+            #    lyrobj.setMetaData("ows_abstract",  layer.abstract)
+            lyrobj.setMetaData("wfs_typename", name)
+            lyrobj.setMetaData("wfs_version",self.capabilities.version)
             lyrobj.setConnectionType(mapscript.MS_OGR,'')
             lyrobj.connection = self.layerDefFile
             lyrobj.data = name
 
             if ds:
                 ogrLayer = ds.GetLayerByName(name)
-                extent = self.getLayerExtent(ogrLayer)
+                # TODO : udelat to pomoci owslib
+                extent = self.getLayerExtent(layer,layer.crsOptions[0])
                 lyrobj.setMetaData("wms_extent","%s %s %s %s" % \
                         (extent[0],extent[1],extent[2],extent[3]))
-                if ogrLayer:
-                    feature = ogrLayer.GetNextFeature()
-                    if feature:
-                        geom = feature.GetGeometryRef()
-                        if geom:
-                            lyrobj.type = self.getGeomName(geom.GetGeometryName())
-                        else:
-                            mapobj.removeLayer(mapobj.numlayers-1)
-                            logging.debug("No ogrGeometry found")
-                            continue
-                    else:
-                        mapobj.removeLayer(mapobj.numlayers-1)
-                        logging.debug("No ogrFeature found")
-                        continue
-                else:
-                    mapobj.removeLayer(mapobj.numlayers-1)
-                    logging.debug("No ogrLayer found")
-                    continue
+                lyrobj.type = self._getLayerType(ogrLayer)
             else:
                 mapobj.removeLayer(mapobj.numlayers-1)
                 logging.debug("No ogrDataSource found")
                 continue
 
-            if self.capabilities.attrib["version"] == "1.0.0":
-                lyrobj.setProjection(layer.SRS.text)
-            else:
-                lyrobj.setProjection(layer.DefaultSRS.text)
+            lyrobj.setProjection(layer.crsOptions[0])
+
             lyrobj.dump = mapscript.MS_TRUE 
             lyrobj.template = "foo"
             cls = mapscript.classObj(lyrobj)
@@ -109,36 +91,69 @@ class WFS(OWS):
     def setMapName(self,mapobj):
         mapobj.name = self.config.get("MapServer","name")
 
-        if self.capabilities.attrib["version"] == "1.0.0":
-            mapobj.setMetaData("wms_title",self.capabilities["{%s}%s"%(self.wfsns,"Service")].Title.text)
-            mapobj.setMetaData("wms_abstract",self.capabilities.Service.Abstract.text)
-
-        else:
-            mapobj.setMetaData("wms_title",self.capabilities["{%s}%s"%(self.owsns,"ServiceIdentification")].Title.text)
-            mapobj.setMetaData("wms_abstract",self.capabilities["{%s}%s"%(self.owsns,"ServiceIdentification")].Abstract.text)
+        if self.capabilities.identification.title:
+            mapobj.setMetaData("wms_title",self.capabilities.identification.title)
+        if self.capabilities.identification.abstract:
+            mapobj.setMetaData("wms_abstract",self.capabilities.identification.abstract)
 
-    def getLayerExtent(self,layer):
+    def getLayerExtent(self,layer,crs):
         """Get extent of layer in form of minx, miny, maxx,maxy
         """
 
-        # in WFS 1.1 is inverted axes orientation for some epsg
-        # codes (4000-5000)
-        # According to FrankW, python gdal-1.8.0 does not export
-        # ReferenceSystem.GetAxis() method
-        # so , if WFS version == 1.0.0 AND 4000<=ESPSG<=5000
-        # invert the axes
-        sr =  layer.GetSpatialRef()
-        sr.AutoIdentifyEPSG()
-        e = layer.GetExtent()
-        if 4000 <= int(sr.GetAuthorityCode('GEOGCS')) <= 5000 and \
-                self.capabilities.attrib["version"] == "1.1.0":
-            # invert X and Y
-            extent = (e[2],e[0],e[3],e[1])
+        dest = osr.SpatialReference()
+        dest.ImportFromEPSG(int(crs.split(":")[1]))
+        source = osr.SpatialReference()
+        source.ImportFromEPSG(4326)
 
-        else:
-            extent = (e[0],e[2],e[1],e[3])
+        bbox = []
+
+        geom = ogr.CreateGeometryFromWkt("""POINT(%s %s)""" % (layer.boundingBoxWGS84[0],layer.boundingBoxWGS84[1]),source)
+        geom.TransformTo(dest)
+        bbox.append(geom.GetX())
+        bbox.append(geom.GetY())
+
+        geom = ogr.CreateGeometryFromWkt("""POINT(%s %s)""" % (layer.boundingBoxWGS84[2],layer.boundingBoxWGS84[3]),source)
+        geom.TransformTo(dest)
+        bbox.append(geom.GetX())
+        bbox.append(geom.GetY())
 
         logging.debug("Setting extent for layer <%s> to %s" %\
-                (layer.GetName(),extent))
-        return extent
+                (layer.id,bbox))
+        return bbox
+
+    def _getLayerType(self,layer):
+        """Returns MS layer type based on ogr.Layer.GetGeomType
+
+        with ogr:
+
+            wkbGeometryCollection = 7
+            wkbGeometryCollection25D = -2147483641
+            wkbLineString = 2
+            wkbLineString25D = -2147483646
+            wkbLinearRing = 101
+            wkbMultiLineString = 5
+            wkbMultiLineString25D = -2147483643
+            wkbMultiPoint = 4
+            wkbMultiPoint25D = -2147483644
+            wkbMultiPolygon = 6
+            wkbMultiPolygon25D = -2147483642
+            wkbNDR = 1
+            wkbNone = 100
+            wkbPoint = 1
+            wkbPoint25D = -2147483647
+            wkbPolygon = 3
+            wkbPolygon25D = -2147483645
+            wkbUnknown = 0
+        """
+
+        geomType = layer.GetGeomType()
+        if geomType in [ogr.wkbPolygon,
+                        ogr.wkbMultiPolygon,
+                        ogr.wkbLinearRing]:
+               return mapscript.MS_LAYER_POLYGON
+        elif geomType in [ogr.wkbLineString,
+                          ogr.wkbMultiLineString]:
+               return mapscript.MS_LAYER_LINE
+        else:
+               return mapscript.MS_LAYER_POINT