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

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

More code to support StoredQuery? handling

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 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', 'DescribeStoredQueries'])
43    validVersions = ['1.1.0', '2.0.0']
44   
45
46    #-------------------------------------------------------------------------
47
48    def __before__(self, **kwargs):
49        """
50        This default implementation of __before__() will pass all routes
51        arguments to the layer mapper to retrieve a list of layers for
52        this WFS.
53
54        It will be called automatically by pylons before each action method.
55
56
57        """
58        log.debug('loading layers')
59        self.layers, self.featureset = self.layerMapper.map(**kwargs)
60        log.debug('Feature instances %s'%self.featureset.featureinstances)
61   
62        #-------------------------------------------------------------------------
63        # Methods implementing stubs in OWSController
64
65    def _renderCapabilities(self, version, format):
66        """
67        Renders capabilities document.
68        """
69        if version == '1.1.0':
70            t = ows_controller.templateLoader.load('wfs_capabilities_1_1_0.xml')
71        elif version == '2.0.0':
72            t = ows_controller.templateLoader.load('wfs_capabilities_2_0_0.xml')
73        else:
74            # We should never get here!  The framework should raise an exception before now.
75            raise RuntimeError("Version %s not supported" % version)
76       
77        return t.generate(c=c).render()
78
79    def _loadCapabilities(self):
80        """
81        @note: Assumes self.layers has already been created by __before__().
82        Builds capabilities document.
83
84        """
85        log.info('Loading WFS Capabilites')
86       
87        ows_controller.addOperation('GetFeature')
88        ows_controller.addOperation('DescribeFeature')
89        ows_controller.addOperation('DescribeStoredQueries')
90       
91       
92        featureInfoFormats = Set()
93
94        log.debug('Loading capabilities contents')
95        c.capabilities.contents = Contents()
96       
97       
98        ftlist={}
99        #       
100       
101        for layerName, layer in self.layers.items():
102            log.info('Loading layer %s' % layerName)
103#            log.info('feature type %s'%layer._feature)
104
105            wgs84BBox = WGS84BoundingBox(layer.wgs84BBox[:2],
106                                         layer.wgs84BBox[2:])
107           
108            ds = WfsFeatureSummary(keywords=layer.keywords, 
109                                   outputformats=layer.outputformats, 
110                                   identifier=layerName,
111                                   titles=[layer.title],
112                                   abstracts=[layer.abstract],                                   
113                                   wgs84BoundingBoxes=[wgs84BBox])
114
115            c.capabilities.contents.datasetSummaries.append(ds)
116
117    def _buildStoredQueries(self):
118        return self.layerMapper.queryDescriptions.queries
119
120    def _getSchema(self, typename):
121        namespace = typename.split(':')[0]
122        schemalocation = conf
123       
124    def _parsetypename(self, typename):
125        """ parse feature type name into schema and name"""       
126        if typename not in self.layers.keys():
127            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')
128   
129        namespace, ft = typename.split(':')
130        wfsconfiglocation=config['wfsconfig']
131        wfscfg = ConfigParser.ConfigParser()
132        wfscfg.read(wfsconfiglocation)     
133        xmlschema=open(wfscfg.get('application_schemas', namespace)).read()     
134        log.debug('location of application schema %s' %(xmlschema))
135        return xmlschema
136
137    def DescribeFeatureType(self):
138        """ DescribeFeatureType """
139        version = self.getOwsParam('version', default=self.validVersions[0])
140        if version not in self.validVersions:
141            raise InvalidParameterValue('Version %s not supported' % version,
142                                        'version')
143        typename=self.getOwsParam('typename')
144        ftschema =self._parsetypename(typename)
145        log.debug(self.layers.items())       
146               
147        outputformat=self.getOwsParam('outputformat', default='text/xml')
148       
149        #temporarily returns entire schema
150        #TODO: return single featuretype definition
151        msg  = ftschema
152        response.headers['content-type'] = 'text/xml'
153        return msg
154 
155    def GetFeature(self):
156        """ GetFeature request
157        """
158        #TODO QUERY model
159        version = self.getOwsParam('version', default=self.validVersions[0])
160        if version not in self.validVersions:
161            raise InvalidParameterValue('Version %s not supported' % version,
162                                        'version')
163
164        #The GetFeature request may either use the 'query' filter encoding or a
165        #storedquery, but not both:
166#        if self.getOwsParam('storedquery_id'):
167       
168        #Parse the query to analyse the filters it contains
169        queryxml=self.getOwsParam('query',default=None)
170        storedqueryid=self.getOwsParam('storedquery_id', default=None)
171        if queryxml:
172            qp=FEQueryProcessor()
173            c.resultset=qp.evaluate(self.featureset, queryxml)
174            log.debug('Final resultset from query processor %s'%c.resultset)
175        elif storedqueryid:
176            storedquery, func=self.layerMapper.queryDescriptions.queries[storedqueryid]
177            c.resultset=func(arg1='cat', arg2='dog')
178            log.debug('Final resultset from stored query %s'%c.resultset)
179        else:
180            pass #TODO need to raise error if neither query or storedquery_id are provided
181       
182        #Group resultset together in a wfs feature collection (use template)
183        response.headers['content-type'] = 'text/xml'
184        t = ows_controller.templateLoader.load('wfs_featurecollection.xml')
185        return t.generate(c=c).render()           
186
187
188   
189    def DescribeStoredQueries(self):
190        """ DescribeStoredQueries method. Takes zero or more stored query ids as args"""
191        c.storedqueries = self._buildStoredQueries()
192        t = ows_controller.templateLoader.load('wfs_describestoredqueries.xml')
193        return t.generate(c=c).render() 
194         
Note: See TracBrowser for help on using the repository browser.