source: exist/trunk/python/ndgUtils/eXistConnector.py @ 4240

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/exist/trunk/python/ndgUtils/eXistConnector.py@4240
Revision 4240, 6.1 KB checked in by cbyrom, 11 years ago (diff)

Extend Person object to include comparison method for object equality
checks + add enum style 'type' constants and update references to use
these to make code clearer + add addAuthors() method to ensure Person
data is added and updated correctly + add string cast to eXistInterface
method to avoid problems sending DOS characters to eXist + add extra
logging and checks for setting up eXist connection.

Line 
1# Code inspired by example on eXist website.
2import urllib2, base64, urllib, urlparse, httplib, xmlrpclib, types, os, logging
3
4class InstanceObject(object):
5    def __init__(self, **kw):
6        self.dict={}
7        self.dict.update(kw)
8    def __getattr__(self,arg):
9        return self.dict[arg]
10    def __str__(self):
11        return 'InstanceObject: %s '%self.dict
12       
13class edict(dict):
14    '''An extended dictionary which allows one to set and get values
15    as attributes (kudos Joe Gregorio's 1812)
16    The extended part allows you to get and set values as attributes.
17    That is,
18       d.fred
19    is the same as
20       d['fred']
21    '''
22    def __init__(self,**kw):
23        for a in kw:
24            self[a]=kw[a]
25    def __getattr__(self, key):
26        try:
27            return self.__dict__[key]
28        except KeyError:
29            pass
30        try:
31            assert not key.startswith('_')
32            return self.__getitem__(key)
33        except:
34            raise AttributeError, "object has no attribute '%s'" % key
35    def __setattr__(self, key, value):
36        if key.startswith('_'):
37            self.__dict__[key] = value
38        else:
39            return self.__setitem__(key, value)
40
41
42class eXistConnector(object):
43   
44    # default collections for the various file types in eXist
45    BASE_COLLECTION_PATH = "/db/atoms/"
46    OLD_COLLECTION_PATH = "old/"
47    PUBLISHED_COLLECTION_PATH = "Published/"
48    SMALL_P_PUBLISHED_COLLECTION_PATH = "published/"
49    WORKING_COLLECTION_PATH = "working/"
50    BACKUP_COLLECTION_PATH = "/db/atoms_backup/"
51    GRANULE_COLLECTION_PATH = "data_granules/"
52    DEPLOYMENT_COLLECTION_PATH = "deployment_data/"
53    DE_COLLECTION_PATH = "data_entities/"
54    NDG_A_COLLECTION_PATH = "/db/ndg_A_metadata/"
55    NDG_A_COLLECTION_PATH_BACKUP = "/db/ndg_A_metadata_backup/"
56
57    """Access class for eXist"""
58    def __init__(self,constants=None):
59        ''' Instantiates the eXist connector using supplied constants '''
60        logging.debug("Setting up xmlrpc connection to eXist")
61        if constants is None: raise 'NoExistConstants'
62        logging.debug("Host: '%s', User: '%s'" %(constants.host, constants.userid))
63        authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm()
64        authinfo.add_password(None,
65                                  constants.host,
66                                  constants.userid,
67                                  constants.password)
68        authHandler = urllib2.HTTPBasicAuthHandler(authinfo)
69        opener = urllib2.build_opener(authHandler)
70        s = constants.userid+':'+constants.password
71        z = base64.encodestring(s)[:-1] # strip trailing 12
72        opener.addheaders.append(('Authorization', 'Basic %s' % z))
73        self.http_headers = {'Authorization':'Basic %s' % z}
74        self.opener = opener
75        # also create an xmlrpc Server object
76       
77        xmlrpc_uri = '%s%s:%s@%s:%d%s' % ( 
78                                            'http://',
79                                            constants.userid,
80                                            constants.password,
81                                            constants.host,
82                                            constants.port,
83                                            constants.xmlrpc_base_path
84                                        )
85        self.xmlrpc = xmlrpclib.Server(xmlrpc_uri)
86        logging.debug("xmlrpc connection set up")
87
88
89    def executeQuery(self, xquery, params={}):
90        '''Execute an xquery string, return session and summary information'''
91        logging.debug("Executing xquery on eXist:\n%s" %xquery)
92        xquery=xmlrpclib.Binary(str(xquery))
93        id = self.xmlrpc.executeQuery(xquery, params)
94        summary = self.xmlrpc.querySummary(id)
95        logging.debug("XQuery executed")
96        return id,summary
97
98    def release(self,id):
99        ''' Release an executeQuery session '''
100        self.xmlrpc.releaseQueryResult(id)
101       
102    def retrieve(self,id,pos,params={}):
103        ''' Retrieve a specific document from an executeQuery result set '''
104        logging.debug("Retrieving document from eXist...")
105        xml = self.xmlrpc.retrieve(id,pos,params).data
106        logging.debug("Document retrieved.")
107        return xml
108 
109    def executeChunkedQuery(self,xquery,start,number,params={}):
110        ''' Execute a query, return a specific part of the result set, and
111        dump the session automagically '''
112        xquery=xmlrpclib.Binary(xquery)
113        r=self.xmlrpc.query(xquery,number,start,params)
114        return r
115   
116    def querySummary(self,id):
117        ''' Returns a summary of query results for the result-set referenced by id (which was returned by a previous query '''
118        return self.xmlrpc.querySummary(id)
119   
120    def getHits(self,id):
121        ''' Return the number of hits associated with the query that created session id '''
122        return self.xmlrpc.getHits(id)
123   
124    def getDoc(self,collectionName,documentName):
125        '''
126    Lightweight interface to the getDocument method
127    '''
128    # atoms have a more structured collection directory - as a result
129    # AtomList.xq returns the full path to the listed docs - so avoid
130    # concat'ing the collectionName for these
131        if documentName.startswith(collectionName):
132            name = documentName
133        else:
134            name='%s/%s'%(collectionName,documentName)
135        r=self.xmlrpc.getDocumentAsString(name,{})
136        return r
137   
138    def removeCollection(self,collectionPath):
139        ''' Remove a collection in the eXist database '''
140        r=self.xmlrpc.removeCollection(collectionPath)
141        return r
142   
143    def removeDoc(self, docPath):
144        ''' Remove a document from the eXist database '''
145        r=self.xmlrpc.remove(docPath)
146        return r
147   
148    def createCollection(self,collectionPath):
149        ''' Create a collection in the eXist database at collectionPath '''
150        logging.info("Creating collection: '%s'" %collectionPath)
151        r=self.xmlrpc.createCollection(collectionPath)
152        logging.info("Collection created")
153        return r
154   
155    def storeXML(self,xml,path,overwrite=0):
156        ''' Store some XML into the databse at path '''
157        return self.xmlrpc.parse(xml,path,overwrite)
158       
159 
Note: See TracBrowser for help on using the repository browser.