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

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

Minor dif mods and configuration options for discovery standalone service

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        self.AccessConstraints=helper.getText(self.tree,'Access_Constraints')
85        self.UseConstraints=helper.getText(self.tree,'Use_Constraints')
86        self.distribution=[]
87        for e in helper.findall(self.tree,'Distribution'):
88            d=dict([(k,helper.getText(e,k)) for k in 
89                ('Fees','Distribution_Media','Distribution_Size','Distribution_Format')])
90            addit=0
91            for k in d: 
92                if d[k]!='': addit=1
93            if addit: self.distribution.append(d)
94        #need entity.parameters, entity.bbox, entity.timeCoverage, entity.curator, entity.creators
95        # nb, two ways of parameters being stored
96     
97        self.parameters=[]
98        for parameter in helper.findall(self.tree,'Parameters'):
99            name=''
100            for level in ['Category','Topic','Term','Variable','Detailed_Variable']:
101                    name+=helper.getText(parameter,level)+'>'
102            name=name.rstrip('>')
103            #print '[%s]\n%s'%(name,ET.tostring(parameter))
104            if name=='':
105                name=helper.getText(parameter,'.')#.text
106                if name is not None: 
107                    #self.parameters.append(name.replace('>','/'))
108                    while len(name.split('>'))<5:name+='>'
109            self.parameters.append(name)
110        self.parameters=collapse2(self.parameters)
111       
112        #sensors are pretty important too
113        self.sensors=[]
114        for sensor in helper.findall(self.tree,'Sensor_Name'):
115            s,l=helper.getText(sensor,'Short_Name'),helper.getText(sensor,'Long_Name')
116            self.sensors=shortLong(self.sensors,s,l)
117               
118        #and sources
119        self.sources=[]
120        for source in helper.findall(self.tree,'Source_Name'):
121            s,l=helper.getText(source,'Short_Name'),helper.getText(source,'Long_Name')
122            self.sources=shortLong(self.sources,s,l)
123
124        #load up information about spatial bounding box
125        self.bbox=Bounding(self.tree,helper,entity='DIF')
126       
127        #load up information about temporal extent
128        # nb, some DIFS use Stop Date, some use End Date
129        date=helper.find(self.tree,'Temporal_Coverage')
130        e1,e2=helper.getText(date,'Stop_Date'),helper.getText(date,'End_Date')
131        start=helper.getText(date,'Start_Date')
132        status=helper.getText(self.tree,'Data_Set_Progress')
133        if e1<>'':
134            self.timeCoverage=[(start,e1,status)]
135        else:
136            self.timeCoverage=[(start,e2,status)]
137       
138        #load up those silly paleo keywords
139        self.paleoKeywords=[]
140        paleoElements=helper.findall(self.tree,'Paleo_Temporal_Coverage')
141        for e in paleoElements:
142            self.paleoKeywords.append(helper.getText(e,'Chronostratigraphic_Unit'))
143           
144        #Data curator information
145        self.centre=DIFcontact(helper,helper.find(self.tree,'Data_Center'))
146        #self.curator=DIFcontact(helper,helper.find(self.tree,'Data_Curator'))
147       
148        #Data Creators
149        self.creators=[]
150        # Let's first see if we get an author out of the citation,
151        self.authors=helper.getText(self.tree,'Data_Set_Citation/Dataset_Creator') 
152        self.date=dateParse(helper.getText(self.tree,'Data_Set_Citation/Dataset_Release_Date'),'YYYY')
153        #if self.date=='': self.date='XXXX'
154        self.title=helper.getText(self.tree,'Data_Set_Citation/Dataset_Title')
155        self.briefCitation=''
156        if (self.authors!='' and self.date!='' and self.title!=''):
157            self.briefCitation='%s (%s): %s'%(self.authors,self.date,self.title)
158        #for now
159        self.citation=self.briefCitation
160       
161        #an empty element sends something back, we don't want that:
162        self.personnel=[DIFcontact(helper,f) for f in helper.findall(self.tree,'Personnel')]
163        #services
164        self.services=[]
165
166        for item in helper.findall(self.tree,'Related_URL'):
167            self.services.append(
168                DIFService(
169                 helper.getText(item,'URL_Content_Type'),
170                 helper.getText(item,'URL'),
171                 helper.getText(item,'Description') ))
172       
173        if self.ndgObject is None:
174            self.binding=None
175        else:
176            if self.ndgObject.discoveryURL is not None:
177                self.binding=DIFService('DISCOVERY',self.ndgObject.discoveryURL,'Discovery record')
178                #explicitly do late binding on NDG-B URL
179                #... and override contents in metadatarecord
180                B='%s__%s__%s'%(self.ndgObject.repository,'NDG-B1',self.ndgObject.localID)
181                Bobject=ndgObject(B,config=self.ndgObject.config)
182                bdone=0
183                if Bobject.gettable!=-1:
184                    for s in self.services:
185                        if s.contentType=='NDG_B_SERVICE': 
186                            s.url=Bobject.URL
187                            bdone=1
188                    if not bdone: self.services.append(
189                                DIFService('NDG_B_SERVICE',Bobject.URL,'NDG Browse Metadata Service'))
190            else: self.binding=None
191        if self.debug:
192           f=open('difs.log','a')
193           f.write('%s##\n%s\n##################################\n'%(self.entryID,self.xml))
194           f.close()
195
196
197import unittest
198
199class TestCase(unittest.TestCase):
200    """
201    """
202
203    inputFile = 'examples/neodc.eg1.dif'
204    inputFile2= 'examples/bodc.eg2.edmed.dif'
205    inputFile2= 'examples/bodc.eg3.difChange.dif'
206    inputFile2= 'examples/ndg.noc.soton.ac.uk__DIF__NOCSDAT162.xml'
207    configFile= 'config/ndgDiscovery.config'
208   
209    def setUp(self):
210        ''' Load example config and DIF files for testing '''
211        from xmlHandler2 import xmlHandler
212        x=xmlHandler(self.inputFile2)
213        self.dif=DIF(x.tree,et=1)
214        self.config=myConfig(self.configFile)
215
216    def testEntries(self):
217        ''' Testing the DIF object can be loaded and some key entries extracted '''
218        print 'Entry ID [%s]'%self.dif.entryID
219        print 'Author [%s]'%self.dif.authors
220        print 'Abstract [%s]'%self.dif.abstract
221        print 'BBox [%s]'%self.dif.bbox.boxes
222   
223    def testParameters(self):
224        ''' Testing obtaining parameters from an edmed dif in original format '''
225        print 'Parameters %s'%self.dif.parameters
226       
227    def testDifficult(self):
228        ''' Grab a test example from the internet and load it '''
229        from ndgRetrieve import ndgRetrieve
230        #testURI='grid.bodc.nerc.ac.uk__DIF__EDMED1048008'
231        testURI='neodc.nerc.ac.uk__DIF__NEODC_NEXTMAP'
232        uri=ndgObject(testURI,config=self.config)
233        status,xml=ndgRetrieve(uri,self.config)
234        self.assertEqual(status,1)
235        d=DIF(xml.tree,et=1)
236        print d.entryID,[str(i) for i in d.services]
237
238
239if __name__=="__main__":
240    unittest.main()
241
242       
243       
Note: See TracBrowser for help on using the repository browser.