source: cows/trunk/cows/pylons/wfs_controller.py @ 4298

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows/trunk/cows/pylons/wfs_controller.py@4298
Revision 4298, 6.4 KB checked in by domlowe, 11 years ago (diff)

Added machinery for parsing filter encoding queries

Line 
1"""
2WFS controller for OGC Web Services (OWS).
3
4@author: Dominic Lowe
5"""
6
7import re
8from cStringIO import StringIO
9from sets import Set
10from matplotlib.cm import get_cmap
11from pylons import request, response, c, config
12import ConfigParser
13
14import logging
15log = logging.getLogger(__name__)
16
17import Image
18
19from cows.model.wfs import WfsFeatureSummary
20from cows.model.filterencoding import FEQuery, FEQueryProcessor
21from cows.model import PossibleValues, WGS84BoundingBox, BoundingBox, Contents
22from cows.pylons import ows_controller
23from cows.exceptions import *
24from cows import bbox_util
25
26class WFSController(ows_controller.OWSController):
27    """
28    Subclass this controller in a pylons application and set the layerMapper
29    class attribute to implement a WFS. Each layer can be mapped to a Feature for the WFS.
30
31    @cvar layerMapper: an cows.service.wxs_iface.ILayerMapper object.
32   
33
34    """
35    layerMapper = None
36    _layerSlabCache = {}
37
38    #-------------------------------------------------------------------------
39    # Attributes required by OWSController
40
41    service = 'WFS'
42    owsOperations = (ows_controller.OWSController.owsOperations + ['DescribeFeatureType', 'GetFeature'])
43    validVersions = ['1.1.0']
44
45    #-------------------------------------------------------------------------
46
47    def __before__(self, **kwargs):
48        """
49        This default implementation of __before__() will pass all routes
50        arguments to the layer mapper to retrieve a list of layers for
51        this WFS.
52
53        It will be called automatically by pylons before each action method.
54
55
56        """
57        log.debug('loading layers')
58        self.layers, self.featureset = self.layerMapper.map(**kwargs)
59        log.debug('Feature instances %s'%self.featureset.featureinstances)
60   
61        #-------------------------------------------------------------------------
62        # Methods implementing stubs in OWSController
63
64    def _renderCapabilities(self, version, format):
65        """
66        Renders capabilities document.
67        """
68        if version == '1.1.0':
69            t = ows_controller.templateLoader.load('wfs_capabilities_1_1_0.xml')
70        else:
71            # We should never get here!  The framework should raise an exception before now.
72            raise RuntimeError("Version %s not supported" % version)
73       
74        return t.generate(c=c).render()
75
76    def _loadCapabilities(self):
77        """
78        @note: Assumes self.layers has already been created by __before__().
79        Builds capabilities document.
80
81        """
82        log.info('Loading WFS Capabilites')
83       
84        ows_controller.addOperation('GetFeature')
85        ows_controller.addOperation('DescribeFeature')
86       
87       
88        featureInfoFormats = Set()
89
90        log.debug('Loading capabilities contents')
91        c.capabilities.contents = Contents()
92       
93       
94        ftlist={}
95        #       
96       
97        for layerName, layer in self.layers.items():
98            log.info('Loading layer %s' % layerName)
99#            log.info('feature type %s'%layer._feature)
100
101            wgs84BBox = WGS84BoundingBox(layer.wgs84BBox[:2],
102                                         layer.wgs84BBox[2:])
103           
104            ds = WfsFeatureSummary(keywords=layer.keywords, 
105                                   outputformats=layer.outputformats, 
106                                   identifier=layerName,
107                                   titles=[layer.title],
108                                   abstracts=[layer.abstract],                                   
109                                   wgs84BoundingBoxes=[wgs84BBox])
110
111            c.capabilities.contents.datasetSummaries.append(ds)
112
113    def _getSchema(self, typename):
114        namespace = typename.split(':')[0]
115        schemalocation = conf
116       
117    def _parsetypename(self, typename):
118        """ parse feature type name into schema and name"""       
119        if typename not in self.layers.keys():
120            raise InvalidParameterValue('Invalid typename parameter: %s. Typename must consist of namespace and featuretype separated with a colon, as displayed in the GetCapabilities response.'%typename, 'typename')
121   
122        namespace, ft = typename.split(':')
123        wfsconfiglocation=config['wfsconfig']
124        wfscfg = ConfigParser.ConfigParser()
125        wfscfg.read(wfsconfiglocation)     
126        xmlschema=open(wfscfg.get('application_schemas', namespace)).read()     
127        log.debug('location of application schema %s' %(xmlschema))
128        return xmlschema
129
130               
131    def DescribeFeatureType(self):
132        """ DescribeFeatureType """
133        version = self.getOwsParam('version', default=self.validVersions[0])
134        if version not in self.validVersions:
135            raise InvalidParameterValue('Version %s not supported' % version,
136                                        'version')
137        typename=self.getOwsParam('typename')
138        ftschema =self._parsetypename(typename)
139        log.debug(self.layers.items())       
140               
141        outputformat=self.getOwsParam('outputformat', default='text/xml')
142       
143        #temporarily returns entire schema
144        #TODO: return single featuretype definition
145        msg  = ftschema
146        response.headers['content-type'] = 'text/xml'
147        return msg
148 
149    def GetFeature(self):
150        """ GetFeature request
151        """
152        #TODO QUERY model
153        version = self.getOwsParam('version', default=self.validVersions[0])
154        if version not in self.validVersions:
155            raise InvalidParameterValue('Version %s not supported' % version,
156                                        'version')
157
158        #Parse the query to analyse the filters it contains
159        query=FEQuery(self.getOwsParam('query'))
160        filters=query.getFilters()
161       
162        #now apply the filters to the featureset
163        qp=FEQueryProcessor(self.featureset, filters)
164        #TODO: Group resultset together in a wfs feature collection (use template)
165#        return qp.resultset
166        c.resultset=qp.resultset
167        response.headers['content-type'] = 'text/xml'
168        t = ows_controller.templateLoader.load('wfs_featurecollection.xml')
169        return t.generate(c=c).render()           
170
171
172#        featureid=self.getOwsParam('featureid')
173#        #TODO populate self.featureinstances!
174#        feature=self.featureset.featureinstances[featureid]   
175#        response.headers['content-type'] = 'text/xml'
176#        return feature.toGML()
177#       
178   
179   
Note: See TracBrowser for help on using the repository browser.