Beta merge 2
[profile/ivi/wrt-plugins-tizen.git] / src / standards / Tizen / Messaging / ConverterMessage.cpp
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License. 
15 */
16
17
18 /**
19  *
20  *
21  * @file       ConverterMessage.cpp
22  * @author     Pawel Misiak (p.misiak@samsung.com)
23  * @author     Grzegorz Krawczyk (g.krawczyk@samsung.com)
24  * @version    0.1
25  * @brief
26  */
27 #include <dpl/assert.h>
28 #include <Commons/Exception.h>
29 #include <CommonsJavaScript/PrivateObject.h>
30 #include <CommonsJavaScript/Validator.h>
31 #include <CommonsJavaScript/JSUtils.h>
32 #include <CommonsJavaScript/JSDOMExceptionFactory.h>
33 #include "ConverterMessage.h"
34 #include "JSMessage.h"
35 #include "JSMessagePrivateObject.h"
36 #include "JSRecipientArray.h"
37 #include "JSMessagingListener.h"
38 #include <CommonsJavaScript/ScopedJSStringRef.h>
39 #include "JSMessageAttachment.h"
40 #include "JSConversation.h"
41 #include "JSMessageFolder.h"
42
43 #if 0 // MESSAGING ATTACHMENT IS BLOCKED
44 #include <Tizen/Filesystem/JSFile.h>
45 #endif
46
47 using namespace std;
48 using namespace WrtDeviceApis::Commons;
49 using namespace WrtDeviceApis::CommonsJavaScript;
50
51 namespace {
52 const char* SEND_PROPERTY_ONSUCCESS = "onsuccess";
53 const char* SEND_PROPERTY_ONMESSAGESENDSUCCESS = "onmessagesendsuccess";
54 const char* SEND_PROPERTY_ONMESSAGESENDERROR = "onmessagesenderror";
55 }
56
57 namespace TizenApis {
58 namespace Tizen1_0 {
59
60 MessageFunctions ConverterMessage::m_callbackNames[MESSAGING_MULTI_FUNTION_MAX]
61 {
62         {"messagesAdded", "messagesUpdated", "messagesRemoved"},
63         {"conversationsAdded", "conversationsUpdated", "conversationsRemoved"},
64         {"foldersAdded", "foldersUpdated", "foldersRemoved"}
65 };
66
67 ConverterMessage::ConverterMessage(JSContextRef context) :
68     Converter(context)
69 {
70 }
71
72 ConverterMessage::~ConverterMessage()
73 {
74 }
75
76 JSContextRef ConverterMessage::toJSGlobalContext(JSObjectRef arg)
77 {
78     // get private object
79     WrtDeviceApis::CommonsJavaScript::PrivateObjectT<void>::Type* priv =
80         static_cast<WrtDeviceApis::CommonsJavaScript::PrivateObjectT<void>::Type*>(JSObjectGetPrivate(
81                                                               arg));
82     if (!priv) {
83         LogError("Private object not initialized");
84         ThrowMsg(WrtDeviceApis::Commons::NullPointerException,
85                  "Private object not initialized");
86     }
87     return priv->getContext();
88 }
89
90 JSValueRef ConverterMessage::toJSValueRef(Api::Messaging::FolderType arg)
91 {
92     switch (arg) {
93     case Api::Messaging::INBOX:
94         return toJSValueRef(messageFolderInbox);
95     case Api::Messaging::OUTBOX:
96         return toJSValueRef(messageFolderOutbox);
97     case Api::Messaging::DRAFTBOX:
98         return toJSValueRef(messageFolderDrafts);
99     case Api::Messaging::SENTBOX:
100         return toJSValueRef(messageFolderSentbox);
101     default:
102         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "folder not supported");
103     }
104 }
105
106 JSValueRef ConverterMessage::toJSValueRef(Api::Messaging::MessageType arg)
107 {
108     switch (arg) {
109     case Api::Messaging::SMS:
110         return toJSValueRef(messageTypeSms);
111     case Api::Messaging::MMS:
112         return toJSValueRef(messageTypeMms);
113     case Api::Messaging::EMAIL:
114         return toJSValueRef(messageTypeEmail);
115     default:
116         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "message type not supported");
117     }
118 }
119
120 JSValueRef ConverterMessage::toJSValueRef(const Api::Messaging::IMessagePtr& arg,
121         Api::Messaging::EventUpdateMessageAnswerReceiver* listener)
122 {
123     switch (arg->getMessageType()) {
124     case Api::Messaging::SMS:
125     case Api::Messaging::MMS:
126     case Api::Messaging::EMAIL:
127         return JSMessage::createJSObject(m_context, arg, listener);
128
129     default:
130         LogError("unknown type");
131         Throw(WrtDeviceApis::Commons::ConversionException);
132     }
133 }
134
135 JSValueRef ConverterMessage::toJSValueRef(
136         const std::vector<Api::Messaging::IMessagePtr>& arg,
137         Api::Messaging::EventUpdateMessageAnswerReceiver* listener)
138 {
139     vector<JSValueRef> msgsJS;
140     for (size_t i = 0; i < arg.size(); i++) {
141         msgsJS.push_back(toJSValueRef(arg[i], listener));
142     }
143     return toJSValueRef(msgsJS);
144 }
145
146 JSValueRef ConverterMessage::toJSValueRef(const std::vector<Api::Messaging::IConversationPtr>& conversations)
147 {
148     vector<JSValueRef> conversationJS;
149
150         for (size_t i = 0; i < conversations.size(); i++)
151         {
152                 JSValueRef value = JSConversation::createJSObject(m_context, conversations[i]);
153         conversationJS.push_back(value);
154     }
155
156     return toJSValueRef(conversationJS);
157 }
158
159 JSValueRef ConverterMessage::toJSValueRef(const std::vector<Api::Messaging::IMessageFolderPtr>& messagefolders)
160 {
161     vector<JSValueRef> messagefolderJS;
162
163         for (size_t i = 0; i < messagefolders.size(); i++)
164         {
165                 JSValueRef value = JSMessageFolder::createJSObject(m_context, messagefolders[i]);
166         messagefolderJS.push_back(value);
167     }
168
169     return toJSValueRef(messagefolderJS);
170 }
171
172 JSValueRef ConverterMessage::toJSValueRef(const Api::Messaging::MessagePriority& arg)
173 {
174     switch (arg.getPriority()) {
175     case Api::Messaging::MessagePriority::LOW:
176         return toJSValueRef(false);
177         break;
178     case Api::Messaging::MessagePriority::NORMAL:
179         return toJSValueRef(false);
180         break;
181     case Api::Messaging::MessagePriority::HIGH:
182         return toJSValueRef(true);
183         break;
184     default:
185         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Unknown priority");
186         break;
187     }
188 }
189
190 JSValueRef ConverterMessage::keyToJSValue(JSValueRef value,
191         const string& key)
192 {
193     JSValueRef retVal = NULL;
194
195     if (NULL == value) {
196         LogError("jsValue null");
197         Throw(WrtDeviceApis::Commons::ConversionException);
198     }
199     JSObjectRef argObj = JSValueToObject(m_context, value, NULL);
200     if (NULL == argObj) {
201         LogError("conversion to jsobject fail");
202         Throw(WrtDeviceApis::Commons::ConversionException);
203     }
204     const JSStringRef keyJSStr = JSStringCreateWithUTF8CString(key.c_str());
205     retVal = JSObjectGetProperty(m_context, argObj, keyJSStr, NULL);
206     JSStringRelease(keyJSStr);
207     if (NULL == retVal) {
208         LogWarning("key \"" << key << "\" not found in JSValue map");
209     }
210     // return NULL if no key in map
211     return retVal;
212 }
213
214 Api::Messaging::IMessagePtr ConverterMessage::toIMessage(JSValueRef arg)
215 {
216     return toIMessage(toJSObjectRef(arg));
217 }
218
219 Api::Messaging::IMessagePtr ConverterMessage::toIMessage(JSObjectRef arg)
220 {
221     LogDebug("message object=" << arg);
222     if (!arg) {
223         LogError("Object is null");
224         ThrowMsg(WrtDeviceApis::Commons::NullPointerException,
225                  "Private object not initialized");
226     }
227     Api::Messaging::IMessagePtr retVal;
228     // get private object
229     JSMessagePrivateObject* priv =
230         static_cast<JSMessagePrivateObject*>(JSObjectGetPrivate(arg));
231     if (!priv) {
232         LogError("Private object not initialized");
233         ThrowMsg(WrtDeviceApis::Commons::NullPointerException,
234                  "Private object not initialized");
235     }
236     retVal = priv->getObject();
237     if (!retVal) {
238         LogError("Message private object not initialized");
239         ThrowMsg(WrtDeviceApis::Commons::NullPointerException,
240                  "Private object not initialized");
241     }
242     return retVal;
243 }
244
245 Api::Messaging::IAttachmentPtr ConverterMessage::toIAttachment(JSValueRef arg)
246 {
247         return toIAttachment(toJSObjectRef(arg));
248 }
249
250 Api::Messaging::IAttachmentPtr ConverterMessage::toIAttachment(JSObjectRef arg)
251 {
252         if (!arg)
253         {
254                 LogError("Object is Null");
255                 ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object not initialized");
256         }
257
258         Api::Messaging::IAttachmentPtr retVal;
259         JSMessageAttachmentPrivate* priv =
260         static_cast<JSMessageAttachmentPrivate*>(JSObjectGetPrivate(arg));
261
262         if (!priv) {
263         LogError("Private object not initialized");
264         ThrowMsg(WrtDeviceApis::Commons::NullPointerException,
265                  "Private object not initialized");
266         }
267
268         retVal = priv->getObject();
269         if (!retVal) {
270         LogError("Message private object not initialized");
271         ThrowMsg(WrtDeviceApis::Commons::NullPointerException,
272                  "Private object not initialized");
273         }
274         return retVal;
275 }
276
277 Api::Messaging::IMessageFolderPtr ConverterMessage::toIMessageFolder(JSValueRef arg)
278 {
279         return toIMessageFolder(toJSObjectRef(arg));
280 }
281
282 Api::Messaging::IMessageFolderPtr ConverterMessage::toIMessageFolder(JSObjectRef arg)
283 {
284         if (!arg)
285         {
286                 LogError("Object is Null");
287                 ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object not initialized");
288         }
289
290         Api::Messaging::IMessageFolderPtr retVal;
291         JSMessageFolderPriv* priv =
292         static_cast<JSMessageFolderPriv*>(JSObjectGetPrivate(arg));
293
294         if (!priv) {
295         LogError("Private object not initialized");
296         ThrowMsg(WrtDeviceApis::Commons::NullPointerException,
297                  "Private object not initialized");
298         }
299
300         retVal = priv->getObject();
301         if (!retVal) {
302         LogError("Message private object not initialized");
303         ThrowMsg(WrtDeviceApis::Commons::NullPointerException,
304                  "Private object not initialized");
305         }
306         return retVal;
307 }
308
309 Api::Messaging::Recipients ConverterMessage::toRecipients(JSValueRef arg)
310 {
311     if (JSValueIsObjectOfClass(m_context, arg,
312                                JSRecipientArray::getClassRef())) {
313         Api::Messaging::RecipientsPtr recipients =
314             JSRecipientArray::getRecipients(m_context, toJSObjectRef(arg));
315         if (!recipients) {
316             Throw(WrtDeviceApis::Commons::ConversionException);
317         }
318         return *recipients;
319     }
320     Api::Messaging::Recipients retVal;
321     // convert JS value to vector of recipient addresses
322     vector<string> recip = toVectorOfStrings(arg);
323     retVal.setRecipients(recip);
324     return retVal;
325 }
326
327 OnMessagesChanged ConverterMessage::toMessageMultifunctions(JSValueRef argument)
328 {
329         OnMessagesChanged result;
330         Validator validator(m_context);
331         JSObjectRef objectCallbacks = toJSObjectRef(argument);
332         std::string callbackName = toString(argument);
333         int index = 0;
334
335         LogDebug("Enter\n");
336
337         for (index = 0; index < MESSAGING_MULTI_FUNTION_MAX; index++)
338         {
339                 ScopedJSStringRef propName(toJSStringRef(m_callbackNames[index].addedFunction));
340
341                 if (JSObjectHasProperty(m_context, objectCallbacks, propName.get()))
342                 {
343                         LogDebug("Callback name :" << m_callbackNames[index].addedFunction << " "
344                         << m_callbackNames[index].updatedFunction << " " << m_callbackNames[index].removedFunction);
345
346                         result.messagesAdded = JSUtils::getJSPropertyOrUndefined(m_context, objectCallbacks, m_callbackNames[index].addedFunction);
347                         result.messagesUpdated = JSUtils::getJSPropertyOrUndefined(m_context, objectCallbacks, m_callbackNames[index].updatedFunction);
348                         result.messagesRemoved = JSUtils::getJSPropertyOrUndefined(m_context, objectCallbacks, m_callbackNames[index].removedFunction);
349                         break;
350                 }
351
352         }
353
354         result.functionIndex = index;
355
356         if ((!validator.isNullOrUndefined(result.messagesAdded) && !validator.isCallback(result.messagesAdded)) ||
357         (!validator.isNullOrUndefined(result.messagesUpdated) && !validator.isCallback(result.messagesUpdated)) ||
358         (!validator.isNullOrUndefined(result.messagesRemoved) && !validator.isCallback(result.messagesRemoved)))
359         {
360                 LogError("java script call back set error");
361                 Throw(WrtDeviceApis::Commons::InvalidArgumentException);
362         }
363
364         return result;
365 }
366
367
368 std::vector<Api::Messaging::FolderType> ConverterMessage::toVectorOfFolderTypes(
369         JSValueRef arg)
370 {
371     return toVectorOfT_(arg, &ConverterMessage::toFolderType, this);
372 }
373
374 Api::Messaging::FolderType ConverterMessage::toFolderType(const JSValueRef& arg)
375 {
376     // convert JS value to folder type
377     messageFolders folder = static_cast<messageFolders>(toInt(arg));
378     switch (folder) {
379     case messageFolderInbox:
380         return Api::Messaging::INBOX;
381     case messageFolderOutbox:
382         return Api::Messaging::OUTBOX;
383     case messageFolderDrafts:
384         return Api::Messaging::DRAFTBOX;
385     case messageFolderSentbox:
386         return Api::Messaging::SENTBOX;
387     default:
388         ThrowMsg(WrtDeviceApis::Commons::InvalidArgumentException, "folder not supported");
389     }
390 }
391
392 Api::Messaging::MessageType ConverterMessage::toMessageType(JSValueRef arg)
393 {
394          return toMessageType(toJSObjectRef(arg));
395 }
396
397 Api::Messaging::MessageType ConverterMessage::toMessageType(JSObjectRef arg)
398 {
399     // convert JSvalue to message type enum
400         std::string strMsgType = toString(arg);
401         LogDebug("Messasge Type : " << strMsgType);
402
403         if ( strMsgType.compare("messaging.sms") == 0 ) 
404         {
405                 return Api::Messaging::SMS;
406         }
407         else if ( strMsgType.compare("messaging.mms") == 0 ) 
408         {
409                 return Api::Messaging::MMS;
410         }
411         else if ( strMsgType.compare("messaging.email") == 0 )
412         {
413                 return Api::Messaging::EMAIL;
414         }
415         else
416         {
417                 ThrowMsg(WrtDeviceApis::Commons::ConversionException, "message type not supported");
418         }
419
420 }
421
422 std::string ConverterMessage::toMessageType( long msgtype )
423 {
424         LogDebug("Messasge Type : " << msgtype);
425
426         switch (msgtype)
427         {
428                 case Api::Messaging::SMS:
429                         return "messaging.sms";
430                 case Api::Messaging::MMS:
431                         return "messaging.mms";
432                 case Api::Messaging::EMAIL:
433                         return "messaging.email";
434                 default :
435                         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "message type not supported");
436         }
437 }
438
439 std::string ConverterMessage::toMessageStatusType( long msgstatus )
440 {
441         LogDebug("Messasge Status : " << msgstatus);
442
443         switch (msgstatus)
444         {
445                 case Api::Messaging::MESSAGE_STATUS_SENT:
446                         return "SENT";
447                 case Api::Messaging::MESSAGE_STATUS_SENDING:
448                         return "SENDING";
449                 case Api::Messaging::MESSAGE_STATUS_FAILED:
450                         return "FAILED";
451                 case Api::Messaging::MESSAGE_STATUS_DRAFT:
452                         return "DRAFT";
453                 default :
454                         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "message status not supported");
455         }
456 }
457
458 Api::Messaging::IConversationPtr ConverterMessage::toConversation(const JSValueRef& arg)
459 {
460         return JSConversation::getConversation(m_context, arg);
461 }
462
463 std::vector<Api::Messaging::IConversationPtr> ConverterMessage::toVectorOfConversation(const JSValueRef& arg)
464 {
465         std::vector<Api::Messaging::IConversationPtr> result;
466
467         JSObjectRef jsObject = toJSObjectRef(arg);
468
469         for (std::size_t i = 0; i < JSGetArrayLength(m_context, jsObject); ++i)
470         {
471         JSValueRef element = JSGetArrayElement(m_context, jsObject, i);
472         result.push_back(toConversation(element));
473     }
474
475     return result;
476
477 }
478 Api::Messaging::AddressType ConverterMessage::toAddressType(JSValueRef arg)
479 {
480     // convert JSvalue to address type enum
481     string addressType = toString(arg);
482     if ("destination" == addressType) {
483         return Api::Messaging::TO_ADDRESS;
484     } else if ("cc" == addressType) {
485         return Api::Messaging::CC_ADDRESS;
486     } else if ("bcc" == addressType) {
487         return Api::Messaging::BCC_ADDRESS;
488     } else {
489         LogError("unknown address type");
490         Throw(WrtDeviceApis::Commons::InvalidArgumentException);
491     }
492 }
493
494 Api::Messaging::MessagePriority::Priority ConverterMessage::toMessagePriority(
495         JSValueRef arg)
496 {
497     if (toBool(arg)) {
498         return Api::Messaging::MessagePriority::HIGH;
499     } else {
500         return Api::Messaging::MessagePriority::NORMAL;
501     }
502 }
503
504 #if 0 // MESSAGING ATTACHMENT IS BLOCKED
505 Api::Filesystem::INodePtr ConverterMessage::toFilesystemNode(JSValueRef arg)
506 {
507     // TODO It doesn't work even when object IS a JS File, not sure what to do?
508     //    if (!JSValueIsObjectOfClass(m_context, arg, JSFile::getClassRef())) {
509     //        ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Not a JSFile object.");
510     //    }
511
512     JSObjectRef attObj = toJSObjectRef(arg);
513     JSFile::PrivateObject* privateObject =
514         static_cast<JSFile::PrivateObject*>(JSObjectGetPrivate(attObj));
515     if (!privateObject) {
516         ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is NULL.");
517     }
518
519     Api::Filesystem::INodePtr result = privateObject->getObject();
520     if (!result) {
521         ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Node object is NULL.");
522     }
523
524     return result;
525 }
526 #endif
527
528 JSValueRef ConverterMessage::toFunctionOrNull(const JSValueRef& arg)
529 {
530     Assert(arg && "Argument is NULL.");
531
532     if (Validator(m_context).isCallback(arg)) {
533         return arg;
534     } else if (!JSValueIsNull(m_context,
535                               arg) && !JSValueIsUndefined(m_context, arg)) {
536         ThrowMsg(ConversionException, "Not a function nor JS null.");
537     }
538     return NULL;
539 }
540
541 JSValueRef ConverterMessage::toFunction(const JSValueRef& arg)
542 {
543     Assert(arg && "Argument is NULL.");
544
545     if (Validator(m_context).isCallback(arg)) {
546         return arg;
547     } else if (JSValueIsNull(m_context,
548                              arg) || JSValueIsUndefined(m_context, arg)) {
549         ThrowMsg(InvalidArgumentException, "JS null passed as function.");
550     }
551     ThrowMsg(ConversionException, "Not a function nor JS null.");
552 }
553
554 MessageSendCallback
555 ConverterMessage::toMessageSendCallback(const JSValueRef& arg)
556 {
557     JSObjectRef object = toJSObjectRef(arg);
558
559     MessageSendCallback result;
560     Validator validator(m_context);
561
562     result.onSuccess = JSUtils::getJSPropertyOrUndefined(
563             m_context, object, SEND_PROPERTY_ONSUCCESS
564             );
565     if (!validator.isNullOrUndefined(result.onSuccess) &&
566         !validator.isCallback(result.onSuccess)) {
567         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Not a valid callback.");
568     }
569
570     result.onMessageSendSuccess = JSUtils::getJSPropertyOrUndefined(
571             m_context, object, SEND_PROPERTY_ONMESSAGESENDSUCCESS
572             );
573     if (!validator.isNullOrUndefined(result.onMessageSendSuccess) &&
574         !validator.isCallback(result.onMessageSendSuccess)) {
575         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Not a valid callback.");
576     }
577
578     result.onMessageSendError = JSUtils::getJSPropertyOrUndefined(
579             m_context, object, SEND_PROPERTY_ONMESSAGESENDERROR
580             );
581     if (!validator.isNullOrUndefined(result.onMessageSendError) &&
582         !validator.isCallback(result.onMessageSendError)) {
583         ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Not a valid callback.");
584     }
585
586     return result;
587 }
588 }
589 }