source: TI05-delivery/ows_framework/trunk/ows_server/ows_server/models/DIF.py @ 3093

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

Most of the coding for geospatial operators. Improvements
to results display for multiple bounding boxes.

Line 
1# python class to support methods on a DIF ... to conform with
2# renderEntity etc ...
3#
4from Utilities import *
5from geoUtilities import *
6from People2 import *
7from AccessControl import AccessControl
8from ETxmlView import loadET, nsdumb
9from ServiceBinding import DIFService
10from ndgObject import ndgObject
11from stubB import collapse2
12try: #python 2.5
13    from xml.etree import ElementTree as ET
14except ImportError:
15    try:
16        # if you've installed it yourself it comes this way
17        import ElementTree as ET
18    except ImportError:
19        # if you've egged it this is the way it comes
20        from elementtree import ElementTree as ET
21debug=1
22   
23def shortLong(targetList,s,l):
24    ''' Format a short-long name combination as a string, and add to a list if non-empty,
25    and a non-duplicate'''
26    r=''
27    if l<>'':
28        if s<>'': 
29            r='%s (%s)'%(l,s)
30        else:
31            r=l
32    elif s<>'': r=s
33    if r not in targetList: targetList.append(r)
34    return targetList
35
36class DIF:
37    ''' Supports the NASA GCMD DIF format for python operations,
38    note ... not a complete implementation, currently minimum to
39    show a reasonable piece of content '''
40    def __init__(self,xml,et=0,debug=0,ndgObj=None):
41       
42        '''Initialise a python dif instance based on an xml document (expected
43        to be an input string if et=0, otherwise an ElementTree instance) '''
44        if et:
45            try:
46                self.tree=xml
47                self.xml=ET.tostring(xml)
48            except:
49                raise TypeError,'DIF input is not a valid ElementTree instance'
50        else:
51            try:
52                self.tree=loadET(xml)
53                self.xml=xml
54            except: # for some reason we can't parse the document, and it's worth knowing why
55                if isinstance(xml,str):
56                    l=min(len(xml),300)-1
57                    if l!=len(xml):xml=xml[0:l]+'\n...'
58                    raise ValueError('DIF input cannot be parsed into an ElementTree instance:\n%s'%xml)
59                else:
60                    raise TypeError('DIF input of type [%s] needs to be a string!'%type(xml))
61       
62        self.debug=debug
63       
64        # if this is an ndgObject that'll have been sorted externally ...
65        self.ndgObject=ndgObj
66       
67        # now try and interpret it
68       
69        helper=nsdumb(self.tree)
70        self.metadataType='DIF'
71        if helper.strip(self.tree.tag)!=self.metadataType: 
72            self.tree=helper.find(self.tree,self.metadataType)
73            if self.tree is None: 
74                raise ValueError, 'DIF input does not include a DIF element:\n%s'%self.xml
75       
76        self.entryID=helper.getText(self.tree,'Entry_ID')
77        self.abstract=helper.getText(self.tree,'Summary')
78        self.name=helper.getText(self.tree,'Entry_Title')
79        self.abbreviation=self.name[0:min(5,len(self.name))]
80       
81        #Note that entity.constraints.html is about access control on the metadata,
82        #and so we don't populate this here ...
83        self.constraints=AccessControl(None)
84       
85        #need entity.parameters, entity.bbox, entity.timeCoverage, entity.curator, entity.creators
86        # nb, two ways of parameters being stored
87        self.parameters=[]
88        for parameter in helper.findall(self.tree,'Parameters'):
89            name=''
90            for level in ['Category','Topic','Term','Variable','Detailed_Variable']:
91                    name+=helper.getText(parameter,level)+'>'
92            name=name.rstrip('>')
93            #print '[%s]\n%s'%(name,ET.tostring(parameter))
94            if name=='':
95                name=helper.getText(parameter,'.')#.text
96                if name is not None: 
97                    #self.parameters.append(name.replace('>','/'))
98                    while len(name.split('>'))<5:name+='>'
99            self.parameters.append(name)
100        self.parameters=collapse2(self.parameters)
101       
102        #sensors are pretty important too
103        self.sensors=[]
104        for sensor in helper.findall(self.tree,'Sensor_Name'):
105            s,l=helper.getText(sensor,'Short_Name'),helper.getText(sensor,'Long_Name')
106            self.sensors=shortLong(self.sensors,s,l)
107               
108        #and sources
109        self.sources=[]
110        for source in helper.findall(self.tree,'Source_Name'):
111            s,l=helper.getText(source,'Short_Name'),helper.getText(source,'Long_Name')
112            self.sources=shortLong(self.sources,s,l)
113
114        #load up information about spatial bounding box
115        self.bbox=Bounding(self.tree,helper,entity='DIF')
116       
117        #load up information about temporal extent
118        # nb, some DIFS use Stop Date, some use End Date
119        date=helper.find(self.tree,'Temporal_Coverage')
120        e1,e2=helper.getText(date,'Stop_Date'),helper.getText(date,'End_Date')
121        start=helper.getText(date,'Start_Date')
122        status=helper.getText(self.tree,'Data_Set_Progress')
123        if e1<>'':
124            self.timeCoverage=[(start,e1,status)]
125        else:
126            self.timeCoverage=[(start,e2,status)]
127       
128        #load up those silly paleo keywords
129        self.paleoKeywords=[]
130        paleoElements=helper.findall(self.tree,'Paleo_Temporal_Coverage')
131        for e in paleoElements:
132            self.paleoKeywords.append(helper.getText(e,'Chronostratigraphic_Unit'))
133           
134        #Data curator information
135        self.centre=DIFcontact(helper,helper.find(self.tree,'Data_Center'))
136        #self.curator=DIFcontact(helper,helper.find(self.tree,'Data_Curator'))
137       
138        #Data Creators
139        self.creators=[]
140        # Let's first see if we get an author out of the citation,
141        self.authors=helper.getText(self.tree,'Data_Set_Citation/Dataset_Creator') 
142        self.date=dateParse(helper.getText(self.tree,'Data_Set_Citation/Dataset_Release_Date'),'YYYY')
143        #if self.date=='': self.date='XXXX'
144        self.title=helper.getText(self.tree,'Data_Set_Citation/Dataset_Title')
145        self.briefCitation=''
146        if (self.authors!='' and self.date!='' and self.title!=''):
147            self.briefCitation='%s (%s): %s'%(self.authors,self.date,self.title)
148        #for now
149        self.citation=self.briefCitation
150       
151        self.personnel=[DIFcontact(helper,f) for f in helper.findall(self.tree,'Personnel')]
152       
153        #services
154        self.services=[]
155
156        for item in helper.findall(self.tree,'Related_URL'):
157            self.services.append(
158                DIFService(
159                 helper.getText(item,'URL_Content_Type'),
160                 helper.getText(item,'URL'),
161                 helper.getText(item,'Description') ))
162       
163        if self.ndgObject is None:
164            self.binding=None
165        else:
166            if self.ndgObject.discoveryURL is not None:
167                self.binding=DIFService('DISCOVERY',self.ndgObject.discoveryURL,'Discovery record')
168                #explicitly do late binding on NDG-B URL
169                #... and override contents in metadatarecord
170                B='%s__%s__%s'%(self.ndgObject.repository,'NDG-B1',self.ndgObject.localID)
171                Bobject=ndgObject(B,config=self.ndgObject.config)
172                bdone=0
173                if Bobject.gettable!=-1:
174                    for s in self.services:
175                        if s.contentType=='NDG_B_SERVICE': 
176                            s.url=Bobject.URL
177                            bdone=1
178                    if not bdone: self.services.append(
179                                DIFService('NDG_B_SERVICE',Bobject.URL,'NDG Browse Metadata Service'))
180            else: self.binding=None
181        if self.debug:
182           f=open('difs.log','a')
183           f.write('%s##\n%s\n##################################\n'%(self.entryID,self.xml))
184           f.close()
185
186
187import unittest
188
189class TestCase(unittest.TestCase):
190    """
191    """
192
193    inputFile = 'examples/neodc.eg1.dif'
194    inputFile2= 'examples/bodc.eg2.edmed.dif'
195    inputFile2= 'examples/bodc.eg3.difChange.dif'
196    inputFile2= 'examples/ndg.noc.soton.ac.uk__DIF__NOCSDAT162.xml'
197    configFile= 'config/ndgDiscovery.config'
198   
199    def setUp(self):
200        ''' Load example config and DIF files for testing '''
201        from xmlHandler2 import xmlHandler
202        x=xmlHandler(self.inputFile2)
203        self.dif=DIF(x.tree,et=1)
204        self.config=myConfig(self.configFile)
205
206    def testEntries(self):
207        ''' Testing the DIF object can be loaded and some key entries extracted '''
208        print 'Entry ID [%s]'%self.dif.entryID
209        print 'Author [%s]'%self.dif.authors
210        print 'Abstract [%s]'%self.dif.abstract
211        print 'BBox [%s]'%self.dif.bbox.boxes
212   
213    def testParameters(self):
214        ''' Testing obtaining parameters from an edmed dif in original format '''
215        print 'Parameters %s'%self.dif.parameters
216       
217    def testDifficult(self):
218        ''' Grab a test example from the internet and load it '''
219        from ndgRetrieve import ndgRetrieve
220        #testURI='grid.bodc.nerc.ac.uk__DIF__EDMED1048008'
221        testURI='neodc.nerc.ac.uk__DIF__NEODC_NEXTMAP'
222        uri=ndgObject(testURI,config=self.config)
223        status,xml=ndgRetrieve(uri,self.config)
224        self.assertEqual(status,1)
225        d=DIF(xml.tree,et=1)
226        print d.entryID,[str(i) for i in d.services]
227
228
229if __name__=="__main__":
230    unittest.main()
231
232       
233       
Note: See TracBrowser for help on using the repository browser.