Changed zouba directory heirarchy.
[ptas] / zouba / misc / rss / preview / script / lib / sapi / Messaging.js
1 /**
2  * Messaging.js
3  * 
4  * Nokia Web Runtime Service API emulation 
5  * WRT v1.1
6  * 
7  * Copyright 2009 Nokia Corporation. All rights reserved.
8 */
9   
10 (function(){
11         
12         var provider = 'Service.Messaging' ,
13                 Interface = 'IMessaging';
14                 
15         /**
16          * Messaging service
17          */
18         var MessagingService = function(){
19                 this.GetList                            = __GetList;
20                 this.Send                                       = __Send;
21                 this.RegisterNotification       = __RegisterNotification;
22                 this.CancelNotification         = __CancelNotification;
23                 this.ChangeStatus                       = __ChangeStatus;
24                 this.Delete                                     = __Delete;
25                 this.Cancel                             = __Cancel;
26         }
27
28         device.implementation.extend(provider, Interface, new MessagingService() );
29
30
31         /******************************************************/        
32         /******************************************************/        
33         /******************************************************/        
34
35         var     context = device.implementation.context,
36                 _t = context._t,
37                 method = '',
38                 result = false,
39                 DBase = null;
40         
41         /**
42          * Messaging: GetList
43          * @param {Object} criteria
44          */
45         function __GetList(criteria){
46
47                 if ((result = validator.apply('GetList', arguments)) !== false)
48                         return result; 
49         
50                 if (!criteria.Type)
51                         return error(device.implementation.ERR_MISSING_ARGUMENT, msg.missingType);
52
53                 if (!/^Inbox$/i.test(criteria.Type))
54                         return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badType);
55         
56                 var returnValue = [], 
57                         match = null,
58                         filter = criteria.Filter || null;
59  
60                 DBase = context.getData(provider);
61
62                 // filter by MessageId
63                 if (filter && filter.MessageId) {
64                         returnValue = findByKey(DBase.Inbox, filter.MessageId, 'MessageId'); 
65                         if (returnValue.length == 0)
66                                 return error(device.implementation.ERR_NOT_FOUND);
67                 }
68                 // return all messages
69                 else {
70                         returnValue = DBase.Inbox;
71                 }
72
73                 // unsupported filters 
74                 if (filter 
75                         && (match = context.keys(filter).join().match(/MessageTypeList|SenderList|Subject|StartDate|EndDate/ig)) ) {
76                         context.notify(_t('%s:: GetList : filter %s not implemented in preview').arg(provider, match.join()));
77                 }
78                 // unsupported sort                     
79                 if (criteria.Sort) { 
80                         context.notify(_t('%s:: GetList : sort not implemented in preview').arg(provider));
81                 }
82                 return context.Result(context.Iterator(returnValue));
83         }
84                         
85         /**
86          * Messaging: Send
87          * @param {Object} criteria
88          * @param {Function} [callback] function for async call (optional)
89          */
90         function __Send(criteria, callback){
91
92                 if ((result = validator.apply('Send', arguments)) !== false)
93                         return result; 
94
95                 if (!criteria.MessageType)
96                         return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.missingMessageType);
97                         
98                 if (!/^(SMS|MMS)$/i.test(criteria.MessageType))
99                         return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badMessageType);
100
101                 if (!criteria.To)
102                         return error(device.implementation.ERR_MISSING_ARGUMENT, msg.missingTo);
103                 
104                 // async call?
105                 if (typeof callback == 'function') {
106                         return context.callAsync(this, arguments.callee, criteria, callback);
107                 }
108
109                 context.notify(_t('%s:: Send : message sent!').arg(provider));
110
111                 // return success
112                 return error(device.implementation.ERR_SUCCESS);
113         }
114                         
115
116         /**
117          * Messaging: RegisterNotification
118          * @param {Object} criteria
119          * @param {function} callback function for async call (mandatory)
120          */
121         function __RegisterNotification(criteria, callback){
122
123                 if ((result = validator.apply('RegisterNotification', arguments)) !== false)
124                         return result; 
125
126                 // callback is mandatory
127                 if (typeof callback != 'function')
128                         return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badAsync);
129                 
130                 // continue validation after callback check             
131                 if (typeof criteria.Type == 'undefined') 
132                         return error(device.implementation.ERR_MISSING_ARGUMENT, msg.missingType);
133                 
134                 if (!/^NewMessage$/i.test(criteria.Type)) 
135                         return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badType);
136
137                 var eventType =  'NewMessage';
138
139                 // check for multiple registration
140                 if (context.hasListener(provider, eventType))
141                         return error(device.implementation.ERR_ENTRY_EXISTS);
142                                 
143                 // process notify
144                 return context.addListener(provider, eventType, criteria, callback, notifyHandler);
145         }
146                         
147         function notifyHandler(transactionID, criteria, callback, data){
148                 
149                 var result,
150                         eventCode = {completed:2, error:4, progress:9},
151                         code = eventCode.progress;
152                 try{
153                         DBase = context.getData(provider);
154                         
155                         // make new message
156                         var now = new Date();
157                         var message = {
158                                 "MessageType": "SMS",
159                                 "Sender": "0435445454",
160                                 "Subject": "new message",
161                                 "Time": _t("%s, %s").arg(now.toString().substr(0,3), now.toLocaleString()),
162                                 "Priority": "Medium",
163                                 "Attachment": false,
164                                 "Unread": true,
165                                 "MessageId": context.getUniqueID(),
166                                 "BodyText": "My hovercraft is full of eels!"
167                         };
168                         
169                         // extend with optional data
170                         data = typeof data=='object' && !(data instanceof Array) ? data : {};
171                         var returnValue = context.extend(message, data);
172
173                         result = context.Result(returnValue);
174                         
175                         /// add to top of inbox
176                         DBase.Inbox.unshift(message);
177                 } 
178                 catch(e){
179                         code = eventCode.error;
180                 }
181                 callback(transactionID, code, result);
182         }
183         
184         /**
185          * Messaging: CancelNotification
186          * @param {Object} criteria
187          */
188         function __CancelNotification(criteria){
189
190                 if ((result = validator.apply('CancelNotification', arguments)) !== false)
191                         return result; 
192
193                 if (typeof criteria.Type == 'undefined') 
194                         return error(device.implementation.ERR_MISSING_ARGUMENT, msg.missingType);
195
196                 if (!/^NewMessage$/i.test(criteria.Type)) 
197                         return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badType);
198
199                 var eventType = 'NewMessage';
200                 context.removeListener(provider, eventType);
201                 return context.ErrorResult(device.implementation.ERR_SUCCESS);
202         }
203                         
204                         
205         /**
206          * Messaging: ChangeStatus
207          * @param {Object} criteria
208          */
209         function __ChangeStatus(criteria){
210
211                 if ((result = validator.apply('ChangeStatus', arguments)) !== false)
212                         return result; 
213
214                 if (!criteria.MessageId)
215                         return error(device.implementation.ERR_MISSING_ARGUMENT, msg.is_missing ,'MessageId');
216                         
217                 if (typeof criteria.MessageId != 'number')
218                         return error(device.implementation.ERR_BAD_ARGUMENT_TYPE, msg.badMessageIdType);
219                         
220                 if (!criteria.Status)
221                         return error(device.implementation.ERR_MISSING_ARGUMENT, msg.is_missing ,'Status');
222
223                 if (!/^(Read|Unread|Replied|Forwarded)$/i.test(criteria.Status))
224                         return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badStatus);
225         
226                 // check if a callback was provided
227                 if (arguments.length > 1)
228                         return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badAsync2);
229                         
230                 DBase = context.getData(provider);
231
232                 var i,item, found = false;
233                 for (i in DBase.Inbox) {
234                         item = DBase.Inbox[i];
235                         if (criteria.MessageId == item.MessageId) {
236                                 item.Unread = /Unread/i.test(criteria.Status);
237                                 found = true;
238                         }
239                 }
240                 if (!found)
241                         return error(device.implementation.ERR_NOT_FOUND);
242
243                 // return success
244                 return error(device.implementation.ERR_SUCCESS);                                
245         }
246                                                 
247         /**
248          * Messaging: Delete
249          * @param {Object} criteria
250          */
251         function __Delete(criteria){
252                 
253                 if ((result = validator.apply('Delete', arguments)) !== false)
254                         return result; 
255
256                 if (typeof criteria.MessageId == 'undefined')
257                         return error(device.implementation.ERR_MISSING_ARGUMENT, msg.missingMessageId);
258
259                 if (typeof criteria.MessageId != 'number')
260                         return error(device.implementation.ERR_BAD_ARGUMENT_TYPE, msg.badMessageIdType);
261                                         
262                 if (criteria.MessageId < 0)
263                         return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badMessageId);
264                         
265                 DBase = context.getData(provider);
266
267                 var i,item, found = false;
268                 for (i in DBase.Inbox) {
269                         item = DBase.Inbox[i];
270                         if (criteria.MessageId == item.MessageId) {
271                                 DBase.Inbox.splice(i, 1);
272                                 found = true;
273                         }
274                 }
275                 if (!found)
276                         return error(device.implementation.ERR_NOT_FOUND);
277                         
278                 // return success
279                 return error(device.implementation.ERR_SUCCESS);                                
280         }
281                         
282
283         /**
284          * Messaging: Cancel
285          * @param {Object} criteria
286          */
287         function __Cancel(criteria){
288                 method = 'Cancel';
289                 if (!criteria || !criteria.TransactionID)
290                         return error(device.implementation.ERR_MISSING_ARGUMENT, msg.is_missing, 'TransactionID');
291                 
292                 clearTimeout(criteria.TransactionID);
293                 return context.ErrorResult(device.implementation.ERR_SUCCESS);
294         }
295
296         
297         /*******************************
298          * helper functions
299          *******************************/
300         
301         function error(code, msg /*, args...*/){
302
303                 var args = ['Messaging',method].concat([].slice.call(arguments,2));
304                 msg = msg ? _t().arg.apply(msg,args) : undefined;
305                 return context.ErrorResult(code, msg);
306         }
307
308         /**
309          * validate common input arguments
310          * 'this' is string (object) name of calling function
311          * 
312          * @param {arguments} arguments of calling function
313          * @return {Result} Result object if error, false if no error.
314          */
315         function validator() {
316                 method = ''+this;
317                 var     failed = false,
318                         criteria = arguments[0] || false;
319
320                 if (!criteria || typeof criteria != 'object')
321                         return error(device.implementation.ERR_MISSING_ARGUMENT, 
322                                 method == 'Send' 
323                                 ? msg.missingMessageType 
324                                 : (/ChangeStatus|Delete/.test(method) 
325                                         ? msg.missingMessageId 
326                                         : msg.missingType) );
327                         
328                 return failed;
329         }
330
331
332         function findByKey(dbase, value, key){
333                 var result = [];
334                 for (var i in dbase) {
335                         if (value == dbase[i][key]) {
336                                 result.push(dbase[i]);
337                         }
338                 }
339                 return result;
340         }
341
342         /** 
343          * error messages
344          * order of %s args: Service name, method name, parameter name 
345          */
346         var msg = {
347                 missingType             : '%s:%s:Type Missing',
348                 badType                 : '%s:%s:Type Value Incorrect',
349                 missingTo               : '%s:%s:To Missing',
350                 badTo                   : '%s:%s:To Value Incorrect',
351                 missingMessageType      : '%s:%s:MessageType Missing',
352                 badMessageType  : '%s:%s:MessageType Value Incorrect',
353                 badAsync                : '%s:%s:Synchronous Operation not supported',
354                 badAsync2               : '%s:%s:Asynchronous Operation not supported',
355                 missingMessageId        : '%s:%s:MessageId Missing',
356                 badMessageIdType: '%s:%s:MessageId Type Invalid',
357                 badMessageId    : '%s:%s:MessageId Value Incorrect',
358                 badStatus               : '%s:%s:Status Value Incorrect',
359
360                 is_missing              : '%s:%s:%s Missing',
361                 is_invalid              : '%s:%s:%s Value Incorrect'
362         };
363                 
364
365 }) ()
366