]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/dojo/openils/PermaCrud.js
reverting previous. sorry, folks
[working/Evergreen.git] / Open-ILS / web / js / dojo / openils / PermaCrud.js
1 /* ---------------------------------------------------------------------------
2  * Copyright (C) 2008  Equinox Software, Inc
3  * Mike Rylander <miker@esilibrary.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
17 if(!dojo._hasResource["openils.PermaCrud"]) {
18
19     dojo._hasResource["openils.PermaCrud"] = true;
20     dojo.provide("openils.PermaCrud");
21     dojo.require("fieldmapper.Fieldmapper");
22     dojo.require("openils.User");
23
24     dojo.declare('openils.PermaCrud', null, {
25
26         session : null,
27         authtoken : null,
28         connnected : false,
29
30         constructor : function ( kwargs ) {
31             kwargs = kwargs || {};
32
33             this.authtoken = kwargs.authtoken;
34
35             this.session =
36                 kwargs.session ||
37                 new OpenSRF.ClientSession('open-ils.pcrud');
38
39             if (
40                 this.session &&
41                 this.session.state == OSRF_APP_SESSION_CONNECTED
42             ) this.connected = true;
43         },
44
45         auth : function (token) {
46             if (token) this.authtoken = token;
47             return this.authtoken || openils.User.authtoken;
48         },
49
50         connect : function ( onerror ) {
51             if (!this.connected && !this.session.connect()) {
52                 this.connected = false;
53                 if (onerror) onerror(this.session);
54                 return false;
55             }
56             this.connected = true;
57             return true;
58         },
59
60         disconnect : function ( onerror ) {
61             this.connected = false;
62             return true;
63             // disconnect returns nothing, which is null, which is not true, cause the following to always run ... arg.
64             if (!this.session.disconnect()) {
65                 if (onerror) onerror(this.session);
66                 return false;
67             }
68         },
69         
70
71         retrieve : function ( fm_class /* Fieldmapper class hint */, id /* Fieldmapper object primary key value */,  opts /* Option hash */) {
72             if(!opts) opts = {};
73             var req_hash = dojo.mixin(
74                 opts, 
75                 { method : 'open-ils.pcrud.retrieve.' + fm_class,
76                   params : [ this.auth(), id ]
77                 }
78             );
79
80             if (!opts.async && !opts.timeout) req_hash.timeout = 10;
81
82             var _pcrud = this;
83             var req = this.session.request( req_hash );
84
85             if (!req.onerror)
86                 req.onerror = function (r) { throw js2JSON(r); };
87
88             // if it's an async call and the user does not care about 
89             // the responses, pull them off the network and discard them
90             if (!req_hash.timeout && !req.oncomplete)
91                 req.oncomplete = function (r) { while(r.recv()){}; };
92
93             req.send();
94
95             // for synchronous calls with no handlers, return the first received value
96             if (req_hash.timeout && !opts.oncomplete && !opts.onresponse) {
97                 var resp = req.recv();
98                 if(resp) return resp.content();
99                 return null;
100             }
101
102             return req;
103         },
104
105         retrieveAll : function ( fm_class /* Fieldmapper class hint */, opts /* Option hash */) {
106             var pkey = fieldmapper[fm_class].Identifier;
107
108             if(!opts) opts = {};
109             var order_by = {};
110             if (opts.order_by) order_by.order_by = opts.order_by;
111             if (opts.select) order_by.select = opts.select;
112             if (opts.limit) order_by.limit = opts.limit;
113             if (opts.offset) order_by.offset = opts.offset;
114             if (opts.join) order_by.join = opts.join;
115             
116             var method = 'open-ils.pcrud.search.' + fm_class;
117             if(!opts.streaming) method += '.atomic';
118
119             var search = {};
120             search[pkey] = { '!=' : null };
121
122             var req_hash = dojo.mixin(
123                 opts, 
124                 { method : method,
125                   params : [ this.auth(), search, order_by ]
126                 }
127             );
128
129             if (!opts.async && !opts.timeout) req_hash.timeout = 10;
130
131             var _pcrud = this;
132             var req = this.session.request( req_hash );
133
134             if (!req.onerror)
135                 req.onerror = function (r) { throw js2JSON(r); };
136             
137             // if it's an async call and the user does not care about 
138             // the responses, pull them off the network and discard them
139             if (!req_hash.timeout && !req.oncomplete)
140                 req.oncomplete = function (r) { while(r.recv()){}; };
141
142             req.send();
143
144             // for synchronous calls with no handlers, return the first received value
145             if (req_hash.timeout && !opts.oncomplete && !opts.onresponse) {
146                 var resp = req.recv();
147                 if(resp) return resp.content();
148                 return null;
149             }
150
151             return req;
152         },
153
154         search : function ( fm_class /* Fieldmapper class hint */, search /* Fieldmapper query object */, opts /* Option hash */) {
155             var return_type = 'search';
156             if(!opts) opts = {};
157             var order_by = {};
158             if (opts.order_by) order_by.order_by = opts.order_by;
159             if (opts.select) order_by.select = opts.select;
160             if (opts.limit) order_by.limit = opts.limit;
161             if (opts.offset) order_by.offset = opts.offset;
162             if (opts.join) order_by.join = opts.join;
163             if (opts.id_list) return_type = 'id_list';
164
165             var method = 'open-ils.pcrud.' + return_type + '.' + fm_class;
166             if(!opts.streaming) method += '.atomic';
167
168             var req_hash = dojo.mixin(
169                 opts, 
170                 { method : method,
171                   params : [ this.auth(), search, order_by ]
172                 }
173             );
174
175             if (!opts.async && !opts.timeout) req_hash.timeout = 10;
176
177             var _pcrud = this;
178             var req = this.session.request( req_hash );
179
180             if (!req.onerror)
181                 req.onerror = function (r) { throw js2JSON(r); };
182
183             // if it's an async call and the user does not care about 
184             // the responses, pull them off the network and discard them
185             if (!req_hash.timeout && !req.oncomplete)
186                 req.oncomplete = function (r) { while(r.recv()){}; };
187
188             req.send();
189
190             // for synchronous calls with no handlers, return the first received value
191             if (req_hash.timeout && !opts.oncomplete && !opts.onresponse) {
192                 var resp = req.recv();
193                 if(resp) return resp.content();
194                 return null;
195             }
196
197             return req;
198         },
199
200         _CUD : function ( method /* 'create' or 'update' or 'delete' */, list /* Fieldmapper object */, opts /* Option hash */) {
201             if(!opts) opts = {};
202
203             if (dojo.isArray(list)) {
204                 if (list.classname) list = [ list ];
205             } else {
206                 list = [ list ];
207             }
208
209             if (!this.connected) this.connect();
210
211             var _pcrud = this;
212             var _return_list = [];
213
214             function _CUD_recursive ( obj_list, pos, final_complete, final_error ) {
215                 var obj = obj_list[pos];
216                 var req_hash = {
217                     method : 'open-ils.pcrud.' + method + '.' + obj.classname,
218                     params : [ _pcrud.auth(), obj ],
219                     onerror : final_error || function (r) { _pcrud.disconnect(); throw '_CUD: Error creating, deleting or updating ' + js2JSON(obj); }
220                 };
221
222                 var req = _pcrud.session.request( req_hash );
223                 req._final_complete = final_complete;
224                 req._final_error = final_error;
225
226                 if (++pos == obj_list.length) {
227                     req.oncomplete = function (r) {
228                         var res = r.recv();
229
230                         if ( res && res.content() ) {
231                             _return_list.push( res.content() );
232                             _pcrud.session.request({
233                                 method : 'open-ils.pcrud.transaction.commit',
234                                 timeout : 10,
235                                 params : [ _pcrud.auth() ],
236                                 onerror : function (r) {
237                                     _pcrud.disconnect();
238                                     throw 'Transaction commit error';
239                                 },      
240                                 oncomplete : function (r) {
241                                     var res = r.recv();
242                                     if ( res && res.content() ) {
243                                         if(req._final_complete)
244                                             req._final_complete(req, _return_list);
245                                         _pcrud.disconnect();
246                                     } else {
247                                         _pcrud.disconnect();
248                                         throw 'Transaction commit error';
249                                     }
250                                 },
251                             }).send();
252                         } else {
253                             _pcrud.disconnect();
254                             throw '_CUD: Error creating, deleting or updating ' + js2JSON(obj);
255                         }
256                     };
257
258                     req.onerror = function (r) {
259                         if (r._final_error) r._final_error(r);
260                         _pcrud.disconnect();
261                         throw '_CUD: Error creating, deleting or updating ' + js2JSON(obj);
262                     };
263
264                 } else {
265                     req._pos = pos;
266                     req._obj_list = obj_list;
267                     req.oncomplete = function (r) {
268                         var res = r.recv();
269                         if ( res && res.content() ) {
270                             _return_list.push( res.content() );
271                             _CUD_recursive( r._obj_list, r._pos, r._final_complete );
272                         } else {
273                             _pcrud.disconnect();
274                             throw '_CUD: Error creating, deleting or updating ' + js2JSON(obj);
275                         }
276                     };
277                     req.onerror = function (r) {
278                         if (r._final_error) r._final_error(r);
279                         _pcrud.disconnect();
280                         throw '_CUD: Error creating, deleting or updating ' + js2JSON(obj);
281                     };
282                 }
283
284                 req.send();
285             }
286
287             var f_complete = opts.oncomplete;
288             var f_error = opts.onerror;
289
290             this.session.request({
291                 method : 'open-ils.pcrud.transaction.begin',
292                 timeout : 10,
293                 params : [ _pcrud.auth() ],
294                 onerror : function (r) {
295                     _pcrud.disconnect();
296                     throw 'Transaction begin error';
297                 },      
298                 oncomplete : function (r) {
299                     var res = r.recv();
300                     if ( res && res.content() ) {
301                         _CUD_recursive( list, 0, f_complete, f_error );
302                     } else {
303                         _pcrud.disconnect();
304                         throw 'Transaction begin error';
305                     }
306                 },
307             }).send();
308
309             return _return_list;
310
311         },
312
313         create : function ( list, opts ) {
314             return this._CUD( 'create', list, opts );
315         },
316
317         update : function ( list, opts ) {
318             var id_list = this._CUD( 'update', list, opts );
319             var obj_list = [];
320
321             for (var idx = 0; idx < id_list.length; idx++) {
322                 obj_list.push(
323                     this.retrieve( list[idx].classname, id_list[idx] )
324                 );
325             }
326
327             return obj_list;
328         },
329
330         /* 
331          * 'delete' is a reserved keyword in JavaScript and can't be used
332          * in browsers like IE or Chrome, so we define a safe synonym
333      * NOTE: delete() is now removed -- use eliminate instead
334
335         delete : function ( list, opts ) {
336             return this._CUD( 'delete', list, opts );
337         },
338
339          */
340         eliminate: function ( list, opts ) {
341             return this._CUD( 'delete', list, opts );
342         },
343
344         apply : function ( list, opts ) {
345             this._auto_CUD( list, opts );
346         },
347
348         _auto_CUD : function ( list /* Fieldmapper object */, opts /* Option hash */) {
349
350             if(!opts) opts = {};
351
352             if (dojo.isArray(list)) {
353                 if (list.classname) list = [ list ];
354             } else {
355                 list = [ list ];
356             }
357
358             if (!this.connected) this.connect();
359
360             var _pcrud = this;
361
362             function _auto_CUD_recursive ( obj_list, pos, final_complete, final_error ) {
363                 var obj = obj_list[pos];
364
365                 var method;
366                 if (obj.ischanged()) method = 'update';
367                 if (obj.isnew())     method = 'create';
368                 if (obj.isdeleted()) method = 'delete';
369                 if (!method) {
370                     return _auto_CUD_recursive(obj_list, pos+1, final_complete, final_error);
371                 }
372
373                 var req_hash = {
374                     method : 'open-ils.pcrud.' + method + '.' + obj.classname,
375                     timeout : 10,
376                     params : [ _pcrud.auth(), obj ],
377                     onerror : final_error || function (r) { _pcrud.disconnect(); throw '_auto_CUD: Error creating, deleting or updating ' + js2JSON(obj); }
378                 };
379
380                 var req = _pcrud.session.request( req_hash );
381                 req._final_complete = final_complete;
382                 req._final_error = final_error;
383
384                 if (++pos == obj_list.length) {
385                     req.oncomplete = function (r) {
386
387                         _pcrud.session.request({
388                             method : 'open-ils.pcrud.transaction.commit',
389                             timeout : 10,
390                             params : [ _pcrud.auth() ],
391                             onerror : function (r) {
392                                 _pcrud.disconnect();
393                                 throw 'Transaction commit error';
394                             },      
395                             oncomplete : function (r) {
396                                 var res = r.recv();
397                                 if ( res && res.content() ) {
398                                     if (r._final_complete) 
399                                         req._final_complete(req, _return_list);
400                                     _pcrud.disconnect();
401                                 } else {
402                                     _pcrud.disconnect();
403                                     throw 'Transaction commit error';
404                                 }
405                             },
406                         }).send();
407                     };
408
409                     req.onerror = function (r) {
410                         if (r._final_error) r._final_error(r);
411                         _pcrud.disconnect();
412                     };
413
414                 } else {
415                     req._pos = pos;
416                     req._obj_list = obj_list;
417                     req.oncomplete = function (r) {
418                         var res = r.recv();
419                         if ( res && res.content() ) {
420                             _auto_CUD_recursive( r._obj_list, r._pos, r._final_complete, r._final_error );
421                         } else {
422                             _pcrud.disconnect();
423                             throw '_auto_CUD: Error creating, deleting or updating ' + js2JSON(obj);
424                         }
425                     };
426                 }
427
428                 req.send();
429             }
430
431             var f_complete = opts.oncomplete;
432             var f_error = opts.onerror;
433
434             this.session.request({
435                 method : 'open-ils.pcrud.transaction.begin',
436                 timeout : 10,
437                 params : [ _pcrud.auth() ],
438                 onerror : function (r) {
439                     _pcrud.disconnect();
440                     throw 'Transaction begin error';
441                 },      
442                 oncomplete : function (r) {
443                     var res = r.recv();
444                     if ( res && res.content() ) {
445                         _auto_CUD_recursive( list, 0, f_complete, f_error );
446                     } else {
447                         _pcrud.disconnect();
448                         throw 'Transaction begin error';
449                     }
450                 },
451             }).send();
452         }
453
454     });
455 }
456
457