|
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 |