merge wrt-plugins-tizen_0.2.0-3
[platform/framework/web/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 "ContactWrapper.h"
38 #include "ContactSearchEngine.h"
39 #include "ContactFilterValidator.h"
40 #include "DownloadManager.h"
41
42 namespace TizenApis {
43 namespace Platform {
44 namespace Contact {
45
46 using namespace TizenApis::Api::Contact;
47 using namespace TizenApis::Api::Tizen;
48 using namespace WrtDeviceApis::Commons;
49 using namespace std;
50
51 AddressBook::AddressBook(IAddressBook::AddressBookType changeType) :
52                 IAddressBook(changeType),
53                 m_name("TEST_ADDRESS_BOOK")
54 {
55     LogDebug("entered");
56 }
57
58 AddressBook::~AddressBook()
59 {
60 }
61
62 ContactPtr AddressBook::get(const std::string &contactId)
63 {
64         LogDebug("entered");
65
66         return internalGetById(contactId);
67 }
68
69 void AddressBook::add(const ContactPtr &contact)
70 {
71         LogDebug("entered");
72         if(!contact)
73                 ThrowMsg(InvalidArgumentException, "Contact argument is wrong");
74
75         internalAddContact(contact);
76         m_latestVersion = get_contact_version();
77 }
78
79 void AddressBook::update(const ContactPtr &contact)
80 {
81         LogDebug("entered");
82         if(!contact)
83                 ThrowMsg(InvalidArgumentException, "Contact argument is wrong");
84
85         internalAddContact(contact);
86         m_latestVersion = get_contact_version();
87 }
88
89 void AddressBook::remove(const string &id)
90 {
91         LogDebug("entered");
92         int contactId;
93
94         try {
95                 istringstream iss(id);
96                 iss >> contactId;
97         } catch (...) {
98                 ThrowMsg(InvalidArgumentException, "Id changeType is wrong.");
99         }
100
101         Try {
102                 internalDeleteContactById(contactId);
103         } Catch (NotFoundException) {
104                 LogError("Contact (id:" << contactId << ") does not exist.");
105                 ThrowMsg(NotFoundException, "Contact (id:" << contactId << ") does not exist.");
106         } Catch (PlatformException) {
107                 LogError("Error during deleting contact. " << _rethrown_exception.GetMessage());
108                 ThrowMsg(PlatformException, "Error during deleting contact.");
109         }
110         m_latestVersion = get_contact_version();
111 }
112
113 long AddressBook::addChangeListener(const EventAddressBookChangeListenerEmitterPtr &emitter)
114 {
115         DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
116
117         if(m_addressBookEmitters.size() == 0)
118         {
119                 m_latestVersion = get_contact_version();
120                 contacts_svc_subscribe_change(CTS_SUBSCRIBE_CONTACT_CHANGE,
121                                 contactsSvcContactChangedCallback, reinterpret_cast<void *>(this));
122                 contacts_svc_subscribe_change(CTS_SUBSCRIBE_ADDRESSBOOK_CHANGE,
123                                 refresh_addressbook_list, reinterpret_cast<void *>(this));
124         }
125
126         m_addressBookEmitters.attach(emitter);
127
128     return static_cast<long>(emitter->getId());
129 }
130
131 void AddressBook::removeChangeListener(const long watchId)
132 {
133         DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
134         m_addressBookEmitters.detach(watchId);
135
136         if(m_addressBookEmitters.size() == 0)
137         {
138                 m_latestVersion = 0;
139                 contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_CONTACT_CHANGE,
140                                 contactsSvcContactChangedCallback);
141                 contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_ADDRESSBOOK_CHANGE,
142                                 refresh_addressbook_list);
143         }
144 }
145
146 void AddressBook::OnRequestReceived(const EventAddressBookAddBatchPtr &event)
147 {
148         LogDebug("entered");
149         ContactArrayPtr contacts(NULL);
150
151         Try {
152                 if(!event->getContactsIsSet())
153                         ThrowMsg(InvalidArgumentException, "Contacts were not set.");
154
155                 contacts = event->getContacts();
156                 if(!contacts)
157                         ThrowMsg(InvalidArgumentException, "No contacts.");
158
159         } Catch(InvalidArgumentException) {
160                 LogError("Invalid arguments for adding contacts : " << _rethrown_exception.GetMessage());
161                 event->setResult(false);
162                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
163                 return;
164         }
165
166         Try
167         {
168                 int ret = contacts_svc_begin_trans();
169                 if (ret < 0) {
170                         LogError("error code " << ret);
171                         ThrowMsg(PlatformException, "Error during executing contacts_svc_begin_trans()");
172                 }
173
174                 for(ContactArray::iterator i = contacts->begin(); i != contacts->end(); i++)
175                 {
176                         ContactPtr contact = *i;
177
178                         internalAddContact(contact);
179                 }
180                 contacts_svc_end_trans(true);
181                 if (ret < 0) {
182                         LogError("error code " << ret);
183                         ThrowMsg(PlatformException, "Error during executing contacts_svc_end_trans()");
184                 }
185         }
186         Catch (NotFoundException)
187         {
188                 contacts_svc_end_trans(false);
189                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
190                 event->setResult(false);
191                 event->setExceptionCode(ExceptionCodes::NotFoundException);
192                 return;
193         }
194         Catch (PlatformException) {
195                 contacts_svc_end_trans(false);
196                 LogError("Error during adding contact : " << _rethrown_exception.GetMessage());
197                 event->setResult(false);
198                 event->setExceptionCode(ExceptionCodes::PlatformException);
199                 return;
200         }
201         m_latestVersion = get_contact_version();
202
203         event->setResult(true);
204         event->setExceptionCode(ExceptionCodes::None);
205 }
206
207 void AddressBook::OnRequestReceived(const EventAddressBookUpdateBatchPtr &event)
208 {
209         LogDebug("entered");
210         ContactArrayPtr contacts(NULL);
211
212         Try {
213                 if(!event->getContactsIsSet())
214                         ThrowMsg(InvalidArgumentException, "Contacts were not set.");
215
216                 contacts = event->getContacts();
217                 if(!contacts)
218                         ThrowMsg(InvalidArgumentException, "No contacts.");
219
220         } Catch(InvalidArgumentException) {
221                 LogError("Invalid arguments for updating contacts : " << _rethrown_exception.GetMessage());
222                 event->setResult(false);
223                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
224                 return;
225         }
226
227         Try
228         {
229                 int ret = contacts_svc_begin_trans();
230                 if (ret < 0) {
231                         LogError("error code " << ret);
232                         ThrowMsg(PlatformException, "Error during executing contacts_svc_begin_trans()");
233                 }
234
235                 for(ContactArray::iterator i = contacts->begin(); i != contacts->end(); i++)
236                 {
237                         ContactPtr contact = *i;
238
239                         internalAddContact(contact);
240                 }
241                 contacts_svc_end_trans(true);
242                 if (ret < 0) {
243                         LogError("error code " << ret);
244                         ThrowMsg(PlatformException, "Error during executing contacts_svc_end_trans()");
245                 }
246         }
247         Catch (NotFoundException)
248         {
249                 contacts_svc_end_trans(false);
250                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
251                 event->setResult(false);
252                 event->setExceptionCode(ExceptionCodes::NotFoundException);
253                 return;
254         }
255         Catch (PlatformException) {
256                 contacts_svc_end_trans(false);
257                 LogError("Error during updating contact : " << _rethrown_exception.GetMessage());
258                 event->setResult(false);
259                 event->setExceptionCode(ExceptionCodes::PlatformException);
260                 return;
261         }
262         m_latestVersion = get_contact_version();
263
264         event->setResult(true);
265         event->setExceptionCode(ExceptionCodes::None);
266 }
267
268
269 void AddressBook::OnRequestReceived(const EventAddressBookRemoveBatchPtr &event)
270 {
271         LogDebug("entered");
272         StringArrayPtr contactIds(NULL);
273
274         Try {
275                 if(!event->getContactIdsIsSet())
276                         ThrowMsg(InvalidArgumentException, "Contacts were not set.");
277
278                 contactIds = event->getContactIds();
279                 if(!contactIds)
280                         ThrowMsg(InvalidArgumentException, "No contacts.");
281
282         } Catch(InvalidArgumentException) {
283                 LogError("Invalid arguments for updating contacts : " << _rethrown_exception.GetMessage());
284                 event->setResult(false);
285                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
286                 return;
287         }
288
289         Try
290         {
291                 int ret = contacts_svc_begin_trans();
292                 if (ret < 0) {
293                         LogError("error code " << ret);
294                         ThrowMsg(PlatformException, "Error during executing contacts_svc_begin_trans()");
295                 }
296                 for(StringArray::iterator i = contactIds->begin(); i != contactIds->end(); i++)
297                 {
298                         string contactIdStr = *i;
299
300                         int contactId;
301
302                         try {
303                                 istringstream iss(contactIdStr);
304                                 iss >> contactId;
305                         } catch (...) {
306                                 ThrowMsg(InvalidArgumentException, "Id (" << contactIdStr << ") changeType is wrong.");
307                         }
308
309                         internalDeleteContactById(contactId);
310                 }
311                 contacts_svc_end_trans(true);
312                 if (ret < 0) {
313                         LogError("error code " << ret);
314                         ThrowMsg(PlatformException, "Error during executing contacts_svc_end_trans()");
315                 }
316         }
317         Catch (InvalidArgumentException)
318         {
319                 contacts_svc_end_trans(false);
320                 LogError("Invalid contact id : " << _rethrown_exception.GetMessage());
321                 event->setResult(false);
322                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
323                 return;
324         }
325         Catch (NotFoundException)
326         {
327                 contacts_svc_end_trans(false);
328                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
329                 event->setResult(false);
330                 event->setExceptionCode(ExceptionCodes::NotFoundException);
331                 return;
332         }
333         Catch (PlatformException) {
334                 contacts_svc_end_trans(false);
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 EventAddressBookFindPtr &event)
347 {
348         LogDebug("entered");
349         Try     {
350                 ContactSearchEnginePtr searchEngine(new ContactSearchEngine(ContactSearchEngine::CONTACT_QUERY));
351
352                 if(event->getFilterIsSet())
353                 {
354                         FilterPtr filter = event->getFilter();
355
356                         // FIXME validator have to be placed at JS binding.
357                         FilterValidatorPtr validator = ContactFilterValidatorFactory::getContactFilterValidator();
358                         bool success = filter->validate(validator);
359
360                         if(!success)
361                                 ThrowMsg(InvalidArgumentException, "Invalid filter arguments.");
362
363                         searchEngine->setCondition(filter);
364                 }
365
366                 // Currently not support attributeOfInterests
367                 //if (event->getAttributesOfInterestIsSet())
368                 //      searchEngine->setAttributeOfInterest(event->getAttributesOfInterest());
369                 //else
370                 //      searchEngine->setAttributeOfInterest();
371
372                 searchEngine->setAttributeOfInterest();
373
374                 if (event->getSortModeIsSet())
375                 {
376                         searchEngine->setSortMode(event->getSortMode());
377                 }
378                 else
379                         searchEngine->setSortMode();
380
381                 event->setContacts(searchEngine->getContactSearchResult());
382                 event->setResult(true);
383
384         } Catch (NotFoundException) {
385                 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
386                 event->setExceptionCode(ExceptionCodes::NotFoundException);
387                 event->setResult(false);
388
389         } Catch (PlatformException) {
390                 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
391                 event->setExceptionCode(ExceptionCodes::PlatformException);
392                 event->setResult(false);
393
394         } Catch (InvalidArgumentException) {
395                 LogError("Invalid Arguments : " << _rethrown_exception.GetMessage());
396                 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
397                 event->setResult(false);
398         }
399 }
400
401 void AddressBook::internalAddContact(const ContactPtr &newContact)
402 {
403         LogDebug("entered");
404
405         DPL::Mutex::ScopedLock lock(&m_contactEditingMutex);
406
407         //translate provided path to real filesystem path
408         if (newContact->getPhotoURIIsSet())
409         {
410                 string realpath = DownloadManager::getInstance()->getRealPath(newContact->getPhotoURI());
411                 newContact->setPhotoURI(realpath);
412         }
413
414         ContactWrapperPtr contactWrapper(new ContactWrapper(m_bookType));
415         contactWrapper->setAbstractContact(newContact, false);
416         CTSstruct* contact = contactWrapper->getPlatformContact();
417         if (!contact)
418         {
419                 LogError("Error during converting contact object");
420                 ThrowMsg(PlatformException, "Error during converting contact object");
421         }
422
423         if ( newContact->getIdIsSet() )
424         {
425                 int ret = contacts_svc_update_contact(contact);
426                 if (ret == CTS_ERR_DB_RECORD_NOT_FOUND)
427                         ThrowMsg(NotFoundException, "Error during executing contacts_svc_update_contact()");
428                 else if (ret < 0) {
429                         LogError("error code " << ret);
430                         ThrowMsg(PlatformException, "Error during executing contacts_svc_update_contact()");
431                 }
432         }
433         else
434         {
435                 query_error error_code = QUERY_SUCCESS;
436                 int addressBookId = 0;
437                 int accountId = 0;
438
439                 string accountIdStr = newContact->getAccount()->getAccountServiceId();
440                 try {
441                         istringstream iss(accountIdStr);
442                         iss >> accountId;
443                 } catch (...) {
444                         LogDebug("accountId changeType is wrong. (id:" << accountIdStr << ")");
445                         accountId = 0;
446                 }
447
448                 addressBookId = find_addressbook_id(accountId, &error_code);
449                 if(error_code != QUERY_SUCCESS)
450                         addressBookId = 0;
451
452                 int id = contacts_svc_insert_contact(addressBookId, contact);
453                 if (id < 0) {
454                         LogError("error code " << id);
455                         ThrowMsg(PlatformException, "Error during executing contacts_svc_insert_contact()");
456                 }
457
458                 std::stringstream oss;
459                 oss << id;
460                 std::string idStr = oss.str();
461                 ContactPtr insertedContact = internalGetById(idStr);
462
463                 newContact->copy(insertedContact);
464         }
465 }
466
467 void AddressBook::internalDeleteContactById(int id)
468 {
469         LogDebug("entered with id " << id);
470
471         if (id == -1)
472                 return;
473
474         DPL::Mutex::ScopedLock lock(&m_contactEditingMutex);
475
476         int res = contacts_svc_delete_contact(id);
477         if (res == CTS_ERR_DB_RECORD_NOT_FOUND)
478                 ThrowMsg(NotFoundException, "Error during executing contacts_svc_delete_contact()");
479         else if (res != CTS_SUCCESS)
480                 ThrowMsg(PlatformException, "Error during executing contacts_svc_delete_contact()");
481 }
482
483 ContactPtr AddressBook::internalGetById(const std::string &contactId)
484 {
485         if(contactId == "")
486                 ThrowMsg(InvalidArgumentException, "contactId argument is wrong");
487
488         ContactSearchEnginePtr searchEngine(new ContactSearchEngine(ContactSearchEngine::CONTACT_QUERY));
489
490         searchEngine->setCondition(contactId);
491         searchEngine->setAttributeOfInterest();
492         searchEngine->setSortMode();
493
494         ContactArrayPtr contacts = searchEngine->getContactSearchResult();
495
496         if(contacts->size() == 0)
497                 ThrowMsg(NotFoundException, "No contact with ID:" << contactId);
498
499         return contacts->at(0);
500 }
501
502 void AddressBook::contactsSvcContactChangedCallback(void *data)
503 {
504         AddressBook *addressBook = static_cast<AddressBook *>(data);
505         addressBook->contactsSvcContactChangedCallback();
506 }
507
508 void AddressBook::contactsSvcContactChangedCallback()
509 {
510         LogDebug("entered");
511         if(m_addressBookEmitters.size() == 0)
512                 return;
513
514         CTSiter *iter;
515         int changeId = 0;
516         int changeType = 0;
517         int changeVersion = 0;
518
519         bool contactInserted = false;
520         bool contactUpdated = false;
521         bool contactDeleted = false;
522
523         int *addressBookIds = NULL;
524         int addressBookIdCount = 0;
525
526         addressBookIds = get_all_addressbook_id(&addressBookIdCount);
527
528         EventInfoAddressBookChangeAddedPtr contactsAdded(new EventInfoAddressBookChangeAdded());
529         EventInfoAddressBookChangeUpdatedPtr contactsUpdated(new EventInfoAddressBookChangeUpdated());
530         EventInfoAddressBookChangeRemovedPtr contactsRemoved(new EventInfoAddressBookChangeRemoved());
531
532         ContactArrayPtr addedContacts(new ContactArray());
533         ContactArrayPtr updatedContacts(new ContactArray());
534         StringArrayPtr removedContactIds(new StringArray());
535
536         for(int i = 0; i < addressBookIdCount; i++)
537         {
538                 int ret = contacts_svc_get_updated_contacts(addressBookIds[i], m_latestVersion, &iter);
539                 if(ret == CTS_SUCCESS)
540                 {
541                         while (contacts_svc_iter_next(iter) == CTS_SUCCESS)
542                         {
543                                 CTSstruct *contact= NULL;
544                                 CTSvalue *row_info = NULL;
545                                 row_info = contacts_svc_iter_get_info(iter);
546
547                                 changeId = contacts_svc_value_get_int(row_info, CTS_LIST_CHANGE_ID_INT);
548                                 changeType = contacts_svc_value_get_int(row_info, CTS_LIST_CHANGE_TYPE_INT);
549                                 changeVersion = contacts_svc_value_get_int(row_info, CTS_LIST_CHANGE_VER_INT);
550
551                                 if(changeType == CTS_OPERATION_INSERTED)
552                                 {
553                                         contactInserted = true;
554                                         contacts_svc_get_contact(changeId, &contact);
555
556                                         ContactWrapperPtr contactWrapper(new ContactWrapper(m_bookType));
557                                         contactWrapper->setPlatformContact(contact);
558                                         ContactPtr absContact = contactWrapper->getAbstractContact();
559                                         if(absContact != NULL)
560                                                 addedContacts->push_back(absContact);
561                                 }
562
563                                 if(changeType == CTS_OPERATION_UPDATED)
564                                 {
565                                         contactUpdated = true;
566                                         contacts_svc_get_contact(changeId, &contact);
567
568                                         ContactWrapperPtr contactWrapper(new ContactWrapper(m_bookType));
569                                         contactWrapper->setPlatformContact(contact);
570                                         ContactPtr absContact = contactWrapper->getAbstractContact();
571                                         if(absContact != NULL)
572                                                 updatedContacts->push_back(absContact);
573                                 }
574
575                                 if(changeType == CTS_OPERATION_DELETED)
576                                 {
577                                         contactDeleted = true;
578                                         contacts_svc_get_contact(changeId, &contact);
579
580                                         ContactWrapperPtr contactWrapper(new ContactWrapper(m_bookType));
581                                         contactWrapper->setPlatformContact(contact);
582                                         ContactPtr absContact = contactWrapper->getAbstractContact();
583                                         if(absContact != NULL)
584                                         {
585                                                 if(absContact->getIdIsSet())
586                                                         removedContactIds->push_back(absContact->getId());
587                                         }
588                                 }
589
590                                 contacts_svc_value_free(row_info);
591                         }
592                         contacts_svc_iter_remove(iter);
593                 }
594         }
595
596         m_latestVersion = get_contact_version();
597
598         if(addressBookIds)
599                 free(addressBookIds);
600
601         if(contactInserted)
602         {
603                 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
604                 contactsAdded->setContacts(addedContacts);
605                 EventInfoAddressBookChangePtr event = DPL::StaticPointerCast<EventInfoAddressBookChange>(contactsAdded);
606                 EventAddressBookChangeListenerPtr listener(new EventAddressBookChangeListener(event));
607                 m_addressBookEmitters.emit(listener);
608         }
609
610         if(contactUpdated)
611         {
612                 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
613                 contactsUpdated->setContacts(updatedContacts);
614                 EventInfoAddressBookChangePtr event = DPL::StaticPointerCast<EventInfoAddressBookChange>(contactsUpdated);
615                 EventAddressBookChangeListenerPtr listener(new EventAddressBookChangeListener(event));
616                 m_addressBookEmitters.emit(listener);
617         }
618
619         if(contactDeleted)
620         {
621                 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
622                 contactsRemoved->setContactIds(removedContactIds);
623                 EventInfoAddressBookChangePtr event = DPL::StaticPointerCast<EventInfoAddressBookChange>(contactsRemoved);
624                 EventAddressBookChangeListenerPtr listener(new EventAddressBookChangeListener(event));
625                 m_addressBookEmitters.emit(listener);
626         }
627 }
628
629 } // Contact
630 } // Platform
631 } // TizenApis