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