source: TI05-delivery/ows_framework/trunk/ows_server/ows_server/models/stubB.py @ 2756

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/ows_framework/trunk/ows_server/ows_server/models/stubB.py@2756
Revision 2756, 9.9 KB checked in by lawrence, 12 years ago (diff)

Fix for ticket:820

Line 
1#!/usr/bin/env python
2#
3# This python code (will) handle all forms of stub-B and provide HTML
4# methods to the extent required by the NDG browse functionality.
5# NB, It would be cleaner to use Dom's way of doing things but we'd
6# need a schema for that ...
7# BNL April 2006
8#
9
10from Utilities import *
11from AccessControl import AccessControl
12from geoUtilities import Bounding
13from People import *
14from ndgObject import ndgObject
15#from DeploymentHandling import *
16try: #python 2.5
17    from xml.etree import ElementTree as ET
18except ImportError:
19    try:
20        # if you've installed it yourself it comes this way
21        import ElementTree as ET
22    except ImportError:
23        # if you've egged it this is the way it comes
24        from elementtree import ElementTree as ET
25
26
27def collapse2(keywords,split='>'):
28    ''' Take the last element of a DIF parameter tree entry, and put them in a dictionary
29    under the DIF category '''
30    d={}
31    for item in keywords:
32        line=item.split(split)
33        category=line[0]
34        if category not in d: d[category]=[]
35        while line<>[]:
36            c=line.pop()
37            if c<>'': 
38                if c<>category:
39                    d[category].append(c)
40                line=[]
41    return d
42
43
44def idconvert(helper,elem,config=None,idelem='dgMetadataID'):
45    ''' Given an elementTree element for a dgMetadataID, create
46    a standard ndg URI, and produce an ndgObject '''
47    id=helper.find(elem,idelem)
48    entryID='%s__%s__%s'%(helper.getText(id,'repositoryIdentifier'),
49                            helper.getText(id,'schemeIdentifier'),
50                            helper.getText(id,'localIdentifier'))
51    uri=ndgObject(entryID,config)
52    return uri
53
54class ndgLink:
55    ''' This is a holder for an ndgObject which has a name (and possibly abbreviation) '''
56    def __init__(self,name,abbrev,ndgO,label='',image=None):
57        self.ndgObject=ndgO
58        self.name=name
59        self.abbrev=abbrev
60        self.image=image
61        self.label=label
62        self.URL=ndgO.BURL
63    def toHTML(self):
64        ### needs to be finished
65        return self.ndgObject.URL
66
67class dataGranule:
68        ''' Provides support for data granule structures '''
69        def __init__(self,helper,elem,config,name=''):
70            self.elem=elem
71            self.constraints=AccessControl(helper.find(elem,'accessControlPolicy'))
72            self.name=name
73            self.uri=idconvert(helper,elem,config,idelem='dataModelID')
74            self.entryID=self.uri.uri
75
76class ObservationStation:
77    def __init__(self,h,e):
78        self.e=e
79        if e is None: return
80class DataProductionTool:
81    def __init__(self,h,e):
82        self.e=e
83        if e is None: return
84class Activity:
85    def __init__(self,h,e):
86        self.e=e
87        if e is None: return
88       
89def Deployments(elem,helper,config):
90    ''' This is the late June 2007 version '''
91    if elem is None: return None
92    types={'dptList':'dataproductiontool','activityList':'activity','obsStnList':'observationstation','deList':''}
93    names={'dptList':'Data Production Tools','activityList':'Activities','obsStnList':'Observation Stations','deList':'Data Entities'}
94    result={}
95    for alist in types:
96        blist=helper.find(elem,alist)
97        collection=[]
98        if blist is not None:
99            for object in blist:
100                uri=idconvert(helper,object,config=config)
101                name=helper.getText(object,'name')
102                shortName=helper.getText(object,'abbreviation')
103                collection.append((uri,name,shortName))
104            result[names[alist]]=collection
105    return result
106           
107class DataEntity:
108    def __init__(self,helper,element):
109        ''' Attempt to instantiate this stubB as a data entity'''
110        self.elem=element
111        self.helper=helper
112        #just one curator
113        self.curator=dgContact(self.elem.find('dgDataRoles/dgDataCurator'),ctype='organisation')
114        #possibly multiple creators
115        self.creators=[dgContact(i) for i in self.elem.findall('dgDataRoles/dgDataCreator')]
116        host,service = '','' # dummy for now
117        #possibly multiple granules
118        self.getGranules()
119        #bounding box, handled as a class because this is going to be difficult ...
120        self.bbox=Bounding(self.elem,entity='stubB')
121        self.temporal()
122        #parameters
123        plist=wrapGetText(self.elem,'dgDataSummary/dgParameterSummary/ParameterName',multiple=1)
124        self.parameters=collapse2(plist,split='/')
125       
126       
127    def getGranules(self):
128        ''' Load up the granule content within the entity '''
129        granList=self.elem.findall('dgDataGranule')
130        self.granules=[]
131        i=0
132        for item in granList:
133            i+=1
134            #following needs to be refactored when granule definition includes a proper name ...
135            name=wrapGetText(item,'dgGranuleSummary/dgGranuleName')
136            if name=='': name='Granule %s'%i
137            self.granules.append(dataGranule(self.helper,item,self.config,name=name))
138               
139    def temporal(self):
140        '''Instantiate the timeCoverage attribute by parsing for temporal coverage '''
141        t=self.elem.find('dgDataSummary/dgDataCoverage/dgTemporalCoverage/DateRange')
142        if t is not None:
143           try:
144                self.timeCoverage=(float(i.text) for i in t)
145           except:
146                self.timeCoverage=('',)
147                               
148        else:
149           t=self.elem.find('dgDataSummary/dgDataCoverage/dgTemporalCoverage/DateSingle')
150           try:
151                self.timeCoverage=(t.text,)
152           except:
153                self.timeCoverage=('',)
154
155class dgMetadataDescription:
156   
157    def __init__(self,helper,elem):
158        ''' Initialise a Metadata Description '''
159        n=idconvert(helper,elem)
160        self.uri=n.uri
161        self.abstract=helper.getText(elem,'abstract/abstractText')
162        self.texts=[]
163        self.onlineRefs=[]
164        for e in helper.findall(elem,'descriptionSection'):
165            self.texts.append((helper.getText(e,'dgDescriptionText'),helper.getText(e,'contentType')))
166        online=helper.findall(elem,'descriptionSection/descriptionOnlineReference/dgSimpleLink')
167        for o in online:
168            self.onlineRefs.append((helper.getText(o,'name'),helper.getText(o,'URI')))
169
170
171class stubB(DataEntity,ObservationStation,DataProductionTool,Activity):
172       
173        ''' Holds the stub-b document and provides methods which get and manipulate it '''
174       
175        def __init__(self,elem,config):
176               
177                '''Instantiate with an element tree elem '''
178               
179                self.tree=elem
180                self.metadataType='NDG-B1'
181                self.services=[]
182                self.config=config
183                self.citation=''
184                self.personnel=[] # for DIF compatiability for the moment.
185                self.parameters=None
186                self.granules=[]
187               
188                try:
189                        helper=nsdumb(self.tree)
190                        self.name=helper.getText(self.tree,'name')
191                except Exception,e:
192                        raise ValueError('Error instantiating stubB [%s]'%e)
193
194                self.ndgObject=idconvert(helper,self.tree,self.config)
195                self.entryID=self.ndgObject.uri
196               
197                #Note that the root of the ElementTree instance is dgMetadataRecord
198                #so we don't need (or want) that in our xpath expressions.
199               
200                self.constraints=AccessControl(helper.find(self.tree,'dgMetadataSecurity'))
201                self.abbreviation=helper.getText(self.tree,'abbreviation')
202                if self.abbreviation=='': self.abbreviation=self.name[0:min(15,len(self.name))]
203               
204                for i in ('dgDataEntity','dgActivity','dgDataProductionTool','dgObservationStation'):
205                    elem=helper.find(self.tree,i)
206                    if elem is not None: break
207                if elem is None:
208                    f=file('tmp.xml','w')
209                    f.write(self.xml)
210                    f.close()
211                    raise ValueError('StubB record does not contain an Activity, DE, DPT, ObsStn')
212                elif elem.tag=='dgDataEntity':
213                        DataEntity.__init__(self,helper,elem)
214                elif elem.tag=='dgActivity':
215                        Activity.__init__(self,helper,elem)
216                elif elem.tag=='dgDataProductionTool':
217                        DataProductionTool.__init__(self,helper,elem)
218                elif elem.tag=='dgObservationStation':
219                        ObservationStation.__init__(self,helper,elem)
220
221                self.description=dgMetadataDescription(helper,helper.find(self.tree,'dgMetadataDescription'))
222                self.abstract=self.description.abstract
223                self.stubBtype=elem.tag
224             
225                # now go get all the related links
226               
227                self.related=Deployments(helper.find(elem,'DeploymentSummary'),helper,self.config)
228
229
230if __name__=="__main__":
231    import unittest
232    import os.path
233   
234    de='examples/badc.nerc.ac.uk__NDG-B1__dataent_chablis.xml'
235    dpt='examples/badc.nerc.ac.uk__NDG-B1__dpt_11634276941110630.xml'
236   
237    class TestCase(unittest.TestCase):
238   
239            def testDE(self):
240                ''' Test rendering a DataEntity stubB '''
241                fname=de
242                self.doit(fname)
243               
244            def testDPT(self):
245                ''' Test rendering a Data Production Tool stubB '''
246                fname=dpt
247                self.doit(fname)
248               
249               
250            def doit(self,fname):
251                xml=open(fname,'r').read()
252                config=myConfig('ndgDiscovery.config')
253                layoutdir=config.get('layout','layoutdir')
254                x=stubB(xml,config)
255                y='''<?xml version="1.0" encoding="UTF-8"?>
256                    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
257                    <html xmlsns="http://www.w3.org/1999/xhtml" xml:lang="en">
258                            <head>
259                                    <META http-equiv="Content-Type" content="text/xhtml; charset=iso-8859-1"/>
260                                    <title>stubB</title>
261                                    <LINK media="all, screen" href="%s/layout/ndg.css" type="text/css" rel="stylesheet"/>
262                            </head> '''%layoutdir+x.toHTML(config)
263                ff=fname+'-output.html'
264                f=file(ff,'w')
265                f.write(y)
266               
267   
268    unittest.main()
269           
270           
Note: See TracBrowser for help on using the repository browser.