source: mauRepo/HPFos/trunk/src/HPFos/osImpl/myimpl.py @ 8466

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/mauRepo/HPFos/trunk/src/HPFos/osImpl/myimpl.py@8466
Revision 8466, 13.2 KB checked in by mnagni, 7 years ago (diff)

Complete - # 22488: CEDA Observation Collection - Geographical Extent
 http://team.ceda.ac.uk/trac/ceda/ticket/22488
Complete - # 22518: The description is broken
 http://team.ceda.ac.uk/trac/ceda/ticket/22518

Now uses the cedaMarkup 0.0.6

  • Property svn:mime-type set to text/plain
Line 
1'''
2BSD Licence
3Copyright (c) 2012, Science & Technology Facilities Council (STFC)
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without modification,
7are permitted provided that the following conditions are met:
8
9    * Redistributions of source code must retain the above copyright notice,
10        this list of conditions and the following disclaimer.
11    * Redistributions in binary form must reproduce the above copyright notice,
12        this list of conditions and the following disclaimer in the documentation
13        and/or other materials provided with the distribution.
14    * Neither the name of the Science & Technology Facilities Council (STFC)
15        nor the names of its contributors may be used to endorse or promote
16        products derived from this software without specific prior written permission.
17
18THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29Created on 5 May 2012
30
31@author: Maurizio Nagni
32'''
33from xml.dom import minidom
34from datetime import datetime
35from libs.postgisutil import create_st_setSRID
36from ceda_markup.opensearch.osquery import OSQuery
37from ceda_markup.opensearch.osParam import OSParam
38from ceda_markup.atom.atom import createID, createUpdated,\
39    createPublished, createAtomDocument, createEntry
40from ceda_markup.atom.info import createTitle, HTML_TYPE, createContent
41from ceda_markup.dc.dc import createDate
42from ceda_markup.gml.gml import createPosList, createLinearRing, createExterior,\
43    createPolygon
44from ceda_markup.georss.georss import createWhere
45from ceda_markup.atom.link import REL_SEARCH, REL_SELF, REL_FIRST, REL_NEXT,\
46    REL_LAST, REL_ALTERNATE
47from ceda_markup.opensearch.os_response import createOpenSearchRespose
48from ceda_markup.opensearch import filterResults, COUNT_DEFAULT,\
49    START_INDEX_DEFAULT, START_PAGE_DEFAULT, createAutodiscoveryLink,\
50    generateAutodiscoveryPath
51from ceda_markup.opensearch.template.osresponse import Result
52from xml.etree.ElementTree import tostring
53from ceda_markup.opensearch.template.atom import OSAtomResponse
54from ceda_markup.opensearch.template.html import OSHTMLResponse
55from ea_model.ceda_metadatamodel.ceda_observationcollection.ceda_observationcollection import CEDA_ObservationCollection
56from ea_model.ceda_metadatamodel.ceda_observation.ceda_observation import CEDA_Observation
57from ea_model.ceda_metadatamodel.ceda_result.ceda_result import CEDA_Result
58
59GUID = 'guid'
60COLLECTION = 'collection'
61OBSERVATION = 'observation'
62RESULT = 'result'
63BBOX = 'bbox'
64DUMMY_GUID = 'dummy_guid'
65
66CEDA_TITLE = 'ceda_title'
67
68
69
70class MyOSAtomResponse(OSAtomResponse):
71    '''
72    classdocs
73    '''
74
75    def __init__(self):
76        #query_params = {"q": "searchTerms", "pw":"startPage"}
77        super(MyOSAtomResponse, self).__init__()
78       
79        '''
80        Constructor
81        '''
82
83    def _get_tot_results(self, results):
84        if results is None:
85            return 0
86       
87        if isinstance(results, list):
88            return len(results)
89       
90        return 1
91
92    def digestSearchResults(self, results, context):
93        count, startIndex, startPage = self._importCountAndPage(context)
94       
95        filtered = None
96        tot_results = 0
97       
98        if type(results) == CEDA_ObservationCollection:
99            filtered = filterResults(results.member, count, startIndex, startPage)
100            tot_results = self._get_tot_results(results.member)
101        elif type(results) == CEDA_Observation:
102            #to be done
103            filtered = filterResults(results.result, count, startIndex, startPage)
104            tot_results = self._get_tot_results(results.result)       
105        else:
106            filtered = filterResults(results, count, startIndex, startPage)
107            tot_results = self._get_tot_results(results)
108             
109        subresults = []
110        for result in filtered:
111            item = None
112            if type(result) != CEDA_Result:           
113                result_guid = context['moles3EPB'].retrieveGUIDFromInstance(result)
114                ititle = self._extractTitle(result)
115                item = Subresult(result_guid.id, ititle, result.description,  datetime.now().isoformat())
116            else:   
117                item = Subresult(DUMMY_GUID, 'dummy_resultTitle', 'dummy_resultDescription',  datetime.now().isoformat())
118            subresults.append(item)
119       
120        return Result(count, startIndex, startPage, tot_results, subresult = subresults)
121                       
122    def generateResponse(self, results, queries, osHostURL, context):
123        ospath = generateAutodiscoveryPath(osHostURL, None, self.extension, rel = None)
124       
125        #Generates the ATOM document
126        atomdoc = createAtomDocument(ospath + "atom", results.title, results.updated)
127
128        #Generate feed's links
129        self.generateFeedLinks(atomdoc, ospath, None, results.totalResult, results.count)
130       
131        #Inserts the OpenSearchResponse elements
132        createOpenSearchRespose(atomdoc, results.totalResult, results.startIndex, results.count, queries)
133        self.generateEntries(atomdoc, results.subresult, ospath)
134       
135        reparsed = minidom.parseString(tostring(atomdoc))
136        return reparsed.toprettyxml(indent="  ")
137
138    def generateFeedLinks(self, atomroot, path, linkid = None, total_results = None, step = 0):
139        atomroot.append(createAutodiscoveryLink(atomroot, path, self.extension, \
140                                                linkid, startIndex = None, rel = REL_SEARCH))       
141        atomroot.append(createAutodiscoveryLink(atomroot, path, self.extension, \
142                                                linkid, startIndex = 0, rel = REL_SELF))       
143        atomroot.append(createAutodiscoveryLink(atomroot, path, self.extension, \
144                                                linkid, startIndex = 0, rel = REL_FIRST))
145       
146        if total_results > 2*step:
147            atomroot.append(createAutodiscoveryLink(atomroot, path, self.extension, \
148                                                    linkid, step, rel = REL_NEXT))
149            atomroot.append(createAutodiscoveryLink(atomroot, path, self.extension, \
150                                                    linkid, total_results - (total_results % step), rel = REL_LAST))
151        else:
152            if total_results > step:
153                atomroot.append(createAutodiscoveryLink(atomroot, path, self.extension, \
154                                                        linkid, step, rel = REL_NEXT))                   
155                atomroot.append(createAutodiscoveryLink(atomroot, path, self.extension, \
156                                                        linkid, step, rel = REL_LAST))
157            else:
158                atomroot.append(createAutodiscoveryLink(atomroot, path, self.extension, \
159                                                        linkid, 0, rel = REL_NEXT))                                 
160                atomroot.append(createAutodiscoveryLink(atomroot, path, self.extension, \
161                                                        linkid, step, rel = REL_LAST))                                 
162       
163    def generateEntryLinks(self, entry, atomroot, path, linkid = None):
164        entry.append(createAutodiscoveryLink(atomroot, path, self.extension, linkid, None, rel = REL_ALTERNATE))
165        entry.append(createAutodiscoveryLink(atomroot, path, self.extension, linkid, None, rel = REL_SEARCH))               
166
167    def generateEntries(self, atomroot, subresults, path):
168        entries = []
169       
170        for subresult in subresults:
171            #Here could loop over results
172            atomID = createID(path + subresult.id + '/' + self.extension, root = atomroot)
173            ititle = createTitle(root = atomroot, body = subresult.title, itype = HTML_TYPE)
174            atomContent = createContent(root = atomroot, body = subresult.description, itype = HTML_TYPE)
175            atomUpdated = createUpdated(subresult.updated, root = atomroot)
176            atomPublished = createPublished('TO_BE_DONE_2011-01-21T11:05:29.511Z', root = atomroot)           
177            entry = createEntry(atomID, ititle, atomUpdated,
178                                published=atomPublished,
179                                content=atomContent, root = atomroot)
180            #xmlentry = entry.buildElement()
181           
182            idate = createDate(root = atomroot,
183                               body = 'TO_BE_DONE_2002-10-18T08:07:37.387Z/2012-03-29T07:12:20.735Z')       
184            entry.append(idate)
185           
186            posList = createPosList(root = atomroot, body = '-90 -180 90 -180 90 180 -90 180 -90 -180', srsDimension = '2')
187            linearRing = createLinearRing(root = atomroot, body = posList)
188            exterior = createExterior(root = atomroot, body = linearRing)
189            polygon = createPolygon(root = atomroot, body = exterior)
190            where = createWhere(root = atomroot, body = polygon)
191            entry.append(where)
192            self.generateEntryLinks(entry, atomroot, path, subresult.id)           
193            entries.append(entry)
194
195        for entry in entries:
196            atomroot.append(entry)
197
198    def _importCountAndPage(self, context):       
199        count = COUNT_DEFAULT
200        startIndex = START_INDEX_DEFAULT
201        startPage = START_PAGE_DEFAULT
202       
203        try:
204            count = int(context['count'])
205        except:
206            pass       
207       
208        try:
209            startIndex = int(context['startIndex'])
210        except:
211            pass
212       
213        try:
214            startPage = int(context['startPage'])
215        except:
216            pass
217       
218        return count, startIndex, startPage
219
220    def _extractTitle(self, cedaObj):
221        if hasattr(cedaObj, 'identifier'):
222            for ident in cedaObj.identifier:
223                if ident.authority.title == CEDA_TITLE:
224                    return ident.code 
225
226class MyOSHTMLResponse(OSHTMLResponse):
227    '''
228    classdocs
229    '''
230
231    def __init__(self):
232        '''
233        Constructor
234        '''
235        super(MyOSHTMLResponse, self).__init__()
236       
237    def generateResponse(self, result, queries, ospath, **kwargs):
238        return result + " HTML!"
239       
240class MyOSQuery(OSQuery):
241    '''
242    classdocs
243    '''
244
245    def __init__(self):
246        '''
247            Constructor
248        '''
249        #param_1 = OSParam("q", "searchTerms", namespace = "http://example.com/opensearchextensions/1.0/")       
250        param_1 = OSParam("count", "count")
251        param_2 = OSParam("startPage", "startPage")
252        param_3 = OSParam("startIndex", "startIndex")               
253        param_4 = OSParam("q", "searchTerms")           
254        param_5 = OSParam("uid", "uid", namespace = "http://a9.com/-/opensearch/extensions/geo/1.0/")       
255        param_6 = OSParam(BBOX, BBOX, namespace = "http://a9.com/-/opensearch/extensions/geo/1.0/")       
256        param_7 = OSParam("start", "start", namespace = "http://a9.com/-/opensearch/extensions/geo/1.0/")       
257        param_8 = OSParam("stop", "stop", namespace = "http://a9.com/-/opensearch/extensions/time/1.0/")       
258        params = [param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8]
259        super(MyOSQuery, self).__init__(params)
260       
261    def doSearch(self, context):
262        ibbox = None
263        if context is not None and context.has_key(BBOX) and context[BBOX] is not None:
264            coords = context[BBOX].split(',')
265            try:
266                if len(coords) == 4:
267                    ibbox = create_st_setSRID(int(coords[0]),int(coords[1]),int(coords[2]),int(coords[3]))
268            except:
269                pass
270       
271        if not context.has_key(GUID) or context[GUID] is None:
272            return context['moles3EPB'].getObservationCollections(bbox = ibbox)       
273             
274        obj = context['moles3EPB'].getInstanceFromGUID(context[GUID])   
275        if obj is None:
276            return None
277        if type(obj) == CEDA_ObservationCollection:
278            return context['moles3EPB'].searchSelectiveLoadByInstance(obj, 'member') #need to add bbox & phenomTime
279        elif type(obj) == CEDA_Observation:
280            return context['moles3EPB'].searchSelectiveLoadByInstance(obj, 'result') #need to add bbox & phenomTime
281       
282
283class Subresult(object):
284    def __init__(self, iid, title, description, updated):
285        '''
286            Constructor
287            @param id: a unique identifier, eventually an URI
288            @param title: an atom.Entry instance
289            @param updated: the last time the record was updated                       
290        '''
291        self.id = iid
292        self.title = title
293        self.description = description       
294        self.updated = updated
Note: See TracBrowser for help on using the repository browser.