1 /**
  2  * @fileOverview JavaScript representation of the Finesse User object
  3  *
  4  * @name finesse.restservices.User
  5  * @requires finesse.clientservices.ClientServices
  6  * @requires Class
  7  * @requires finesse.FinesseBase
  8  * @requires finesse.restservices.RestBase
  9  */
 10 
 11 var finesse = finesse || {};
 12 finesse.restservices = finesse.restservices || {};
 13 
 14 /** @private */
 15 finesse.restservices.User = finesse.restservices.RestBase.extend(/** @lends finesse.restservices.User.prototype */{
 16 
 17     _dialogs : null,
 18     _clientLogObj : null,
 19     _wrapUpReasons : null,
 20     _phoneBooks : null,
 21     _mediaPropertiesLayout : null,
 22     _queues : null,
 23     /**
 24      * @class
 25      * JavaScript representation of a User object. Also exposes methods to operate
 26      * on the object against the server.
 27      *
 28      * @param {Object} options
 29      *     An object with the following properties:<ul>
 30      *         <li><b>id:</b> The id of the object being constructed</li>
 31      *         <li><b>onLoad(this): (optional)</b> when the object is successfully loaded from the server</li>
 32      *         <li><b>onChange(this): (optional)</b> when an update notification of the object is received</li>
 33      *         <li><b>onAdd(this): (optional)</b> when a notification that the object is created is received</li>
 34      *         <li><b>onDelete(this): (optional)</b> when a notification that the object is deleted is received</li>
 35      *         <li><b>onError(rsp): (optional)</b> if loading of the object fails, invoked with the error response object:<ul>
 36      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
 37      *             <li><b>content:</b> {String} Raw string of response</li>
 38      *             <li><b>object:</b> {Object} Parsed object of response</li>
 39      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
 40      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
 41      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
 42      *             </ul></li>
 43      *         </ul></li>
 44      *         <li><b>parentObj: (optional)</b> The parent object</li></ul>
 45      * @constructs finesse.restservices.User
 46      **/
 47     init: function (options) {
 48         this._super(options);
 49     },
 50 
 51     /**
 52      * @private
 53      * Gets the REST class for the current object - this is the User object.
 54      */
 55     getRestClass: function () {
 56         return finesse.restservices.User;
 57     },
 58 
 59     /**
 60     * @private
 61      * Gets the REST type for the current object - this is a "User".
 62      */
 63     getRestType: function () {
 64         return "User";
 65     },
 66     /**
 67      * overloading this to return URI
 68      */
 69     getXMPPNodePath: function () {
 70         return this.getRestUrl();
 71     },
 72     /**
 73     * @private
 74      * Returns whether this object supports subscriptions
 75      */
 76     supportsSubscriptions: function () {
 77         return true;
 78     },
 79 
 80     /**
 81      * Getter for the firstName of this User
 82      * @returns {String}
 83      *     The firstName for this User
 84      */
 85     getFirstName: function () {
 86         this.isLoaded();
 87         return this.getData().firstName;
 88     },
 89 
 90     /**
 91      * Getter for the lastName of this User
 92      * @returns {String}
 93      *     The lastName for this User
 94      */
 95     getLastName: function () {
 96         this.isLoaded();
 97         return this.getData().lastName;
 98     },
 99 
100     /**
101      * Getter for the extension of this User
102      * @returns {String}
103      *     The extension, if any, of this User
104      */
105     getExtension: function () {
106         this.isLoaded();
107         return this.getData().extension;
108     },
109 
110     /**
111      * Is user an agent?
112      * @returns {boolean} if user has role of agent
113      */
114     hasAgentRole: function () {
115         this.isLoaded();
116         return this.hasRole("Agent");
117     },
118 
119     /**
120      * Is user a supervisor?
121      * @returns {boolean} if user has role of supervisor
122      */
123     hasSupervisorRole: function () {
124         this.isLoaded();
125         return this.hasRole("Supervisor");
126     },
127 
128     /**
129      * Checks to see if user has "theRole"
130      * @returns {boolean}
131      */
132     hasRole: function (theRole) {
133         this.isLoaded();
134         var result = false, i, roles, len;
135 
136         roles = this.getData().roles.role;
137         len = roles.length;
138         if (typeof roles === 'string') {
139             if (roles === theRole) {
140                 result = true;
141             }
142         } else {
143             for (i = 0; i < len ; i = i + 1) {
144                 if (roles[i] === theRole) {
145                     result = true;
146                     break;
147                 }
148             }
149         }
150 
151         return result;
152     },
153 
154     /**
155      * Getter for the state of this User
156      * @returns {String}
157      *     The current (or last fetched) state of this User
158      */
159     getState: function () {
160         this.isLoaded();
161         return this.getData().state;
162     },
163     
164     /**
165      * Getter for the state change time of this User
166      * @returns {String}
167      *     The state change time of this User
168      */
169     getStateChangeTime: function () {
170         this.isLoaded();
171         return this.getData().stateChangeTime;
172     },
173 
174     /**
175      * Checks to see if the user is considered a mobile agent by checking for
176      * the existance of the mobileAgent node.
177      * @returns {Boolean}
178      *      True if this agent is a mobile agent.
179      */
180     isMobileAgent: function () {
181         this.isLoaded();
182         var ma = this.getData().mobileAgent;
183         return ma !== null && typeof ma === "object";
184     },
185 
186     /**
187      * Getter for the mobile agent work mode.
188      * @returns {String}
189      *      If available, return the mobile agent work mode, otherwise null
190      */
191     getMobileAgentMode: function () {
192         this.isLoaded();
193         if (this.isMobileAgent()) {
194             return this.getData().mobileAgent.mode;
195         }
196         return null;
197     },
198 
199     /**
200      * Getter for the mobile agent dial number.
201      * @returns {String}
202      *      If available, return the mobile agent dial number, otherwise null.
203      */
204     getMobileAgentDialNumber: function () {
205         this.isLoaded();
206         if (this.isMobileAgent()) {
207             return this.getData().mobileAgent.dialNumber;
208         }
209         return null;
210     },
211 
212     /**
213      * Getter for a Dialogs collection object that is associated with User.
214      * @returns {Dialogs}
215      *     A Dialogs collection object.
216      */
217     getDialogs: function (callbacks) {
218         var options = callbacks || {};
219         options.parentObj = this;
220         this.isLoaded();
221 
222         if (this._dialogs === null) {
223             this._dialogs = new finesse.restservices.Dialogs(options);
224         }
225 
226         return this._dialogs;
227     },
228     
229     /**
230      * Getter for a ClientLog object that is associated with User.
231      * @returns {ClientLog}
232      *     A ClientLog collection object.
233      */
234     getClientLog: function (callbacks) {
235         var options = callbacks || {};
236         options.parentObj = this;
237         this.isLoaded();
238        
239         if (this._clientLogObj === null) {
240             this._clientLogObj = new finesse.restservices.ClientLog(options);
241         }
242         else {
243             if(options.onLoad && typeof options.onLoad === "function") {
244             options.onLoad(this._clientLogObj);
245             }
246         }
247         return this._clientLogObj;
248     },
249    
250     /**
251      * Getter for a Queues collection object that is associated with User.
252      * @returns {Queues}
253      *     A Queues collection object.
254      */
255     getQueues: function (callbacks) {
256         var options = callbacks || {};
257         options.parentObj = this;
258         this.isLoaded();
259 
260         if (this._queues === null) {
261             this._queues = new finesse.restservices.Queues(options);
262         }
263 
264         return this._queues;
265     },
266 
267     /**
268      * Getter for a WrapUpReasons collection object that is associated with User.
269      * @param handlers
270      * @returns {WrapUpReasons}
271      *     A WrapUpReasons collection object.
272      */
273     getWrapUpReasons: function (callbacks) {
274         var options = callbacks || {};
275         options.parentObj = this;
276         this.isLoaded();
277 
278         if (this._wrapUpReasons === null) {
279             this._wrapUpReasons = new finesse.restservices.WrapUpReasons(options);
280         }
281 
282         return this._wrapUpReasons;
283     },
284 
285     /**
286      * Getter for a PhoneBooks collection object that is associated with User.
287      * @param handlers
288      * @returns {PhoneBooks}
289      *     A PhoneBooks collection object.
290      */
291     getPhoneBooks: function (callbacks) {
292         var options = callbacks || {};
293         options.parentObj = this;
294         this.isLoaded();
295 
296         if (this._phoneBooks === null) {
297             this._phoneBooks = new finesse.restservices.PhoneBooks(options);
298         }
299 
300         return this._phoneBooks;
301     },
302 
303     /**
304      * Getter for a MediaPropertiesLayout object that is associated with User.
305      * @returns {finesse.restservices.MediaPropertiesLayout}
306      *     The MediaPropertiesLayout object associated with this user
307      */
308     getMediaPropertiesLayout: function (callbacks) {
309         var options = callbacks || {};
310         options.parentObj = this;
311         options.id = this._id;
312 
313         this.isLoaded();
314         if (this._mediaPropertiesLayout === null) {
315             this._mediaPropertiesLayout = new finesse.restservices.MediaPropertiesLayout(options);
316         }
317         return this._mediaPropertiesLayout;
318     },
319 
320     /**
321      * Getter for the supervised Teams this User (Supervisor) supervises, if any
322      * @returns {Array}
323      *     An array of teams supervised by this User (Supervisor)
324      */
325     getSupervisedTeams: function () {
326         this.isLoaded();
327 
328         try {
329             return finesse.utilities.Utilities.getArray(this.getData().teams.Team);
330         } catch (e) {
331             return [];
332         }
333 
334     },
335 
336     /**
337      * Perform an agent login for this user, associating him with the
338      * specified extension.
339      * @param {Object} params
340      *     An object containing properties for agent login.
341      * @param {String} params.extension
342      *     The extension to associate with this user
343      * @param {Object} [params.mobileAgent]
344      *     A mobile agent object containing the mode and dial number properties.
345      * @param {Object} params.handlers
346      *     An object containing the following (optional) handlers for the request:<ul>
347      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
348      *         response object as its only parameter:<ul>
349      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
350      *             <li><b>content:</b> {String} Raw string of response</li>
351      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
352      *         <li>A error callback function for an unsuccessful request to be invoked with the
353      *         error response object as its only parameter:<ul>
354      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
355      *             <li><b>content:</b> {String} Raw string of response</li>
356      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
357      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
358      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
359      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
360      *             </ul></li>
361      *         </ul>
362      * @returns {finesse.restservices.User}
363      *     This User object to allow cascading
364      * @private
365      */
366     _login: function (params) {
367         var handlers, contentBody = {},
368         restType = this.getRestType();
369         
370         // Protect against null derefernecing.
371         params = params || {};
372 
373         contentBody[restType] = {
374             "state": finesse.restservices.User.States.LOGIN,
375             "extension": params.extension
376         };
377 
378         // Create mobile agent node if available.
379         if (typeof params.mobileAgent === "object") {
380             contentBody[restType].mobileAgent = {
381                 "mode": params.mobileAgent.mode,
382                 "dialNumber": params.mobileAgent.dialNumber
383             };
384         }
385 
386         // Protect against null dereferencing of options allowing its (nonexistant) keys to be read as undefined
387         handlers = params.handlers || {};
388 
389         this.restRequest(this.getRestUrl(), {
390             method: 'PUT',
391             success: handlers.success,
392             error: handlers.error,
393             content: contentBody
394         });
395 
396         return this; // Allow cascading
397     },
398 
399     /**
400      * Perform an agent login for this user, associating him with the
401      * specified extension.
402      * @param {String} extension
403      *     The extension to associate with this user
404      * @param {Object} handlers
405      *     An object containing the following (optional) handlers for the request:<ul>
406      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
407      *         response object as its only parameter:<ul>
408      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
409      *             <li><b>content:</b> {String} Raw string of response</li>
410      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
411      *         <li>A error callback function for an unsuccessful request to be invoked with the
412      *         error response object as its only parameter:<ul>
413      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
414      *             <li><b>content:</b> {String} Raw string of response</li>
415      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
416      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
417      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
418      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
419      *             </ul></li>
420      *         </ul>
421      * @returns {finesse.restservices.User}
422      *     This User object to allow cascading
423      */
424     login: function (extension, handlers) {
425         this.isLoaded();
426         var params = {
427             "extension": extension,
428             "handlers": handlers
429         };
430         return this._login(params);
431     },
432 
433     /**
434      * Perform an agent login for this user, associating him with the
435      * specified extension.
436      * @param {String} extension
437      *     The extension to associate with this user
438      * @param {String} mode
439      *     The mobile agent work mode as defined in finesse.restservices.User.WorkMode.
440      * @param {String} extension
441      *     The external dial number desired to be used by the mobile agent.
442      * @param {Object} handlers
443      *     An object containing the following (optional) handlers for the request:<ul>
444      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
445      *         response object as its only parameter:<ul>
446      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
447      *             <li><b>content:</b> {String} Raw string of response</li>
448      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
449      *         <li>A error callback function for an unsuccessful request to be invoked with the
450      *         error response object as its only parameter:<ul>
451      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
452      *             <li><b>content:</b> {String} Raw string of response</li>
453      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
454      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
455      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
456      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
457      *             </ul></li>
458      *         </ul>
459      * @returns {finesse.restservices.User}
460      *     This User object to allow cascading
461      */
462     loginMobileAgent: function (extension, mode, dialNumber, handlers) {
463         this.isLoaded();
464         var params = {
465             "extension": extension,
466             "mobileAgent": {
467                 "mode": mode,
468                 "dialNumber": dialNumber
469             },
470             "handlers": handlers
471         };
472         return this._login(params);
473     },
474 
475     /**
476      * Perform an agent logout for this user.
477      * @param {String} reasonCode
478      *     The reason this user is logging out.  Pass null for no reason.
479      * @param {Object} handlers
480      *     An object containing the following (optional) handlers for the request:<ul>
481      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
482      *         response object as its only parameter:<ul>
483      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
484      *             <li><b>content:</b> {String} Raw string of response</li>
485      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
486      *         <li>A error callback function for an unsuccessful request to be invoked with the
487      *         error response object as its only parameter:<ul>
488      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
489      *             <li><b>content:</b> {String} Raw string of response</li>
490      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
491      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
492      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
493      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
494      *             </ul></li>
495      *         </ul>
496      * @returns {finesse.restservices.User}
497      *     This User object to allow cascading
498      */
499     logout: function (reasonCode, handlers) {
500         return this.setState("LOGOUT", reasonCode, handlers);
501     },
502 
503     /**
504      * Set the state of the user.
505      * @param {String} newState
506      *     The state you are setting
507      * @param {ReasonCode} reasonCode
508      *     The reason this user is logging out.  Pass null for no reason.
509      * @param {Object} handlers
510      *     An object containing the following (optional) handlers for the request:<ul>
511      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
512      *         response object as its only parameter:<ul>
513      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
514      *             <li><b>content:</b> {String} Raw string of response</li>
515      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
516      *         <li>A error callback function for an unsuccessful request to be invoked with the
517      *         error response object as its only parameter:<ul>
518      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
519      *             <li><b>content:</b> {String} Raw string of response</li>
520      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
521      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
522      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
523      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
524      *             </ul></li>
525      *         </ul>
526      * @returns {finesse.restservices.User}
527      *     This User object to allow cascading
528      */
529     setState: function (newState, reasonCode, handlers) {
530         this.isLoaded();
531 
532         var options, contentBody = {};
533 
534         if (!reasonCode) {
535             contentBody[this.getRestType()] = {
536                 "state": newState
537             };
538         } else {
539             contentBody[this.getRestType()] = {
540                 "state": newState,
541                 "reasonCodeId": reasonCode.id
542             };
543         }
544 
545         // Protect against null dereferencing of options allowing its (nonexistant) keys to be read as undefined
546         handlers = handlers || {};
547 
548         options = {
549             method: 'PUT',
550             success: handlers.success,
551             error: handlers.error,
552             content: contentBody
553         };
554 
555         // After removing the selective 202 handling, we should be able to just use restRequest
556         this.restRequest(this.getRestUrl(), options);
557 
558         return this; // Allow cascading
559     },
560 
561     /**
562      * Make call to a particular phone number.
563      *
564      * @param {String} The number to call
565      * @param {Object} handlers
566      *     An object containing the following (optional) handlers for the request:<ul>
567      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
568      *         response object as its only parameter:<ul>
569      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
570      *             <li><b>content:</b> {String} Raw string of response</li>
571      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
572      *         <li>A error callback function for an unsuccessful request to be invoked with the
573      *         error response object as its only parameter:<ul>
574      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
575      *             <li><b>content:</b> {String} Raw string of response</li>
576      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
577      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
578      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
579      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
580      *             </ul></li>
581      *         </ul>
582      */
583     makeCall: function (number, handlers) {
584         this.isLoaded();
585 
586         this.getDialogs().createNewCallDialog(number, this.getExtension(), handlers);
587 
588         return this; // Allow cascading
589     },
590 
591     /**
592      * Make a silent monitor call to a particular agent's phone number.
593      *
594      * @param number to call
595      * @param {Object} handlers
596      *     An object containing the following (optional) handlers for the request:<ul>
597      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
598      *         response object as its only parameter:<ul>
599      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
600      *             <li><b>content:</b> {String} Raw string of response</li>
601      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
602      *         <li>A error callback function for an unsuccessful request to be invoked with the
603      *         error response object as its only parameter:<ul>
604      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
605      *             <li><b>content:</b> {String} Raw string of response</li>
606      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
607      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
608      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
609      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
610      *             </ul></li>
611      *         </ul>
612      */
613     makeSMCall: function (number, handlers) {
614         this.isLoaded();
615 
616         var actionType = "SILENT_MONITOR";
617 
618         this.getDialogs().createNewSuperviseCallDialog(number, this.getExtension(), actionType, handlers);
619 
620         return this; // Allow cascading
621     },
622     
623 
624     /**
625      * Make a silent monitor call to a particular agent's phone number.
626      *
627      * @param number to call
628      * @param {String} dialogUri
629      *     The associated uri of SUPERVISOR_MONITOR call
630      * @param {Object} handlers
631      *     An object containing the following (optional) handlers for the request:<ul>
632      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
633      *         response object as its only parameter:<ul>
634      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
635      *             <li><b>content:</b> {String} Raw string of response</li>
636      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
637      *         <li>A error callback function for an unsuccessful request to be invoked with the
638      *         error response object as its only parameter:<ul>
639      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
640      *             <li><b>content:</b> {String} Raw string of response</li>
641      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
642      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
643      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
644      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
645      *             </ul></li>
646      *         </ul>
647      */
648     makeBargeCall:function (number,dialogURI, handlers) {
649         this.isLoaded();
650         var actionType = "BARGE_CALL";
651         this.getDialogs().createNewBargeCall( this.getExtension(), number, actionType, dialogURI,handlers);
652 
653         return this; // Allow cascading
654     },
655     
656     /**
657      * Returns true if the user's current state will result in a pending state change. A pending state
658      * change is a request to change state that does not result in an immediate state change. For
659      * example if an agent attempts to change to the NOT_READY state while in the TALKING state, the
660      * agent will not change state until the call ends.
661      *
662      * The current set of states that result in pending state changes is as follows:
663      *     TALKING
664      *     HOLD
665      *     RESERVED_OUTBOUND_PREVIEW
666      */
667     isPendingStateChange: function () {
668         var state = this.getState();
669         return state && ((state === finesse.restservices.User.States.TALKING) || (state === finesse.restservices.User.States.HOLD) || (state === finesse.restservices.User.States.RESERVED_OUTBOUND_PREVIEW));
670     },
671 
672     /**
673      * Parses a uriString to retrieve the id portion
674      * @param {String} uriString
675      * @return {String} id
676      */
677     _parseIdFromUriString : function (uriString) {
678         return finesse.utilities.Utilities.getId(uriString);
679     },
680 
681     /**
682      * Gets the user's Not Ready reason code.
683      * @return undefined if not set or indeterminate
684      */
685     getNotReadyReasonCodeId : function () {
686         this.isLoaded();
687 
688         var reasoncodeIdResult, finesseServerReasonCodeId;
689         finesseServerReasonCodeId = this.getData().reasonCodeId;
690 
691         //FinesseServer will give "-l" => we will set to undefined (for convenience)
692         if (finesseServerReasonCodeId !== "-1") {
693             reasoncodeIdResult = finesseServerReasonCodeId;
694         }
695 
696         return reasoncodeIdResult;
697     },
698 
699     /**
700      * Performs a GET against the Finesse server looking up the reasonCodeId specified.
701      * @param {Object} handlers
702      *     An object containing the following (optional) handlers for the request:<ul>
703      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
704      *         response object as its only parameter:<ul>
705      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
706      *             <li><b>content:</b> {String} Raw string of response</li>
707      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
708      *         <li>A error callback function for an unsuccessful request to be invoked with the
709      *         error response object as its only parameter:<ul>
710      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
711      *             <li><b>content:</b> {String} Raw string of response</li>
712      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
713      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
714      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
715      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
716      *             </ul></li>
717      *         </ul>
718      * @param {String} reasonCodeId is the id for the reason code to lookup
719      */
720     getReasonCodeById : function (handlers, reasonCodeId)
721     {
722         var self = this, contentBody, reasonCode, url;
723         contentBody = {};
724 
725         url = this.getRestUrl() + "/ReasonCode/" + reasonCodeId;
726         this.restRequest(url, {
727             method: 'GET',
728             success: function (rsp) {
729                 reasonCode = {
730                     uri: rsp.object.ReasonCode.uri,
731                     label: rsp.object.ReasonCode.label,
732                     id: self._parseIdFromUriString(rsp.object.ReasonCode.uri)
733                 };
734                 handlers.success(reasonCode);
735             },
736             error: function (rsp) {
737                 handlers.error(rsp);
738             },
739             content: contentBody
740         });
741     },
742 
743     /**
744      * Performs a GET against Finesse server retrieving all the specified type of reason codes.
745      * @param {String} type (LOGOUT or NOT_READY)
746      * @param {Object} handlers
747      *     An object containing the following (optional) handlers for the request:<ul>
748      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
749      *         response object as its only parameter:<ul>
750      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
751      *             <li><b>content:</b> {String} Raw string of response</li>
752      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
753      *         <li>A error callback function for an unsuccessful request to be invoked with the
754      *         error response object as its only parameter:<ul>
755      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
756      *             <li><b>content:</b> {String} Raw string of response</li>
757      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
758      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
759      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
760      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
761      *             </ul></li>
762      *         </ul>
763      */
764     _getReasonCodesByType : function (type, handlers)
765     {
766         var self = this, contentBody = {}, url, reasonCodes, i, reasonCodeArray;
767 
768         url = this.getRestUrl() + "/ReasonCodes?category=" + type;
769         this.restRequest(url, {
770             method: 'GET',
771             success: function (rsp) {
772                 reasonCodes = [];
773 
774                 reasonCodeArray = rsp.object.ReasonCodes.ReasonCode;
775                 if (reasonCodeArray === undefined) {
776                     reasonCodes = undefined;
777                 } else if (reasonCodeArray[0] !== undefined) {
778                     for (i = 0; i < reasonCodeArray.length; i = i + 1) {
779                         reasonCodes[i] = {
780                             label: rsp.object.ReasonCodes.ReasonCode[i].label,
781                             id: self._parseIdFromUriString(rsp.object.ReasonCodes.ReasonCode[i].uri)
782                         };
783                     }
784                 } else {
785                     reasonCodes[0] = {
786                         label: rsp.object.ReasonCodes.ReasonCode.label,
787                         id: self._parseIdFromUriString(rsp.object.ReasonCodes.ReasonCode.uri)
788                     };
789                 }
790                 handlers.success(reasonCodes);
791             },
792             error: function (rsp) {
793                 handlers.error(rsp);
794             },
795             content: contentBody
796         });
797     },
798 
799     /**
800      * Performs a GET against Finesse server retrieving all the Signout reason codes.
801      * @param {Object} handlers
802      *     An object containing the following (optional) handlers for the request:<ul>
803      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
804      *         response object as its only parameter:<ul>
805      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
806      *             <li><b>content:</b> {String} Raw string of response</li>
807      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
808      *         <li>A error callback function for an unsuccessful request to be invoked with the
809      *         error response object as its only parameter:<ul>
810      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
811      *             <li><b>content:</b> {String} Raw string of response</li>
812      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
813      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
814      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
815      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
816      *             </ul></li>
817      *         </ul>
818      */
819     getSignoutReasonCodes : function (handlers)
820     {
821         this._getReasonCodesByType("LOGOUT", handlers);
822     },
823 
824     /**
825      * Performs a GET against Finesse server retrieving all the Not Ready reason codes.
826      * @param {Object} handlers
827      *     An object containing the following (optional) handlers for the request:<ul>
828      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
829      *         response object as its only parameter:<ul>
830      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
831      *             <li><b>content:</b> {String} Raw string of response</li>
832      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
833      *         <li>A error callback function for an unsuccessful request to be invoked with the
834      *         error response object as its only parameter:<ul>
835      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
836      *             <li><b>content:</b> {String} Raw string of response</li>
837      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
838      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
839      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
840      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
841      *             </ul></li>
842      *         </ul>
843      */
844     getNotReadyReasonCodes : function (handlers)
845     {
846         this._getReasonCodesByType("NOT_READY", handlers);
847     }
848 
849 });
850 
851 /**
852  * State constants
853  */
854 finesse.restservices.User.States = {
855     LOGIN: "LOGIN",
856     LOGOUT: "LOGOUT",
857     NOT_READY: "NOT_READY",
858     READY: "READY",
859     RESERVED: "RESERVED",
860     RESERVED_OUTBOUND: "RESERVED_OUTBOUND",
861     RESERVED_OUTBOUND_PREVIEW: "RESERVED_OUTBOUND_PREVIEW",
862     TALKING: "TALKING",
863     HOLD: "HOLD",
864     WORK: "WORK",
865     WORK_READY: "WORK_READY"
866 };
867 
868 /**
869  * Mobile agent/supervisor work modes.
870  */
871 finesse.restservices.User.WorkMode = {
872     CALL_BY_CALL: "CALL_BY_CALL",
873     NAILED_CONNECTION: "NAILED_CONNECTION"
874 };
875