source: ndgCommon/trunk/ndg/common/src/models/MolesEntity.py @ 5177

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/ndgCommon/trunk/ndg/common/src/models/MolesEntity.py@5177
Revision 5177, 9.9 KB checked in by cbyrom, 12 years ago (diff)

Extend moles data model and schema to include the various new
metadata requested - updating the import/export methods + simplifying
object set up by allowing the use of the input dict to specify fields
+ extend test data and test suite.

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'''
6from xml.etree import cElementTree as ET
7import logging, datetime, re
8from ndg.common.src.lib.utilities import escapeSpecialCharacters
9from ndg.common.src.models.ndgObject import ndgObject
10
11class MolesEntity(object):
12   
13    # URL which points to the browse service - NB ensure this is properly defined
14    BROWSE_URL = "http://ndg.badc.rl.ac.uk:8080/view"
15   
16    def __init__(self, **inputs):
17        '''
18        Constructor - initialise the atom variables
19        '''
20        logging.info("Initialising MolesEntity")
21
22        # an array of Atom.Person objects
23        self.responsibleParties = []
24        self.deployments = {}
25        self.abbreviation = None
26        self.providerID = None
27        self.createdDate = None
28               
29        self.datasetLanguage = 'English'
30        self.metadataLanguage = 'English'
31       
32        self.updateFrequency = ''
33        self.lineage = ''
34        self.quality = ''
35
36        self.spatialResolution = None
37        self.verticalExtent = None
38       
39        # helper arrays to produce summary info for atom in templates
40        self.activities = []
41        self.obs = []
42        self.dpts = []
43        logging.info("MolesEntity initialised")
44       
45        # if inputs passed in as dict, add these now
46        if inputs:
47            logging.info("Adding info to moles entity from input dict")
48            logging.debug(inputs)
49            self.__dict__.update(inputs)
50
51
52    def addResponsibleParty(self, partyVals):
53        '''
54        Add a responsible party - using the input string format,
55        ' name | uri | role '
56        '''
57        logging.debug("Adding responsible party data")
58        from ndg.common.src.models.Atom import Person
59        if type(partyVals) is not list:
60            partyVals = [partyVals]
61       
62        for vals in partyVals:
63            rp = Person(personType = Person.RESPONSIBLE_PARTY_TYPE)
64            rp.fromString(vals)
65            self.responsibleParties.append(rp)
66        logging.debug("Finished adding responsible party data")
67
68       
69    def toXML(self):
70        '''
71        Convert the atom into XML representation and return this
72        @return: xml version of atom
73        '''
74        logging.info("Creating formatted XML version of MolesEntity")
75        molesEntity = ET.Element("moles:entity")
76        molesEntity.attrib["xmlns:moles"] = ndgObject.MOLES_NS
77       
78        molesISO = ET.SubElement(molesEntity, "moles:molesISO")
79        datasetLanguage = ET.SubElement(molesISO, "moles:datasetLanguage")
80        datasetLanguage.text = self.datasetLanguage
81        metadataLanguage = ET.SubElement(molesISO, "moles:metadataLanguage")
82        metadataLanguage.text = self.metadataLanguage
83
84        if self.responsibleParties:
85            rpElement = ET.SubElement(molesISO, "moles:responsibleParties")
86            logging.info("Adding responsible parties info")
87            for party in self.responsibleParties:
88                rpElement.append(party.toXML())
89
90        if self.updateFrequency:
91            updateFrequencyEl = ET.SubElement(molesISO, "moles:updateFrequency")
92            updateFrequencyEl.text = self.updateFrequency
93
94        if self.lineage:
95            lineageEl = ET.SubElement(molesISO, "moles:lineage")
96            lineageEl.text = self.lineage
97
98        if self.quality:
99            qualityEl = ET.SubElement(molesISO, "moles:quality")
100            qualityEl.text = self.quality
101
102        if self.spatialResolution:
103            srEl = ET.SubElement(molesISO, "moles:spatialResolution")
104            srEl.text = self.spatialResolution
105
106        if self.verticalExtent:
107            veEl = ET.SubElement(molesISO, "moles:verticalExtent")
108            veEl.text = self.verticalExtent
109
110        if self.abbreviation:
111            logging.info("Adding abbreviation element")
112            abbreviationElement = ET.SubElement(molesISO, "moles:abbreviation")
113            abbreviationElement.text = self.abbreviation
114
115        if self.providerID:
116            logging.info("Adding providerID element")
117            subElement = ET.SubElement(molesISO, "moles:providerID")
118            subElement.text = self.providerID
119           
120        # if there's a created date already defined, use this, otherwise assume this is the creation point
121        # so use current time
122        if not self.createdDate:
123            self.createdDate = datetime.datetime.today().strftime("%Y-%m-%dT%H:%M:%SZ")
124
125        createdElement = ET.SubElement(molesISO, "moles:created")
126        createdElement.text = self.createdDate
127
128        logging.info("XML version of MolesEntity created")
129        return molesEntity
130
131
132    def fromET(self, tree):
133        '''
134        Initialise MolesEntity object using an elementtree
135        @param tree: ElementTree with moles entity data
136        '''
137        logging.info("Ingesting data from ElementTree object")
138        authorElements = tree.findall('{%s}molesISO/{%s}responsibleParties/{%s}responsibleParty' \
139                                      %(ndgObject.MOLES_NS, ndgObject.MOLES_NS, ndgObject.MOLES_NS))
140        from ndg.common.src.models.Atom import Person
141        for authorElement in authorElements:
142            logging.debug("Adding atom author data")
143            author = Person(personType = Person.RESPONSIBLE_PARTY_TYPE)
144            author.fromETElement(authorElement)
145            self.responsibleParties.append(author)
146               
147        self.abbreviation = tree.findtext('{%s}molesISO/{%s}abbreviation' \
148                                          %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
149
150        self.providerID = tree.findtext('{%s}molesISO/{%s}providerID' \
151                                        %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
152
153        self.datasetLanguage = tree.findtext('{%s}molesISO/{%s}datasetLanguage' \
154                                             %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
155        self.metadataLanguage = tree.findtext('{%s}molesISO/{%s}metadataLanguage' \
156                                              %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
157        self.updateFrequency = tree.findtext('{%s}molesISO/{%s}updateFrequency' \
158                                              %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
159        self.lineage = tree.findtext('{%s}molesISO/{%s}lineage' \
160                                     %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
161        self.quality = tree.findtext('{%s}molesISO/{%s}quality' \
162                                     %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
163        self.spatialResolution = tree.findtext('{%s}molesISO/{%s}spatialResolution' \
164                                     %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
165        self.verticalExtent = tree.findtext('{%s}molesISO/{%s}verticalExtent' \
166                                     %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
167
168        createdDate = tree.findtext('{%s}molesISO/{%s}created' \
169                                    %(ndgObject.MOLES_NS, ndgObject.MOLES_NS)) or ""
170        if createdDate:
171            logging.debug("Adding created date")
172            self.createdDate = createdDate
173           
174        logging.info("Data ingested from tree")
175           
176           
177    def fromString(self, xmlString):
178        '''
179        Initialise MolesEntity object using an xmlString
180        @param xmlString: representation of atom as an XML string
181        '''
182        logging.info("Ingesting data from XML string")
183       
184        # now create elementtree with the XML string
185        logging.debug("Create elementtree instance with XML string")
186        # NB, there is every chance that the namespace will not be available in
187        # the input xmlString - since it is likely to be part of the Atom string
188        # passed in - and this will have the namespaces defined in the parent tag
189        # - check and add the moles NS if it is missing
190        xmlString = self.__addMolesNS(xmlString)
191       
192        tree = ET.fromstring(xmlString)
193        self.fromET(tree)
194        logging.info("Completed data ingest from XML string")
195
196
197    def __addMolesNS(self, xmlString):
198        '''
199        Check an XML string representation of the moles entity to see if it
200        contains the required moles namespace; if not, add it
201        '''
202        logging.debug("Checking if entity requires moles namespace adding")
203        if xmlString.find(ndgObject.MOLES_NS) > -1:
204            logging.debug("- namespace found - returning entity as is")
205            return
206
207        logging.debug("- namespace not found - adding this now")
208       
209        # firstly get the local namespace prefix name
210        prefix = re.search('<(\w+):', xmlString).group(1)
211        elementName = prefix + ':entity '
212       
213        # now do a replace on this to add in the namespace
214        xmlString = xmlString.replace(elementName, elementName + "xmlns:%s= '%s' " \
215                                      %(prefix, ndgObject.MOLES_NS))
216       
217        return xmlString
218
219       
220    def setAttribute(self, attributeName, attributeValue):
221        '''
222        Set the value of an atom attribute - and do some basic tidying up of the string content
223        - to escape any XML unfriendly characters
224        @param attributeName: name of the attribute whose value to set
225        @param attributeValue: value to set the attribute to 
226        '''
227        logging.debug("Setting attribute, %s, to %s" %(attributeName, attributeValue))
228        origValue = attributeValue
229       
230        # escape any special characters if a value has been specified
231        # NB, need to cope with both single values and arrays
232        if attributeValue:
233            if type(attributeValue) is list:
234                newVals = []
235                for val in attributeValue:
236                    newVals.append(escapeSpecialCharacters(val))
237                attributeValue = newVals
238            else:
239                attributeValue = escapeSpecialCharacters(attributeValue) 
240        setattr(self, attributeName, attributeValue)
Note: See TracBrowser for help on using the repository browser.