Update change log and spec for wrt-plugins-tizen_0.4.70
[framework/web/wrt-plugins-tizen.git] / src / Contact / JSAddressBook.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        JSAddressBook.cpp
20  * @author      Kisub Song (kisubs.song@samsung.com)
21  * @version     0.1
22  * @brief       Implementation of the JSAddressBook class
23  */
24
25 #include <CommonsJavaScript/Validator.h>
26 #include <CommonsJavaScript/Converter.h>
27 #include <CommonsJavaScript/JSCallbackManager.h>
28 #include <CommonsJavaScript/JSUtils.h>
29 #include <CommonsJavaScript/JSPendingOperation.h>
30 #include <SecurityExceptions.h>
31 #include <FilterConverter.h>
32 #include "ContactFactory.h"
33 #include "EventAddressBookAddBatch.h"
34 #include "EventAddressBookUpdateBatch.h"
35 #include "EventAddressBookRemoveBatch.h"
36 #include "EventAddressBookFind.h"
37 #include "EventAddressBookChangeListener.h"
38 #include "EventAddressBookRemoveBatch.h"
39 #include "plugin_config_impl.h"
40 #include "JSAddressBook.h"
41 #include "JSContact.h"
42 #include "JSContactGroup.h"
43 #include "ContactConverter.h"
44 #include "AddressBookController.h"
45 #include "JSAddressBookChangeCallbackManager.h"
46 #include "ContactAsyncCallbackManager.h"
47 #include "ContactListenerManager.h"
48 #include "ContactFilterConverter.h"
49 #include <ArgumentValidator.h>
50 #include <JSWebAPIErrorFactory.h>
51 #include <JSUtil.h>
52 #include <TimeTracer.h>
53 #include <Security.h>
54 #include <Logger.h>
55 #include "ContactUtility.h"
56
57 using namespace std;
58
59 #define TIZEN_ADDRESS_BOOK_ID           "id"
60 #define TIZEN_ADDRESS_BOOK_NAME         "name"
61 #define TIZEN_ADDRESS_BOOK_READ_ONLY    "readOnly"
62 #define TIZEN_ADDRESS_BOOK_ACCOUNT_ID   "accountId"
63
64 #define TIZEN_ADDRESS_BOOK              "AddressBook"
65
66 namespace DeviceAPI {
67 namespace Contact {
68
69 using namespace DeviceAPI::Common;
70 using namespace DeviceAPI::Tizen;
71 using namespace WrtDeviceApis::Commons;
72 using namespace WrtDeviceApis::CommonsJavaScript;
73
74 JSClassRef JSAddressBook::m_jsClassRef = NULL;
75
76 JSClassDefinition JSAddressBook::m_classInfo = {
77         0,
78         kJSClassAttributeNone,
79         TIZEN_ADDRESS_BOOK,
80         0,
81         m_property,
82         m_function,
83         Initialize,
84         Finalize,
85         NULL, //HasProperty,
86         NULL, //GetProperty,
87         NULL, //SetProperty,
88         NULL, //DeleteProperty,
89         NULL, //GetPropertyNames,
90         NULL, //CallAsFunction,
91         NULL, //CallAsConstructor,
92         NULL, //HasInstance,
93         NULL, //ConvertToType,
94 };
95
96 JSStaticValue JSAddressBook::m_property[] = {
97         { TIZEN_ADDRESS_BOOK_ID, getId, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
98         { TIZEN_ADDRESS_BOOK_NAME, getName, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
99         { TIZEN_ADDRESS_BOOK_READ_ONLY, getReadOnly, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
100 //      { TIZEN_ADDRESS_BOOK_ACCOUNT_ID, getAccountId, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
101         { 0, 0, 0, 0 }
102 };
103
104 JSStaticFunction JSAddressBook::m_function[] = {
105         { "get", get, kJSPropertyAttributeNone },
106         { "add", add, kJSPropertyAttributeNone },
107         { "addBatch", addBatch, kJSPropertyAttributeNone },
108         { "update", update, kJSPropertyAttributeNone },
109         { "updateBatch", updateBatch, kJSPropertyAttributeNone },
110         { "remove", remove, kJSPropertyAttributeNone },
111         { "removeBatch", removeBatch, kJSPropertyAttributeNone },
112         { "find", find, kJSPropertyAttributeNone },
113         { "addChangeListener", addChangeListener, kJSPropertyAttributeNone },
114         { "removeChangeListener", removeChangeListener, kJSPropertyAttributeNone },
115         { "getGroup", getGroup, kJSPropertyAttributeNone },
116         { "addGroup", addGroup, kJSPropertyAttributeNone },
117         { "updateGroup", updateGroup, kJSPropertyAttributeNone },
118         { "removeGroup", removeGroup, kJSPropertyAttributeNone },
119         { "getGroups", getGroups, kJSPropertyAttributeNone },
120         { 0, 0, 0 }
121 };
122
123 const JSClassDefinition* JSAddressBook::getClassInfo()
124 {
125         return &m_classInfo;
126 }
127
128 const JSClassRef JSAddressBook::getClassRef()
129 {
130         LoggerI("entered");
131         if (!m_jsClassRef) {
132                 m_jsClassRef = JSClassCreate(&m_classInfo);
133         }
134         return m_jsClassRef;
135 }
136
137 void JSAddressBook::Initialize(JSContextRef context,
138                 JSObjectRef object)
139 {
140 //      AddressBookController *priv =
141 //              static_cast<AddressBookController*>(JSObjectGetPrivate(object));
142 }
143
144 void JSAddressBook::Finalize(JSObjectRef object)
145 {
146         AddressBookController *priv =
147                 static_cast<AddressBookController*>(JSObjectGetPrivate(object));
148
149         delete priv;
150 }
151
152 bool JSAddressBook::isObjectOfClass(JSContextRef context, JSValueRef value)
153 {
154         return JSValueIsObjectOfClass(context, value, getClassRef());
155 }
156
157 AddressBookPtr JSAddressBook::getAddressBook(JSContextRef context, JSValueRef value)
158 {
159         if (!isObjectOfClass(context, value)) {
160                 Throw(InvalidArgumentException);
161         }
162         JSObjectRef object = JSValueToObject(context, value, NULL);
163         if (!object) {
164                 Throw(InvalidArgumentException);
165         }
166         AddressBookController *priv = static_cast<AddressBookController*>(JSObjectGetPrivate(object));
167         if (!priv) {
168                 Throw(NullPointerException);
169         }
170         return priv->getObject();
171 }
172
173 AddressBookPtr JSAddressBook::getPrivData(JSObjectRef object)
174 {
175         AddressBookController *priv =
176                 static_cast<AddressBookController*>(JSObjectGetPrivate(object));
177         if (priv) {
178                 return priv->getObject();
179         }
180         Throw(NullPointerException);
181 }
182
183 JSValueRef JSAddressBook::getId(JSContextRef context,
184                 JSObjectRef object,
185                 JSStringRef propertyName,
186                 JSValueRef* exception)
187 {
188         Try
189         {
190                 ContactConverterFactory::ConverterType converter =
191                                 ContactConverterFactory::getConverter(context);
192                 AddressBookPtr addressBook = getPrivData(object);
193                 string id = addressBook->getId();
194                 if(id != "")
195                         return converter->toJSValueRef(id);
196                 else
197                         return JSValueMakeNull(context);
198         }
199         Catch(WrtDeviceApis::Commons::Exception)
200         {
201                 LoggerW("trying to get incorrect value");
202         }
203         return JSValueMakeUndefined(context);
204 }
205
206 JSValueRef JSAddressBook::getName(JSContextRef context,
207                 JSObjectRef object,
208                 JSStringRef propertyName,
209                 JSValueRef* exception)
210 {
211         Try
212         {
213                 ContactConverterFactory::ConverterType converter =
214                                 ContactConverterFactory::getConverter(context);
215                 AddressBookPtr addressBook = getPrivData(object);
216                 return converter->toJSValueRef(addressBook->getName());
217         }
218         Catch(WrtDeviceApis::Commons::Exception)
219         {
220                 LoggerW("trying to get incorrect value");
221         }
222
223         return JSValueMakeUndefined(context);
224 }
225
226 JSValueRef JSAddressBook::getReadOnly(JSContextRef context,
227                 JSObjectRef object,
228                 JSStringRef propertyName,
229                 JSValueRef* exception)
230 {
231         Try
232         {
233                 ContactConverterFactory::ConverterType converter =
234                                 ContactConverterFactory::getConverter(context);
235                 AddressBookPtr addressBook = getPrivData(object);
236                 return converter->toJSValueRef(addressBook->getReadOnly());
237         }
238         Catch(WrtDeviceApis::Commons::Exception)
239         {
240                 LoggerW("trying to get incorrect value");
241         }
242
243         return JSValueMakeUndefined(context);
244 }
245
246 JSValueRef JSAddressBook::getAccountId(JSContextRef context,
247                 JSObjectRef object,
248                 JSStringRef propertyName,
249                 JSValueRef* exception)
250 {
251         Try
252         {
253                 ContactConverterFactory::ConverterType converter =
254                                 ContactConverterFactory::getConverter(context);
255                 AddressBookPtr addressBook = getPrivData(object);
256                 string accountId = addressBook->getAccountId();
257                 if(accountId != "")
258                         return converter->toJSValueRef(accountId);
259                 else
260                         return JSValueMakeNull(context);
261         }
262         Catch(WrtDeviceApis::Commons::Exception)
263         {
264                 LoggerW("trying to get incorrect value");
265         }
266         return JSValueMakeUndefined(context);
267 }
268
269 JSValueRef JSAddressBook::get(JSContextRef context,
270                 JSObjectRef object,
271                 JSObjectRef thisObject,
272                 size_t argumentCount,
273                 const JSValueRef arguments[],
274                 JSValueRef* exception)
275 {
276         LoggerD("entered");
277         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
278         AddressBookPtr addressBook;
279         AddressBookController *controller;
280         JSContextRef gContext;
281
282         Try     {
283                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
284                 if (!controller) {
285                         ThrowMsg(InvalidArgumentException, "No private object.");
286                 }
287                 addressBook = controller->getObject();
288                 gContext = controller->getContext();
289
290         } Catch(Exception) {
291                 LoggerE("No private object");
292                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
293         }
294
295         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_GET);
296
297         string id;
298
299         try     {
300                 ArgumentValidator validator(context, argumentCount, arguments);
301                 id = validator.toString(0, false);
302         } catch (const TypeMismatchException& err ) {
303                 return JSWebAPIErrorFactory::postException(context, exception, err);
304         } catch(const BasePlatformException& err) {
305                 return JSWebAPIErrorFactory::postException(context, exception, err);
306         } catch(const ConversionException& err) {
307                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
308         } catch(const NullPointerException& err) {
309                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
310         }
311
312         if(!ContactUtility::checkStrIsUInt(id))
313                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "");
314
315         EventAddressBookGetPtr dplEvent(new EventAddressBookGet());
316
317         dplEvent->setId(id);
318     dplEvent->setForSynchronousCall();
319
320         Try {
321                 addressBook->get(dplEvent);
322         } Catch(Exception) {
323                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
324                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
325         }
326
327         if (!dplEvent->getResult() || !dplEvent->getContactIsSet())
328         {
329                 std::stringstream oss;
330                 switch (dplEvent->getExceptionCode())
331                 {
332                 case ExceptionCodes::NotFoundException:
333                 case ExceptionCodes::InvalidArgumentException:
334                         LoggerE("Not Found error : " << id);
335                         oss << "No Contact id '" << id << "'";
336                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
337                         break;
338                 case ExceptionCodes::PlatformException:
339                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
340                         break;
341                 default:
342                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
343                         break;
344                 }
345         }
346
347         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
348
349         ContactPtr contact = dplEvent->getContact();
350         JSValueRef result;
351         Try {
352                 result = converter->toJSValueRef(contact);
353         } Catch(Exception) {
354                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
355                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
356         }
357
358         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
359         return result;
360 }
361
362 JSValueRef JSAddressBook::add(JSContextRef context,
363                 JSObjectRef object,
364                 JSObjectRef thisObject,
365                 size_t argumentCount,
366                 const JSValueRef arguments[],
367                 JSValueRef* exception)
368 {
369         LoggerD("entered");
370         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
371         AddressBookPtr addressBook;
372         AddressBookController *controller;
373         JSContextRef gContext;
374
375         Try     {
376                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
377                 if (!controller) {
378                         ThrowMsg(InvalidArgumentException, "No private object.");
379                 }
380                 addressBook = controller->getObject();
381                 gContext = controller->getContext();
382         } Catch(Exception) {
383                 LoggerE("No private object");
384                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
385         }
386
387         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD);
388
389         try {
390                 ArgumentValidator validator(context, argumentCount, arguments);
391                 validator.toObject(0, false);
392         } catch (const TypeMismatchException& err ) {
393                 return JSWebAPIErrorFactory::postException(context, exception, err);
394         } catch(const BasePlatformException& err) {
395                 return JSWebAPIErrorFactory::postException(context, exception, err);
396         } catch(const ConversionException& err) {
397                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
398         } catch(const NullPointerException& err) {
399                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
400         }
401
402         ContactPtr contact(NULL);
403
404         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
405         Try     {
406                 if (!JSContact::isObjectOfClass(context, arguments[0]))
407                         ThrowMsg(InvalidArgumentException, "1st argument is not a 'Contact object'.");
408                 contact = converter->toContact(arguments[0]);
409         } Catch(Exception) {
410                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
411                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "1st argument must be a 'Contact object'");
412         }
413
414         EventAddressBookAddPtr dplEvent(new EventAddressBookAdd());
415
416         dplEvent->setContact(contact);
417     dplEvent->setForSynchronousCall();
418
419         Try {
420                 addressBook->add(dplEvent);
421         } Catch(Exception) {
422                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
423                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
424         }
425
426         if (!dplEvent->getResult())
427         {
428                 switch (dplEvent->getExceptionCode())
429                 {
430                 case ExceptionCodes::PlatformException:
431                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
432                         break;
433                 case ExceptionCodes::InvalidArgumentException:
434                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "There is Invalid input value");
435                         break;
436                 default:
437                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
438                         break;
439                 }
440         }
441
442         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
443         return JSValueMakeUndefined(context);
444 }
445
446 JSValueRef JSAddressBook::addBatch(JSContextRef context,
447                 JSObjectRef object,
448                 JSObjectRef thisObject,
449                 size_t argumentCount,
450                 const JSValueRef arguments[],
451                 JSValueRef* exception)
452 {
453         LoggerD("entered");
454         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
455         AddressBookPtr addressBook;
456         JSContextRef gContext;
457         AddressBookController *controller;
458
459         bool js2ndParamIsFunction = false;
460         bool js3rdParamIsFunction = false;
461
462         Try     {
463                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
464                 if (!controller) {
465                         ThrowMsg(InvalidArgumentException, "No private object.");
466                 }
467                 addressBook = controller->getObject();
468                 gContext = controller->getContext();
469         } Catch(Exception) {
470                 LoggerE("No private object");
471                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
472         }
473
474         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_BATCH);
475
476         try {
477                 ArgumentValidator validator(context, argumentCount, arguments);
478
479                 validator.toObject(0, false);
480                 JSObjectRef successObj = validator.toFunction(1, true);
481                 if(successObj)
482                         js2ndParamIsFunction = true;
483
484                 JSObjectRef errorObj = validator.toFunction(2, true);
485                 if(errorObj)
486                         js3rdParamIsFunction = true;
487
488         } catch (const TypeMismatchException& err ) {
489                 return JSWebAPIErrorFactory::postException(context, exception, err);
490         } catch(const BasePlatformException& err) {
491                 return JSWebAPIErrorFactory::postException(context, exception, err);
492         } catch(const ConversionException& err) {
493                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
494         } catch(const NullPointerException& err) {
495                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
496         }
497
498         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
499
500         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
501
502         if(js2ndParamIsFunction)
503                 callbackManager->setOnSuccess(arguments[1]);
504
505         if(js3rdParamIsFunction)
506                 callbackManager->setOnError(arguments[2]);
507
508         callbackManager->setObject(thisObject);
509
510         EventAddressBookAddBatchPtr dplEvent(new EventAddressBookAddBatch());
511         Try {
512                 dplEvent->setContacts(converter->toContactArray(arguments[0]));
513         } Catch(ConversionException) {
514                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
515                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "1st argument must be an array of 'Contact object'");
516         }
517
518         // set event handler's data
519         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
520         dplEvent->setForAsynchronousCall(controller);
521
522 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
523 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
524
525         Try {
526                 addressBook->addBatch(dplEvent);
527                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
528         } Catch(Exception) {
529                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
530                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
531         }
532
533         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
534 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
535         return JSValueMakeUndefined(context);
536 }
537
538 JSValueRef JSAddressBook::update(JSContextRef context,
539                 JSObjectRef object,
540                 JSObjectRef thisObject,
541                 size_t argumentCount,
542                 const JSValueRef arguments[],
543                 JSValueRef* exception)
544 {
545         LoggerD("entered");
546         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
547         AddressBookPtr addressBook;
548         AddressBookController *controller;
549         JSContextRef gContext;
550
551         Try     {
552                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
553                 if (!controller) {
554                         ThrowMsg(InvalidArgumentException, "No private object.");
555                 }
556                 addressBook = controller->getObject();
557                 gContext = controller->getContext();
558         } Catch(Exception) {
559                 LoggerE("No private object");
560                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
561         }
562
563         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE);
564
565         try {
566                 ArgumentValidator validator(context, argumentCount, arguments);
567                 validator.toObject(0, false);
568
569         } catch (const TypeMismatchException& err ) {
570                 return JSWebAPIErrorFactory::postException(context, exception, err);
571         } catch(const BasePlatformException& err) {
572                 return JSWebAPIErrorFactory::postException(context, exception, err);
573         } catch(const ConversionException& err) {
574                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
575         } catch(const NullPointerException& err) {
576                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
577         }
578
579         ContactPtr contact(NULL);
580
581         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
582         Try     {
583                 if (!JSContact::isObjectOfClass(context, arguments[0]))
584                         ThrowMsg(InvalidArgumentException, "1st argument is not a 'Contact object'.");
585                 contact = converter->toContact(arguments[0]);
586         } Catch(Exception) {
587                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
588                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "1st argument is not a 'Contact object'");
589         }
590
591         EventAddressBookUpdatePtr dplEvent(new EventAddressBookUpdate());
592
593         dplEvent->setContact(contact);
594     dplEvent->setForSynchronousCall();
595
596         Try {
597                 addressBook->update(dplEvent);
598         } Catch(Exception) {
599                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
600                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
601         }
602
603         if (!dplEvent->getResult())
604         {
605                 std::stringstream oss;
606                 switch (dplEvent->getExceptionCode())
607                 {
608                 case ExceptionCodes::NotFoundException:
609                 case ExceptionCodes::InvalidArgumentException:
610                         oss << "No Contact id '" << contact->getId() << "'";
611                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
612                         break;
613                 case ExceptionCodes::PlatformException:
614                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
615                         break;
616                 default:
617                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
618                         break;
619                 }
620         }
621
622         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
623         return JSValueMakeUndefined(context);
624 }
625
626 JSValueRef JSAddressBook::updateBatch(JSContextRef context,
627                 JSObjectRef object,
628                 JSObjectRef thisObject,
629                 size_t argumentCount,
630                 const JSValueRef arguments[],
631                 JSValueRef* exception)
632 {
633         LoggerD("entered");
634         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
635         AddressBookPtr addressBook;
636         JSContextRef gContext;
637         AddressBookController *controller;
638
639         bool js2ndParamIsFunction = false;
640         bool js3rdParamIsFunction = false;
641
642         Try     {
643                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
644                 if (!controller) {
645                         ThrowMsg(InvalidArgumentException, "No private object.");
646                 }
647                 addressBook = controller->getObject();
648                 gContext = controller->getContext();
649         } Catch(Exception) {
650                 LoggerE("No private object");
651                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
652         }
653
654         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_BATCH);
655
656         try {
657                 ArgumentValidator validator(context, argumentCount, arguments);
658
659                 validator.toObject(0, false);
660
661                 JSObjectRef successObj = validator.toFunction(1, true);
662                 if(successObj)
663                         js2ndParamIsFunction = true;
664
665                 JSObjectRef errorObj = validator.toFunction(2, true);
666                 if(errorObj)
667                         js3rdParamIsFunction = true;
668
669         } catch (const TypeMismatchException& err ) {
670                 return JSWebAPIErrorFactory::postException(context, exception, err);
671         } catch(const BasePlatformException& err) {
672                 return JSWebAPIErrorFactory::postException(context, exception, err);
673         } catch(const ConversionException& err) {
674                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
675         } catch(const NullPointerException& err) {
676                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
677         }
678
679         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
680
681         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
682
683         if(js2ndParamIsFunction)
684                 callbackManager->setOnSuccess(arguments[1]);
685
686         if(js3rdParamIsFunction)
687                 callbackManager->setOnError(arguments[2]);
688
689         callbackManager->setObject(thisObject);
690
691         EventAddressBookUpdateBatchPtr dplEvent(new EventAddressBookUpdateBatch());
692         Try {
693                 dplEvent->setContacts(converter->toContactArray(arguments[0]));
694         } Catch(ConversionException) {
695                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
696                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "First argument must be an array of 'Contact object'");
697         }
698
699         // set event handler's data
700         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
701         dplEvent->setForAsynchronousCall(controller);
702
703 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
704 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
705
706         Try {
707                 addressBook->updateBatch(dplEvent);
708                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
709         } Catch(Exception) {
710                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
711                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
712         }
713
714         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
715 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
716         return JSValueMakeUndefined(context);
717 }
718
719 JSValueRef JSAddressBook::remove(JSContextRef context,
720                 JSObjectRef object,
721                 JSObjectRef thisObject,
722                 size_t argumentCount,
723                 const JSValueRef arguments[],
724                 JSValueRef* exception)
725 {
726         LoggerD("entered");
727         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
728         AddressBookPtr addressBook;
729         AddressBookController *controller;
730
731         Try     {
732                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
733                 if (!controller) {
734                         ThrowMsg(InvalidArgumentException, "No private object.");
735                 }
736                 addressBook = controller->getObject();
737         } Catch(Exception) {
738                 LoggerE("No private object");
739                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
740         }
741
742         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE);
743
744         ArgumentValidator validator(context, argumentCount, arguments);
745         string contactId;
746         try     {
747                 contactId = validator.toString(0, false);
748         } catch (const TypeMismatchException& err ) {
749                 return JSWebAPIErrorFactory::postException(context, exception, err);
750         } catch(const BasePlatformException& err) {
751                 return JSWebAPIErrorFactory::postException(context, exception, err);
752         } catch(const ConversionException& err) {
753                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
754         } catch(const NullPointerException& err) {
755                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
756         }
757         if(!ContactUtility::checkStrIsUInt(contactId))
758                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "");
759
760         EventAddressBookRemovePtr dplEvent(new EventAddressBookRemove());
761
762         dplEvent->setContactId(contactId);
763     dplEvent->setForSynchronousCall();
764
765         Try {
766                 addressBook->remove(dplEvent);
767         } Catch(Exception) {
768                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
769                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
770         }
771
772         if (!dplEvent->getResult())
773         {
774                 std::stringstream oss;
775                 switch (dplEvent->getExceptionCode())
776                 {
777                 case ExceptionCodes::NotFoundException:
778                 case ExceptionCodes::InvalidArgumentException:
779                         LoggerE("Not Found error : " << contactId);
780                         oss << "No Contact id '" << contactId << "'";
781                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
782                         break;
783                 case ExceptionCodes::PlatformException:
784                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
785                         break;
786                 default:
787                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
788                         break;
789                 }
790         }
791         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
792         return JSValueMakeUndefined(context);
793 }
794
795 JSValueRef JSAddressBook::removeBatch(JSContextRef context,
796                 JSObjectRef object,
797                 JSObjectRef thisObject,
798                 size_t argumentCount,
799                 const JSValueRef arguments[],
800                 JSValueRef* exception)
801 {
802         LoggerD("entered");
803         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
804         AddressBookPtr addressBook;
805         JSContextRef gContext;
806         AddressBookController *controller;
807
808         bool js2ndParamIsFunction = false;
809         bool js3rdParamIsFunction = false;
810
811         Try     {
812                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
813                 if (!controller) {
814                         ThrowMsg(InvalidArgumentException, "No private object.");
815                 }
816                 addressBook = controller->getObject();
817                 gContext = controller->getContext();
818         } Catch(Exception) {
819                 LoggerE("No private object");
820                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
821         }
822
823         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_BATCH);
824
825         try {
826                 ArgumentValidator validator(context, argumentCount, arguments);
827
828                 validator.toObject(0, false);
829                 JSObjectRef successObj = validator.toFunction(1, true);
830                 if(successObj)
831                         js2ndParamIsFunction = true;
832
833                 JSObjectRef errorObj = validator.toFunction(2, true);
834                 if(errorObj)
835                         js3rdParamIsFunction = true;
836
837         } catch (const TypeMismatchException& err ) {
838                 return JSWebAPIErrorFactory::postException(context, exception, err);
839         } catch(const BasePlatformException& err) {
840                 return JSWebAPIErrorFactory::postException(context, exception, err);
841         } catch(const ConversionException& err) {
842                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
843         } catch(const NullPointerException& err) {
844                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
845         }
846
847         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
848
849         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
850
851         if(js2ndParamIsFunction)
852                 callbackManager->setOnSuccess(arguments[1]);
853
854         if(js3rdParamIsFunction)
855                 callbackManager->setOnError(arguments[2]);
856
857         callbackManager->setObject(thisObject);
858
859         EventAddressBookRemoveBatchPtr dplEvent(new EventAddressBookRemoveBatch());
860         Try {
861                 dplEvent->setContactIds(converter->toStringArray(arguments[0]));
862         } Catch(ConversionException) {
863                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
864                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "3rd argument must be an array of 'Contact id'");
865         }
866
867         // set event handler's data
868         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
869         dplEvent->setForAsynchronousCall(controller);
870
871 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
872 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
873
874         Try {
875                 addressBook->removeBatch(dplEvent);
876                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
877         } Catch(Exception) {
878                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
879                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
880         }
881
882         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
883 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
884         return JSValueMakeUndefined(context);
885 }
886
887 JSValueRef JSAddressBook::find(JSContextRef context,
888                 JSObjectRef object,
889                 JSObjectRef thisObject,
890                 size_t argumentCount,
891                 const JSValueRef arguments[],
892                 JSValueRef* exception)
893 {
894         LoggerD("entered");
895         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
896         AddressBookPtr addressBook;
897         JSContextRef gContext;
898         AddressBookController *controller;
899
900         bool js2ndParamIsFunction = false;
901         bool js3rdParamIsObject = false;
902         bool js4thParamIsObject = false;
903
904         Try     {
905                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
906                 if (!controller) {
907                         ThrowMsg(InvalidArgumentException, "No private object.");
908                 }
909                 addressBook = controller->getObject();
910                 gContext = controller->getContext();
911         } Catch(Exception) {
912                 LoggerE("No private object");
913                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
914         }
915
916         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_FIND);
917
918         try {
919                 ArgumentValidator validator(context, argumentCount, arguments);
920
921                 validator.toFunction(0, false);
922                 JSObjectRef errorObj = validator.toFunction(1, true);
923                 if(errorObj)
924                         js2ndParamIsFunction = true;
925
926                 JSObjectRef filterObj = validator.toObject(2, true);
927                 if(filterObj)
928                         js3rdParamIsObject = true;
929
930                 JSObjectRef sortObj = validator.toObject(3, true);
931                 if(sortObj)
932                         js4thParamIsObject = true;
933
934         } catch (const TypeMismatchException& err ) {
935                 return JSWebAPIErrorFactory::postException(context, exception, err);
936         } catch(const BasePlatformException& err) {
937                 return JSWebAPIErrorFactory::postException(context, exception, err);
938         } catch(const ConversionException& err) {
939                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
940         } catch(const NullPointerException& err) {
941                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
942         }
943
944         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
945
946         callbackManager->setOnSuccess(arguments[0]);
947
948         if (js2ndParamIsFunction)
949                 callbackManager->setOnError(arguments[1]);
950
951         callbackManager->setObject(thisObject);
952
953         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
954         ContactFilterConverterFactory::ConverterType filterConverter = ContactFilterConverterFactory::getConverter(context);
955
956         EventAddressBookFindPtr dplEvent(new EventAddressBookFind());
957         Try {
958                 if (js3rdParamIsObject){
959                         FilterPtr filter = filterConverter->toFilter(arguments[2]);
960                         if(filter)
961                                 dplEvent->setFilter(filter);
962                         else
963                                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "3rd argument must be an Correct 'Filter object' or 'null'");
964                 }
965         } Catch(Exception) {
966                 LoggerE("Error on 3rd parameter conversion : " << _rethrown_exception.GetMessage());
967                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "3rd argument must be an 'Filter object' or 'null'");
968         }
969
970         Try {
971                 if (js4thParamIsObject){
972                         SortModePtr sortMode = filterConverter->toSortMode(arguments[3]);
973                         dplEvent->setSortMode(sortMode);
974                 }
975         } Catch(Exception) {
976                 LoggerE("Error on 4th parameter conversion : " << _rethrown_exception.GetMessage());
977                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "4th argument must be an 'SortMode object' or 'null'");
978         }
979
980         // set event handler's data
981         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
982         dplEvent->setForAsynchronousCall(controller);
983
984 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
985 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
986
987         Try {
988                 addressBook->find(dplEvent);
989                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
990         } Catch(Exception) {
991                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
992                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
993         }
994
995         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
996 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
997         return JSValueMakeUndefined(context);
998 }
999
1000 JSValueRef JSAddressBook::addChangeListener(JSContextRef context,
1001                 JSObjectRef object,
1002                 JSObjectRef thisObject,
1003                 size_t argumentCount,
1004                 const JSValueRef arguments[],
1005                 JSValueRef* exception)
1006 {
1007         LoggerD("entered");
1008         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
1009         AddressBookPtr addressBook;
1010         JSContextRef gContext;
1011         AddressBookController *controller;
1012
1013         bool js2ndParamIsFunction = false;
1014
1015         Try     {
1016                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
1017                 if (!controller) {
1018                         ThrowMsg(InvalidArgumentException, "No private object.");
1019                 }
1020                 addressBook = controller->getObject();
1021                 gContext = controller->getContext();
1022         } Catch(Exception) {
1023                 LoggerE("No private object");
1024                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
1025         }
1026
1027         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_CHANGE_LISTENER);
1028
1029         BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
1030         try {
1031                 ArgumentValidator Argvalidator(context, argumentCount, arguments);
1032                 Argvalidator.toObject(0, false);
1033                 JSObjectRef errorObj = Argvalidator.toFunction(1, true);
1034                 if(errorObj)
1035                         js2ndParamIsFunction = true;
1036         } catch (const TypeMismatchException& err ) {
1037                 return JSWebAPIErrorFactory::postException(context, exception, err);
1038         } catch(const BasePlatformException& err) {
1039                 return JSWebAPIErrorFactory::postException(context, exception, err);
1040         } catch(const ConversionException& err) {
1041                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1042         } catch(const NullPointerException& err) {
1043                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1044         }
1045
1046         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
1047
1048         JSValueRef oncontactsadded;
1049         JSValueRef oncontactsupdated;
1050         JSValueRef oncontactsdeleted;
1051         Try {
1052                 JSObjectRef callbackObject = converter->toJSObjectRef(arguments[0]);
1053
1054                 oncontactsadded = JSUtils::getJSPropertyOrUndefined(context, callbackObject, "oncontactsadded");
1055                 if (validator->isNullOrUndefined(oncontactsadded))
1056                         oncontactsadded = NULL;
1057                 else if (!validator->isCallback(oncontactsadded)) {
1058                         ThrowMsg(ConversionException, "2nd argument's oncontactsadded attribute is not a 'function'");
1059                 }
1060
1061                 oncontactsupdated = JSUtils::getJSPropertyOrUndefined(context, callbackObject, "oncontactsupdated");
1062                 if (validator->isNullOrUndefined(oncontactsupdated))
1063                         oncontactsupdated = NULL;
1064                 else if (!validator->isCallback(oncontactsupdated)) {
1065                         ThrowMsg(ConversionException, "2nd argument's oncontactsupdated attribute is not a 'function'");
1066                 }
1067
1068                 oncontactsdeleted = JSUtils::getJSPropertyOrUndefined(context, callbackObject, "oncontactsremoved");
1069                 if (validator->isNullOrUndefined(oncontactsdeleted))
1070                         oncontactsdeleted = NULL;
1071                 else if (!validator->isCallback(oncontactsdeleted)) {
1072                         ThrowMsg(ConversionException, "2nd argument's oncontactsremoved attribute is not a 'function'");
1073                 }
1074
1075                 if (oncontactsadded == NULL && oncontactsupdated == NULL && oncontactsdeleted == NULL)
1076                         ThrowMsg(ConversionException, "2nd argument must have at least one function");
1077
1078         } Catch(ConversionException) {
1079                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
1080                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
1081         }
1082
1083         JSAddressBookChangeCallbackManagerPtr callbackManager = JSAddressBookChangeCallbackManager::createObject(gContext);
1084
1085         callbackManager->setOnContactsAdded(oncontactsadded);
1086         callbackManager->setOnContactsUpdated(oncontactsupdated);
1087         callbackManager->setOnContactsDeleted(oncontactsdeleted);
1088         if(js2ndParamIsFunction)
1089                 callbackManager->setOnError(arguments[1]);
1090
1091         EventAddressBookChangeListenerEmitterPtr emitter(new EventAddressBookChangeListenerEmitter());
1092
1093         emitter->setEventPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
1094         emitter->setListener(controller);
1095
1096         EventAddressBookAddChangeListenerPtr dplEvent(new EventAddressBookAddChangeListener());
1097
1098         dplEvent->setEmitter(emitter);
1099     dplEvent->setForSynchronousCall();
1100
1101         Try {
1102                 addressBook->addChangeListener(dplEvent);
1103         } Catch(Exception) {
1104                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1105                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1106         }
1107
1108         if (!dplEvent->getResult() || !dplEvent->getIdIsSet())
1109         {
1110                 switch (dplEvent->getExceptionCode())
1111                 {
1112                 case ExceptionCodes::InvalidArgumentException:
1113                 case ExceptionCodes::PlatformException:
1114                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1115                         break;
1116                 default:
1117                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1118                         break;
1119                 }
1120         }
1121
1122         long watchId = dplEvent->getId();
1123
1124         ContactsChangeListenerCancellerPtr canceller = ContactsChangeListenerCancellerPtr(new ContactsChangeListenerCanceller(gContext, thisObject, watchId));
1125         DeviceAPI::Common::IListenerItemPtr listenerItem = DPL::StaticPointerCast<DeviceAPI::Common::IListenerItem>(canceller);
1126         ContactListenerManagerSingleton::Instance().registerListener(listenerItem, gContext);
1127
1128         JSValueRef result;
1129         Try {
1130                 result = JSUtil::toJSValueRef(context, watchId);
1131 //              result = converter->toJSValueRefLong(watchId);
1132         } Catch(Exception) {
1133                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
1134                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1135         }
1136         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1137         return result;
1138 }
1139
1140 JSValueRef JSAddressBook::removeChangeListener(JSContextRef context,
1141                 JSObjectRef object,
1142                 JSObjectRef thisObject,
1143                 size_t argumentCount,
1144                 const JSValueRef arguments[],
1145                 JSValueRef* exception)
1146 {
1147         LoggerD("entered");
1148         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
1149         AddressBookPtr addressBook;
1150         JSContextRef gContext;
1151         AddressBookController *controller;
1152
1153         Try     {
1154                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
1155                 if (!controller) {
1156                         ThrowMsg(InvalidArgumentException, "No private object.");
1157                 }
1158                 addressBook = controller->getObject();
1159                 gContext = controller->getContext();
1160         } Catch(Exception) {
1161                 LoggerE("No private object");
1162                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
1163         }
1164
1165         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_CHANGE_LISTENER);
1166
1167         long watchId = 0;
1168         string id;
1169
1170         try {
1171                 ArgumentValidator validator(context, argumentCount, arguments);
1172                 watchId = validator.toLong(0, false);
1173                 id = validator.toString(0, false);
1174         } catch (const TypeMismatchException& err ) {
1175                 return JSWebAPIErrorFactory::postException(context, exception, err);
1176         } catch(const BasePlatformException& err) {
1177                 return JSWebAPIErrorFactory::postException(context, exception, err);
1178         } catch(const ConversionException& err) {
1179                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1180         } catch(const NullPointerException& err) {
1181                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1182         }
1183
1184         if(!ContactUtility::checkStrIsUInt(id))
1185                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "");
1186
1187         EventAddressBookRemoveChangeListenerPtr dplEvent(new EventAddressBookRemoveChangeListener());
1188
1189         dplEvent->setId(watchId);
1190     dplEvent->setForSynchronousCall();
1191
1192         Try {
1193                 addressBook->removeChangeListener(dplEvent);
1194         } Catch(Exception) {
1195                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1196                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1197         }
1198
1199         ContactsChangeListenerCancellerPtr canceller = ContactsChangeListenerCancellerPtr(new ContactsChangeListenerCanceller(gContext, thisObject, watchId));
1200         DeviceAPI::Common::IListenerItemPtr listenerItem = DPL::StaticPointerCast<DeviceAPI::Common::IListenerItem>(canceller);
1201         ContactListenerManagerSingleton::Instance().unregisterListener(listenerItem);
1202
1203         if (!dplEvent->getResult())
1204         {
1205                 switch (dplEvent->getExceptionCode())
1206                 {
1207                 case ExceptionCodes::InvalidArgumentException:
1208                 case ExceptionCodes::NotFoundException:
1209                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, "Watch id not found");
1210                         break;
1211                 default:
1212                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1213                         break;
1214                 }
1215         }
1216         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1217         return JSValueMakeUndefined(context);
1218 }
1219
1220 JSValueRef JSAddressBook::getGroup(JSContextRef context,
1221                 JSObjectRef object,
1222                 JSObjectRef thisObject,
1223                 size_t argumentCount,
1224                 const JSValueRef arguments[],
1225                 JSValueRef* exception)
1226 {
1227         LoggerD("entered");
1228         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
1229         AddressBookPtr addressBook;
1230         AddressBookController *controller;
1231         JSContextRef gContext;
1232
1233         Try     {
1234                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
1235                 if (!controller) {
1236                         ThrowMsg(InvalidArgumentException, "No private object.");
1237                 }
1238                 addressBook = controller->getObject();
1239                 gContext = controller->getContext();
1240         } Catch(Exception) {
1241                 LoggerE("No private object");
1242                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
1243         }
1244
1245         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUP);
1246
1247         string id;
1248
1249         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
1250         try     {
1251                 ArgumentValidator validator(context, argumentCount, arguments);
1252                 id = validator.toString(0, false);
1253         } catch (const TypeMismatchException& err ) {
1254                 return JSWebAPIErrorFactory::postException(context, exception, err);
1255         } catch(const BasePlatformException& err) {
1256                 return JSWebAPIErrorFactory::postException(context, exception, err);
1257         } catch(const ConversionException& err) {
1258                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1259         } catch(const NullPointerException& err) {
1260                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1261         }
1262
1263         if(!ContactUtility::checkStrIsUInt(id))
1264                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "");
1265
1266         EventAddressBookGetGroupPtr dplEvent(new EventAddressBookGetGroup());
1267
1268         dplEvent->setId(id);
1269     dplEvent->setForSynchronousCall();
1270
1271         Try {
1272                 addressBook->getGroup(dplEvent);
1273         } Catch(Exception) {
1274                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1275                 return JSWebAPIErrorFactory::postException(context, exception,
1276                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1277         }
1278
1279         if (!dplEvent->getResult() || !dplEvent->getContactGroupIsSet())
1280         {
1281                 std::stringstream oss;
1282                 switch (dplEvent->getExceptionCode())
1283                 {
1284                 case ExceptionCodes::NotFoundException:
1285                 case ExceptionCodes::InvalidArgumentException:
1286                         LoggerE("Not Found error : " << id);
1287                         oss << "No Group id '" << id << "'";
1288                         return JSWebAPIErrorFactory::postException(context, exception,
1289                                         JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
1290                         break;
1291                 case ExceptionCodes::PlatformException:
1292                         return JSWebAPIErrorFactory::postException(context, exception,
1293                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1294                         break;
1295                 default:
1296                         return JSWebAPIErrorFactory::postException(context, exception,
1297                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1298                         break;
1299                 }
1300         }
1301
1302         ContactGroupPtr group = dplEvent->getContactGroup();
1303
1304         JSValueRef result;
1305         Try {
1306                 result = converter->toJSValueRef(group);
1307         } Catch(Exception) {
1308                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
1309                 return JSWebAPIErrorFactory::postException(context, exception,
1310                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1311         }
1312         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1313         return result;
1314 }
1315
1316 JSValueRef JSAddressBook::addGroup(JSContextRef context,
1317                 JSObjectRef object,
1318                 JSObjectRef thisObject,
1319                 size_t argumentCount,
1320                 const JSValueRef arguments[],
1321                 JSValueRef* exception)
1322 {
1323         LoggerD("entered");
1324         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
1325         AddressBookPtr addressBook;
1326         AddressBookController *controller;
1327         JSContextRef gContext;
1328
1329         Try     {
1330                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
1331                 if (!controller) {
1332                         ThrowMsg(InvalidArgumentException, "No private object.");
1333                 }
1334                 addressBook = controller->getObject();
1335                 gContext = controller->getContext();
1336         } Catch(Exception) {
1337                 LoggerE("No private object");
1338                 return JSWebAPIErrorFactory::postException(context, exception,
1339                                 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
1340         }
1341
1342         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_GROUP);
1343
1344         try {
1345                 ArgumentValidator validator(context, argumentCount, arguments);
1346                 validator.toObject(0, false);
1347
1348         } catch (const TypeMismatchException& err ) {
1349                 return JSWebAPIErrorFactory::postException(context, exception, err);
1350         } catch(const BasePlatformException& err) {
1351                 return JSWebAPIErrorFactory::postException(context, exception, err);
1352         } catch(const ConversionException& err) {
1353                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1354         } catch(const NullPointerException& err) {
1355                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1356         }
1357
1358         ContactGroupPtr group(NULL);
1359
1360         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
1361         Try     {
1362                 if (!JSContactGroup::isObjectOfClass(context, arguments[0]))
1363                         ThrowMsg(InvalidArgumentException, "1st argument is not a 'ContactGroup object'.");
1364
1365                 group = converter->toContactGroup(arguments[0]);
1366         } Catch(Exception) {
1367                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
1368                 return JSWebAPIErrorFactory::postException(context, exception,
1369                                 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "1st argument must be a 'ContactGroup object'");
1370         }
1371
1372         EventAddressBookAddGroupPtr dplEvent(new EventAddressBookAddGroup());
1373
1374         dplEvent->setContactGroup(group);
1375     dplEvent->setForSynchronousCall();
1376
1377         Try {
1378                 addressBook->addGroup(dplEvent);
1379         } Catch(Exception) {
1380                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1381                 return JSWebAPIErrorFactory::postException(context, exception,
1382                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1383         }
1384
1385         if (!dplEvent->getResult())
1386         {
1387                 switch (dplEvent->getExceptionCode())
1388                 {
1389                 case ExceptionCodes::PlatformException:
1390                         return JSWebAPIErrorFactory::postException(context, exception,
1391                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1392                         break;
1393                 default:
1394                         return JSWebAPIErrorFactory::postException(context, exception,
1395                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1396                         break;
1397                 }
1398         }
1399         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1400         return JSValueMakeUndefined(context);
1401 }
1402
1403 JSValueRef JSAddressBook::updateGroup(JSContextRef context,
1404                 JSObjectRef object,
1405                 JSObjectRef thisObject,
1406                 size_t argumentCount,
1407                 const JSValueRef arguments[],
1408                 JSValueRef* exception)
1409 {
1410         LoggerD("entered");
1411         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
1412         AddressBookPtr addressBook;
1413         AddressBookController *controller;
1414         JSContextRef gContext;
1415
1416         Try     {
1417                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
1418                 if (!controller) {
1419                         ThrowMsg(InvalidArgumentException, "No private object.");
1420                 }
1421                 addressBook = controller->getObject();
1422                 gContext = controller->getContext();
1423         } Catch(Exception) {
1424                 LoggerE("No private object");
1425                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
1426         }
1427
1428         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_GROUP);
1429
1430         try {
1431                 ArgumentValidator validator(context, argumentCount, arguments);
1432                 validator.toObject(0, false);
1433
1434         } catch (const TypeMismatchException& err ) {
1435                 return JSWebAPIErrorFactory::postException(context, exception, err);
1436         } catch(const BasePlatformException& err) {
1437                 return JSWebAPIErrorFactory::postException(context, exception, err);
1438         } catch(const ConversionException& err) {
1439                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1440         } catch(const NullPointerException& err) {
1441                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1442         }
1443
1444         ContactGroupPtr contact(NULL);
1445
1446         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
1447         Try     {
1448                 if (!JSContactGroup::isObjectOfClass(context, arguments[0]))
1449                         ThrowMsg(InvalidArgumentException, "1st argument is not a 'ContactGroup object'.");
1450                 contact = converter->toContactGroup(arguments[0]);
1451         } Catch(Exception) {
1452                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
1453                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "1st argument is not a 'ContactGroup object'");
1454         }
1455
1456         EventAddressBookUpdateGroupPtr dplEvent(new EventAddressBookUpdateGroup());
1457
1458         dplEvent->setContactGroup(contact);
1459     dplEvent->setForSynchronousCall();
1460
1461         Try {
1462                 addressBook->updateGroup(dplEvent);
1463         } Catch(Exception) {
1464                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1465                 return JSWebAPIErrorFactory::postException(context, exception,
1466                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1467         }
1468
1469         if (!dplEvent->getResult())
1470         {
1471                 std::stringstream oss;
1472                 switch (dplEvent->getExceptionCode())
1473                 {
1474                 case ExceptionCodes::NotFoundException:
1475                 case ExceptionCodes::InvalidArgumentException:
1476                         oss << "No Group id '" << contact->getId() << "'";
1477                         return JSWebAPIErrorFactory::postException(context, exception,
1478                                         JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
1479                         break;
1480                 case ExceptionCodes::PlatformException:
1481                         return JSWebAPIErrorFactory::postException(context, exception,
1482                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1483                         break;
1484                 default:
1485                         return JSWebAPIErrorFactory::postException(context, exception,
1486                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1487                         break;
1488                 }
1489         }
1490         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1491         return JSValueMakeUndefined(context);
1492 }
1493
1494 JSValueRef JSAddressBook::removeGroup(JSContextRef context,
1495                 JSObjectRef object,
1496                 JSObjectRef thisObject,
1497                 size_t argumentCount,
1498                 const JSValueRef arguments[],
1499                 JSValueRef* exception)
1500 {
1501         LoggerD("entered");
1502         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
1503         AddressBookPtr addressBook;
1504         AddressBookController *controller;
1505
1506         Try     {
1507                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
1508                 if (!controller) {
1509                         ThrowMsg(InvalidArgumentException, "No private object.");
1510                 }
1511                 addressBook = controller->getObject();
1512         } Catch(Exception) {
1513                 LoggerE("No private object");
1514                 return JSWebAPIErrorFactory::postException(context, exception,
1515                                 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
1516         }
1517
1518         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_GROUP);
1519
1520         string groupId;
1521
1522         try     {
1523                 ArgumentValidator validator(context, argumentCount, arguments);
1524                 groupId = validator.toString(0, false);
1525         } catch (const TypeMismatchException& err ) {
1526                 return JSWebAPIErrorFactory::postException(context, exception, err);
1527         } catch(const BasePlatformException& err) {
1528                 return JSWebAPIErrorFactory::postException(context, exception, err);
1529         } catch(const ConversionException& err) {
1530                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1531         } catch(const NullPointerException& err) {
1532                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1533         }
1534         if(!ContactUtility::checkStrIsUInt(groupId))
1535                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "");
1536
1537         EventAddressBookRemoveGroupPtr dplEvent(new EventAddressBookRemoveGroup());
1538
1539         dplEvent->setContactGroupId(groupId);
1540     dplEvent->setForSynchronousCall();
1541
1542         Try {
1543                 addressBook->removeGroup(dplEvent);
1544         } Catch(Exception) {
1545                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1546                 return JSWebAPIErrorFactory::postException(context, exception,
1547                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1548         }
1549
1550         if (!dplEvent->getResult())
1551         {
1552                 std::stringstream oss;
1553                 switch (dplEvent->getExceptionCode())
1554                 {
1555                 case ExceptionCodes::NotFoundException:
1556                 case ExceptionCodes::InvalidArgumentException:
1557                         LoggerE("Not Found error : " << groupId);
1558                         oss << "No Group id '" << groupId << "'";
1559                         return JSWebAPIErrorFactory::postException(context, exception,
1560                                         JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
1561                         break;
1562                 case ExceptionCodes::PlatformException:
1563                         return JSWebAPIErrorFactory::postException(context, exception,
1564                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1565                         break;
1566                 default:
1567                         return JSWebAPIErrorFactory::postException(context, exception,
1568                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1569                         break;
1570                 }
1571         }
1572         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1573         return JSValueMakeUndefined(context);
1574 }
1575
1576 JSValueRef JSAddressBook::getGroups(JSContextRef context,
1577                 JSObjectRef object,
1578                 JSObjectRef thisObject,
1579                 size_t argumentCount,
1580                 const JSValueRef arguments[],
1581                 JSValueRef* exception)
1582 {
1583         LoggerD("entered");
1584         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
1585         AddressBookPtr addressBook;
1586         AddressBookController *controller;
1587         JSContextRef gContext;
1588
1589         Try     {
1590                 controller = static_cast<AddressBookController*>(JSObjectGetPrivate(thisObject));
1591                 if (!controller) {
1592                         ThrowMsg(InvalidArgumentException, "No private object.");
1593                 }
1594                 addressBook = controller->getObject();
1595                 gContext = controller->getContext();
1596         } Catch(Exception) {
1597                 LoggerE("No private object");
1598                 return JSWebAPIErrorFactory::postException(context, exception,
1599                                 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
1600         }
1601
1602         TIZEN_CHECK_ACCESS(context, exception, controller, CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUPS);
1603
1604         string id;
1605
1606         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
1607
1608         EventAddressBookGetGroupsPtr dplEvent(new EventAddressBookGetGroups());
1609
1610     dplEvent->setForSynchronousCall();
1611
1612         Try {
1613                 addressBook->getGroups(dplEvent);
1614         } Catch(Exception) {
1615                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1616                 return JSWebAPIErrorFactory::postException(context, exception,
1617                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1618         }
1619
1620         if (!dplEvent->getResult() || !dplEvent->getContactGroupsIsSet())
1621         {
1622                 std::stringstream oss;
1623                 switch (dplEvent->getExceptionCode())
1624                 {
1625                 case ExceptionCodes::NotFoundException:
1626                 case ExceptionCodes::InvalidArgumentException:
1627                         LoggerE("Not Found error : " << id);
1628                         oss << "No Group id '" << id << "'";
1629                         return JSWebAPIErrorFactory::postException(context, exception,
1630                                         JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
1631                         break;
1632                 case ExceptionCodes::PlatformException:
1633                         return JSWebAPIErrorFactory::postException(context, exception,
1634                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1635                         break;
1636                 default:
1637                         return JSWebAPIErrorFactory::postException(context, exception,
1638                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1639                         break;
1640                 }
1641         }
1642
1643         ContactGroupArrayPtr groups = dplEvent->getContactGroups();
1644
1645         JSValueRef result;
1646         Try {
1647                 result = converter->toJSValueRef(groups);
1648         } Catch(Exception) {
1649                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
1650                 return JSWebAPIErrorFactory::postException(context, exception,
1651                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1652         }
1653         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1654         return result;
1655 }
1656
1657 } // Contact
1658 } // DeviceAPI