source: TI01-discovery/trunk/OAIInfoEditor/oai_info_editor/dal/editorfileclient.py @ 5226

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI01-discovery/trunk/OAIInfoEditor/oai_info_editor/dal/editorfileclient.py@5226
Revision 5226, 10.9 KB checked in by cbyrom, 11 years ago (diff)

Initial check in of code for the OAI Info Editor pylons based web app.

This includes basic controllers for viewing provider info - with the
associated repository info. Also included is the model and dal layer,
allowing the provider info to be processed and imported/exported to
XML file. Unit tests for the dal and model packages are included.
Templates for rendering provider and repository info are included.

  • Property svn:executable set to *
Line 
1'''
2 Class representing the data access object for provider info data - with
3 methods to create, update, retrieve and delete data - uses a simple client
4 to do ops direct to a flat file.
5 
6 @author: C Byrom, Tessella Apr 2009
7'''
8from xml.etree import cElementTree as ET
9import logging, datetime, os, uuid, urllib, shutil
10
11import oai_info_editor.lib.constants as c
12from oai_info_editor.model.providerinfocollection import ProviderInfoCollection
13from oai_info_editor.dal.interfaceeditordbclient import InterfaceEditorDataClient
14from ndg.common.src.lib.fileutilities import *
15
16
17class EditorFileClient(InterfaceEditorDataClient):
18
19    FILE_SUFFIX_1 = "_provider_info_data"
20    FILE_SUFFIX_2 = ".xml"
21   
22    def __init__(self, configFile = None):
23        '''
24        Constructor - initialise the client
25        @keyword configFile: myConfig object to use to set up client
26        '''
27        logging.info("Initialising EditorFileClient object")
28        self.cf = configFile
29        if configFile:
30            self.__setUpFileClient()
31        else:
32            self.dataDir = None
33            self.backupDir = None
34           
35        # field to allow easy access to collection info from outside of the client
36        # - primarily for testing purposes
37        self.pic = None
38        logging.info("EditorFileClient initialised")
39       
40
41    def __setUpFileClient(self):
42        '''
43        Do basic setting up of client - get config details and
44        ensure the required directory structure exists
45        '''
46        logging.debug("Setting up file client")
47        self.__getConfigInfo()
48       
49        createDir(self.dataDir)
50        createDir(self.backupDir)
51
52        logging.debug("- file client set up")
53
54
55    def __getConfigInfo(self):
56        '''
57        Retrieve file system info from the config file - in order to
58        establish where to create/backup data to
59        @raises SystemError: if no config file specified
60        @raises ValueError: if inappropriate config info specified
61        '''
62        logging.debug("Getting config info for data store")
63        if not self.cf:
64            raise SystemError("Cannot retrieve app data since a config file has not been specified")
65       
66        self.dataFileName = self.cf.get('DATA_STORE', 'appDataFileName')
67        self.dataDir = self.cf.get('DATA_STORE', 'appDataFileDir')
68        self.backupDir = self.cf.get('DATA_STORE', 'backupFileDir')
69       
70        if not self.dataDir or not self.backupDir or not self.dataFileName:
71            raise ValueError("Config file missing info - need keys, 'appDataFileName', 'appDataFileDir' and 'backupFileDir' specified")
72
73        logging.debug("Config info retrieved")
74
75
76    def __loadProviderInfoFile(self, fileName):
77        '''
78        Load the specified filename containing provider info - and
79        return this in a ProviderInfoCollection data model object
80        @param fileName: Name of file to open
81        @return: ProviderInfoCollection object with the file data in
82        '''
83        logging.debug("Reading provider info data from file, '%s'" %fileName)
84        f = open(fileName, 'r')
85        xml = f.read()
86        f.close()
87        pic = ProviderInfoCollection(fileName, xmlString = xml)
88        logging.debug("Returning info from file")
89        return pic
90
91
92    def _deleteProviderInfoFile(self, fileName):
93        '''
94        Delete the specified filename containing provider info - NB, this
95        is primarily for use in test cases to tidy up things
96        @param fileName: Name of file to delete
97        @return: True, if successful, False otherwise
98        '''
99        logging.debug("Deleting file, '%s'" %fileName)
100        if not os.path.isfile(fileName):
101            raise IOError("File to delete, '%s', does not exist" %fileName)
102       
103        os.remove(fileName)
104        logging.debug("File deleted successfully")
105        return True
106   
107
108    def __getProviderInfoData(self):
109        '''
110        Get the provider info
111        - if data already exists, load this in and return as a populated
112        ProviderInfoCollection object, otherwise create and return a new
113        ProviderInfoCollection
114        @return: ProviderInfoCollection object with the current provider info data and filename
115        '''
116        logging.debug("Getting provider info data")
117       
118        fileName = self.__generateFileName()
119       
120        pic = None
121        if os.path.isfile(fileName):
122            logging.debug("- config data already exists for this vocab list - load this now")
123            pic = self.__loadProviderInfoFile(fileName)
124           
125        else:
126            logging.debug(" - no data found for this list - setting up a new data collection")
127            pic = ProviderInfoCollection(fileName) 
128
129        return pic, fileName
130
131
132    def __createOrUpdatePICollection(self, pic):
133        '''
134        Create a new file containing the data from the input provider info
135        collection.  NB, firstly check if the collection file
136        already exists and, if it does, backup the old collection.
137        @param pic: ProviderInfoCollection object with data to output
138        @return ProviderInfoCollection created
139        '''
140        logging.info("Creating or updating provider info collection file")
141       
142        fileName = self.__generateFileName()
143        if os.path.isfile(fileName):
144            logging.info("- found existing file - creating backup")
145            logging.debug("- this will be a backup file")
146           
147            backupFileName = self.__generateFileName(isBackup = True)
148            logging.info("- backup change request collection file, '%s'" %backupFileName)
149           
150            shutil.copy(fileName, backupFileName)
151            pic.backupFile = backupFileName
152            if not os.path.isfile(backupFileName):
153                raise IOError("Problem occurred whilst creating backup file, '%s'" %backupFileName)
154           
155            # update the version number of the collection
156            pic.version = str(int(pic.version) + 1)
157
158        logging.info("- create provider info collection file, '%s'" %fileName)
159        createFile(fileName, pic.toXMLString())
160        return pic
161       
162       
163    def createProviderInfo(self, providerInfo):
164        '''
165        Create a new provider info record
166        @param providerInfo: ProviderInfo object with which to create the new
167        change request record
168        @raise ValueError if provider with same name already exists
169        @return ProviderInfo, fileName: object with any new data from the creation in + filename
170        '''
171        self.pic, fileName = self.__getProviderInfoData()
172        logging.info("Creating new provider info in file, '%s'" %fileName)
173       
174        # check provider with the same name doesn't already exist
175        pi = self.getProviderInfo(providerInfo.name)
176        if pi:
177            raise ValueError("Cannot create new provider info - a provider with the name, '%s' already exists" \
178                             %providerInfo.name)
179           
180        self.pic.addProviderInfo(providerInfo)
181       
182        # now, just dump the data out to the file
183        self.pic = self.__createOrUpdatePICollection(self.pic)
184       
185        logging.info("New provider info created in XML file")
186        return providerInfo, fileName
187   
188   
189    def updateProviderInfo(self, providerInfo):
190        '''
191        Update the input providerInfo
192        @param providerInfo: ProviderInfo object to update
193        @raise ValueError: if ProviderInfo doesn't have a name specified
194        @return ProviderInfo, fileName: object with any new data from the creation in
195        '''
196        logging.info("Updating provider info in XML file")
197
198        if not providerInfo.name:
199            raise ValueError("Provider info name is not specified: cannot update entry")
200       
201        self.pic, fileName = self.__getProviderInfoData()
202       
203        self.pic.addProviderInfo(providerInfo, raiseErrorIfNotFound = True)
204        self.pic = self.__createOrUpdatePICollection(self.pic)
205
206        logging.info("Change request updated in file")
207        return providerInfo
208
209       
210    def deleteProviderInfo(self, providerInfo):
211        '''
212        Delete the input providerInfo from the backend data file
213        @param providerInfo: ProviderInfo object to delete
214        @return True if successful, False otherwise
215        '''
216        logging.info("Deleting provider info in provider info collection")
217        self.pic, fileName = self.__getProviderInfoData()
218       
219        self.pic.removeProviderInfo(providerInfo)
220        self.pic = self.__createOrUpdatePICollection(self.pic)
221        logging.info("Delete complete successfully")
222        return True
223
224
225    def getProviderInfo(self, providerInfoName):
226        '''
227        Get the change request details for the specified list
228        @param providerInfoName: name of the provider info to retrieve
229        @raise ValueError: if provider info with name not found
230        @return ProviderInfo: object with requested data in or None, if data not found
231        ''' 
232        logging.info("Retrieving provider info with name, '%s'" %(providerInfoName))
233        pi = None
234        self.pic, fileName = self.__getProviderInfoData()
235       
236        try:
237            pi = self.pic.getProviderInfoByName(providerInfoName)
238            logging.info("- returning provider info details")
239        except ValueError:
240            logging.info("- no data found with specified name - returning None")
241           
242        return pi
243
244
245    def getProviderInfoForUser(self, user):
246        '''
247        Return provider info records valid to the input user
248        @param user: a User object with user details
249        @return list of ProviderInfo objects which the user can update
250        '''
251        self.pic, fileName = self.__getProviderInfoData()
252       
253        pis = self.pic.getProviderInfoForUser(user)
254           
255        return pis
256       
257
258    def __generateFileName(self, isBackup = False):
259        '''
260        Generate the filename for the provider info data.  If keyword, 'isBackup'
261        is set to True, generate an appropriate backup filename
262        @keyword isBackup: If True, generate a name for a backup file - with datestamp
263        and in the backup directory.  Default = False.
264        @return fileName: full path to file
265        '''
266        logging.debug("Generating filename to store provider info")
267
268        # check we have the necessary config info
269        if not self.dataDir:
270            self.__setUpFileClient()
271           
272        if isBackup:
273            logging.debug("- this will be a backup file")
274            dateStamp = datetime.datetime.now().strftime(c.DATE_FORMAT)
275            fileName = self.backupDir + os.sep + self.dataFileName + self.FILE_SUFFIX_1 + dateStamp 
276        else:
277            fileName = self.dataDir + os.sep + self.dataFileName + self.FILE_SUFFIX_1
278       
279        fileName = fileName + self.FILE_SUFFIX_2
280        # remove colons - for the benefit of Windows
281        fileName = fileName.replace(':', '.')
282
283        logging.debug("- returning filename, '%s'" %fileName)
284        return fileName
Note: See TracBrowser for help on using the repository browser.