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

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

Adjust atom to include atom type term ID as well as the vocab url - and
update the vocab data to include the terms for the various different
atom subtypes.

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        self._addDeploymentDetails(deploymentLink)
179
180        if deploymentID not in self.deployments:
181            logging.debug("Creating new deployment type: %s" %deploymentID)
182            self.deployments[deploymentID] = Deployments(deploymentID, deploymentLink)
183        else:
184            logging.debug("Adding to existing deployment")
185            deployment = self.deployments[deploymentID]
186            deployment.addDeploymentLinks(deploymentLink)
187
188        logging.info("New deployment link data added to moles entity")
189
190       
191    def _addDeploymentDetails(self, deploymentLink):
192        '''
193        Add deployment details to local arrays for easy access by templates
194        '''
195        deploymentType = None
196        # first, determine type of deployment
197        if deploymentLink.vocabUrl.startswith(VTD.TERM_DATA[VTD.ACTIVITY_TERM].vocabURL):
198            deploymentType = self.activities
199        elif deploymentLink.vocabUrl.startswith(VTD.TERM_DATA[VTD.OBS_TERM].vocabURL):
200            deploymentType = self.obs
201        elif deploymentLink.vocabUrl.startswith(VTD.TERM_DATA[VTD.DPT_TERM].vocabURL):
202            deploymentType = self.dpts
203        else:
204            return
205
206        # Now check if this has already been added; return if so
207        for link in deploymentType:
208            if link == deploymentLink:
209                return
210
211        deploymentType.append(deploymentLink)
212
213       
214    def toXML(self):
215        '''
216        Convert the atom into XML representation and return this
217        @return: xml version of atom
218        '''
219        logging.info("Creating formatted XML version of MolesEntity")
220        molesEntity = ET.Element("moles:entity")
221        molesEntity.attrib["xmlns:moles"] = "http://ndg.nerc.ac.uk/schema/moles2alpha"
222       
223        molesISO = ET.SubElement(molesEntity, "moles:molesISO")
224        datasetLanguage = ET.SubElement(molesISO, "moles:datasetLanguage")
225        datasetLanguage.text = self.datasetLanguage
226        metadataLanguage = ET.SubElement(molesISO, "moles:metadataLanguage")
227        metadataLanguage.text = self.metadataLanguage
228
229        if self.responsibleParties:
230            rpElement = ET.SubElement(molesISO, "moles:responsibleParties")
231            logging.info("Adding responsible parties info")
232            for party in self.responsibleParties:
233                rpElement.append(party.toXML())
234
235        if self.abbreviation:
236            logging.info("Adding abbreviation element")
237            abbreviationElement = ET.SubElement(molesISO, "moles:abbreviation")
238            abbreviationElement.text = self.abbreviation
239
240        if self.providerID:
241            logging.info("Adding providerID element")
242            subElement = ET.SubElement(molesISO, "moles:providerID")
243            subElement.text = self.providerID
244
245        if self.deployments:
246            deploymentsElement = ET.SubElement(molesISO, "moles:deployments")
247           
248            for deployment in self.deployments:
249                deploymentsElement.append(self.deployments[deployment].toET())
250           
251        # if there's a created date already defined, use this, otherwise assume this is the creation point
252        # so use current time
253        if not self.createdDate:
254            self.createdDate = datetime.datetime.today().strftime("%Y-%m-%dT%H:%M:%SZ")
255
256        createdElement = ET.SubElement(molesISO, "moles:created")
257        createdElement.text = self.createdDate
258
259        logging.info("XML version of MolesEntity created")
260        return molesEntity
261
262
263    def fromET(self, tree):
264        '''
265        Initialise MolesEntity object using an elementtree
266        @param tree: ElementTree with moles entity data
267        '''
268        logging.info("Ingesting data from ElementTree object")
269       
270        authorElements = tree.findall('molesISO/responsibleParties/responsibleParty')
271        from ndgUtils.models.Atom import Person
272        for authorElement in authorElements:
273            logging.debug("Adding atom author data")
274            author = Person(tagName = 'responsibleParty', namespace = 'moles')
275            author.fromETElement(authorElement)
276            self.responsibleParties.append(author)
277               
278        self.abbreviation = tree.findtext('molesISO/abbreviation')
279
280        self.providerID = tree.findtext('molesISO/providerID')
281
282        self.datasetLanguage = tree.findtext('molesISO/datasetLanguage')
283        self.metadataLanguage = tree.findtext('molesISO/metadataLanguage')
284
285        createdDate = tree.findtext('molesISO/created')
286        if createdDate:
287            logging.debug("Adding created date")
288            self.createdDate = createdDate
289           
290        deploymentElements = tree.findall('molesISO/deployments/deployment')
291        for deploymentElement in deploymentElements:
292            self._addDeploymentData(deploymentElement)
293           
294        logging.info("Data ingested from tree")
295
296
297    def _addDeploymentData(self, deploymentElement):
298        '''
299        Parse a deployment element and extract all the required data from it
300        @param deploymentElement: ElementTree element representing a deployment element
301        '''
302        id = deploymentElement.attrib.get('id')
303        startDate = deploymentElement.findtext('startDate')
304        endDate = deploymentElement.findtext('endDate')
305        linkElements = deploymentElement.findall('link')
306        self.addDeployment(id, startDate, endDate)
307        for linkElement in linkElements:
308            contentURL = linkElement.attrib.get('href')
309            vocabURL = linkElement.attrib.get('rel')
310            title = linkElement.attrib.get('title')
311            self.addDeploymentLink(id, contentURL, vocabURL, title = title)
312           
313           
314    def fromString(self, xmlString):
315        '''
316        Initialise MolesEntity object using an xmlString
317        @param xmlString: representation of atom as an XML string
318        '''
319        logging.info("Ingesting data from XML string")
320       
321        # firstly, remove any namespaces used - to avoid problems with elementtree
322        logging.debug("Stripping moles namespace from string to allow easy handling with elementtree")
323        xmlString = xmlString.replace('moles:', '')
324
325        # now create elementtree with the XML string
326        logging.debug("Create elementtree instance with XML string")
327        tree = ET.fromstring(xmlString)
328        self.fromET(tree)
329        logging.info("Completed data ingest from XML string")
330
331       
332    def setAttribute(self, attributeName, attributeValue):
333        '''
334        Set the value of an atom attribute - and do some basic tidying up of the string content
335        - to escape any XML unfriendly characters
336        @param attributeName: name of the attribute whose value to set
337        @param attributeValue: value to set the attribute to 
338        '''
339        logging.debug("Setting attribute, %s, to %s" %(attributeName, attributeValue))
340        origValue = attributeValue
341       
342        # escape any special characters if a value has been specified
343        # NB, need to cope with both single values and arrays
344        if attributeValue:
345            if type(attributeValue) is list:
346                newVals = []
347                for val in attributeValue:
348                    newVals.append(escapeSpecialCharacters(val))
349                attributeValue = newVals
350            else:
351                attributeValue = escapeSpecialCharacters(attributeValue) 
352        setattr(self, attributeName, attributeValue)
Note: See TracBrowser for help on using the repository browser.