source: ndgCommon/trunk/ndg/common/src/models/abstractrecord.py @ 5231

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

Extend ndgcommon code for use with the OAI Info Editor - fix checking
for non-empty ETs - if these only have an attribute set on them, they
won't be evaluated to 'True' in an 'if' statement. Add methods for
getting bools from strings + for setting up select lists.

Line 
1'''
2 Abstract implementation of InterfaceRecord adding generic methods
3   
4 @author: C Byrom, Tessella Feb 2009
5'''
6from xml.etree import cElementTree as ET
7import logging, datetime, re
8from ndg.common.src.lib.ETxmlView import et2text
9from interfacerecord import InterfaceRecord
10from ndg.common.src.lib.utilities import DATE_FORMAT
11
12class AbstractRecord(InterfaceRecord):
13
14    STRING_MESSAGE = "%s type data record - attributes: "
15   
16    CREATED_DATE = 'createdDate'
17    ATTS_TO_SKIP = [CREATED_DATE, 'entryTermLastMod', 'listLastMod', 
18                    'createdDate', 'fields', 'changeNote']
19   
20    def __init__(self, et = None, **inputs):
21        '''
22        Constructor - initialise the CF Standard name object
23        @keyword et: elementtree entry representing a Standard Name entry - to
24        read in
25        '''
26        logging.debug("Initialising AbstractRecord object")
27
28        logging.debug("Initialising fields")
29        for att in self.__slots__:
30            setattr(self, att, '')
31
32        self.id = ''
33        self.createdDate = datetime.datetime.now().strftime(DATE_FORMAT)
34        logging.debug("Fields initialised")
35
36        if et != None:
37            self.fromET(et)
38
39        for key, val in inputs.items():
40            logging.debug("Adding inputs dict data: %s = %s" %(key, val))
41            setattr(self, key, val)
42
43        logging.debug("AbstractRecord initialised")
44
45
46    def isEmpty(self):
47        '''
48        Determine whether the record has any values set on it
49        @return True if the object is effectively empty, False otherwise
50        '''
51        for att in self.__slots__:
52            if att in self.ATTS_TO_SKIP:
53                continue
54           
55            if getattr(self, att):
56                return False
57       
58        return True
59           
60       
61    def __cmp__(self, other):
62        '''
63        Override standard compare to allow sorting on createdDate
64        @param other: other object with which to compare this object to
65        '''
66        if not other or not isinstance(other, InterfaceRecord):
67            return -1
68       
69        d0 = datetime.datetime.strptime(self.createdDate, DATE_FORMAT)
70        d1 = datetime.datetime.strptime(other.createdDate, DATE_FORMAT)
71        if self is other:
72            return 0
73        elif d0 == d1:
74            return 0
75        elif d0 < d1:
76            return -1
77        return 1
78
79
80    def __eq__(self, other):
81        '''
82        Override object equals to check for equality.  NB, ignore the createdDate
83        as this is not usually important
84        @param other: other object with which to compare this object to
85        @return True if objects are equal, False otherwise
86        '''
87        for att in self.__slots__:
88            if att in self.ATTS_TO_SKIP:
89                continue
90           
91            if getattr(self, att) != getattr(other, att):
92                return False
93
94        return True
95
96
97    def __ne__(self, other):
98        '''
99        Override object unequals to check for unequality.  NB, ignore the createdDate
100        as this is not usually important
101        @param other: other object with which to compare this object to
102        @return True if objects are equal, False otherwise
103        '''
104        return not self.__eq__(other)
105
106
107    def __str__(self):
108        outString = self.STRING_MESSAGE %type(self)
109        attString = ""
110        for att in self.__slots__:
111            if attString:
112                attString += ', '
113            attString += "%s = '%s'" %(att, getattr(self, att))
114       
115        return outString + attString
116
117
118    def toET(self):
119        '''
120        Convert the Record data into ElementTree representation and return this
121        @return: ElementTree version of data
122        '''
123        raise NotImplementedError("This is an interface class and this method has not " + \
124                                  "been implemented yet")
125
126       
127    def fromET(self, et):
128        '''
129        Extract and add data from an elementtree object
130        @param et: Elementtree object representing a Record data entry
131        '''
132        raise NotImplementedError("This is an interface class and this method has not " + \
133                                  "been implemented yet")
134
135
136    def toXMLString(self):
137        '''
138        Returns data as nicely formatted XML string
139        @return xmlString: record object in XML string representation
140        '''
141        xml = self.toET()
142
143        # create the string
144        logging.debug("Converting the elementtree object into a string")
145        # NB, the commented out approach is the simplest - but this doesn't
146        # preserve tab spacing and new lines
147        prettyXML = et2text(xml)#ET.tostring(xml)
148
149        logging.debug("Created formatted version of XML object")
150        return prettyXML
151
152           
153    def fromXMLString(self, xmlString):
154        '''
155        Initialise Record object using an xmlString
156        @param xmlString: representation of Record as an XML string
157        @return ElementTree representation of string
158        '''
159        logging.debug("Ingesting data from XML string")
160        logging.debug("Create elementtree instance with XML string")
161        tree = ET.fromstring(xmlString)
162        self.fromET(tree)
163        logging.debug("Completed data ingest")
164        return tree
165
166
167    def getRecordTypeName(self):
168        '''
169        Return the type of record, i.e. the class name, in a nice formatted
170        way
171        @return typeName: class name of record in formatted readable way
172        '''
173        logging.debug("Getting record type name for '%s' record" %type(self))
174        # get the class name, without the package info - there may be an easier way to do this??
175        typeName = str(type(self)).split('\'')[1].split('.')[-1]
176        # and fix any camelcase - putting into words
177        typeName = re.sub('([A-Z])', r" \1", typeName).strip()
178        logging.debug(" - returning type name, '%s'" %typeName)
179        return typeName
180   
181   
Note: See TracBrowser for help on using the repository browser.