f87958eb8e8c96fc99b594e29329d793e70e10d4
[profile/ivi/wrt-plugins-tizen.git] / src / platform / Tizen / Contact / AddressBook.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  * @file        AddressBook.cpp
19  * @author      Kisub Song (kisubs.song@samsung.com)
20  * @version     0.1
21  * @brief
22  */
23
24 #include <ctime>
25 #include <cstdlib>
26 #include <cstddef>
27 #include <fstream>
28 #include <sstream>
29 #include <pcrecpp.h>
30 #include <dpl/log/log.h>
31 #include <dpl/exception.h>
32 #include <Commons/Exception.h>
33 #include <Commons/Regex.h>
34 #include <API/Contact/IAddressBook.h>
35 #include <API/Contact/IContact.h>
36 #include "AddressBook.h"
37 #include "Contact.h"
38 #include "ContactWrapper.h"
39 #include "ContactSearchEngine.h"
40 #include "ContactFilterValidator.h"
41 #include "DownloadManager.h"
42
43 namespace TizenApis {
44 namespace Platform {
45 namespace Contact {
46
47 using namespace TizenApis::Api::Contact;
48 using namespace TizenApis::Api::Tizen;
49 using namespace WrtDeviceApis::Commons;
50 using namespace std;
51
52 AddressBook::AddressBook(IAddressBook::AddressBookType changeType) :
53                 IAddressBook(changeType),
54                 m_name("TEST_ADDRESS_BOOK"),
55                 m_watchIdAcc(0)
56 {
57     LogDebug("entered");
58 }
59
60 AddressBook::~AddressBook()
61 {
62 }
63
64 void AddressBook::OnRequestReceived(const EventAddressBookGetPtr &event)
65 {
66         LogDebug("entered");
67
68         Try     {
69                 if(!event->getIdIsSet())
70                         ThrowMsg(InvalidArgumentException, "Invalid contact id");
71
72                 string contactId = event->getId();
73
74                 ContactPtr contact = internalGetById(contactId);
75
76                 event->setContact(contact);
77                 event->setResult(true);
78
79         } Catch (NotFoundException) {
80                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
81                 event->setExceptionCode(ExceptionCodes::NotFoundException);
82                 event->setResult(false);
83
84         } Catch (PlatformException) {
85                 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
86                 event->setExceptionCode(ExceptionCodes::PlatformException);
87                 event->setResult(false);
88
89         } Catch (InvalidArgumentException) {
90                 LogError("Invalid Arguments : " << _rethrown_exception.GetMessage());
91                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
92                 event->setResult(false);
93
94         } Catch(Exception) {
95                 LogError("Error on platform : " << _rethrown_exception.GetMessage());
96                 event->setExceptionCode(ExceptionCodes::UnknownException);
97                 event->setResult(false);
98         }
99 }
100
101 void AddressBook::OnRequestReceived(const EventAddressBookAddPtr &event)
102 {
103         LogDebug("entered");
104
105         ContactPtr contact(NULL);
106
107         Try {
108                 if(!event->getContactIsSet())
109                         ThrowMsg(InvalidArgumentException, "Contacts were not set.");
110
111                 contact = event->getContact();
112                 if(!contact)
113                         ThrowMsg(InvalidArgumentException, "No contacts.");
114
115         } Catch(InvalidArgumentException) {
116                 LogError("Invalid arguments for adding contacts : " << _rethrown_exception.GetMessage());
117                 event->setResult(false);
118                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
119                 return;
120         }
121
122         Try
123         {
124                 internalAddContact(contact);
125
126                 string id = contact->getId();
127                 if(id != "")
128                 {
129                         ContactPtr insertedContact = internalGetById(id);
130                         contact->copy(insertedContact);
131                 }
132         }
133         Catch (PlatformException) {
134                 LogError("Error during adding contact : " << _rethrown_exception.GetMessage());
135                 event->setResult(false);
136                 event->setExceptionCode(ExceptionCodes::PlatformException);
137                 return;
138         }
139         Catch (Exception) {
140                 LogError("Error during adding contact : " << _rethrown_exception.GetMessage());
141                 event->setResult(false);
142                 event->setExceptionCode(ExceptionCodes::UnknownException);
143                 return;
144         }
145         //m_latestVersion = get_contact_version();
146
147         event->setResult(true);
148         event->setExceptionCode(ExceptionCodes::None);
149 }
150
151 void AddressBook::OnRequestReceived(const EventAddressBookAddBatchPtr &event)
152 {
153         LogDebug("entered");
154         ContactArrayPtr contacts(NULL);
155
156         Try {
157                 if(!event->getContactsIsSet())
158                         ThrowMsg(InvalidArgumentException, "Contacts were not set.");
159
160                 contacts = event->getContacts();
161                 if(!contacts)
162                         ThrowMsg(InvalidArgumentException, "No contacts.");
163
164         } Catch(InvalidArgumentException) {
165                 LogError("Invalid arguments for adding contacts : " << _rethrown_exception.GetMessage());
166                 event->setResult(false);
167                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
168                 return;
169         }
170
171         Try
172         {
173                 int ret = contacts_svc_begin_trans();
174                 if (ret < 0) {
175                         LogError("error code " << ret);
176                         ThrowMsg(PlatformException, "Error during executing contacts_svc_begin_trans()");
177                 }
178
179                 for(ContactArray::iterator i = contacts->begin(); i != contacts->end(); i++)
180                 {
181                         ContactPtr contact = *i;
182
183                         internalAddContact(contact);
184                 }
185                 ret = contacts_svc_end_trans(true);
186                 if (ret < 0) {
187                         LogError("error code " << ret);
188                         ThrowMsg(PlatformException, "Error during executing contacts_svc_end_trans()");
189                 }
190
191                 for(ContactArray::iterator i = contacts->begin(); i != contacts->end(); i++)
192                 {
193                         ContactPtr contact = *i;
194
195                         string id = contact->getId();
196                         if(id != "")
197                         {
198                                 ContactPtr insertedContact = internalGetById(id);
199                                 contact->copy(insertedContact);
200                         }
201                 }
202         }
203         Catch (NotFoundException)
204         {
205                 contacts_svc_end_trans(false);
206                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
207                 event->setResult(false);
208                 event->setExceptionCode(ExceptionCodes::NotFoundException);
209                 return;
210         }
211         Catch (PlatformException) {
212                 contacts_svc_end_trans(false);
213                 LogError("Error during adding contact : " << _rethrown_exception.GetMessage());
214                 event->setResult(false);
215                 event->setExceptionCode(ExceptionCodes::PlatformException);
216                 return;
217         }
218         Catch (Exception) {
219                 contacts_svc_end_trans(false);
220                 LogError("Error during adding contact : " << _rethrown_exception.GetMessage());
221                 event->setResult(false);
222                 event->setExceptionCode(ExceptionCodes::PlatformException);
223                 return;
224         }
225         //m_latestVersion = get_contact_version();
226
227         event->setResult(true);
228         event->setExceptionCode(ExceptionCodes::None);
229 }
230
231 void AddressBook::OnRequestReceived(const EventAddressBookUpdatePtr &event)
232 {
233         ContactPtr contact(NULL);
234
235         Try {
236                 if(!event->getContactIsSet())
237                         ThrowMsg(InvalidArgumentException, "Contacts were not set.");
238
239                 contact = event->getContact();
240                 if(!contact)
241                         ThrowMsg(InvalidArgumentException, "No contacts.");
242
243         } Catch(InvalidArgumentException) {
244                 LogError("Invalid arguments for adding contacts : " << _rethrown_exception.GetMessage());
245                 event->setResult(false);
246                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
247                 return;
248         }
249
250         Try
251         {
252                 internalAddContact(contact);
253         }
254         Catch (NotFoundException)
255         {
256                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
257                 event->setResult(false);
258                 event->setExceptionCode(ExceptionCodes::NotFoundException);
259                 return;
260         }
261         Catch (PlatformException) {
262                 LogError("Error during adding contact : " << _rethrown_exception.GetMessage());
263                 event->setResult(false);
264                 event->setExceptionCode(ExceptionCodes::PlatformException);
265                 return;
266         }
267         Catch (Exception) {
268                 LogError("Error during adding contact : " << _rethrown_exception.GetMessage());
269                 event->setResult(false);
270                 event->setExceptionCode(ExceptionCodes::PlatformException);
271                 return;
272         }
273         //m_latestVersion = get_contact_version();
274
275         event->setResult(true);
276         event->setExceptionCode(ExceptionCodes::None);
277 }
278
279 void AddressBook::OnRequestReceived(const EventAddressBookUpdateBatchPtr &event)
280 {
281         LogDebug("entered");
282         ContactArrayPtr contacts(NULL);
283
284         Try {
285                 if(!event->getContactsIsSet())
286                         ThrowMsg(InvalidArgumentException, "Contacts were not set.");
287
288                 contacts = event->getContacts();
289                 if(!contacts)
290                         ThrowMsg(InvalidArgumentException, "No contacts.");
291
292         } Catch(InvalidArgumentException) {
293                 LogError("Invalid arguments for updating contacts : " << _rethrown_exception.GetMessage());
294                 event->setResult(false);
295                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
296                 return;
297         }
298
299         Try
300         {
301                 int ret = contacts_svc_begin_trans();
302                 if (ret < 0) {
303                         LogError("error code " << ret);
304                         ThrowMsg(PlatformException, "Error during executing contacts_svc_begin_trans()");
305                 }
306
307                 for(ContactArray::iterator i = contacts->begin(); i != contacts->end(); i++)
308                 {
309                         ContactPtr contact = *i;
310
311                         internalAddContact(contact);
312                 }
313                 contacts_svc_end_trans(true);
314                 if (ret < 0) {
315                         LogError("error code " << ret);
316                         ThrowMsg(PlatformException, "Error during executing contacts_svc_end_trans()");
317                 }
318         }
319         Catch (NotFoundException)
320         {
321                 contacts_svc_end_trans(false);
322                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
323                 event->setResult(false);
324                 event->setExceptionCode(ExceptionCodes::NotFoundException);
325                 return;
326         }
327         Catch (PlatformException) {
328                 contacts_svc_end_trans(false);
329                 LogError("Error during updating contact : " << _rethrown_exception.GetMessage());
330                 event->setResult(false);
331                 event->setExceptionCode(ExceptionCodes::PlatformException);
332                 return;
333         }
334         Catch (Exception) {
335                 LogError("Error during updating contact : " << _rethrown_exception.GetMessage());
336                 event->setResult(false);
337                 event->setExceptionCode(ExceptionCodes::PlatformException);
338                 return;
339         }
340         //m_latestVersion = get_contact_version();
341
342         event->setResult(true);
343         event->setExceptionCode(ExceptionCodes::None);
344 }
345
346 void AddressBook::OnRequestReceived(const EventAddressBookRemovePtr &event)
347 {
348         LogDebug("entered");
349         int contactId;
350
351         Try
352         {
353                 if(!event->getContactIdIsSet())
354                         ThrowMsg(InvalidArgumentException, "Contacts were not set.");
355
356                 string contactIdStr = event->getContactId();
357
358                 if(!validate("^[0-9]+$", contactIdStr, VALIDATE_MATCH_CASELESS))
359                         ThrowMsg(InvalidArgumentException, "Id is wrong (" << contactIdStr << ")" );
360
361                 try {
362                         istringstream iss(contactIdStr);
363                         iss >> contactId;
364                 } catch (...) {
365                         ThrowMsg(InvalidArgumentException, "Id is wrong (" << contactIdStr << ")" );
366                 }
367
368                 internalDeleteContactById(contactId);
369         }
370         Catch (InvalidArgumentException)
371         {
372                 LogError("Invalid contact id : " << _rethrown_exception.GetMessage());
373                 event->setResult(false);
374                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
375                 return;
376         }
377         Catch (NotFoundException)
378         {
379                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
380                 event->setResult(false);
381                 event->setExceptionCode(ExceptionCodes::NotFoundException);
382                 return;
383         }
384         Catch (PlatformException) {
385                 LogError("Error during updating contact : " << _rethrown_exception.GetMessage());
386                 event->setResult(false);
387                 event->setExceptionCode(ExceptionCodes::PlatformException);
388                 return;
389         }
390         Catch (Exception) {
391                 LogError("Error during updating contact : " << _rethrown_exception.GetMessage());
392                 event->setResult(false);
393                 event->setExceptionCode(ExceptionCodes::PlatformException);
394                 return;
395         }
396         //m_latestVersion = get_contact_version();
397
398         event->setResult(true);
399         event->setExceptionCode(ExceptionCodes::None);
400 }
401
402 void AddressBook::OnRequestReceived(const EventAddressBookRemoveBatchPtr &event)
403 {
404         LogDebug("entered");
405         StringArrayPtr contactIds(NULL);
406
407         Try {
408                 if(!event->getContactIdsIsSet())
409                         ThrowMsg(InvalidArgumentException, "Contacts were not set.");
410
411                 contactIds = event->getContactIds();
412                 if(!contactIds)
413                         ThrowMsg(InvalidArgumentException, "No contacts.");
414
415         } Catch(InvalidArgumentException) {
416                 LogError("Invalid arguments for updating contacts : " << _rethrown_exception.GetMessage());
417                 event->setResult(false);
418                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
419                 return;
420         }
421
422         Try
423         {
424                 int ret = contacts_svc_begin_trans();
425                 if (ret < 0) {
426                         LogError("error code " << ret);
427                         ThrowMsg(PlatformException, "Error during executing contacts_svc_begin_trans()");
428                 }
429                 for(StringArray::iterator i = contactIds->begin(); i != contactIds->end(); i++)
430                 {
431                         string contactIdStr = *i;
432
433                         int contactId;
434
435                         if(!validate("^[0-9]+$", contactIdStr, VALIDATE_MATCH_CASELESS))
436                                 ThrowMsg(InvalidArgumentException, "Id is wrong (" << contactIdStr << ")" );
437
438                         try {
439                                 istringstream iss(contactIdStr);
440                                 iss >> contactId;
441                         } catch (...) {
442                                 ThrowMsg(InvalidArgumentException, "Id is wrong (" << contactIdStr << ")" );
443                         }
444
445                         internalDeleteContactById(contactId);
446                 }
447                 contacts_svc_end_trans(true);
448                 if (ret < 0) {
449                         LogError("error code " << ret);
450                         ThrowMsg(PlatformException, "Error during executing contacts_svc_end_trans()");
451                 }
452         }
453         Catch (InvalidArgumentException)
454         {
455                 contacts_svc_end_trans(false);
456                 LogError("Invalid contact id : " << _rethrown_exception.GetMessage());
457                 event->setResult(false);
458                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
459                 return;
460         }
461         Catch (NotFoundException)
462         {
463                 contacts_svc_end_trans(false);
464                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
465                 event->setResult(false);
466                 event->setExceptionCode(ExceptionCodes::NotFoundException);
467                 return;
468         }
469         Catch (PlatformException) {
470                 contacts_svc_end_trans(false);
471                 LogError("Error during updating contact : " << _rethrown_exception.GetMessage());
472                 event->setResult(false);
473                 event->setExceptionCode(ExceptionCodes::PlatformException);
474                 return;
475         }
476         Catch (Exception) {
477                 contacts_svc_end_trans(false);
478                 LogError("Error during updating contact : " << _rethrown_exception.GetMessage());
479                 event->setResult(false);
480                 event->setExceptionCode(ExceptionCodes::PlatformException);
481                 return;
482         }
483         //m_latestVersion = get_contact_version();
484
485         event->setResult(true);
486         event->setExceptionCode(ExceptionCodes::None);
487 }
488
489 void AddressBook::OnRequestReceived(const EventAddressBookFindPtr &event)
490 {
491         LogDebug("entered");
492         Try     {
493                 ContactSearchEnginePtr searchEngine(new ContactSearchEngine(ContactSearchEngine::CONTACT_QUERY));
494
495                 if(event->getFilterIsSet())
496                 {
497                         FilterPtr filter = event->getFilter();
498
499                         FilterValidatorPtr validator = ContactFilterValidatorFactory::getContactFilterValidator();
500                         bool success = filter->validate(validator);
501
502                         if(!success)
503                                 ThrowMsg(InvalidArgumentException, "Invalid filter arguments.");
504
505                         searchEngine->setCondition(filter);
506                 }
507
508                 // Currently not support attributeOfInterests
509                 //if (event->getAttributesOfInterestIsSet())
510                 //      searchEngine->setAttributeOfInterest(event->getAttributesOfInterest());
511                 //else
512                 //      searchEngine->setAttributeOfInterest();
513
514                 searchEngine->setAttributeOfInterest();
515
516                 if (event->getSortModeIsSet())
517                 {
518                         searchEngine->setSortMode(event->getSortMode());
519                 }
520                 else
521                         searchEngine->setSortMode();
522
523                 event->setContacts(searchEngine->getContactSearchResult());
524                 event->setResult(true);
525
526         } Catch (NotFoundException) {
527                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
528                 event->setExceptionCode(ExceptionCodes::NotFoundException);
529                 event->setResult(false);
530
531         } Catch (PlatformException) {
532                 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
533                 event->setExceptionCode(ExceptionCodes::PlatformException);
534                 event->setResult(false);
535
536         } Catch (InvalidArgumentException) {
537                 LogError("Invalid Arguments : " << _rethrown_exception.GetMessage());
538                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
539                 event->setResult(false);
540
541         } Catch (Exception) {
542                 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
543                 event->setExceptionCode(ExceptionCodes::PlatformException);
544                 event->setResult(false);
545         }
546 }
547
548 void AddressBook::OnRequestReceived(const EventAddressBookGetCategoriesPtr &event)
549 {
550         LogDebug("entered");
551
552         Try     {
553                 StringArrayPtr categories = StringArrayPtr(new StringArray());
554
555                 CTSiter *iter = NULL;
556                 if(CTS_SUCCESS != contacts_svc_get_list(CTS_LIST_ALL_GROUP, &iter))
557                         ThrowMsg(PlatformException, "Fail to get categories list.");
558
559                 while(CTS_SUCCESS == contacts_svc_iter_next(iter))
560                 {
561                         CTSvalue *group = contacts_svc_iter_get_info(iter);
562                         if(group == NULL)
563                                 break;
564
565                         const char *groupCStr = contacts_svc_value_get_str(group, CTS_LIST_GROUP_NAME_STR);
566                         if(groupCStr)
567                                 categories->push_back(string(groupCStr));
568
569                         contacts_svc_value_free(group);
570                 }
571                 contacts_svc_iter_remove(iter);
572
573                 event->setCategories(categories);
574                 event->setResult(true);
575
576         } Catch (NotFoundException) {
577                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
578                 event->setExceptionCode(ExceptionCodes::NotFoundException);
579                 event->setResult(false);
580
581         } Catch (PlatformException) {
582                 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
583                 event->setExceptionCode(ExceptionCodes::PlatformException);
584                 event->setResult(false);
585
586         } Catch (InvalidArgumentException) {
587                 LogError("Invalid Arguments : " << _rethrown_exception.GetMessage());
588                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
589                 event->setResult(false);
590
591         } Catch(Exception) {
592                 LogError("Error on platform : " << _rethrown_exception.GetMessage());
593                 event->setExceptionCode(ExceptionCodes::UnknownException);
594                 event->setResult(false);
595         }
596 }
597
598 void AddressBook::OnRequestReceived(const EventAddressBookAddChangeListenerPtr &event)
599 {
600         LogDebug("entered");
601
602         Try     {
603                 if(!event->getEmitterIsSet())
604                         ThrowMsg(InvalidArgumentException, "Invalid arguments.");
605
606                 EventAddressBookChangeListenerEmitterPtr emitter = event->getEmitter();
607                 if(emitter == NULL)
608                         ThrowMsg(InvalidArgumentException, "Invalid arguments.");
609
610                 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
611
612                 if(m_addressBookEmitters.size() == 0)
613                 {
614                         LogDebug("Watch registered initially");
615
616                         m_latestVersion = get_contact_version();
617                         contacts_svc_subscribe_change(CTS_SUBSCRIBE_CONTACT_CHANGE,
618                                         contactsSvcContactChangedCallback, reinterpret_cast<void *>(this));
619                         contacts_svc_subscribe_change(CTS_SUBSCRIBE_ADDRESSBOOK_CHANGE,
620                                         refresh_addressbook_list, reinterpret_cast<void *>(this));
621                 }
622
623                 m_addressBookEmitters.attach(emitter);
624
625                 long id = ++m_watchIdAcc;
626                 m_watchIdMap[id] = emitter->getId();
627
628             event->setId(id);
629                 event->setResult(true);
630
631         } Catch (NotFoundException) {
632                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
633                 event->setExceptionCode(ExceptionCodes::NotFoundException);
634                 event->setResult(false);
635
636         } Catch (PlatformException) {
637                 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
638                 event->setExceptionCode(ExceptionCodes::PlatformException);
639                 event->setResult(false);
640
641         } Catch (InvalidArgumentException) {
642                 LogError("Invalid Arguments : " << _rethrown_exception.GetMessage());
643                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
644                 event->setResult(false);
645
646         } Catch (Exception) {
647                 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
648                 event->setExceptionCode(ExceptionCodes::PlatformException);
649                 event->setResult(false);
650         }
651 }
652
653 void AddressBook::OnRequestReceived(const EventAddressBookRemoveChangeListenerPtr &event)
654 {
655         LogDebug("entered");
656
657         Try     {
658                 if(!event->getIdIsSet())
659                         ThrowMsg(InvalidArgumentException, "Invalid arguments.");
660
661                 long id = event->getId();
662                 if(m_watchIdMap.find(id) == m_watchIdMap.end())
663                         ThrowMsg(NotFoundException, "No watchId : " << id);
664
665                 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
666                 bool success = m_addressBookEmitters.detach(m_watchIdMap[id]);
667                 if(!success)
668                         ThrowMsg(NotFoundException, "No watchId : " << id);
669
670                 m_watchIdMap.erase(id);
671
672                 if(m_addressBookEmitters.size() == 0)
673                 {
674                         LogDebug("No watcher is registered. unsubscribing from contact service.");
675
676                         m_latestVersion = 0;
677                         contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_CONTACT_CHANGE,
678                                         contactsSvcContactChangedCallback);
679                         contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_ADDRESSBOOK_CHANGE,
680                                         refresh_addressbook_list);
681                 }
682
683                 event->setResult(true);
684
685         } Catch (NotFoundException) {
686                 LogError("WatchId doesn't exist : " << _rethrown_exception.GetMessage());
687                 event->setExceptionCode(ExceptionCodes::NotFoundException);
688                 event->setResult(false);
689
690         } Catch (PlatformException) {
691                 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
692                 event->setExceptionCode(ExceptionCodes::PlatformException);
693                 event->setResult(false);
694
695         } Catch (InvalidArgumentException) {
696                 LogError("Invalid Arguments : " << _rethrown_exception.GetMessage());
697                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
698                 event->setResult(false);
699
700         } Catch (Exception) {
701                 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
702                 event->setExceptionCode(ExceptionCodes::PlatformException);
703                 event->setResult(false);
704         }
705 }
706
707
708 void AddressBook::internalAddContact(const ContactPtr &newContact)
709 {
710         LogDebug("entered");
711
712         DPL::Mutex::ScopedLock lock(&m_contactEditingMutex);
713
714         //translate provided path to real filesystem path
715         if (newContact->getPhotoURIIsSet())
716         {
717                 string realPath = DownloadManager::getInstance()->getRealPath(newContact->getPhotoURI());
718                 if(realPath.length() <= MAXPATHLEN)
719                         newContact->setPhotoURI(realPath);
720         }
721
722         DPL::SharedPtr<TizenApis::Platform::Contact::Contact> newContactT =
723                         DPL::StaticPointerCast<TizenApis::Platform::Contact::Contact>(newContact);
724
725         ContactWrapperPtr contactWrapper(new ContactWrapper(m_bookType));
726
727         CTSstruct* contact = newContactT->getCTSStruct();
728         if(contact == NULL)
729         {
730                 contactWrapper->setAbstractContact(newContact, false);
731                 contact = contactWrapper->getPlatformContact();
732         }
733         else
734         {
735                 contactWrapper->convertAbstractToPlatform(newContact, contact, false);
736         }
737
738         if (!contact)
739         {
740                 LogError("Error during converting contact object");
741                 ThrowMsg(PlatformException, "Error during converting contact object");
742         }
743
744         if ( newContact->getIdIsSet() )
745         {
746                 int ret = contacts_svc_update_contact(contact);
747                 if (ret == CTS_ERR_DB_RECORD_NOT_FOUND)
748                         ThrowMsg(NotFoundException, "Error during executing contacts_svc_update_contact()");
749                 else if (ret < 0) {
750                         LogError("error code " << ret);
751                         ThrowMsg(PlatformException, "Error during executing contacts_svc_update_contact()");
752                 }
753         }
754         else
755         {
756                 query_error error_code = QUERY_SUCCESS;
757                 int addressBookId = 0;
758                 int accountId = 0;
759
760                 string accountIdStr = newContact->getAccountId();
761                 try {
762                         istringstream iss(accountIdStr);
763                         iss >> accountId;
764                 } catch (...) {
765                         LogDebug("accountId changeType is wrong. (id:" << accountIdStr << ")");
766                         accountId = 0;
767                 }
768
769                 addressBookId = find_addressbook_id(accountId, &error_code);
770                 if(error_code != QUERY_SUCCESS)
771                         addressBookId = 0;
772
773                 int id = contacts_svc_insert_contact(addressBookId, contact);
774                 if (id < 0) {
775                         LogError("error code " << id);
776                         ThrowMsg(PlatformException, "Error during executing contacts_svc_insert_contact()");
777                 }
778                 newContact->setId(id);
779         }
780 }
781
782 void AddressBook::internalDeleteContactById(int id)
783 {
784         LogDebug("entered with id " << id);
785
786         if (id == -1)
787                 return;
788
789         DPL::Mutex::ScopedLock lock(&m_contactEditingMutex);
790
791         int res = contacts_svc_delete_contact(id);
792         if (res == CTS_ERR_DB_RECORD_NOT_FOUND)
793                 ThrowMsg(NotFoundException, "Error during executing contacts_svc_delete_contact()");
794         else if (res != CTS_SUCCESS)
795                 ThrowMsg(PlatformException, "Error during executing contacts_svc_delete_contact()");
796 }
797
798 ContactPtr AddressBook::internalGetById(const std::string &contactId)
799 {
800         if(contactId == "")
801                 ThrowMsg(InvalidArgumentException, "contactId argument is wrong");
802
803         ContactSearchEnginePtr searchEngine(new ContactSearchEngine(ContactSearchEngine::CONTACT_QUERY));
804
805         searchEngine->setCondition(contactId);
806         searchEngine->setAttributeOfInterest();
807         searchEngine->setSortMode();
808
809         ContactArrayPtr contacts = searchEngine->getContactSearchResult();
810
811         if(contacts->size() == 0)
812                 ThrowMsg(NotFoundException, "No contact with ID:" << contactId);
813
814         return contacts->at(0);
815 }
816
817 void AddressBook::contactsSvcContactChangedCallback(void *data)
818 {
819         AddressBook *addressBook = static_cast<AddressBook *>(data);
820         addressBook->contactsSvcContactChangedCallback();
821 }
822
823 void AddressBook::contactsSvcContactChangedCallback()
824 {
825         LogDebug("entered");
826         if(m_addressBookEmitters.size() == 0)
827                 return;
828
829         CTSiter *iter;
830         int changeId = 0;
831         int changeType = 0;
832         int changeVersion = 0;
833
834         bool contactInserted = false;
835         bool contactUpdated = false;
836         bool contactDeleted = false;
837
838         int *addressBookIds = NULL;
839         int addressBookIdCount = 0;
840
841         addressBookIds = get_all_addressbook_id(&addressBookIdCount);
842
843         EventInfoAddressBookChangeAddedPtr contactsAdded(new EventInfoAddressBookChangeAdded());
844         EventInfoAddressBookChangeUpdatedPtr contactsUpdated(new EventInfoAddressBookChangeUpdated());
845         EventInfoAddressBookChangeRemovedPtr contactsRemoved(new EventInfoAddressBookChangeRemoved());
846
847         ContactArrayPtr addedContacts(new ContactArray());
848         ContactArrayPtr updatedContacts(new ContactArray());
849         StringArrayPtr removedContactIds(new StringArray());
850
851         for(int i = 0; i < addressBookIdCount; i++)
852         {
853                 int ret = contacts_svc_get_updated_contacts(addressBookIds[i], m_latestVersion, &iter);
854                 if(ret == CTS_SUCCESS)
855                 {
856                         while (contacts_svc_iter_next(iter) == CTS_SUCCESS)
857                         {
858                                 CTSstruct *contact= NULL;
859                                 CTSvalue *row_info = NULL;
860                                 row_info = contacts_svc_iter_get_info(iter);
861
862                                 changeId = contacts_svc_value_get_int(row_info, CTS_LIST_CHANGE_ID_INT);
863                                 changeType = contacts_svc_value_get_int(row_info, CTS_LIST_CHANGE_TYPE_INT);
864                                 changeVersion = contacts_svc_value_get_int(row_info, CTS_LIST_CHANGE_VER_INT);
865
866                                 if(changeType == CTS_OPERATION_INSERTED)
867                                 {
868                                         contactInserted = true;
869                                         contacts_svc_get_contact(changeId, &contact);
870
871                                         ContactWrapperPtr contactWrapper(new ContactWrapper(m_bookType));
872                                         contactWrapper->setPlatformContact(contact, false);
873                                         ContactPtr absContact = contactWrapper->getAbstractContact();
874                                         if(absContact != NULL)
875                                                 addedContacts->push_back(absContact);
876
877                                         if(contact != NULL)
878                                         {
879                                                 contacts_svc_struct_free(contact);
880                                                 contact = NULL;
881                                         }
882                                 }
883
884                                 if(changeType == CTS_OPERATION_UPDATED)
885                                 {
886                                         contactUpdated = true;
887                                         contacts_svc_get_contact(changeId, &contact);
888
889                                         ContactWrapperPtr contactWrapper(new ContactWrapper(m_bookType));
890                                         contactWrapper->setPlatformContact(contact, false);
891                                         ContactPtr absContact = contactWrapper->getAbstractContact();
892                                         if(absContact != NULL)
893                                                 updatedContacts->push_back(absContact);
894
895                                         if(contact != NULL)
896                                         {
897                                                 contacts_svc_struct_free(contact);
898                                                 contact = NULL;
899                                         }
900                                 }
901
902                                 if(changeType == CTS_OPERATION_DELETED)
903                                 {
904                                         contactDeleted = true;
905
906                                         std::stringstream oss;
907                                         oss << changeId;
908                                         removedContactIds->push_back(oss.str());
909                                 }
910
911                                 contacts_svc_value_free(row_info);
912                         }
913                         contacts_svc_iter_remove(iter);
914                 }
915         }
916
917         m_latestVersion = get_contact_version();
918
919         if(addressBookIds)
920                 free(addressBookIds);
921
922         if(contactInserted)
923         {
924                 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
925                 contactsAdded->setContacts(addedContacts);
926                 EventInfoAddressBookChangePtr event = DPL::StaticPointerCast<EventInfoAddressBookChange>(contactsAdded);
927                 EventAddressBookChangeListenerPtr listener(new EventAddressBookChangeListener(event));
928                 m_addressBookEmitters.emit(listener);
929         }
930
931         if(contactUpdated)
932         {
933                 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
934                 contactsUpdated->setContacts(updatedContacts);
935                 EventInfoAddressBookChangePtr event = DPL::StaticPointerCast<EventInfoAddressBookChange>(contactsUpdated);
936                 EventAddressBookChangeListenerPtr listener(new EventAddressBookChangeListener(event));
937                 m_addressBookEmitters.emit(listener);
938         }
939
940         if(contactDeleted)
941         {
942                 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
943                 contactsRemoved->setContactIds(removedContactIds);
944                 EventInfoAddressBookChangePtr event = DPL::StaticPointerCast<EventInfoAddressBookChange>(contactsRemoved);
945                 EventAddressBookChangeListenerPtr listener(new EventAddressBookChangeListener(event));
946                 m_addressBookEmitters.emit(listener);
947         }
948 }
949
950 } // Contact
951 } // Platform
952 } // TizenApis