source: TI07-MOLES/trunk/PythonCode/existInterface/eXistInterface.py @ 1279

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI07-MOLES/trunk/PythonCode/existInterface/eXistInterface.py@2278
Revision 1279, 6.0 KB checked in by lawrence, 13 years ago (diff)

Simple python interface to exist now supports
chunked queries, but fails with the glue
version of eXist (although it works with the
newer version on Kev's). This is proof of concept for
replacing the java server side web services if we
can't easily fix them.

Line 
1# Code inspired by example on eXist website.
2import urllib2, base64, urllib, urlparse, httplib, xmlrpclib, types
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
11class  eXist_Connector(object):
12    """Access class for eXist"""
13    def __init__(self,constants=None):
14        ''' Instantiates the eXist connector using supplied constants '''
15        if constants is None: raise 'NoExistConstants'
16        authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm()
17        authinfo.add_password(None,
18                                  constants.host,
19                                  constants.userid,
20                                  constants.password)
21        authHandler = urllib2.HTTPBasicAuthHandler(authinfo)
22        opener = urllib2.build_opener(authHandler)
23        s = constants.userid+':'+constants.password
24        z = base64.encodestring(s)[:-1] # strip trailing 12
25        opener.addheaders.append(('Authorization', 'Basic %s' % z))
26        self.http_headers = {'Authorization':'Basic %s' % z}
27        self.opener = opener
28        # also create an xmlrpc Server object
29       
30        xmlrpc_uri = '%s%s:%s@%s:%d%s' % ( 
31                                            'http://',
32                                            constants.userid,
33                                            constants.password,
34                                            constants.host,
35                                            constants.port,
36                                            constants.xmlrpc_base_path
37                                        )
38        print xmlrpc_uri
39        self.xmlrpc = xmlrpclib.Server(xmlrpc_uri)
40
41    def executeQuery(self, xquery, params={}):
42        '''Execute an xquery string, return session and summary information'''
43        xquery=xmlrpclib.Binary(xquery)
44        id = self.xmlrpc.executeQuery(xquery, params)
45        summary = self.xmlrpc.querySummary(id)
46        return id,summary
47
48    def release(self,id):
49        ''' Release an executeQuery session '''
50        self.xmlrpc.releaseQueryResult(id)
51       
52    def retrieve(self,id,pos,params={}):
53        ''' Retrieve a specific document from an executeQuery result set '''
54        return self.xmlrpc.retrieve(id,pos,params).data
55 
56    def executeChunkedQuery(self,xquery,start,number,params={}):
57        ''' Execute a query, return a specific part of the result set, and
58        dump the session automagically '''
59        xquery=xmlrpclib.Binary(xquery)
60        r=self.xmlrpc.query(xquery,number,start,params)
61        return r
62       
63class ndg_eXist(eXist_Connector):
64    ''' Adds ndg methods to a "standard" exist Connector '''
65    def __init__(self,myhost='glue.badc.rl.ac.uk'):
66        f=file('passwords.txt','r')
67        pw={}
68        for line in f.readlines():
69            host,userid,password=line.strip().split(' ')
70            pw[host]=(userid,password)
71        eXistConstants = InstanceObject(host=myhost,
72                                userid=pw[myhost][0],
73                                password=pw[myhost][1],
74                                base_path="/exist/servlet",
75                                xmlrpc_base_path="/exist/xmlrpc",
76                                port=8080)
77       
78        eXist_Connector.__init__(self,eXistConstants)
79        self.ids={}
80       
81    def __buildquery(self,query,target):
82        '''Create an NDG full text query '''
83        s="//%s[. &='%s']"%(target,query)
84        return s#xmlrpclib.Binary(s)
85
86    def __buildParamSearch(self,param,value,target):
87        s="for $x in document()//%s where $x[.%s &= '%s'] return $x"%(target,param,value)
88        return s
89
90    def full_text(self,query,target='DIF'):
91        ''' Carry out a full text search within the "target" collection '''
92        id,summary=self.executeQuery(self.__buildquery(query,target))
93        self.ids[id]=0
94        return id,summary
95
96    def retrieveNext(self,id):
97        ''' Takes a sessionID from an existing query and gets the next document '''
98        try:
99            r=self.retrieve(id, self.ids[id])
100            self.ids[id]+=1
101            return r
102        except xmlrpclib.Fault:
103            return None
104        except KeyError:
105            return None
106   
107    def sessionRelease(self,id):
108        ''' Releases a session and removes the position counter '''
109        try:
110            self.release(id)
111            del self.ids[id]
112            return 1
113        except:
114            return 0
115   
116    def chunkedFullText(self,query,target='DIF',start=1,number=10):
117        ''' Execute a chunked full text query and return the result
118        set '''
119        return self.executeChunkedQuery(self.__buildquery(query,target),start,number,params={})
120   
121   
122    def getDIF(self,entryID,):
123        ''' Get a specific DIF document from a repository by using the entryID '''
124        xq='''for $DE in collection('/db/testdif1')/DIF[Entry_ID='%s'] return $DE'''%entryID
125        xquery='''for $DE in collection('/db/testdif1')/DIF[Entry_ID='%s'] return $DE'''%entryID
126        id,summary=self.executeQuery(xq)#xquery)
127        if summary['hits']==1:
128            r=self.retrieve(id,0,{})
129            self.sessionRelease(id)
130        else:
131            r='none'
132        return r
133
134if __name__=="__main__":
135   
136    existDB=ndg_eXist()
137    gepidaeDB=ndg_eXist(myhost='gepidae.esc.rl.ac.uk')
138   
139    #these both work fine
140    id,summary=existDB.full_text('coapec')
141    print 'GLUE:',summary
142    id,summary=gepidaeDB.full_text('coapec')
143    print 'GEPIDAE: ',summary
144   
145    #we can retrieve them all and look at them ...
146    r=1
147    while r is not None:
148        r=existDB.retrieveNext(id)
149        #if r is not None: print r
150    existDB.release(id)
151   
152    gepidaeDB.release(id)
153    print 'done simple'
154   
155    #now try and get the DIF documents alone:
156    #works fine: print gepidaeDB.getDIF('badc.nerc.ac.uk:DIF:dataent10')
157    #crashes: print existDB.getDIF('badc.nerc.ac.uk:DIF:dataent10')
158   
159    print 'done getDIF'
160   
161    print existDB.chunkedFullText('badc')
162   
163   
Note: See TracBrowser for help on using the repository browser.