source: TI07-MOLES/trunk/PythonCode/wsgi/DIF.py @ 2433

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI07-MOLES/trunk/PythonCode/wsgi/DIF.py@2433
Revision 2433, 9.6 KB checked in by lawrence, 12 years ago (diff)

Fixes for ticket:722, changing to internal unicode (probably not complete),
with decode on the edge coming out ... fixes 722 but may have some
other problems now ...

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