]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/python/oils/utils/csedit.py
Add some documentation to this marvelous class
[Evergreen.git] / Open-ILS / src / python / oils / utils / csedit.py
1 # -----------------------------------------------------------------------
2 # Copyright (C) 2007  Georgia Public Library Service
3 # Bill Erickson <billserickson@gmail.com>
4
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 # -----------------------------------------------------------------------
15
16 from osrf.log import *
17 from osrf.json import *
18 from oils.utils.idl import oilsGetIDLParser
19 from osrf.ses import ClientSession
20 from oils.const import *
21 import re
22
23 ACTIONS = ['create', 'retrieve', 'batch_retrieve', 'update', 'delete', 'search']
24
25 class CSEditor(object):
26     """
27     Contains generated methods for accessing fieldmapper objects using the
28     following syntax:
29     
30         <instance>.<action>_<schema>_<table>(<id>)
31
32       * <instance> = CSEditor class instance
33       * <action>   = one of 'create', 'retrieve', 'batch_retrieve', 'update',
34         'delete', or 'search'
35       * <schema>   = the name of the schema that contains the table
36       * <table>    = the name of the table
37
38     Each generated object has accessor methods corresponding to the fieldmapper
39     name attributes for a given field. The following example demonstrates how to
40     instantiate the CSEditor and a given table object, and how to invoke an
41     accessor method on that table object:
42
43     >>> import oils.utils.csedit
44     >>> import oils.utils.idl
45     >>> import osrf.system
46     >>> osrf.system.connect('/openils/conf/opensrf_core.xml', 'config.opensrf')
47     >>> oils.utils.idl.oilsParseIDL()
48     >>> oils.utils.csedit.oilsLoadCSEditor()
49     >>> editor = oils.utils.csedit.CSEditor()
50     >>> rec = editor.retrieve_biblio_record_entry(-1)
51     >>> print rec.tcn_value()
52     """
53     def __init__(self, **args):
54
55         self.app = args.get('app', OILS_APP_CSTORE)
56         self.authtoken = args.get('authtoken', args.get('auth'))
57         self.requestor = args.get('requestor')
58         self.connect = args.get('connect')
59         self.xact = args.get('xact')
60         self.__session = None
61
62     def die_event(self):
63         pass
64     def checkauth(self):
65         pass
66
67
68     # -------------------------------------------------------------------------
69     # Creates a session if one does not already exist.  If necessary, connects
70     # to the remote service and starts a transaction
71     # -------------------------------------------------------------------------
72     def session(self, ses=None):
73         if not self.__session:
74             self.__session = ClientSession(self.app)
75
76         if self.connect or self.xact:
77             self.log(log_debug,'connecting to ' + self.app)
78             self.__session.connect() 
79
80         if self.xact:
81             self.log(log_info, "starting new db transaction")
82             self.request(self.app + '.transaction.begin')
83
84         return self.__session
85    
86
87     # -------------------------------------------------------------------------
88     # Logs string with some meta info
89     # -------------------------------------------------------------------------
90     def log(self, func, string):
91         s = "editor[";
92         if self.xact: s += "1|"
93         else: s += "0|"
94         if self.requestor: s += str(self.requestor.id())
95         else: s += "0"
96         s += "]"
97         func("%s %s" % (s, string))
98
99
100     # -------------------------------------------------------------------------
101     # Rolls back the existing db transaction
102     # -------------------------------------------------------------------------
103     def rollback(self):
104         if self.__session and self.xact:
105              self.log(log_info, "rolling back db transaction")
106              self.request(self.app + '.transaction.rollback')
107              self.disconnect()
108              
109     # -------------------------------------------------------------------------
110     # Commits the existing db transaction
111     # -------------------------------------------------------------------------
112     def commit(self):
113         if self.__session and self.xact:
114             self.log(log_info, "comitting db transaction")
115             self.request(self.app + '.transaction.commit')
116             self.disconnect()
117
118
119     # -------------------------------------------------------------------------
120     # Disconnects from the remote service
121     # -------------------------------------------------------------------------
122     def disconnect(self):
123         if self.__session:
124             self.__session.disconnect()
125             self.__session = None
126
127
128     # -------------------------------------------------------------------------
129     # Sends a request
130     # -------------------------------------------------------------------------
131     def request(self, method, params=[]):
132
133         # XXX improve param logging here
134
135         self.log(log_info, "request %s %s" % (method, unicode(params)))
136
137         if self.xact and self.session().state != OSRF_APP_SESSION_CONNECTED:
138             self.log(log_error, "csedit lost its connection!")
139
140         val = None
141
142         try:
143             req = self.session().request2(method, params)
144             resp = req.recv()
145             val = resp.content()
146
147         except Exception, e:
148             self.log(log_error, "request error: %s" % unicode(e))
149             raise e
150
151         return val
152
153
154     # -------------------------------------------------------------------------
155     # Returns true if our requestor is allowed to perform the request action
156     # 'org' defaults to the requestors ws_ou
157     # -------------------------------------------------------------------------
158     def allowed(self, perm, org=None):
159         pass # XXX
160
161
162     def runMethod(self, action, type, arg, options={}):
163
164         method = "%s.direct.%s.%s" % (self.app, type, action)
165
166         if options.get('idlist'):
167             method = method.replace('search', 'id_list')
168             del options['idlist']
169
170         if action == 'search':
171             method += '.atomic'
172
173         if action == 'batch_retrieve':
174             method = method.replace('batch_retrieve', 'search')
175             method += '.atomic'
176             arg = {'id' : arg}
177
178         params = [arg];
179         if len(options.keys()):
180             params.append(options)
181
182         val = self.request( method, params )
183
184         return val
185
186     def rawSearch(self, args):
187         method = "%s.json_query.atomic" % self.app
188         self.log(log_debug, "rawSearch args: %s" % unicode(args))
189         return self.request(method, [args])
190
191     def rawSearch2(self, hint, fields, where, from_=None):
192         if not from_:   
193             from_ = {'%s' % hint : {}}
194
195         args = {
196             'select' : { '%s' % hint : fields },
197             'from' : from_,
198             'where' : { "+%s" % hint : where }
199         }
200         return self.rawSearch(args)
201
202
203     def fieldSearch(self, hint, fields, where):
204         return self.rawSearch2(hint, fields, where)
205
206
207
208 # -------------------------------------------------------------------------
209 # Creates a class method for each action on each type of fieldmapper object
210 # -------------------------------------------------------------------------
211 def oilsLoadCSEditor():
212     obj = oilsGetIDLParser().IDLObject
213
214     for k, fm in obj.iteritems():
215         for action in ACTIONS:
216
217             fmname = fm['fieldmapper'].replace('::', '_')
218             type = fm['fieldmapper'].replace('::', '.')
219             name = "%s_%s" % (action, fmname)
220
221             s = 'def %s(self, arg, **options):\n' % name
222             s += '\treturn self.runMethod("%s", "%s", arg, dict(options))\n' % (action, type)
223             s += 'setattr(CSEditor, "%s", %s)' % (name, name)
224
225             exec(s)
226