1 /**
  2  * @fileOverview JavaScript representation of the Finesse Dialog object.
  3  *
  4  * @name finesse.restservices.Dialog
  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.Dialog = finesse.restservices.RestBase.extend(/** @lends finesse.restservices.Dialog.prototype */{
 16 
 17     /**
 18      * @class
 19      * JavaScript representation of a Dialog object. Also exposes methods to operate
 20      * on the object against the server.
 21      *
 22 	 * @param {Object} options
 23 	 *     An object with the following properties:<ul>
 24      *         <li><b>id:</b> The id of the object being constructed</li>
 25      *         <li><b>onLoad(this): (optional)</b> when the object is successfully loaded from the server</li>
 26      *         <li><b>onChange(this): (optional)</b> when an update notification of the object is received</li>
 27      *         <li><b>onAdd(this): (optional)</b> when a notification that the object is created is received</li>
 28      *         <li><b>onDelete(this): (optional)</b> when a notification that the object is deleted is received</li>
 29      *         <li><b>onError(rsp): (optional)</b> if loading of the object fails, invoked with the error response object:<ul>
 30      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
 31      *             <li><b>content:</b> {String} Raw string of response</li>
 32      *             <li><b>object:</b> {Object} Parsed object of response</li>
 33      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
 34      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
 35      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
 36      *             </ul></li>
 37      *         </ul></li>
 38      *         <li><b>parentObj: (optional)</b> The parent object</li></ul>
 39      * @constructs finesse.restservices.Dialog
 40      **/
 41     init: function (options) {
 42         this._super(options);
 43     },
 44 
 45     /**
 46      * @private
 47      * Gets the REST class for the current object - this is the Dialog class.
 48      * @returns {Object} The Dialog class.
 49      */
 50     getRestClass: function () {
 51         return finesse.restservices.Dialog;
 52     },
 53 
 54     /**
 55      * @private
 56      * Gets the REST type for the current object - this is a "Dialog".
 57      * @returns {String} The Dialog string.
 58      */
 59     getRestType: function () {
 60         return "Dialog";
 61     },
 62 
 63     /**
 64      * @private
 65      * Override default to indicate that this object doesn't support making
 66      * requests.
 67      */
 68     supportsRequests: false,
 69 
 70     /**
 71      * @private
 72      * Override default to indicate that this object doesn't support subscriptions.
 73      */
 74     supportsSubscriptions: false,
 75 
 76     /**
 77      * Getter for the DNIS.
 78      * @returns {String} The DNIS.
 79      */
 80     getDNIS: function () {
 81         this.isLoaded();
 82         return this.getData().DNIS;
 83     },
 84 
 85     /**
 86      * Getter for the from address.
 87      * @returns {String} The from address.
 88      */
 89     getFromAddress: function () {
 90         this.isLoaded();
 91         return this.getData().fromAddress;
 92     },
 93 
 94     /**
 95      * Getter for the to address.
 96      * @returns {String} The to address.
 97      */
 98     getToAddress: function () {
 99         this.isLoaded();
100         return this.getData().toAddress;
101     },
102     /**
103      * Getter for the media type.
104      * @returns {String} The media type.
105      */
106     getMediaType: function () {
107         this.isLoaded();
108         return this.getData().mediaType;
109     },
110 
111     /**
112      * Getter for the callType.
113      * @returns {String} The callType.
114      */
115     getCallType: function () {
116         this.isLoaded();
117         return this.getData().mediaProperties.callType;
118     },
119 
120     /**
121      * Getter for the Dialog state.
122      * @returns {String} The Dialog state.
123      */
124     getState: function () {
125         this.isLoaded();
126         return this.getData().state;
127     },
128 
129     /**
130      * Retrieves a list of participants within the Dialog object.
131      * @returns {Object} List of
132      */
133     getParticipants: function () {
134         this.isLoaded();
135         var participants = this.getData().participants.Participant;
136         //Due to the nature of the XML->JSO converter library, a single
137         //element in the XML array will be considered to an object instead of
138         //a real array. This will handle those cases to ensure that an array is
139         //always returned.
140 
141         return finesse.utilities.Utilities.getArray(participants);
142     },
143 
144     /**
145      * Retrieves a list of media properties a.k.a. call variables from the dialog object
146      * @returns {Object} Map of call variables; names mapped to values
147      */
148     getMediaProperties: function () {
149 
150         var mpData, resultMap = {};
151 
152         this.isLoaded();
153 
154         mpData = this.getData().mediaProperties;
155 
156         if (mpData) {
157 
158             if (this.getState() !== finesse.restservices.Dialog.States.INITIATING) {
159 
160                 if (mpData.callvariables && mpData.callvariables.CallVariable) {
161                     jQuery.each(mpData.callvariables.CallVariable, function (i, callVariable) {
162                         resultMap[callVariable.name] = callVariable.value;
163                     });
164                 }
165 
166             }
167 
168             if (mpData.wrapUpReason) {
169                 resultMap.wrapUpReason = mpData.wrapUpReason;
170             }
171 
172         }
173 
174         return resultMap;
175     },
176 
177     /**
178      * @private
179      * Invoke a request to the server given a content body and handlers.
180      *
181      * @param {Object} contentBody
182      *     A JS object containing the body of the action request.
183      * @param {Object} handlers
184      *     An object containing the following (optional) handlers for the request:<ul>
185      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
186      *         response object as its only parameter:<ul>
187      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
188      *             <li><b>content:</b> {String} Raw string of response</li>
189      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
190      *         <li>A error callback function for an unsuccessful request to be invoked with the
191      *         error response object as its only parameter:<ul>
192      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
193      *             <li><b>content:</b> {String} Raw string of response</li>
194      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
195      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
196      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
197      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
198      *             </ul></li>
199      *         </ul>
200      */
201     _makeRequest: function (contentBody, handlers) {
202         // Protect against null dereferencing of options allowing its
203         // (nonexistant) keys to be read as undefined
204         handlers = handlers || {};
205 
206         this.restRequest(this.getRestUrl(), {
207             method: 'PUT',
208             success: handlers.success,
209             error: handlers.error,
210             content: contentBody
211         });
212     },
213 
214     /**
215      * Invoke a consult call out to a destination.
216      *
217      * @param {String} mediaAddress
218      *     The media address of the user performing the consult call.
219      * @param {String} toAddress
220      *     The destination address of the consult call.
221      * @param {Object} handlers
222      *     An object containing the following (optional) handlers for the request:<ul>
223      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
224      *         response object as its only parameter:<ul>
225      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
226      *             <li><b>content:</b> {String} Raw string of response</li>
227      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
228      *         <li>A error callback function for an unsuccessful request to be invoked with the
229      *         error response object as its only parameter:<ul>
230      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
231      *             <li><b>content:</b> {String} Raw string of response</li>
232      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
233      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
234      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
235      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
236      *             </ul></li>
237      *         </ul>
238      */
239     makeConsultCall: function (mediaAddress, toAddress, handlers) {
240         this.isLoaded();
241         var contentBody = {};
242         contentBody[this.getRestType()] = {
243             "targetMediaAddress": mediaAddress,
244             "toAddress": toAddress,
245             "requestedAction": finesse.restservices.Dialog.Actions.CONSULT_CALL
246         };
247         this._makeRequest(contentBody, handlers);
248         return this; // Allow cascading
249     },
250 
251     /**
252      * Update this dialog's wrap-up reason.
253      *
254      * @param {String} wrapUpReason
255      *     The new wrap-up reason for this dialog
256      * @param {Object} handlers
257      *     An object containing the following (optional) handlers for the request:<ul>
258      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
259      *         response object as its only parameter:<ul>
260      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
261      *             <li><b>content:</b> {String} Raw string of response</li>
262      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
263      *         <li>A error callback function for an unsuccessful request to be invoked with the
264      *         error response object as its only parameter:<ul>
265      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
266      *             <li><b>content:</b> {String} Raw string of response</li>
267      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
268      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
269      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
270      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
271      *             </ul></li>
272      *         </ul>
273      */
274     updateWrapUpReason: function (wrapUpReason, options)
275     {
276         this.isLoaded();
277         var mediaProperties =
278         {
279             "wrapUpReason": wrapUpReason
280         };
281 
282         options = options || {};
283         options.content = {};
284         options.content[this.getRestType()] =
285         {
286             "mediaProperties": mediaProperties,
287             "requestedAction": finesse.restservices.Dialog.Actions.UPDATE_CALL_DATA
288         };
289         options.method = "PUT";
290         this.restRequest(this.getRestUrl(), options);
291 
292         return this;
293     },
294 
295     /**
296      * Invoke a request to server based on the action given.
297      * @param {String} mediaAddress
298      *     The media address of the user performing the consult call.
299      * @param {String} action
300      *     The action string indicating the action to invoke on dialog.
301      * @param {Object} handlers
302      *     An object containing the following (optional) handlers for the request:<ul>
303      *         <li><b>success(rsp):</b> A callback function for a successful request to be invoked with the following
304      *         response object as its only parameter:<ul>
305      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
306      *             <li><b>content:</b> {String} Raw string of response</li>
307      *             <li><b>object:</b> {Object} Parsed object of response</li></ul>
308      *         <li>A error callback function for an unsuccessful request to be invoked with the
309      *         error response object as its only parameter:<ul>
310      *             <li><b>status:</b> {Number} The HTTP status code returned</li>
311      *             <li><b>content:</b> {String} Raw string of response</li>
312      *             <li><b>object:</b> {Object} Parsed object of response (HTTP errors)</li>
313      *             <li><b>error:</b> {Object} Wrapped exception that was caught:<ul>
314      *                 <li><b>errorType:</b> {String} Type of error that was caught</li>
315      *                 <li><b>errorMessage:</b> {String} Message associated with error</li>
316      *             </ul></li>
317      *         </ul>
318      * @private
319      */
320     requestAction: function (mediaAddress, action, handlers) {
321         this.isLoaded();
322         var contentBody = {};
323         contentBody[this.getRestType()] = {
324             "targetMediaAddress": mediaAddress,
325             "requestedAction": action
326         };
327         this._makeRequest(contentBody, handlers);
328         return this; // Allow cascading
329     },
330     
331     /**
332      * Invoke a request to server based on the action given.
333      * @param {String} mediaAddress
334      *     The media address of the user performing the consult call.
335      * @param {String} action
336      *     The action string indicating the action to invoke on dialog.
337      * @param {Object} [handlers]
338      *     A set of handlers invoked when async response comes back.
339      * @param {Function} [handlers.success]
340      *     The success handler when request is successful.
341      * @param {Function} [hanlders.error]
342      *     The error handler when request has errors.
343      * @private
344      */
345     sendDTMFRequest: function (mediaAddress, handlers, digit) {
346         this.isLoaded();
347         var contentBody = {};
348         contentBody[this.getRestType()] = {
349             "targetMediaAddress": mediaAddress,
350             "requestedAction": "SEND_DTMF",
351             "actionParams": {
352 				"ActionParam": {
353 					"name": "dtmfString",
354 					"value": digit
355 				}
356 			}
357         };
358         this._makeRequest(contentBody, handlers);
359         return this; // Allow cascading
360     }
361 });
362 
363 /**
364  * Possible dialog state constants.
365  */
366 finesse.restservices.Dialog.States = {
367     ALERTING: "ALERTING",
368     INITIATING: "INITIATING",
369     ACTIVE: "ACTIVE",
370     DROPPED: "DROPPED",
371     HELD: "HELD",
372     INITIATED: "INITIATED",
373     FAILED: "FAILED",
374     INACTIVE: "INACTIVE",
375     WRAP_UP: "WRAP_UP"
376 };
377 
378 /**
379  * Possible dialog state reasons code constants.
380  */
381 finesse.restservices.Dialog.ReasonStates = {
382     BUSY: "BUSY",
383     BAD_DESTINATION: "BAD_DESTINATION",
384     OTHER: "OTHER",
385     DEVICE_RESOURCE_NOT_AVAILABLE : "DEVICE_RESOURCE_NOT_AVAILABLE"
386 };
387 
388 /**
389  * Possible participant actions constants.
390  */
391 finesse.restservices.Dialog.Actions = {
392     DROP: "DROP",
393     ANSWER: "ANSWER",
394     HOLD: "HOLD",
395     MAKE_CALL: "MAKE_CALL",
396     RETRIEVE: "RETRIEVE",
397     CONSULT_CALL: "CONSULT_CALL",
398     TRANSFER: "TRANSFER",
399     CONFERENCE: "CONFERENCE",
400     UPDATE_CALL_DATA: "UPDATE_CALL_DATA"
401 };
402