2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file AddressBook.cpp
19 * @author Kisub Song (kisubs.song@samsung.com)
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"
46 using namespace TizenApis::Api::Contact;
47 using namespace TizenApis::Api::Tizen;
48 using namespace WrtDeviceApis::Commons;
51 AddressBook::AddressBook(IAddressBook::AddressBookType changeType) :
52 IAddressBook(changeType),
53 m_name("TEST_ADDRESS_BOOK")
58 AddressBook::~AddressBook()
62 ContactPtr AddressBook::get(const std::string &contactId)
66 return internalGetById(contactId);
69 void AddressBook::add(const ContactPtr &contact)
73 ThrowMsg(InvalidArgumentException, "Contact argument is wrong");
75 internalAddContact(contact);
76 m_latestVersion = get_contact_version();
79 void AddressBook::update(const ContactPtr &contact)
83 ThrowMsg(InvalidArgumentException, "Contact argument is wrong");
85 internalAddContact(contact);
86 m_latestVersion = get_contact_version();
89 void AddressBook::remove(const string &id)
95 istringstream iss(id);
98 ThrowMsg(InvalidArgumentException, "Id changeType is wrong.");
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.");
110 m_latestVersion = get_contact_version();
113 long AddressBook::addChangeListener(const EventAddressBookChangeListenerEmitterPtr &emitter)
115 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
117 if(m_addressBookEmitters.size() == 0)
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));
126 m_addressBookEmitters.attach(emitter);
128 return static_cast<long>(emitter->getId());
131 void AddressBook::removeChangeListener(const long watchId)
133 DPL::Mutex::ScopedLock lock(&m_addressBookEmittersMutex);
134 m_addressBookEmitters.detach(watchId);
136 if(m_addressBookEmitters.size() == 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);
146 void AddressBook::OnRequestReceived(const EventAddressBookAddBatchPtr &event)
149 ContactArrayPtr contacts(NULL);
152 if(!event->getContactsIsSet())
153 ThrowMsg(InvalidArgumentException, "Contacts were not set.");
155 contacts = event->getContacts();
157 ThrowMsg(InvalidArgumentException, "No contacts.");
159 } Catch(InvalidArgumentException) {
160 LogError("Invalid arguments for adding contacts : " << _rethrown_exception.GetMessage());
161 event->setResult(false);
162 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
168 int ret = contacts_svc_begin_trans();
170 LogError("error code " << ret);
171 ThrowMsg(PlatformException, "Error during executing contacts_svc_begin_trans()");
174 for(ContactArray::iterator i = contacts->begin(); i != contacts->end(); i++)
176 ContactPtr contact = *i;
178 internalAddContact(contact);
180 contacts_svc_end_trans(true);
182 LogError("error code " << ret);
183 ThrowMsg(PlatformException, "Error during executing contacts_svc_end_trans()");
186 Catch (NotFoundException)
188 contacts_svc_end_trans(false);
189 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
190 event->setResult(false);
191 event->setExceptionCode(ExceptionCodes::NotFoundException);
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);
201 m_latestVersion = get_contact_version();
203 event->setResult(true);
204 event->setExceptionCode(ExceptionCodes::None);
207 void AddressBook::OnRequestReceived(const EventAddressBookUpdateBatchPtr &event)
210 ContactArrayPtr contacts(NULL);
213 if(!event->getContactsIsSet())
214 ThrowMsg(InvalidArgumentException, "Contacts were not set.");
216 contacts = event->getContacts();
218 ThrowMsg(InvalidArgumentException, "No contacts.");
220 } Catch(InvalidArgumentException) {
221 LogError("Invalid arguments for updating contacts : " << _rethrown_exception.GetMessage());
222 event->setResult(false);
223 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
229 int ret = contacts_svc_begin_trans();
231 LogError("error code " << ret);
232 ThrowMsg(PlatformException, "Error during executing contacts_svc_begin_trans()");
235 for(ContactArray::iterator i = contacts->begin(); i != contacts->end(); i++)
237 ContactPtr contact = *i;
239 internalAddContact(contact);
241 contacts_svc_end_trans(true);
243 LogError("error code " << ret);
244 ThrowMsg(PlatformException, "Error during executing contacts_svc_end_trans()");
247 Catch (NotFoundException)
249 contacts_svc_end_trans(false);
250 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
251 event->setResult(false);
252 event->setExceptionCode(ExceptionCodes::NotFoundException);
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);
262 m_latestVersion = get_contact_version();
264 event->setResult(true);
265 event->setExceptionCode(ExceptionCodes::None);
269 void AddressBook::OnRequestReceived(const EventAddressBookRemoveBatchPtr &event)
272 StringArrayPtr contactIds(NULL);
275 if(!event->getContactIdsIsSet())
276 ThrowMsg(InvalidArgumentException, "Contacts were not set.");
278 contactIds = event->getContactIds();
280 ThrowMsg(InvalidArgumentException, "No contacts.");
282 } Catch(InvalidArgumentException) {
283 LogError("Invalid arguments for updating contacts : " << _rethrown_exception.GetMessage());
284 event->setResult(false);
285 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
291 int ret = contacts_svc_begin_trans();
293 LogError("error code " << ret);
294 ThrowMsg(PlatformException, "Error during executing contacts_svc_begin_trans()");
296 for(StringArray::iterator i = contactIds->begin(); i != contactIds->end(); i++)
298 string contactIdStr = *i;
303 istringstream iss(contactIdStr);
306 ThrowMsg(InvalidArgumentException, "Id (" << contactIdStr << ") changeType is wrong.");
309 internalDeleteContactById(contactId);
311 contacts_svc_end_trans(true);
313 LogError("error code " << ret);
314 ThrowMsg(PlatformException, "Error during executing contacts_svc_end_trans()");
317 Catch (InvalidArgumentException)
319 contacts_svc_end_trans(false);
320 LogError("Invalid contact id : " << _rethrown_exception.GetMessage());
321 event->setResult(false);
322 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
325 Catch (NotFoundException)
327 contacts_svc_end_trans(false);
328 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
329 event->setResult(false);
330 event->setExceptionCode(ExceptionCodes::NotFoundException);
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);
340 m_latestVersion = get_contact_version();
342 event->setResult(true);
343 event->setExceptionCode(ExceptionCodes::None);
346 void AddressBook::OnRequestReceived(const EventAddressBookFindPtr &event)
350 ContactSearchEnginePtr searchEngine(new ContactSearchEngine(ContactSearchEngine::CONTACT_QUERY));
352 if(event->getFilterIsSet())
354 FilterPtr filter = event->getFilter();
356 // FIXME validator have to be placed at JS binding.
357 FilterValidatorPtr validator = ContactFilterValidatorFactory::getContactFilterValidator();
358 bool success = filter->validate(validator);
361 ThrowMsg(InvalidArgumentException, "Invalid filter arguments.");
363 searchEngine->setCondition(filter);
366 // Currently not support attributeOfInterests
367 //if (event->getAttributesOfInterestIsSet())
368 // searchEngine->setAttributeOfInterest(event->getAttributesOfInterest());
370 // searchEngine->setAttributeOfInterest();
372 searchEngine->setAttributeOfInterest();
374 if (event->getSortModeIsSet())
376 searchEngine->setSortMode(event->getSortMode());
379 searchEngine->setSortMode();
381 event->setContacts(searchEngine->getContactSearchResult());
382 event->setResult(true);
384 } Catch (NotFoundException) {
385 LogError("Contact doesn't exist : " << _rethrown_exception.GetMessage());
386 event->setExceptionCode(ExceptionCodes::NotFoundException);
387 event->setResult(false);
389 } Catch (PlatformException) {
390 LogError("Error during deleting contact : " << _rethrown_exception.GetMessage());
391 event->setExceptionCode(ExceptionCodes::PlatformException);
392 event->setResult(false);
394 } Catch (InvalidArgumentException) {
395 LogError("Invalid Arguments : " << _rethrown_exception.GetMessage());
396 event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
397 event->setResult(false);
401 void AddressBook::internalAddContact(const ContactPtr &newContact)
405 DPL::Mutex::ScopedLock lock(&m_contactEditingMutex);
407 //translate provided path to real filesystem path
408 if (newContact->getPhotoURIIsSet())
410 string realpath = DownloadManager::getInstance()->getRealPath(newContact->getPhotoURI());
411 newContact->setPhotoURI(realpath);
414 ContactWrapperPtr contactWrapper(new ContactWrapper(m_bookType));
415 contactWrapper->setAbstractContact(newContact, false);
416 CTSstruct* contact = contactWrapper->getPlatformContact();
419 LogError("Error during converting contact object");
420 ThrowMsg(PlatformException, "Error during converting contact object");
423 if ( newContact->getIdIsSet() )
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()");
429 LogError("error code " << ret);
430 ThrowMsg(PlatformException, "Error during executing contacts_svc_update_contact()");
435 query_error error_code = QUERY_SUCCESS;
436 int addressBookId = 0;
439 string accountIdStr = newContact->getAccount()->getAccountServiceId();
441 istringstream iss(accountIdStr);
444 LogDebug("accountId changeType is wrong. (id:" << accountIdStr << ")");
448 addressBookId = find_addressbook_id(accountId, &error_code);
449 if(error_code != QUERY_SUCCESS)
452 int id = contacts_svc_insert_contact(addressBookId, contact);
454 LogError("error code " << id);
455 ThrowMsg(PlatformException, "Error during executing contacts_svc_insert_contact()");
458 std::stringstream oss;
460 std::string idStr = oss.str();
461 ContactPtr insertedContact = internalGetById(idStr);
463 newContact->copy(insertedContact);
467 void AddressBook::internalDeleteContactById(int id)
469 LogDebug("entered with id " << id);
474 DPL::Mutex::ScopedLock lock(&m_contactEditingMutex);
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()");
483 ContactPtr AddressBook::internalGetById(const std::string &contactId)
486 ThrowMsg(InvalidArgumentException, "contactId argument is wrong");
488 ContactSearchEnginePtr searchEngine(new ContactSearchEngine(ContactSearchEngine::CONTACT_QUERY));
490 searchEngine->setCondition(contactId);
491 searchEngine->setAttributeOfInterest();
492 searchEngine->setSortMode();
494 ContactArrayPtr contacts = searchEngine->getContactSearchResult();
496 if(contacts->size() == 0)
497 ThrowMsg(NotFoundException, "No contact with ID:" << contactId);
499 return contacts->at(0);
502 void AddressBook::contactsSvcContactChangedCallback(void *data)
504 AddressBook *addressBook = static_cast<AddressBook *>(data);
505 addressBook->contactsSvcContactChangedCallback();
508 void AddressBook::contactsSvcContactChangedCallback()
511 if(m_addressBookEmitters.size() == 0)
517 int changeVersion = 0;
519 bool contactInserted = false;
520 bool contactUpdated = false;
521 bool contactDeleted = false;
523 int *addressBookIds = NULL;
524 int addressBookIdCount = 0;
526 addressBookIds = get_all_addressbook_id(&addressBookIdCount);
528 EventInfoAddressBookChangeAddedPtr contactsAdded(new EventInfoAddressBookChangeAdded());
529 EventInfoAddressBookChangeUpdatedPtr contactsUpdated(new EventInfoAddressBookChangeUpdated());
530 EventInfoAddressBookChangeRemovedPtr contactsRemoved(new EventInfoAddressBookChangeRemoved());
532 ContactArrayPtr addedContacts(new ContactArray());
533 ContactArrayPtr updatedContacts(new ContactArray());
534 StringArrayPtr removedContactIds(new StringArray());
536 for(int i = 0; i < addressBookIdCount; i++)
538 int ret = contacts_svc_get_updated_contacts(addressBookIds[i], m_latestVersion, &iter);
539 if(ret == CTS_SUCCESS)
541 while (contacts_svc_iter_next(iter) == CTS_SUCCESS)
543 CTSstruct *contact= NULL;
544 CTSvalue *row_info = NULL;
545 row_info = contacts_svc_iter_get_info(iter);
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);
551 if(changeType == CTS_OPERATION_INSERTED)
553 contactInserted = true;
554 contacts_svc_get_contact(changeId, &contact);
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);
563 if(changeType == CTS_OPERATION_UPDATED)
565 contactUpdated = true;
566 contacts_svc_get_contact(changeId, &contact);
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);
575 if(changeType == CTS_OPERATION_DELETED)
577 contactDeleted = true;
578 contacts_svc_get_contact(changeId, &contact);
580 ContactWrapperPtr contactWrapper(new ContactWrapper(m_bookType));
581 contactWrapper->setPlatformContact(contact);
582 ContactPtr absContact = contactWrapper->getAbstractContact();
583 if(absContact != NULL)
585 if(absContact->getIdIsSet())
586 removedContactIds->push_back(absContact->getId());
590 contacts_svc_value_free(row_info);
592 contacts_svc_iter_remove(iter);
596 m_latestVersion = get_contact_version();
599 free(addressBookIds);
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);
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);
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);