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

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

Add code to retrieve repository info by name - and add appropriate tests.

  • 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, providerName):
211        '''
212        Delete the input providerInfo from the backend data file
213        @param providerName: Name of provider 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(providerName)
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        @return ProviderInfo: object with requested data - or None if no data found
230        ''' 
231        logging.info("Retrieving provider info with name, '%s'" %(providerInfoName))
232        pi = None
233        self.pic, fileName = self.__getProviderInfoData()
234       
235        try:
236            pi = self.pic.getProviderInfoByName(providerInfoName)
237            logging.info("- returning provider info details")
238        except ValueError:
239            logging.info("- no data found with specified name - returning None")
240           
241        return pi
242       
243       
244    def getRepositoryInfo(self, providerInfoName, repositoryInfoName):
245        '''
246        Get the repository info object for the specified provider and repository name
247        @param providerInfoName: name of the provider info to retrieve
248        @param repositoryInfoName: name of the repository info to retrieve
249        @return RepositoryInfo object with the requested data - or None if no data found
250        '''
251        logging.debug("Retrieving repository info, '%s' for provider, '%s'" \
252                      %(repositoryInfoName, providerInfoName))
253        ri = None
254        self.pic, fileName = self.__getProviderInfoData()
255       
256        try:
257            pi = self.pic.getProviderInfoByName(providerInfoName)
258            ri = pi.getRepositoryInfoByName(repositoryInfoName)
259            logging.info("- returning repository info details")
260        except ValueError:
261            logging.info("- no data found with specified name - returning None")
262        return ri
263
264
265    def getProviderInfoForUser(self, user):
266        '''
267        Return provider info records valid to the input user
268        @param user: a User object with user details
269        @return list of ProviderInfo objects which the user can update
270        '''
271        self.pic, fileName = self.__getProviderInfoData()
272       
273        pis = self.pic.getProviderInfoForUser(user)
274           
275        return pis
276       
277
278    def __generateFileName(self, isBackup = False):
279        '''
280        Generate the filename for the provider info data.  If keyword, 'isBackup'
281        is set to True, generate an appropriate backup filename
282        @keyword isBackup: If True, generate a name for a backup file - with datestamp
283        and in the backup directory.  Default = False.
284        @return fileName: full path to file
285        '''
286        logging.debug("Generating filename to store provider info")
287
288        # check we have the necessary config info
289        if not self.dataDir:
290            self.__setUpFileClient()
291           
292        if isBackup:
293            logging.debug("- this will be a backup file")
294            dateStamp = datetime.datetime.now().strftime(c.DATE_FORMAT)
295            fileName = self.backupDir + os.sep + self.dataFileName + self.FILE_SUFFIX_1 + dateStamp 
296        else:
297            fileName = self.dataDir + os.sep + self.dataFileName + self.FILE_SUFFIX_1
298       
299        fileName = fileName + self.FILE_SUFFIX_2
300        # remove colons - for the benefit of Windows
301        fileName = fileName.replace(':', '.')
302
303        logging.debug("- returning filename, '%s'" %fileName)
304        return fileName
Note: See TracBrowser for help on using the repository browser.