]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/javascript/opensrf_domain_object.js
oops, perl syntax
[OpenSRF.git] / src / javascript / opensrf_domain_object.js
1 // -----------------------------------------------------------------------------
2 // This houses all of the domain object code.
3 // -----------------------------------------------------------------------------
4
5
6
7
8 // -----------------------------------------------------------------------------
9 // DomainObject 
10
11 DomainObject.prototype                                  = new domainObject();
12 DomainObject.prototype.constructor      = DomainObject;
13 DomainObject.prototype.baseClass                = domainObject.prototype.constructor;
14
15 /** Top level DomainObject class.  This most provides convience methods
16   * and a shared superclass
17   */
18 function DomainObject( name ) {
19         if( name ) { this._init_domainObject( name ); }
20 }
21
22 /** Returns the actual element of the given domainObjectAttr. */
23 DomainObject.prototype._findAttr = function ( name ) {
24         
25         var nodes = this.element.childNodes;
26
27         if( ! nodes || nodes.length < 1 ) {
28                 throw new oils_ex_dom( "Invalid xml object in _findAttr: " + this.toString() );
29         }
30
31         var i=0;
32         var node = nodes.item(i);
33
34         while( node != null ) {
35
36                 if( node.nodeName == "oils:domainObjectAttr" &&
37                                 node.getAttribute("name") == name ) {
38                         return node;
39                 }
40
41                 node = nodes.item(++i);
42         }
43
44         return null;
45 }
46
47
48
49
50 /** Returns the value stored in the given attribute */
51 DomainObject.prototype.getAttr = function ( name ) {
52
53         var node = this._findAttr( name );
54         if( node ) { return node.getAttribute( "value" ); }
55         else { 
56                 throw new oils_ex_dom( "getAttr(); Getting nonexistent attribute: " + name ); 
57         }
58 }
59
60 /** Updates the value held by the given attribute */
61 DomainObject.prototype.setAttr = function ( name, value ) {
62
63         var node = this._findAttr( name );
64         if( node ) {
65                 node.setAttribute( "value", value );
66         } else { 
67                 throw new oils_ex_dom( "setAttr(); Setting nonexistent attribute: " + name ); 
68         }
69 }
70
71 /** This takes a raw DOM Element node and creates the DomainObject that the node
72   * embodies and returns the object.  All new DomainObjects should be added to
73   * this list if they require this type of dynamic functionality.
74   * NOTE Much of this will be deprecated as move to a more JSON-centric wire protocol
75   */
76 DomainObject.newFromNode = function( node ) {
77
78         switch( node.getAttribute("name") ) {
79
80                 case "oilsMethod":
81                         return new oilsMethod().replaceNode( node );
82                 
83                 case "oilsMessage":
84                         return new oilsMessage().replaceNode( node );
85
86                 case "oilsResponse":
87                         return new oilsResponse().replaceNode( node );
88
89                 case "oilsResult":
90                         return new oilsResult().replaceNode( node );
91
92                 case "oilsConnectStatus":
93                         return new oilsConnectStatus().replaceNode( node );
94
95                 case "oilsException":
96                         return new oilsException().replaceNode( node );
97
98                 case "oilsMethodException":
99                         return new oilsMethodException().replaceNode( node );
100
101                 case "oilsScalar":
102                         return new oilsScalar().replaceNode( node );
103
104                 case "oilsPair":
105                         return new oilsPair().replaceNode( node );
106
107                 case "oilsArray":
108                         return new oilsArray().replaceNode( node );
109
110                 case "oilsHash":
111                         return new oilsHash().replaceNode( node );
112
113
114         }
115
116 }
117
118
119
120 // -----------------------------------------------------------------------------
121 // oilsMethod
122
123 oilsMethod.prototype = new DomainObject();
124 oilsMethod.prototype.constructor = oilsMethod;
125 oilsMethod.prototype.baseClass = DomainObject.prototype.constructor;
126
127 /**
128   * oilsMethod Constructor
129   * 
130   * @param method_name The name of the method your are sending
131   * to the remote server
132   * @param params_array A Javascript array of the params (any
133   * Javascript data type)
134   */
135
136 function oilsMethod( method_name, params_array ) {
137         this._init_domainObject( "oilsMethod" );
138         this.add( new domainObjectAttr( "method", method_name ) );
139
140         if( params_array ) {
141                 var params = this.doc.createElement( "oils:params" );
142                 this.element.appendChild( params ); 
143                 params.appendChild( this.doc.createTextNode( 
144                                 js2JSON( params_array ) ) ); 
145         }
146 }
147
148
149 /** Locates the params node of this method */
150 oilsMethod.prototype._getParamsNode = function() {
151
152         var nodes = this.element.childNodes;
153         if( ! nodes || nodes.length < 1 ) { return null; }
154         var x=0;
155         var node = nodes.item(x);
156         while( node != null ) {
157                 if( node.nodeName == "oils:params" ) {
158                         return node;
159                 }
160                 node = nodes.item(++x);
161         }
162
163         return null;
164 }
165
166
167 /** Returns an array of param objects  */
168 oilsMethod.prototype.getParams = function() {
169         var node = this._getParamsNode();
170         if(node != null ) { 
171                 return JSON2js( node.textContent ); 
172         }
173 }
174
175
176
177 // -----------------------------------------------------------------------------
178 // oilsMessage
179
180 // -----------------------------------------------------------------------------
181 // oilsMessage message types
182 // -----------------------------------------------------------------------------
183 /** CONNECT Message type */
184 oilsMessage.CONNECT             = 'CONNECT';
185 /** DISCONNECT Message type */
186 oilsMessage.DISCONNECT  = 'DISCONNECT';
187 /** STATUS Message type */
188 oilsMessage.STATUS              = 'STATUS';
189 /** REQUEST Message type */
190 oilsMessage.REQUEST             = 'REQUEST';
191 /** RESULT Message type */
192 oilsMessage.RESULT              = 'RESULT';
193
194
195 oilsMessage.prototype = new DomainObject();
196 oilsMessage.prototype.constructor = oilsMessage;
197 oilsMessage.prototype.baseClass = DomainObject.prototype.constructor;
198
199 /** Core XML object for message passing */
200 function oilsMessage( type, protocol, user_auth ) {
201
202         if( !( type && protocol) ) { 
203                 type = oilsMessage.CONNECT; 
204                 protocol = "1";
205         }
206
207         if( ! ( type == oilsMessage.CONNECT             ||
208                                 type == oilsMessage.DISCONNECT  ||
209                                 type == oilsMessage.STATUS                      ||
210                                 type == oilsMessage.REQUEST             ||
211                                 type == oilsMessage.RESULT      ) ) {
212                 throw new oils_ex_message( "Attempt to create oilsMessage with incorrect type: " + type );
213         }
214
215         this._init_domainObject( "oilsMessage" );
216
217         this.add( new domainObjectAttr( "type", type ) );
218         this.add( new domainObjectAttr( "threadTrace", 0 ) );
219         this.add( new domainObjectAttr( "protocol", protocol ) );       
220
221         if( user_auth ) { this.add( user_auth ); }
222
223 }
224
225 /** Builds a new oilsMessage from raw xml.
226   * Checks are taken to make sure the xml is supposed to be an oilsMessage.  
227   * If not, an oils_ex_dom exception is throw.
228   */
229 oilsMessage.newFromXML = function( xml ) {
230
231         try {
232
233                 if( ! xml || xml == "" ) { throw 1; }
234
235                 var doc = new DOMParser().parseFromString( xml, "text/xml" );
236                 if( ! doc ) { throw 1; }
237
238                 var root = doc.documentElement;
239                 if( ! root ) { throw 1; }
240
241                 // -----------------------------------------------------------------------------
242                 // There are two options here.  One is that we were provided the full message
243                 // xml (i.e. contains the <oils:root> tag.  The other option is that we were
244                 // provided just the message xml portion (top level element is the 
245                 // <oils:domainObject>
246                 // -----------------------------------------------------------------------------
247                 
248                 var element;
249                 if( root.nodeName == "oils:root"  ) { 
250
251                         element = root.firstChild;
252                         if( ! element ) { throw 1; }
253
254                 } else { 
255
256                         if( root.nodeName == "oils:domainObject" ) { 
257                                 element = root;
258
259                         } else { throw 1; }
260
261                 }
262
263
264                 if( element.nodeName != "oils:domainObject" ) { throw 1; } 
265                 if( element.getAttribute( "name" ) != "oilsMessage" ) { throw 1; }
266
267                 return new oilsMessage().replaceNode( element );
268
269         } catch( E ) {
270
271                 if( E && E.message ) {
272                         throw new oils_ex_dom( "Bogus XML for creating oilsMessage: " + E.message + "\n" + xml );
273
274                 } else {
275                         throw new oils_ex_dom( "Bogus XML for creating oilsMessage:\n" + xml );
276                 }
277         }
278
279         return msg;
280 }
281
282
283
284 /** Adds a copy of the given DomainObject to the message */
285 oilsMessage.prototype.addPayload = function( new_DomainObject ) {
286         this.add( new_DomainObject );
287 }
288
289
290 /** Returns the top level DomainObject contained in this message
291   *
292   * Note:  The object retuturned will be the actual object, not just a 
293   * generic DomainObject - e.g. oilsException.
294   */
295 oilsMessage.prototype.getPayload = function() {
296         
297         var nodes = this.element.childNodes;
298         var x=0;
299         var node = nodes.item(0);
300
301         while( node != null ) {
302
303                 if( node.nodeName == "oils:domainObject" ) {
304
305                         new Logger().debug( "Building oilsMessage payload from\n" + 
306                                 new XMLSerializer().serializeToString( node ), Logger.DEBUG );
307                         return DomainObject.newFromNode( node );
308                 }
309                 node = nodes.item(++x);
310         }
311
312         return null;
313 }
314
315 oilsMessage.prototype.getUserAuth = function() {
316
317         var nodes = this.element.getElementsByTagName( "oils:userAuth" );
318         if( ! nodes ) { return null; }
319
320         var auth_elem = nodes.item(0); // should only be one
321         if ( ! auth_elem ) { return null; }
322
323         return new userAuth().replaceNode( auth_elem );
324
325 }
326
327 /** Returns the type of the message */
328 oilsMessage.prototype.getType = function() {
329         return this.getAttr( "type" );
330 }
331
332 /** Returns the message protocol */
333 oilsMessage.prototype.getProtocol = function() {
334         return this.getAttr( "protocol" );
335 }
336
337 /** Returns the threadTrace */
338 oilsMessage.prototype.getThreadTrace = function() {
339         return this.getAttr( "threadTrace" );
340 }
341
342 /** Sets the thread trace - MUST be an integer */
343 oilsMessage.prototype.setThreadTrace = function( trace ) {
344         this.setAttr( "threadTrace", trace );
345 }
346
347 /** Increments the thread trace by 1 */
348 oilsMessage.prototype.updateThreadTrace = function() {
349         var tt = this.getThreadTrace();
350         return this.setThreadTrace( ++tt );
351 }
352
353
354
355
356
357 // -----------------------------------------------------------------------------
358 // oilsResponse
359
360
361 // -----------------------------------------------------------------------------
362 // Response codes
363 // -----------------------------------------------------------------------------
364
365 /**
366   * Below are the various response statuses
367   */
368 oilsResponse.STATUS_CONTINUE                                            = 100
369
370 oilsResponse.STATUS_OK                                                          = 200
371 oilsResponse.STATUS_ACCEPTED                                            = 202
372 oilsResponse.STATUS_COMPLETE                                            = 205
373
374 oilsResponse.STATUS_REDIRECTED                                  = 307
375
376 oilsResponse.STATUS_BADREQUEST                                  = 400
377 oilsResponse.STATUS_UNAUTHORIZED                                        = 401
378 oilsResponse.STATUS_FORBIDDEN                                           = 403
379 oilsResponse.STATUS_NOTFOUND                                            = 404
380 oilsResponse.STATUS_NOTALLOWED                                  = 405
381 oilsResponse.STATUS_TIMEOUT                                             = 408
382 oilsResponse.STATUS_EXPFAILED                                           = 417
383 oilsResponse.STATUS_INTERNALSERVERERROR         = 500
384 oilsResponse.STATUS_NOTIMPLEMENTED                              = 501
385 oilsResponse.STATUS_VERSIONNOTSUPPORTED         = 505
386
387
388 oilsResponse.prototype = new DomainObject();
389 oilsResponse.prototype.constructor = oilsResponse;
390 oilsResponse.prototype.baseClass = DomainObject.prototype.constructor;
391
392 /** Constructor.  status is the text describing the message status and
393   * statusCode must correspond to one of the oilsResponse status code numbers
394   */
395 function oilsResponse( name, status, statusCode ) {
396         if( name && status && statusCode ) {
397                 this._initResponse( name, status, statusCode );
398         }
399 }
400
401 /** Initializes the reponse XML */
402 oilsResponse.prototype._initResponse = function( name, status, statusCode ) {
403
404         this._init_domainObject( name );
405         this.add( new domainObjectAttr( "status", status ));
406         this.add( new domainObjectAttr( "statusCode", statusCode ) );
407 }
408
409
410
411 /** Returns the status of the response */
412 oilsResponse.prototype.getStatus = function() {
413         return this.getAttr( "status" );
414 }
415
416 /** Returns the statusCode of the response */
417 oilsResponse.prototype.getStatusCode = function() {
418         return this.getAttr("statusCode");
419 }
420
421
422 oilsConnectStatus.prototype = new oilsResponse();
423 oilsConnectStatus.prototype.constructor = oilsConnectStatus;
424 oilsConnectStatus.prototype.baseClass = oilsResponse.prototype.constructor;
425
426 /** Constructor.  These give us info on our connection attempts **/
427 function oilsConnectStatus( status, statusCode ) {
428         this._initResponse( "oilsConnectStatus", status, statusCode );
429 }
430
431
432 oilsResult.prototype = new oilsResponse();
433 oilsResult.prototype.constructor = oilsResult;
434 oilsResult.prototype.baseClass = oilsResponse.prototype.constructor;
435
436
437 /** Constructor.  These usually carry REQUEST responses */
438 function oilsResult( status, statusCode ) {
439         if( status && statusCode ) {
440                 this._initResponse( "oilsResult", status, statusCode );
441         }
442 }
443
444 /** Returns the top level DomainObject within this result message.
445   * Note:  The object retuturned will be the actual object, not just a 
446   * generic DomainObject - e.g. oilsException.
447   */
448 oilsResult.prototype.getContent = function() {
449
450         var nodes = this.element.childNodes;
451         if( ! nodes || nodes.length < 1 ) {
452                 throw new oils_ex_dom("Content node for oilsResult is invalid\n" + this.toString() );
453         }
454         var x = 0;
455         var node = nodes.item(x);
456         while( node != null ) {
457
458                 if( node.nodeName == "oils:domainObject"                                        ||
459                                 node.nodeName == "oils:domainObjectCollection" ) {
460
461                         return DomainObject.newFromNode( node );
462                 }
463                 node = nodes.item(++x);
464         }
465
466         throw new oils_ex_dom("Content node for oilsResult is invalid\n" + this.toString() );
467 }
468
469
470 oilsException.prototype = new oilsResponse();
471 oilsException.prototype.constructor = oilsException;
472 oilsException.prototype.baseClass = oilsResponse.prototype.constructor;
473
474 /** Top level exception */
475 function oilsException( status, statusCode ) {
476         if( status && statusCode ) {
477                 this._initResponse( "oilsException", status, statusCode );
478         }
479 }
480
481
482 oilsMethodException.prototype = new oilsException();
483 oilsMethodException.prototype.constructor = oilsMethodException;
484 oilsMethodException.prototype.baseClass = oilsException.prototype.constructor;
485
486 /** Method exception */
487 function oilsMethodException( status, statusCode ) {
488         if( status && statusCode ) {
489                 this._initResponse( "oilsMethodException", status, statusCode );
490         }
491 }
492
493
494 // -----------------------------------------------------------------------------
495 // oilsScalar
496
497
498 oilsScalar.prototype = new DomainObject();
499 oilsScalar.prototype.constructor = oilsScalar;
500 oilsScalar.prototype.baseClass = DomainObject.prototype.constructor;
501
502 /** Contains a single JSON item as its text content */
503 function oilsScalar( value ) {
504         this._init_domainObject( "oilsScalar" );
505         this.element.appendChild( this.doc.createTextNode( value ) );
506 }
507
508 /** Returns the contained item as a Javascript object */
509 oilsScalar.prototype.getValue = function() {
510         return JSON2js( this.element.textContent );
511 }
512
513
514 // -----------------------------------------------------------------------------
515 // oilsPair
516
517
518 oilsPair.prototype = new DomainObject()
519 oilsPair.prototype.constructor = oilsPair;
520 oilsPair.prototype.baseClass = DomainObject.prototype.constructor;
521
522 function oilsPair( key, value ) {
523
524         this._init_domainObject( "oilsPair" );
525         this.element.appendChild( this.doc.createTextNode( value ) );
526         this.element.setAttribute( "key", key );
527 }
528
529 oilsPair.prototype.getKey = function() {
530         return this.element.getAttribute( "key" );
531 }
532
533 oilsPair.prototype.getValue = function() {
534         return this.element.textContent;
535 }
536
537
538
539 // -----------------------------------------------------------------------------
540 // oilsArray - is a domainObjectCollection that stores a list of domainObject's
541 // or domainObjectCollections.
542 // -----------------------------------------------------------------------------
543
544 oilsArray.prototype = new domainObjectCollection()
545 oilsArray.prototype.constructor = oilsArray;
546 oilsArray.prototype.baseClass = domainObjectCollection.prototype.constructor;
547
548 function oilsArray( obj_list ) {
549         this._initCollection( "oilsArray" );
550         if(obj_list) { this.initArray( obj_list ); }
551 }
552
553 // -----------------------------------------------------------------------------
554 // Adds the array of objects to the array, these should be actual objects, not
555 // DOM nodes/elements, etc.
556 // -----------------------------------------------------------------------------
557 oilsArray.prototype.initArray = function( obj_list ) {
558         if( obj_array != null && obj_array.length > 0 ) {
559                 for( var i= 0; i!= obj_array.length; i++ ) {
560                         this.add( obj_array[i] );
561                 }
562         }
563 }
564
565 // -----------------------------------------------------------------------------
566 // Returns an array of DomainObjects or domainObjectCollections.  The objects
567 // returned will already be 'cast' into the correct object. i.e. you will not
568 // receieve an array of DomainObjects, but instead an array of oilsScalar's or
569 // an array of oilsHashe's, etc.
570 // -----------------------------------------------------------------------------
571 oilsArray.prototype.getObjects = function() {
572
573         var obj_list = new Array();
574         var nodes = this.element.childNodes;
575         var i=0;
576         var node = nodes.item(i);
577
578         while( node != null ) {
579
580                 if( node.nodeName == "oils:domainObject"                                        ||
581                                 node.nodeName == "oils:domainObjectCollection" ) {
582                         obj_list[i++] = DomainObject.newFromNode( node );
583                 }
584                 node = nodes.item(i);
585         }
586
587         return obj_list;
588 }
589
590
591 // -----------------------------------------------------------------------------
592 // oilsHash - an oilsHash is an oilsArray except it only stores oilsPair's
593 // -----------------------------------------------------------------------------
594
595 oilsHash.prototype = new oilsArray();
596 oilsHash.prototype.constructor = oilsHash;
597 oilsHash.prototype.baseClass = oilsArray.prototype.constructor;
598
599 function oilsHash( pair_array ) {
600         this._initCollection("oilsHash");
601         if(pair_array) { this.initArray( pair_array ); }
602 }
603
604 // -----------------------------------------------------------------------------
605 // Returns the array of oilsPairs objects that this hash contains
606 // -----------------------------------------------------------------------------
607 oilsHash.prototype.getPairs = function() {
608         return this.getObjects();
609 }
610
611