]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/dojo/openils/PermaCrud.js
Attempt to avoid clashes with browsers that treat 'delete' as a reserved keyword
[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             
113             var method = 'open-ils.pcrud.search.' + fm_class;
114             if(!opts.streaming) method += '.atomic';
115
116             var search = {};
117             search[pkey] = { '!=' : null };
118
119             var req_hash = dojo.mixin(
120                 opts, 
121                 { method : method,
122                   params : [ this.auth(), search, order_by ]
123                 }
124             );
125
126             if (!opts.async && !opts.timeout) req_hash.timeout = 10;
127
128             var _pcrud = this;
129             var req = this.session.request( req_hash );
130
131             if (!req.onerror)
132                 req.onerror = function (r) { throw js2JSON(r); };
133             
134             // if it's an async call and the user does not care about 
135             // the responses, pull them off the network and discard them
136             if (!req_hash.timeout && !req.oncomplete)
137                 req.oncomplete = function (r) { while(r.recv()){}; };
138
139             req.send();
140
141             // for synchronous calls with no handlers, return the first received value
142             if (req_hash.timeout && !opts.oncomplete && !opts.onresponse) {
143                 var resp = req.recv();
144                 if(resp) return resp.content();
145                 return null;
146             }
147
148             return req;
149         },
150
151         search : function ( fm_class /* Fieldmapper class hint */, search /* Fieldmapper query object */, opts /* Option hash */) {
152             if(!opts) opts = {};
153             var order_by = {};
154             if (opts.order_by) order_by.order_by = opts.order_by;
155             if (opts.select) order_by.select = opts.select;
156
157             var method = 'open-ils.pcrud.search.' + fm_class;
158             if(!opts.streaming) method += '.atomic';
159
160             var req_hash = dojo.mixin(
161                 opts, 
162                 { method : method,
163                   params : [ this.auth(), search, order_by ]
164                 }
165             );
166
167             if (!opts.async && !opts.timeout) req_hash.timeout = 10;
168
169             var _pcrud = this;
170             var req = this.session.request( req_hash );
171
172             if (!req.onerror)
173                 req.onerror = function (r) { throw js2JSON(r); };
174
175             // if it's an async call and the user does not care about 
176             // the responses, pull them off the network and discard them
177             if (!req_hash.timeout && !req.oncomplete)
178                 req.oncomplete = function (r) { while(r.recv()){}; };
179
180             req.send();
181
182             // for synchronous calls with no handlers, return the first received value
183             if (req_hash.timeout && !opts.oncomplete && !opts.onresponse) {
184                 var resp = req.recv();
185                 if(resp) return resp.content();
186                 return null;
187             }
188
189             return req;
190         },
191
192         _CUD : function ( method /* 'create' or 'update' or 'delete' */, list /* Fieldmapper object */, opts /* Option hash */) {
193             if(!opts) opts = {};
194
195             if (dojo.isArray(list)) {
196                 if (list.classname) list = [ list ];
197             } else {
198                 list = [ list ];
199             }
200
201             if (!this.connected) this.connect();
202
203             var _pcrud = this;
204
205             function _CUD_recursive ( obj_list, pos, final_complete, final_error ) {
206                 var obj = obj_list[pos];
207                 var req_hash = {
208                     method : 'open-ils.pcrud.' + method + '.' + obj.classname,
209                     params : [ _pcrud.auth(), obj ],
210                     onerror : final_error || function (r) { _pcrud.disconnect(); throw '_CUD: Error creating, deleting or updating ' + js2JSON(obj); }
211                 };
212
213                 var req = _pcrud.session.request( req_hash );
214                 req._final_complete = final_complete;
215                 req._final_error = final_error;
216
217                 if (++pos == obj_list.length) {
218                     req.oncomplete = function (r) {
219
220                         _pcrud.session.request({
221                             method : 'open-ils.pcrud.transaction.commit',
222                             timeout : 10,
223                             params : [ _pcrud.auth() ],
224                             onerror : function (r) {
225                                 _pcrud.disconnect();
226                                 throw 'Transaction commit error';
227                             },      
228                             oncomplete : function (r) {
229                                 var res = r.recv();
230                                 if ( res && res.content() ) {
231                                     if(req._final_complete)
232                                         req._final_complete(req);
233                                     _pcrud.disconnect();
234                                 } else {
235                                     _pcrud.disconnect();
236                                     throw 'Transaction commit error';
237                                 }
238                             },
239                         }).send();
240                     };
241
242                     req.onerror = function (r) {
243                         if (r._final_error) r._final_error(r);
244                         _pcrud.disconnect();
245                     };
246
247                 } else {
248                     req._pos = pos;
249                     req._obj_list = obj_list;
250                     req.oncomplete = function (r) {
251                         var res = r.recv();
252                         if ( res && res.content() ) {
253                             _CUD_recursive( r._obj_list, r._pos, r._final_complete );
254                         } else {
255                             _pcrud.disconnect();
256                             throw '_CUD: Error creating, deleting or updating ' + js2JSON(obj);
257                         }
258                     };
259                 }
260
261                 req.send();
262             }
263
264             var f_complete = opts.oncomplete;
265             var f_error = opts.onerror;
266
267             this.session.request({
268                 method : 'open-ils.pcrud.transaction.begin',
269                 timeout : 10,
270                 params : [ _pcrud.auth() ],
271                 onerror : function (r) {
272                     _pcrud.disconnect();
273                     throw 'Transaction begin error';
274                 },      
275                 oncomplete : function (r) {
276                     var res = r.recv();
277                     if ( res && res.content() ) {
278                         _CUD_recursive( list, 0, f_complete, f_error );
279                     } else {
280                         _pcrud.disconnect();
281                         throw 'Transaction begin error';
282                     }
283                 },
284             }).send();
285         },
286
287         create : function ( list, opts ) {
288             this._CUD( 'create', list, opts );
289         },
290
291         update : function ( list, opts ) {
292             this._CUD( 'update', list, opts );
293         },
294
295         delete : function ( list, opts ) {
296             this._CUD( 'delete', list, opts );
297         },
298
299         /* 
300          * 'delete' is a reserved keyword in JavaScript and can't be used
301          * in browsers like IE or Chrome, so we define a safe synonym
302          */
303         eliminate: function ( list, opts ) {
304             this._CUD( 'delete', list, opts );
305         },
306
307         apply : function ( list, opts ) {
308             this._auto_CUD( list, opts );
309         },
310
311         _auto_CUD : function ( list /* Fieldmapper object */, opts /* Option hash */) {
312
313             if(!opts) opts = {};
314
315             if (dojo.isArray(list)) {
316                 if (list.classname) list = [ list ];
317             } else {
318                 list = [ list ];
319             }
320
321             if (!this.connected) this.connect();
322
323             var _pcrud = this;
324
325             function _auto_CUD_recursive ( obj_list, pos, final_complete, final_error ) {
326                 var obj = obj_list[pos];
327
328                 var method;
329                 if (obj.ischanged()) method = 'update';
330                 if (obj.isnew())     method = 'create';
331                 if (obj.isdeleted()) method = 'delete';
332                 if (!method) throw 'No action detected';
333
334                 var req_hash = {
335                     method : 'open-ils.pcrud.' + method + '.' + obj.classname,
336                     timeout : 10,
337                     params : [ _pcrud.auth(), obj ],
338                     onerror : final_error || function (r) { _pcrud.disconnect(); throw '_auto_CUD: Error creating, deleting or updating ' + js2JSON(obj); }
339                 };
340
341                 var req = _pcrud.session.request( req_hash );
342                 req._final_complete = final_complete;
343                 req._final_error = final_error;
344
345                 if (++pos == obj_list.length) {
346                     req.oncomplete = function (r) {
347
348                         _pcrud.session.request({
349                             method : 'open-ils.pcrud.transaction.commit',
350                             timeout : 10,
351                             params : [ _pcrud.auth() ],
352                             onerror : function (r) {
353                                 _pcrud.disconnect();
354                                 throw 'Transaction commit error';
355                             },      
356                             oncomplete : function (r) {
357                                 var res = r.recv();
358                                 if ( res && res.content() ) {
359                                     _auto_CUD_recursive( list, 0 );
360                                 } else {
361                                     _pcrud.disconnect();
362                                     throw 'Transaction commit error';
363                                 }
364                             },
365                         }).send();
366
367                         if (r._final_complete) r._final_complete(r);
368                         _pcrud.disconnect();
369                     };
370
371                     req.onerror = function (r) {
372                         if (r._final_error) r._final_error(r);
373                         _pcrud.disconnect();
374                     };
375
376                 } else {
377                     req._pos = pos;
378                     req._obj_list = obj_list;
379                     req.oncomplete = function (r) {
380                         var res = r.recv();
381                         if ( res && res.content() ) {
382                             _auto_CUD_recursive( r._obj_list, r._pos, r._final_complete, r._final_error );
383                         } else {
384                             _pcrud.disconnect();
385                             throw '_auto_CUD: Error creating, deleting or updating ' + js2JSON(obj);
386                         }
387                     };
388                 }
389
390                 req.send();
391             }
392
393             var f_complete = opts.oncomplete;
394             var f_error = opts.onerror;
395
396             this.session.request({
397                 method : 'open-ils.pcrud.transaction.begin',
398                 timeout : 10,
399                 params : [ _pcrud.auth() ],
400                 onerror : function (r) {
401                     _pcrud.disconnect();
402                     throw 'Transaction begin error';
403                 },      
404                 oncomplete : function (r) {
405                     var res = r.recv();
406                     if ( res && res.content() ) {
407                         _auto_CUD_recursive( list, 0, f_complete, f_error );
408                     } else {
409                         _pcrud.disconnect();
410                         throw 'Transaction begin error';
411                     }
412                 },
413             }).send();
414         }
415
416     });
417 }
418
419