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

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

Tighten up package definition to allow overlap with ndg.security +
adjust resource finding for this scenario + improve fileutilities
cleandir method, using python code rather than system ops to do work +
relax equality method for abstract records slightly.

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                # NB, allow comparison of bools as strings and booleans
93                if str(getattr(self, att)) != str(getattr(other, att)):
94                    return False
95
96        return True
97
98
99    def __ne__(self, other):
100        '''
101        Override object unequals to check for unequality.  NB, ignore the createdDate
102        as this is not usually important
103        @param other: other object with which to compare this object to
104        @return True if objects are equal, False otherwise
105        '''
106        return not self.__eq__(other)
107
108
109    def __str__(self):
110        outString = self.STRING_MESSAGE %type(self)
111        attString = ""
112        for att in self.__slots__:
113            if attString:
114                attString += ', '
115            attString += "%s = '%s'" %(att, getattr(self, att))
116       
117        return outString + attString
118
119
120    def toET(self):
121        '''
122        Convert the Record data into ElementTree representation and return this
123        @return: ElementTree version of data
124        '''
125        raise NotImplementedError("This is an interface class and this method has not " + \
126                                  "been implemented yet")
127
128       
129    def fromET(self, et):
130        '''
131        Extract and add data from an elementtree object
132        @param et: Elementtree object representing a Record data entry
133        '''
134        raise NotImplementedError("This is an interface class and this method has not " + \
135                                  "been implemented yet")
136
137
138    def toXMLString(self):
139        '''
140        Returns data as nicely formatted XML string
141        @return xmlString: record object in XML string representation
142        '''
143        xml = self.toET()
144
145        # create the string
146        logging.debug("Converting the elementtree object into a string")
147        # NB, the commented out approach is the simplest - but this doesn't
148        # preserve tab spacing and new lines
149        prettyXML = et2text(xml)#ET.tostring(xml)
150
151        logging.debug("Created formatted version of XML object")
152        return prettyXML
153
154           
155    def fromXMLString(self, xmlString):
156        '''
157        Initialise Record object using an xmlString
158        @param xmlString: representation of Record as an XML string
159        @return ElementTree representation of string
160        '''
161        logging.debug("Ingesting data from XML string")
162        logging.debug("Create elementtree instance with XML string")
163        tree = ET.fromstring(xmlString)
164        self.fromET(tree)
165        logging.debug("Completed data ingest")
166        return tree
167
168
169    def getRecordTypeName(self):
170        '''
171        Return the type of record, i.e. the class name, in a nice formatted
172        way
173        @return typeName: class name of record in formatted readable way
174        '''
175        logging.debug("Getting record type name for '%s' record" %type(self))
176        # get the class name, without the package info - there may be an easier way to do this??
177        typeName = str(type(self)).split('\'')[1].split('.')[-1]
178        # and fix any camelcase - putting into words
179        typeName = re.sub('([A-Z])', r" \1", typeName).strip()
180        logging.debug(" - returning type name, '%s'" %typeName)
181        return typeName
182   
183   
Note: See TracBrowser for help on using the repository browser.