#!/usr/bin/env python # coding=utf-8 from OWS import OWS import mapscript import cgi from lxml import objectify import urllib import urlparse import logging from osgeo import ogr import pyproj import os import re class WFS(OWS): service = "WFS" wfsns = "http://www.opengis.net/wfs" layerDefFile = None lyrobj = None def __init__(self,url=None,qstring=None,configFile=None): OWS.__init__(self,url,qstring,configFile) def makeMap(self,mapfilename=None): mapobj = self.getMapObj(mapfilename) # mapobjects exists, do not do any new layers if mapobj.numlayers: return mapobj self.layerDefFile = self.createLayerDefinitionFile("wfs", os.path.join( os.path.dirname(__file__), "templates",'wfs.xml')) ds = ogr.Open(self.layerDefFile) self.setMapName(mapobj) # load mapfile SYMBOLs symbolPath = os.path.join( os.path.dirname(__file__), "symbols.txt") symbolsLoaded = mapobj.setSymbolSet(symbolPath) if symbolsLoaded == mapscript.MS_SUCCESS: logging.debug("Symbols loaded from %s",symbolPath) else: logging.debug("Error loading symbols from %s",symbolPath) logging.debug(self.capabilities.contents) srss = [] for name in self.capabilities.contents: mapobj.setMetaData("wms_srs",self.config.get("MapServer","srs")) mapobj.setMetaData("wfs_srs",self.config.get("MapServer","srs")) mapobj.setMetaData("wfs_connectiontimeout","90") layer = self.capabilities.contents[name] logging.debug("Creating layer %s" % name) srss = srss+filter(lambda y: not y in srss,layer.crsOptions) lyrobj = mapscript.layerObj(mapobj) #lyrobj.name = name.replace(":","_") lyrobj.name = name lyrobj.title = layer.title if layer.title: lyrobj.setMetaData("wms_title",layer.title) lyrobj.setMetaData("wfs_title",layer.title) #if layer.abstract: # lyrobj.setMetaData("ows_abstract", layer.abstract) lyrobj.setMetaData("wfs_typename", name) logging.debug("WFS version %s",self.capabilities.version) lyrobj.setMetaData("wfs_version",self.capabilities.version) lyrobj.setMetaData("gml_include_items","all") lyrobj.setMetaData("wfs_request_method","GET") lyrobj.setConnectionType(mapscript.MS_WFS,'') lyrobj.connection = self.getLayerUrl() lyrobj.data = re.sub(r".*:","",name) crs = self.__getLayerCrs(layer.crsOptions) if ds: ogrLayer = ds.GetLayerByName(name) extent = self.getLayerExtent(layer,crs) if extent: lyrobj.setMetaData("wms_extent","%s %s %s %s" % \ (extent[0],extent[1],extent[2],extent[3])) lyrobj.setMetaData("wfs_extent","%s %s %s %s" % \ (extent[0],extent[1],extent[2],extent[3])) lyrobj.type = self._getLayerType(ogrLayer) else: mapobj.removeLayer(mapobj.numlayers-1) logging.debug("No ogrDataSource found") continue lyrobj.setProjection(crs.getcode()) #lyrobj.setProjection(layer.crsOptions[0].getcode()) lyrobj.dump = mapscript.MS_TRUE lyrobj.template = "foo" cls = mapscript.classObj(lyrobj) style = mapscript.styleObj(cls) style.outlinecolor=mapscript.colorObj(134,81,0) style.color=mapscript.colorObj(238,153,0) style.size=5 style.width=5 if lyrobj.type == mapscript.MS_LAYER_POINT: style.symbol = 1 ## overwrite already set SRSs #if len(srss) > 0: # logging.debug("Overwriting SRS option") # mapobj.setMetaData("wms_srs"," ".join(srss)) self.saveMapfile(mapobj,mapfilename) return mapobj def getGeomName(self,geomname): if geomname.find("LINE") > -1: return mapscript.MS_LAYER_LINE elif geomname.find("POLYGON") > -1: return mapscript.MS_LAYER_POLYGON else: return mapscript.MS_LAYER_POINT def setMapName(self,mapobj): mapobj.name = self.config.get("MapServer","name") if self.capabilities.identification.title: mapobj.setMetaData("wms_title",self.capabilities.identification.title) mapobj.setMetaData("wfs_title",self.capabilities.identification.title) if self.capabilities.identification.abstract: mapobj.setMetaData("wms_abstract",self.capabilities.identification.abstract) mapobj.setMetaData("wfs_abstract",self.capabilities.identification.abstract) 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 == 0: # unknown # brutal force way f = layer.GetNextFeature() if f: gr = f.GetGeometryRef() geomType = gr.GetGeometryType() 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 def __getLayerCrs(self,crss): """ Returns bests (non-degree) coordinate system of the layer, which is available. Ofcourse, sometimes, there is no other option, there EPSG:4326, but take somethign else, if you can """ for crs in crss: if crs.getcode() == "EPSG:4326": return crs return crss[0]