source: ndgCommon/trunk/ndg/common/src/clients/xmldb/abstractxmldbatomclient.py @ 4983

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/ndgCommon/trunk/ndg/common/src/clients/xmldb/abstractxmldbatomclient.py@4983
Revision 4983, 5.4 KB checked in by cbyrom, 11 years ago (diff)

Add a new feed for collecting corrections info submitted by users of
the atom editor + create new method on client to do this + add new
tests and tidy up some code.

Line 
1'''
2 Abstract implement of for providing functionality to support Atom
3 document usage
4 
5 @author: C Byrom - Tessella, Feb 09
6'''
7import os, sys, logging
8from threading import Thread
9from ndg.common.src.clients.xmldb.interfacexmldbatomclient import InterfaceXMLDBAtomClient
10from ndg.common.src.lib.atomutilities import *
11
12
13class DuplicateError(Exception):
14    """
15    Exception handling for when a duplicated atom doc is discovered
16    """
17    def __init__(self, msg):
18        logging.error(msg)
19        Exception.__init__(self, msg)
20
21
22class publishingThread(Thread):
23    '''
24    Class to allow publishing of atom docs asynchronously - i.e. in a new thread
25    '''
26   
27    def __init__ (self, atomClient, atom):
28        '''
29        Constructor for setting up thread
30        @param: AtomClient instance to do the publishing
31        @param: Atom object to publish
32        '''
33        logging.info("Setting up thread to publish atom data for atom, '%s'" %atom.datasetID)
34        Thread.__init__(self)
35        self.atomClient = atomClient
36        self.atom = atom
37        logging.info("- finished setting up thread")
38     
39    def run(self):
40        logging.info("Running thread to publish atom data for atom, '%s'" %self.atom.datasetID)
41        self.atomClient._AtomClient__publishAtom(self.atom)
42        logging.info("- finished publishing atom data")
43
44
45class AbstractXMLDBAtomClient(InterfaceXMLDBAtomClient):
46
47    # avoid looking up datacentre DIF data more than we have to by storing
48    # it in this dict on first retrieval
49    dataCentres = {}
50   
51    # keep track of atom docs and their collections - to reduce db lookups - use
52    # key = filename, val = collectionPath
53    atomCollections = {}
54   
55    def deleteAtom(self, atom):
56        '''
57        Delete the given atom from the XML DB - using the atom
58        details to work out the required path to delete
59        '''
60        logging.info("Deleting atom from eXist")
61        self.deleteDoc(atom.getFullPath())
62        logging.info("Atom deleted")
63
64
65    def _createDIFDocumentFromAtom(self, atom, difCollectionPath):
66        '''
67        Transform an atom into a DIF document and store this in the XML DB
68        - also publish data to relevant feeds, if appropriate
69        @param atom: the Atom data model to convert
70        @param difCollectionPath: path to the collection storing DIF documents
71        @return difFilePath: path to the created DIF file
72        '''
73        logging.info("Creating and storing DIF document")
74        doc = self._transformAtomIntoDIF(atom)
75        fileName = atom.atomName.replace('.atom', '.xml')
76       
77        # now add to eXist
78        providerID = atom.ME.providerID
79        collectionPath = difCollectionPath + providerID
80       
81        # NB, check if a top level provider collection exists; if not, add
82        # this with a feed
83        # NB, the collection will be created along with the DIF file - so set the
84        # feed up after the file has been created
85        setupFeed = False
86        if self.isNewCollection(collectionPath):
87            setupFeed = True
88
89        self.createOrUpdateDoc(doc, collectionPath, fileName)   
90             
91        if setupFeed:
92            logging.info("Creating feed for new provider ID")
93            self.createCollections([collectionPath])
94            self.feedClient.createAtomFeed(collectionPath,
95                                           self.feedClient.PROVIDERLEVEL_DIF_FEED_TITLE %providerID)
96        logging.info("DIF document created and stored")
97        return collectionPath + '/' + fileName
98
99
100    def _transformAtomIntoDIF(self, atom):
101        '''
102        Transform an atom into a DIF document - using an XQuery transform ran
103        in the XML DB
104        @param atom: the Atom data model to convert
105        @return: the produced DIF document
106        '''
107        logging.info("Creating DIF record from atom - using XQuery transform")
108       
109        # get the query and set this up to use properly
110        targetCollection = atom.getPublicationStatePath()
111        providerID = atom.ME.providerID
112       
113        # add a trailing forward slash - otherwise the xquery won't work
114        if not targetCollection.endswith('/'):
115            targetCollection = targetCollection + '/'
116           
117        # NB, using the query() method (via the useChunked keyword) here results
118        # in the namespaces being expanded - which ET doesn't like
119        doc = self.buildAndRunQuery('atom2DIF',
120                                    targetCollection,
121                                    providerID, 
122                                    atom.datasetID,
123                                    useChunked = False)
124
125        if not doc:
126            raise Exception("XQuery produced no results - suggesting a problem with the query")
127       
128        # add various missing info
129        # get the organisation data for the repository
130        # - NB, store for re-use to avoid multiple lookups of the same info
131        if self.dataCentres.has_key(providerID):
132            dataCentre = self.dataCentres[providerID]
133        else:
134            dataCentre = getDataCentreDIFElement(providerID, self)
135            self.dataCentres[providerID] = dataCentre
136
137        # add various other data to atoms - to make up with the incomplete data spec there
138        doc = addOrgData(doc[0], targetCollection, dataCentre)
139        doc = expandParametersData(doc)
140        doc = addStandardKeywords(doc)
141
142        logging.info("Transform completed successfully - returning DIF doc")
143        return doc
144
Note: See TracBrowser for help on using the repository browser.