source: TI07-MOLES/trunk/PythonCode/wsgi/eXistInterface.py @ 1925

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

Further modifications to wsgi discovery and browse. Discovery now links
to the Dublin Core discovery elements, and some browse functions are
beginning to emerge, but it's still rather broken (and insecure).

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   
63    def querySummary(self,id):
64        ''' Returns a summary of query results for the result-set referenced by id (which was returned by a previous query '''
65        return self.xmlrpc.querySummary(id)
66   
67    def getHits(self,id):
68        ''' Return the number of hits associated with the query that created session id '''
69        return self.xmlrpc.getHits(id)
70       
71class ndg_eXist(eXist_Connector):
72    ''' Adds ndg methods to a "standard" exist Connector '''
73    def __init__(self,db='glue.badc.rl.ac.uk',passwordFile='passwords.txt'):
74        f=file(passwordFile,'r')
75        pw={}
76        for line in f.readlines():
77            host,userid,password=line.strip().split(' ')
78            pw[host]=(userid,password)
79        eXistConstants = InstanceObject(host=db,
80                                userid=pw[db][0],
81                                password=pw[db][1],
82                                base_path="/exist/servlet",
83                                xmlrpc_base_path="/exist/xmlrpc",
84                                port=8080)
85       
86        eXist_Connector.__init__(self,eXistConstants)
87        self.ids={}
88       
89    def __buildquery(self,query,target=None):
90        '''Create an NDG full text query '''
91        if target is not None:
92            s="//%s[. &='%s']"%(target,query)
93        else: s="/*[. &='%s']"%query
94        return s#xmlrpclib.Binary(s)
95
96    def __buildParamSearch(self,param,value,target):
97        s="for $x in document()//%s where $x[.%s &= '%s'] return $x"%(target,param,value)
98        return s
99
100    def full_text(self,query,target=None):
101        ''' Carry out a full text search within the "target" collection '''
102        id,summary=self.executeQuery(self.__buildquery(query,target))
103        self.ids[id]=0
104        return id,summary
105
106    def retrieveNext(self,id,pos=None):
107        ''' Takes a sessionID from an existing query and gets the next document '''
108        if pos is not None: self.ids[id]=pos
109        try:
110            r=self.retrieve(id, self.ids[id])
111            self.ids[id]+=1
112            return r
113        except xmlrpclib.Fault:
114            return None
115        except KeyError:
116            return None
117   
118    def sessionRelease(self,id):
119        ''' Releases a session and removes the position counter '''
120        try:
121            self.release(id)
122            del self.ids[id]
123            return 1
124        except:
125            return 0
126   
127    def chunkedFullText(self,query,start=1,number=10,target='DIF'):
128        ''' Execute a chunked full text query and return the result
129        set '''
130        return self.executeChunkedQuery(self.__buildquery(query,target),start,number,params={})
131   
132   
133    def getDIF(self,entryID):
134        ''' Get a specific DIF document from a repository by using the entryID '''
135        xq='''for $DE in collection()/DIF[Entry_ID='%s'] return $DE'''%entryID
136        xquery='''for $DE in collection('/db/testdif1')/DIF[Entry_ID='%s'] return $DE'''%entryID
137        id,summary=self.executeQuery(xq)#xquery)
138        if summary['hits']==1:
139            r=self.retrieve(id,0,{})
140            self.sessionRelease(id)
141        else:
142            r=summary['hits']
143        return r
144
145       
146if __name__=="__main__":
147   
148    existDB=ndg_eXist()
149    gepidaeDB=ndg_eXist(db='gepidae.esc.rl.ac.uk')
150   
151    #these both work fine
152    #id,summary=existDB.full_text('coapec')
153    #print 'GLUE:',summary
154   
155    #print 'GLUE AGAIN:',existDB.querySummary(id)
156   
157    id,summary=gepidaeDB.full_text('coapec')
158    print 'GEPIDAE:\n ',summary
159   
160    #we can retrieve them all and look at them ...
161    r=1
162    # just get one for now
163    #while r is not None:
164    r=gepidaeDB.retrieveNext(id)
165    if r is not None: print r
166
167   
168    #existDB.release(id)
169   
170    gepidaeDB.release(id)
171    #print 'done simple'
172   
173    #now try and get the DIF documents alone:
174    #works fine: print gepidaeDB.getDIF('badc.nerc.ac.uk:DIF:dataent10')
175    #crashes:
176    #print existDB.getDIF('badc.nerc.ac.uk:DIF:dataent10')
177   
178    print 'done getDIF'
179   
180    #start,howmany=4,4
181    #existDB.chunkedFullText('badc',start,howmany)
182   
183   
184
185   
186   
Note: See TracBrowser for help on using the repository browser.