source: TI07-MOLES/trunk/StubB/XSLT/browse/portal/cgi/stubB.py @ 911

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI07-MOLES/trunk/StubB/XSLT/browse/portal/cgi/stubB.py@911
Revision 911, 7.6 KB checked in by lawrence, 14 years ago (diff)

Refactoring browse portal to clearly separate out the service bindings.

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# BNL April 2006
6#
7import ElementTree as ET
8from renderEntity import renderEntity
9from Utilities import *
10from ServiceBinding import *
11       
12class AccessControl:
13       
14        ''' Handle the access control metadata and provide three attributes of the
15        access control: exists (existence), status (modified elsewhere for whether
16        user can access data), and html (a message about the constraints). '''
17       
18        def __init__(self,e):
19                if e is None:
20                        self.status=1
21                        self.exist=0
22                        self.html=''
23                else:
24                        self.status=1
25                        self.exist=1
26                        self.html='constraints'
27       
28class Name:
29        ''' Handles the name type '''
30        def __init__(self,element):
31                if element is None:
32                        self.name=''
33                        return
34                if wrapGetText(element,'nameOrder')=='L2R':
35                        o=('title','initials','familyName')
36                else:
37                        o=('title','familyName','personalName')
38                self.name=''
39                for i in o: self.name+=' '+ wrapGetText(element,i)
40        def __str__(self):
41                return self.name
42       
43class dgContact:
44        '''A simple summary of contact information for an organisation or a person '''
45        #want to contract organisations and people into one simple type here ...
46        #This is moles 1.2.3 ... hopefully we can improve this ...
47        def __init__(self,element,ctype='org'):
48                ''' Instantiate a MOLES person element '''
49                self.elem=element
50                if self.elem is None: return
51                self.data={}
52                self.data['name']=Name(self.elem.find('dgRoleHolder/dgPerson/name'))
53                if ctype=='org':
54                        base='dgRoleHolder/dgOrganisation/'
55                else:
56                        base='dgRoleHolder/dgPerson/'
57                self.data['org']=wrapGetText(self.elem,base+'name')
58                self.data['email']=wrapGetText(self.elem,base+'contactDetails/eMail')
59                self.data['phone']=wrapGetText(self.elem,'contactDetails/telephone')
60                self.data['url']=wrapGetText(self.elem,'contactDetails/URI')
61        def toHTML(self):
62                ''' Convert to simple HTML '''
63                labels={'name':'','org':'Organisation: ','email':'Email: ','phone':'Phone: '}
64                html='<p>'
65                for item in ('name','org','email','phone'):
66                        if str(item) !='': html+='%s%s%s'%(labels[item],self.data[item],'<br/>')
67                html+='</p>'
68                return html
69               
70class Bounding:
71        ''' Separated out because this may change with versions '''
72        def __init__(self,elem):
73                '''Parse a data entity and load a bounding box '''
74                North=wrapGetText(elem,
75                        'dgDataSummary/dgDataCoverage/dgSpatialCoverage/BoundingBox/LimitNorth')
76                South=wrapGetText(elem,
77                        'dgDataSummary/dgDataCoverage/dgSpatialCoverage/BoundingBox/LimitSouth')
78                West=wrapGetText(elem,
79                        'dgDataSummary/dgDataCoverage/dgSpatialCoverage/BoundingBox/LimitWest')
80                East=wrapGetText(elem,
81                        'dgDataSummary/dgDataCoverage/dgSpatialCoverage/BoundingBox/LimitEast')
82                try:
83                        self.box=[float(i) for i in [North, South,West, East]]
84                except:
85                        self.box=None
86        def toHTML(self):
87                if self.box is not None:
88                        html='''<p>
89                                Limit North: %s <br/>
90                                Limit South: %s <br/>
91                                Limit West: %s <br/>
92                                Limit East: %s <br/>   
93                                </p>'''%self.box
94                else:
95                        html='No bounding box available'
96                return html     
97               
98               
99class dataGranule:
100        ''' Provides support for data granule structures '''
101        def __init__(self,elem):
102                self.elem=elem
103                self.constraints=AccessControl(elem.find('accessControlPolicy'))
104                self.binding=ServiceBinding('A',elem.find('dataModelID'))
105                self.Aurl=self.binding.url
106       
107class DataEntity:
108        def __init__(self,element):
109                ''' Attempt to instantiate this stubB as a data entity'''
110                self.elem=element
111                #just one curator
112                self.curator=dgContact(self.elem.find('dgDataRoles/dgDataCurator'),ctype='org')
113                #possibly multiple creators
114                self.creators=[dgContact(i) for i in self.elem.findall('dgDataRoles/dgDataCreator')]
115                host,service = '','' # dummy for now
116                #possibly multiple granules
117                self.getGranules()
118                #bounding box, handled as a class because this is going to be difficult ...
119                self.bbox=Bounding(self.elem)
120                self.temporal()
121                #parameters
122                self.parameters=wrapGetText(self.elem,'dgDataSummary/dgParameterSummary/ParameterName',multiple=1)
123               
124        def getGranules(self):
125                ''' Load up the granule content within the entity '''
126                granList=self.elem.findall('dgDataGranule')
127                self.granules=[]
128                for item in granList:
129                        self.granules.append(dataGranule(item))
130               
131        def temporal(self):
132                '''Instantiate the timeCoverage attribute by parsing for temporal coverage '''
133                t=self.elem.find('dgDataSummary/dgDataCoverage/dgTemporalCoverage/DateRange')
134                if t is not None:
135                        try:
136                                self.timeCoverage=[float(i.text) for i in t]
137                        except:
138                                self.timeCoverage='No time information'
139                else:
140                        t=self.elem.find('dgDataSummary/dgDataCoverage/dgTemporalCoverage/DateSingle')
141                        try:
142                                self.timeCoverage=t.text
143                        except:
144                                self.timeCoverage='No time information'
145
146
147class stubB(DataEntity):
148       
149        ''' Holds the stub-b document and provides methods which get and manipulate it '''
150       
151        def __init__(self,xml,makeHTML=None, ServiceBinding=ServiceBinding):
152               
153                '''Instantiate by parsing an xml document passed in as a string '''
154               
155                self.makeHTML=makeHTML
156                self.metadataType='stubB'
157                self.labels={'activity':'Activity ','observationstation':'Observation Station ',
158                                        'dataproductiontool':'Data Production Tool ','dgDataEntity':'Data Entity '}
159               
160                try:
161                        self.xml=xml
162                        self.tree=ET.fromstring(self.xml)
163                        self.name=wrapGetText(self.tree,'name')
164                except:
165                        self.xml=None
166                        self.tree=None
167                        self.name='Not Found'
168                        return
169               
170                #Note that the root of the ElementTree instance is dgMetadataRecord
171                #so we don't need (or want) that in our xpath expressions.
172               
173                self.constraints=AccessControl(self.tree.find('dgMetadataRecord/dgMetadataSecurity'))
174                self.abbreviation=wrapGetText(self.tree,'abbreviation')
175               
176                elem=self.tree.find('dgDataEntity')
177                if elem is not None:
178                        DataEntity.__init__(self,elem)
179                        self.type='dgDataEntity'
180                        self.others=('activity','observationstation','dataproductiontool')
181                       
182                elem=self.tree.find('dgActivity')
183                if elem is not None:
184                        self.type='dgActivity'
185                        self.others=('dgDataEntity','observationstation','dataproductiontool')
186                       
187                elem=self.tree.find('dgDataProductionTool')
188                if elem is not None:
189                        self.type='dgDataProductionTool'
190                        self.others=('dgDataEntity','observationstation','activity')
191               
192                elem=self.tree.find('dgObservationStation')
193                if elem is not None:
194                        self.type='dgObservationStation'
195                        self.others=('dgDataEntity','dataproductiontool','activity')
196
197                self.abstract=wrapGetText(self.tree,'dgMetadataDescription/abstract/abstractText')
198               
199                self.binding=ServiceBinding('B',self.tree.find('dgMetadataID'))
200                self.Burl=self.binding.url
201               
202                # now go get all the related links
203                self.related=[]
204                for related in self.tree.findall(self.type+'/RelatedDeployment'):
205                        deployment=['empty',[]]  #something should eventually go in the empty slot ...
206                        for item in self.others:
207                                subitems=related.findall(item)
208                                if subitems != []:
209                                        aa=[]
210                                        for subitem in subitems:
211                                                name=wrapGetText(subitem,'name')
212                                                binding=ServiceBinding('B',subitem.find('dgMetadataID'))
213                                                aa.append([name,binding.url])
214                                        deployment[1].append([self.labels[item],aa])
215                        self.related.append(deployment)
216       
217        def toHTML(self):
218                if self.tree is not None:
219                        return self.makeHTML(self)
220                else:
221                        return 'No Valid Stub-B'
222       
223if __name__=="__main__":
224       
225        xml=open("../../exampleB/methyl.example.xml",'r').read()
226        x=stubB(xml,makeHTML=renderEntity)
227        y='''<?xml version="1.0" encoding="UTF-8"?>
228                <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
229                <html xmlsns="http://www.w3.org/1999/xhtml" xml:lang="en">
230                        <head>
231                                <META http-equiv="Content-Type" content="text/xhtml; charset=iso-8859-1"/>
232                                <title>stubB</title>
233                                <LINK media="all, screen" href="../layout/style.css" type="text/css" rel="stylesheet"/>
234                        </head> '''+x.toHTML()
235        print y
Note: See TracBrowser for help on using the repository browser.