source: cows/trunk/cows/model/filterencoding.py @ 4303

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows/trunk/cows/model/filterencoding.py@4303
Revision 4303, 4.2 KB checked in by domlowe, 11 years ago (diff)

Added interfaces for getFeaturesByBBox and getFeaturesByTemporalRange type filters. Also added code for combining filter resultsets.

Line 
1# Copyright (C) 2008 STFC & NERC (Science and Technology Facilities Council).
2# This software may be distributed under the terms of the
3# Q Public License, version 1.0 or later.
4# http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
5
6""" Classes to handle filter encoding queries as used in WFS """
7
8
9from xml.etree import ElementTree as etree
10import logging
11log = logging.getLogger(__name__)
12
13""" utility functions to save writing out fully qualified names """
14nsOGC = 'http://www.opengis.net/ogc'
15def OGC(tag):
16    return "{"+nsOGC+"}"+tag
17
18nsGML = 'http://www.opengis.net/gml'
19def GML(tag):
20    return "{"+nsGML+"}"+tag
21       
22class FEQuery(object):
23    """ Represents a WFS Query string which can contain feature type names and a variety of filters """
24   
25    def __init__(self, querystring):
26        self.querystring=str(querystring) #may be unicode, so convert to string
27        self.elem=etree.fromstring(self.querystring)
28        log.debug("Query String: %s"%self.querystring)
29        log.debug("Query Element: %s"%self.elem)
30       
31    def getTypeName(self):
32        typename=self.elem.get('typeName')   
33        log.debug('TypeName = %s'%typename)
34        return typename   
35   
36    def getFilters(self):
37        """returns parts of query as individual filters which can then be translated into
38        method calls on the wfs_iface. Examples of filters include, getByGMLid, getByBBox, getByTimeRange"""
39        queryfilters=[]
40        for child in self.elem.getchildren():
41            if child.tag==OGC('Filter'):
42                #break <ogc:Filter> down into single filters.
43                fp=FilterParser(child)
44                for filter in fp.filters:
45                    queryfilters.append(filter)
46        return queryfilters     
47
48class FilterParser(object):
49    """ Handles an OGC Filter object which in reality can contain several 'sub-filters'. Breaks this down into individual 'Filters' """
50    def __init__(self, filterelem):
51        self.filters=[]
52        for elem in filterelem.getchildren():
53            if elem.tag == OGC('GmlObjectId'):
54                value=elem.get(GML('id'))
55                f=Filter('GmlObjectId', value)
56                self.filters.append(f)
57       
58class Filter(object):
59    """represents an individual WFS filter (i.e. a filter containing 'And' will be modelled as 2 filters).
60    @ivar filtertype: Type of filter (e.g. 'getByBBox')
61    @ivar fitlervalue: Appropriate value on which to filter (e.g. Bounding box tuple)
62    """
63    def __init__(self, filtertype, filtervalue):
64        self.filtertype = filtertype
65        self.filtervalue = filtervalue
66       
67class FEQueryProcessor(object):
68    """ Given a Featureset and a list of of Filters, applies the filters
69    to the Featureset and creates a resultset
70    Assumptions:
71        1) GmlObjectId is only used as a filter alone or with other GmlObjectId filters, not with other filter types.
72        2) Other filter types, such as bounding box or temporal range fitlers only appear once.
73   
74   
75    """
76   
77    def __init__(self, featureset, filters):
78        self.featureset=featureset
79        self.resultset=[]             
80        temporalrangeresults=[]
81        bboxresults=[]
82        for filter in filters:
83            if filter.filtertype=='GmlObjectId':           
84                feature=self.featureset.getFeatureByGMLid(filter.filtervalue)
85                if feature:
86                    self.resultset.append(feature)   
87            else:
88                #handle other filtertypes, bbox & temporal for now:
89                if filter.filtertype=='BBox':
90                    bboxresults=self.featureset.getFeaturesByBBox()                   
91                if filter.filtertype=='TemporalRange':
92                    temporalrangeresults=self.featureset.getFeaturesByTemporalRange()           
93                self.resultset=self._combineresults([set(temporalrangeresults), set(bboxresults)])
94               
95    def _combineresults(self, results):     
96        """ combine (AND operation) results from two or more filters """
97        baseset=[]
98        for set in results:
99            if baseset == []:
100                baseset = set
101            else:
102                baseset=baseset.intersection(set)                       
103        return baseset
104           
105           
Note: See TracBrowser for help on using the repository browser.