source: exist/trunk/python/ndgUtils/models/MolesEntity.py @ 4209

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/exist/trunk/python/ndgUtils/models/MolesEntity.py@4209
Revision 4209, 13.1 KB checked in by cbyrom, 11 years ago (diff)

Move the Atom and MolesEntity? models, and their associated Utilities class
to the ndgUtils package to allow sensible re-use with the ows_server
stack + refactor references accordingly.

Line 
1'''
2 Class representing moles data that is too structured to be included in the basic Atom elements
3 
4 @author: C Byrom, Tessella Jun 2008
5'''
6try: #python 2.5
7    from xml.etree import cElementTree as ET
8except ImportError:
9    try:
10        # if you've installed it yourself it comes this way
11        import cElementTree as ET
12    except ImportError:
13        # if you've egged it this is the way it comes
14        from ndgUtils.elementtree import cElementTree as ET
15import sys, logging, re, datetime
16from ndgUtils.vocabtermdata import VocabTermData as VTD
17from utilities import getTripleData, escapeSpecialCharacters, tidyUpParameters
18
19class DeploymentLink(object):
20   
21    def __init__(self, url, vocabUrl, title=None):
22        '''
23        Constructor - initialise the deployment link object
24        '''
25        self.url = url
26        self.vocabUrl = vocabUrl
27        self.title = title
28       
29    def toXML(self):
30        logging.info("Creating XML version of Deployment link element")
31        link = self.toET()
32        tree = ET.ElementTree(link)
33        logging.info("XML version of Deployment link element created")
34        return tree
35       
36    def toET(self):
37        logging.info("Creating ElementTree version of Deployment link element")
38        link = ET.Element("link")
39        link.attrib["href"] = self.url
40        link.attrib["rel"] = self.vocabUrl
41        if self.title:
42            link.attrib["title"] = tidyUpParameters(self.title)
43
44        logging.info("ElementTree version of Deployment element link created")
45        return link
46           
47
48class Deployments(object):
49   
50    def __init__(self, id, deploymentLinks, startDate=None, endDate=None):
51        '''
52        Constructor - initialise the deployments object
53        '''
54        self.id = id
55        # ensure deployments is an array
56        self.deploymentLinks = []
57        if deploymentLinks:
58            self.addDeploymentLinks(deploymentLinks)
59        self.startDate = startDate
60        self.endDate = endDate
61       
62    def toXML(self):
63        logging.info("Creating XML version of Deployments element")
64        deployments = self.toET()
65        tree = ET.ElementTree(deployments)
66        logging.info("XML version of Deployments element created")
67        return tree
68
69
70    def toET(self):
71        logging.info("Creating ElementTree version of Deployments element")
72        deploymentElement = ET.Element("moles:deployment")
73        deploymentElement.attrib["id"] = self.id
74        startElement = ET.SubElement(deploymentElement, "moles:startDate")
75        startElement.text = self.startDate
76        endElement = ET.SubElement(deploymentElement, "moles:endDate")
77        endElement.text = self.endDate
78       
79        for deploymentLink in self.deploymentLinks:
80            deploymentElement.append(deploymentLink.toET())
81        logging.info("ElementTree version of Deployments element created")
82        return deploymentElement
83   
84   
85    def addDeploymentLinks(self, deploymentLinks):
86        logging.info("Adding deployment links to deployment")
87        if type(deploymentLinks) != type([]):
88            deploymentLinks = [deploymentLinks]
89        for deploymentLink in deploymentLinks:
90            # do uniqueness check
91            if deploymentLink not in self.deploymentLinks:
92                self.deploymentLinks.append(deploymentLink)
93        logging.info("Deployment links added to deployment")
94       
95
96class MolesEntity(object):
97   
98    # URL which points to the browse service - NB ensure this is properly defined
99    BROWSE_URL = "http://ndg.badc.rl.ac.uk:8080/view"
100
101   
102    def __init__(self):
103        '''
104        Constructor - initialise the atom variables
105        '''
106        logging.info("Initialising MolesEntity")
107
108        # an array of Atom.Person objects
109        self.responsibleParties = []
110        self.deployments = {}
111        self.abbreviation = None
112        self.providerID = None
113        self.createdDate = None
114               
115        self.datasetLanguage = 'English'
116        self.metadataLanguage = 'English'
117       
118        # helper arrays to produce summary info for atom in templates
119        self.activities = []
120        self.obs = []
121        self.dpts = []
122        logging.info("MolesEntity initialised")     
123
124
125    def addResponsibleParty(self, partyVals):
126        '''
127        Add a responsible party - using the input string format,
128        ' name | uri | role '
129        '''
130        logging.debug("Adding responsible party data")
131        from ndgUtils.models.Atom import Person
132        if type(partyVals) is not list:
133            partyVals = [partyVals]
134       
135        for vals in partyVals:
136            rp = Person(tagName = 'responsibleParty', namespace = 'moles')
137            rp.fromString(vals)
138            self.responsibleParties.append(rp)
139        logging.debug("Finished adding responsible party data")
140
141
142
143    def addDeployment(self, deploymentID, startDate=None, endDate=None):
144        '''
145        Add a deployment to the dictionary - ensuring it is unique and has been formatted and tidied appropriately
146        @param deploymentID: ID of the deployment - acts as a key in the deployments dictionary
147        @keyword startDate: optional start date
148        @keyword endDate: optional end date
149        '''
150        logging.info("Adding new deployment data to moles entity")
151        self.deployments[deploymentID] = Deployments(deploymentID, None, startDate=startDate, endDate=endDate)
152        logging.info("New deployment data added to moles entity")
153
154
155    def addDeploymentLink(self, deploymentID, contentURL, vocabURL, title=None):
156        '''
157        Add a deployment link to the dictionary - ensuring it is unique and has been formatted and tidied appropriately
158        @param deploymentID: ID of the deployment - acts as a key in the deployments dictionary
159        @param contentURL: url to deployment content
160        @param vocabURL: url to vocab term identifying type of deployment content
161        @keyword title: title string to display with deployment link
162        '''
163        logging.info("Adding new deployment link data to moles entity")
164        logging.debug("contentURL: '%s', vocabURL: '%s', title: '%s'" %(contentURL, vocabURL, title))
165        deploymentLink = DeploymentLink(contentURL, vocabURL, title=title)
166
167        logging.info(VTD.TERM_DATA[VTD.ACTIVITY_TERM].vocabURL)
168        if vocabURL.startswith(VTD.TERM_DATA[VTD.ACTIVITY_TERM].vocabURL) and \
169            vocabURL not in self.activities:
170            self.activities.append(deploymentLink)
171        elif vocabURL.startswith(VTD.TERM_DATA[VTD.OBS_TERM].vocabURL) and \
172            vocabURL not in self.obs:
173            self.obs.append(deploymentLink)
174        elif vocabURL.startswith(VTD.TERM_DATA[VTD.DPT_TERM].vocabURL) and \
175            vocabURL not in self.dpts:
176            self.dpts.append(deploymentLink)
177
178        if deploymentID not in self.deployments:
179            logging.debug("Creating new deployment type: %s" %deploymentID)
180            self.deployments[deploymentID] = Deployments(deploymentID, deploymentLink)
181        else:
182            logging.debug("Adding to existing deployment")
183            deployment = self.deployments[deploymentID]
184            deployment.addDeploymentLinks(deploymentLink)
185
186        logging.info("New deployment link data added to moles entity")
187       
188       
189    def toXML(self):
190        '''
191        Convert the atom into XML representation and return this
192        @return: xml version of atom
193        '''
194        logging.info("Creating formatted XML version of MolesEntity")
195        molesEntity = ET.Element("moles:entity")
196        molesEntity.attrib["xmlns:moles"] = "http://ndg.nerc.ac.uk/schema/moles2alpha"
197       
198        molesISO = ET.SubElement(molesEntity, "moles:molesISO")
199        datasetLanguage = ET.SubElement(molesISO, "moles:datasetLanguage")
200        datasetLanguage.text = self.datasetLanguage
201        metadataLanguage = ET.SubElement(molesISO, "moles:metadataLanguage")
202        metadataLanguage.text = self.metadataLanguage
203
204        if self.responsibleParties:
205            rpElement = ET.SubElement(molesISO, "moles:responsibleParties")
206            logging.info("Adding responsible parties info")
207            for party in self.responsibleParties:
208                rpElement.append(party.toXML())
209
210        if self.abbreviation:
211            logging.info("Adding abbreviation element")
212            abbreviationElement = ET.SubElement(molesISO, "moles:abbreviation")
213            abbreviationElement.text = self.abbreviation
214
215        if self.providerID:
216            logging.info("Adding providerID element")
217            subElement = ET.SubElement(molesISO, "moles:providerID")
218            subElement.text = self.providerID
219
220        if self.deployments:
221            deploymentsElement = ET.SubElement(molesISO, "moles:deployments")
222           
223            for deployment in self.deployments:
224                deploymentsElement.append(self.deployments[deployment].toET())
225           
226        # if there's a created date already defined, use this, otherwise assume this is the creation point
227        # so use current time
228        if not self.createdDate:
229            self.createdDate = datetime.datetime.today().strftime("%Y-%m-%dT%H:%M:%SZ")
230
231        createdElement = ET.SubElement(molesISO, "moles:created")
232        createdElement.text = self.createdDate
233
234        logging.info("XML version of MolesEntity created")
235        return molesEntity
236
237
238    def fromET(self, tree):
239        '''
240        Initialise MolesEntity object using an elementtree
241        @param tree: ElementTree with moles entity data
242        '''
243        logging.info("Ingesting data from ElementTree object")
244       
245        authorElements = tree.findall('molesISO/responsibleParties/responsibleParty')
246        from ndgUtils.models.Atom import Person
247        for authorElement in authorElements:
248            logging.debug("Adding atom author data")
249            author = Person(tagName = 'responsibleParty', namespace = 'moles')
250            author.fromETElement(authorElement)
251            self.responsibleParties.append(author)
252               
253        self.abbreviation = tree.findtext('molesISO/abbreviation')
254
255        self.providerID = tree.findtext('molesISO/providerID')
256
257        self.datasetLanguage = tree.findtext('molesISO/datasetLanguage')
258        self.metadataLanguage = tree.findtext('molesISO/metadataLanguage')
259
260        createdDate = tree.findtext('molesISO/created')
261        if createdDate:
262            logging.debug("Adding created date")
263            self.createdDate = createdDate
264           
265        deploymentElements = tree.findall('molesISO/deployments/deployment')
266        for deploymentElement in deploymentElements:
267            self._addDeploymentData(deploymentElement)
268           
269        logging.info("Data ingested from tree")
270
271
272    def _addDeploymentData(self, deploymentElement):
273        '''
274        Parse a deployment element and extract all the required data from it
275        @param deploymentElement: ElementTree element representing a deployment element
276        '''
277        id = deploymentElement.attrib.get('id')
278        startDate = deploymentElement.findtext('startDate')
279        endDate = deploymentElement.findtext('endDate')
280        linkElements = deploymentElement.findall('link')
281        self.addDeployment(id, startDate, endDate)
282        for linkElement in linkElements:
283            contentURL = linkElement.attrib.get('href')
284            vocabURL = linkElement.attrib.get('rel')
285            title = linkElement.attrib.get('title')
286            self.addDeploymentLink(id, contentURL, vocabURL, title = title)
287           
288           
289    def fromString(self, xmlString):
290        '''
291        Initialise MolesEntity object using an xmlString
292        @param xmlString: representation of atom as an XML string
293        '''
294        logging.info("Ingesting data from XML string")
295       
296        # firstly, remove any namespaces used - to avoid problems with elementtree
297        logging.debug("Stripping moles namespace from string to allow easy handling with elementtree")
298        xmlString = xmlString.replace('moles:', '')
299
300        # now create elementtree with the XML string
301        logging.debug("Create elementtree instance with XML string")
302        tree = ET.fromstring(xmlString)
303        self.fromET(tree)
304        logging.info("Completed data ingest from XML string")
305
306       
307    def setAttribute(self, attributeName, attributeValue):
308        '''
309        Set the value of an atom attribute - and do some basic tidying up of the string content
310        - to escape any XML unfriendly characters
311        @param attributeName: name of the attribute whose value to set
312        @param attributeValue: value to set the attribute to 
313        '''
314        logging.debug("Setting attribute, %s, to %s" %(attributeName, attributeValue))
315        origValue = attributeValue
316       
317        # escape any special characters if a value has been specified
318        # NB, need to cope with both single values and arrays
319        if attributeValue:
320            if type(attributeValue) is list:
321                newVals = []
322                for val in attributeValue:
323                    newVals.append(escapeSpecialCharacters(val))
324                attributeValue = newVals
325            else:
326                attributeValue = escapeSpecialCharacters(attributeValue) 
327        setattr(self, attributeName, attributeValue)
Note: See TracBrowser for help on using the repository browser.