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

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

Add cmp method to DeploymentLink? to allow for object equality tests +
add new method to MolesEntity? to ensure that only unique deployment
links are added to the helper arrays + add new constructor input to
Atom to allow the content to be defined at creation.

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