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

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

Slight bug fix in browse, improvements in DIF rendering for BGS.

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