diff options
Diffstat (limited to 'lib-contact/ct-list/src/CtListModelMergeContacts.cpp')
-rwxr-xr-x | lib-contact/ct-list/src/CtListModelMergeContacts.cpp | 689 |
1 files changed, 689 insertions, 0 deletions
diff --git a/lib-contact/ct-list/src/CtListModelMergeContacts.cpp b/lib-contact/ct-list/src/CtListModelMergeContacts.cpp new file mode 100755 index 0000000..5ec7a82 --- /dev/null +++ b/lib-contact/ct-list/src/CtListModelMergeContacts.cpp @@ -0,0 +1,689 @@ +/* + * Copyright (c) 2009-2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <map> +#include <string> +#include <list> +#include <thread> +#include <string.h> +#include <contacts.h> +#include "WView.h" +#include "WToastPopup.h" +#include "ContactsDebug.h" +#include "CtType.h" +#include "CtListModelMergeContacts.h" +#include "CtCommon.h" + +__Group::~__Group() +{ +} + +__Person::__Person() +: personId(0) +, addressbookMode(0) +, addressbookId(0) +, representative(false) +,favorite(FALSE) +, group(NULL) +{ +} + +CtListModelMergeContacts::CtListModelMergeContacts() +: __finder(NULL) +, __canceled(false) +, __resultCb(NULL) +{ + WHIT(); + + __simAddressbookIds[0] = -1; + __simAddressbookIds[1] = -1; + __initSimAddressbookIds(); +} + +CtListModelMergeContacts::~CtListModelMergeContacts() +{ + WHIT(); + __canceled = true; + + __finder->join(); + delete __finder; +} + +void CtListModelMergeContacts::findMergeCandidates(std::function<void ()> resultCb) +{ + if (__resultCb) { + return; + } + + __resultCb = resultCb; + + __finder = new std::thread([this]{ + + if (!__canceled) + __makeCandidatesByName(__personInfoMap); + if (!__canceled) + __makeCandidatesByEmail(__personInfoMap); + if (!__canceled) + __makeCandidatesByNumber(__personInfoMap); + + __resultCb(); + }); +} + +std::list<std::unique_ptr<__Group> >& CtListModelMergeContacts::getMergeCandidates() +{ + return __groups; +} + +void CtListModelMergeContacts::lock() +{ + __lock.lock(); +} + +void CtListModelMergeContacts::unlock() +{ + __lock.unlock(); +} + +void CtListModelMergeContacts::__initSimAddressbookIds() +{ + int index = 0; + int addressbookId = 0; + int accountId = 0; + contacts_list_h addressbookList = NULL; + contacts_record_h addressbookRecord = NULL; + + int ret = contacts_db_get_all_records(_contacts_address_book._uri, 0, 0, &addressbookList); + if(ret != CONTACTS_ERROR_NONE) + { + WWARNING("contacts_db_get_all_records() Failed(%d)", ret); + if(addressbookList) + contacts_list_destroy(addressbookList, true); + return; + } + + while(contacts_list_get_current_record_p(addressbookList, &addressbookRecord) == CONTACTS_ERROR_NONE) { + ret = contacts_record_get_int(addressbookRecord, _contacts_address_book.id, &addressbookId); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + ret = contacts_record_get_int(addressbookRecord, _contacts_address_book.account_id, &accountId); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + + if (accountId == 0 && addressbookId != 0) { + if (index < 2) + __simAddressbookIds[index] = addressbookId; + + index++; + } + + contacts_list_next(addressbookList); + } + ret = contacts_list_destroy(addressbookList, true); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_list_get_count() Failed(%d)", ret); + +} + +bool CtListModelMergeContacts::__isSimAddressbook(int addressbookId) +{ + if (addressbookId == __simAddressbookIds[0] || addressbookId == __simAddressbookIds[1]) { + return true; + } + + return false; +} + +void CtListModelMergeContacts::__appendGroup(std::unique_ptr<__Group> group) +{ + lock(); + __groups.push_back(move(group)); + unlock(); +} + +void CtListModelMergeContacts::__makeCandidatesByName(std::map<int, __PersonInfo>& personInfoMap) +{ + WHIT(); + + unsigned int person_contact_projection[] = { + _contacts_person_contact.person_id, + _contacts_person_contact.display_name, + _contacts_person_contact.display_contact_id, + _contacts_person_contact.image_thumbnail_path, + _contacts_person_contact.addressbook_ids, + _contacts_person_contact.contact_id, + _contacts_person_contact.address_book_id, + _contacts_person_contact.address_book_mode, + _contacts_person_contact.is_favorite, + _contacts_person_contact.link_count + }; + + contacts_query_h query = NULL; + int ret = contacts_query_create(_contacts_person_contact._uri, &query); + WPRET_M(ret != CONTACTS_ERROR_NONE, "contacts_query_create() Failed(%d)", ret); + + ret = contacts_query_set_projection(query, person_contact_projection, sizeof(person_contact_projection)/sizeof(int)); + if (ret != CONTACTS_ERROR_NONE) { + WERROR("contacts_query_set_projection failed"); + contacts_query_destroy(query); + return; + } + + int addressbookMode = 0; + int personId = 0; + int contactId = 0; + int displayContactId = 0; + int addressbookId = 0; + int mergeCount = 0; + bool favorite = false; + char* displayName = NULL; + char* thumbnailPath = NULL; + + std::unique_ptr<__Group> currentGroup; + std::unique_ptr<__Person> pendedPerson; + + contacts_record_h personRecord = NULL; + contacts_list_h personList = NULL; + ret = contacts_db_get_records_with_query(query, 0, 0, &personList); + if (ret != CONTACTS_ERROR_NONE) { + WERROR("contacts_db_get_records_with_query failed"); + contacts_query_destroy(query); + if(personList) + contacts_list_destroy(personList, true); + return; + } + + while(contacts_list_get_current_record_p(personList, &personRecord) == CONTACTS_ERROR_NONE) { + if (__canceled) + break; + + ret = contacts_record_get_int(personRecord, _contacts_person_contact.person_id, &personId); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + ret = contacts_record_get_int(personRecord, _contacts_person_contact.link_count, &mergeCount); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + ret = contacts_record_get_int(personRecord, _contacts_person_contact.address_book_mode, &addressbookMode); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + ret = contacts_record_get_int(personRecord, _contacts_person_contact.contact_id, &contactId); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + ret = contacts_record_get_int(personRecord, _contacts_person_contact.display_contact_id, &displayContactId); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + ret = contacts_record_get_bool(personRecord, _contacts_person_contact.is_favorite, &favorite); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + if (contactId != displayContactId) { // skip + contacts_list_next(personList); + continue; + } + + ret = contacts_record_get_int(personRecord, _contacts_person_contact.address_book_id, &addressbookId); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + if (__isSimAddressbook(addressbookId)) { + contacts_list_next(personList); + + __PersonInfo personInfo; + personInfo.grouped = false; + personInfo.inSimAddressbook = true; + personInfo.addressbookId = addressbookId; + personInfo.addressbookMode = addressbookMode; + personInfo.mergeCount = mergeCount; + personInfoMap[personId] = personInfo; + + continue; + } + + ret = contacts_record_get_str_p(personRecord, _contacts_person_contact.display_name, &displayName); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_str_p() Failed(%d)", ret); + ctCommonRemoveNewline(displayName); + + if (displayName == NULL || strlen(displayName) == 0) { + contacts_list_next(personList); + + __PersonInfo personInfo; + personInfo.grouped = false; + personInfo.inSimAddressbook = false; + personInfo.addressbookId = addressbookId; + personInfo.addressbookMode = addressbookMode; + personInfo.mergeCount = mergeCount; + personInfoMap[personId] = personInfo; + + continue; + } + + ret = contacts_record_get_str_p(personRecord, _contacts_person_contact.image_thumbnail_path, &thumbnailPath); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_str_p() Failed(%d)", ret); + std::unique_ptr<__Person> newPerson(new __Person()); + + newPerson->personId = personId; + newPerson->addressbookMode = addressbookMode; + newPerson->addressbookId = addressbookId; + newPerson->mergeCount = mergeCount; + newPerson->displayName = displayName; + newPerson->label = displayName; + newPerson->favorite = favorite; + + if (thumbnailPath) + newPerson->thumbnail = thumbnailPath; + + if (currentGroup == NULL) { + if (pendedPerson == NULL) { + pendedPerson = move(newPerson); + } + else { + if (newPerson->label == pendedPerson->label) { + __PersonInfo personInfo; + + personInfo.grouped = true; + personInfo.inSimAddressbook = false; + personInfo.addressbookId = pendedPerson->addressbookId; + personInfo.addressbookMode = pendedPerson->addressbookMode; + personInfo.mergeCount = pendedPerson->mergeCount; + + personInfoMap[pendedPerson->personId] = personInfo; + + personInfo.grouped = true; + personInfo.inSimAddressbook = false; + personInfo.addressbookId = newPerson->addressbookId; + personInfo.addressbookMode = newPerson->addressbookMode; + personInfo.mergeCount = newPerson->mergeCount; + + personInfoMap[newPerson->personId] = personInfo; + + std::unique_ptr<__Group> newGroup(new __Group); + + newGroup->label = newPerson->label; + newGroup->checkedCount = 0; + + pendedPerson->representative = true; + newGroup->members.push_back(move(pendedPerson)); + newGroup->members.push_back(move(newPerson)); + + currentGroup = move(newGroup); + } + else { + __PersonInfo personInfo; + + personInfo.grouped = false; + personInfo.inSimAddressbook = false; + personInfo.addressbookId = pendedPerson->addressbookId; + personInfo.addressbookMode = pendedPerson->addressbookMode; + personInfo.mergeCount = pendedPerson->mergeCount; + personInfoMap[pendedPerson->personId] = personInfo; + + pendedPerson = move(newPerson); + } + } + } + else { + if (currentGroup->label == newPerson->label) { + __PersonInfo personInfo; + + personInfo.grouped = true; + personInfo.inSimAddressbook = false; + personInfo.addressbookId = newPerson->addressbookId; + personInfo.addressbookMode = newPerson->addressbookMode; + personInfo.mergeCount = newPerson->mergeCount; + personInfoMap[newPerson->personId] = personInfo; + + currentGroup->members.push_back(move(newPerson)); + } + else { + pendedPerson = move(newPerson); + __appendGroup(move(currentGroup)); + } + } + contacts_list_next(personList); + } + + if (currentGroup) { + __appendGroup(move(currentGroup)); + } + + if (pendedPerson) { + __PersonInfo personInfo; + + personInfo.grouped = false; + personInfo.inSimAddressbook = false; + personInfo.addressbookId = pendedPerson->addressbookId; + personInfo.addressbookMode = pendedPerson->addressbookMode; + personInfo.mergeCount = pendedPerson->mergeCount; + + personInfoMap[pendedPerson->personId] = personInfo; + } + + contacts_query_destroy(query); + contacts_list_destroy(personList, true); + + WHIT(); +} + +void CtListModelMergeContacts::__makeCandidatesByEmail(std::map<int, __PersonInfo>& personInfoMap) +{ + WHIT(); + + unsigned int contacts_person_email_projection[] = { + _contacts_person_email.person_id, + _contacts_person_email.display_name, + _contacts_person_email.image_thumbnail_path, + _contacts_person_email.email, + }; + + contacts_query_h query = NULL; + + int personId = 0; + char* displayName = NULL; + char* thumbnailPath = NULL; + char* email = NULL; + + std::unique_ptr<__Group> currentGroup; + std::unique_ptr<__Person> pendedPerson; + + contacts_record_h personRecord = NULL; + contacts_list_h personList = NULL; + + int ret = contacts_query_create(_contacts_person_email._uri, &query); + WPRET_M(ret != CONTACTS_ERROR_NONE, "contacts_query_create() Failed(%d)", ret); + + ret = contacts_query_set_projection(query, contacts_person_email_projection, sizeof(contacts_person_email_projection)/sizeof(int)); + if (ret != CONTACTS_ERROR_NONE) { + WERROR("contacts_query_set_projection failed"); + contacts_query_destroy(query); + return; + } + + ret = contacts_query_set_sort(query, _contacts_person_email.email, true); + if (CONTACTS_ERROR_NONE != ret) { + WERROR("contacts_query_set_sort() Failed(%d)", ret); + contacts_query_destroy(query); + return; + } + + ret = contacts_db_get_records_with_query(query, 0, 0, &personList); + if (ret != CONTACTS_ERROR_NONE) { + WERROR("contacts_db_get_records_with_query failed"); + contacts_query_destroy(query); + if(personList) + contacts_list_destroy(personList, true); + return; + } + + while(contacts_list_get_current_record_p(personList, &personRecord) == CONTACTS_ERROR_NONE) { + if (__canceled) + break; + + ret = contacts_record_get_int(personRecord, _contacts_person_email.person_id, &personId); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + if (pendedPerson && pendedPerson->personId == personId) { + contacts_list_next(personList); + continue; + } + + auto iter = personInfoMap.find(personId); + if (iter == personInfoMap.end()) { // person info does not exist + contacts_list_next(personList); + continue; + } + + if (iter->second.grouped) { // already grouped + contacts_list_next(personList); + continue; + } + + if (iter->second.inSimAddressbook) { // sim contact + contacts_list_next(personList); + continue; + } + + ret = contacts_record_get_str_p(personRecord, _contacts_person_email.email, &email); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_str_p() Failed(%d)", ret); + if (email == NULL || strlen(email) == 0) { + contacts_list_next(personList); + continue; + } + + ret = contacts_record_get_str_p(personRecord, _contacts_person_email.display_name, &displayName); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_str_p() Failed(%d)", ret); + if (displayName == NULL || strlen(displayName) == 0) { + contacts_list_next(personList); + continue; + } + + ctCommonRemoveNewline(displayName); + + ret = contacts_record_get_str_p(personRecord, _contacts_person_contact.image_thumbnail_path, &thumbnailPath); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_str_p() Failed(%d)", ret); + + std::unique_ptr<__Person> newPerson(new __Person()); + + newPerson->personId = personId; + newPerson->addressbookId = personInfoMap[personId].addressbookId; + newPerson->addressbookMode = personInfoMap[personId].addressbookMode; + newPerson->mergeCount = personInfoMap[personId].mergeCount; + newPerson->displayName = displayName; + newPerson->label = email; + + if (thumbnailPath) + newPerson->thumbnail = thumbnailPath; + + if (currentGroup == NULL) { + + if (pendedPerson == NULL) { + pendedPerson = move(newPerson); + } + else { + if (newPerson->label == pendedPerson->label) { + personInfoMap[pendedPerson->personId].grouped = true; + personInfoMap[newPerson->personId].grouped = true; + + std::unique_ptr<__Group> newGroup(new __Group); + + newGroup->label = newPerson->label; + newGroup->checkedCount = 0; + + pendedPerson->representative = true; + newGroup->members.push_back(move(pendedPerson)); + newGroup->members.push_back(move(newPerson)); + + currentGroup = move(newGroup); + } + else { + pendedPerson = move(newPerson); + } + } + } + else { + if (currentGroup->label == newPerson->label) { + personInfoMap[newPerson->personId].grouped = true; + currentGroup->members.push_back(move(newPerson)); + } + else { + pendedPerson = move(newPerson); + __appendGroup(move(currentGroup)); + } + } + contacts_list_next(personList); + } + + if (currentGroup) { + __appendGroup(move(currentGroup)); + } + + contacts_query_destroy(query); + contacts_list_destroy(personList, true); + + WHIT(); +} + +void CtListModelMergeContacts::__makeCandidatesByNumber(std::map<int, __PersonInfo>& personInfoMap) +{ + WHIT(); + unsigned int contacts_person_number_projection[] = { + _contacts_person_number.person_id, + _contacts_person_number.display_name, + _contacts_person_number.image_thumbnail_path, + _contacts_person_number.number, + _contacts_person_number.type, + }; + + int personId = 0; + int type = 0; + char* displayName = NULL; + char* thumbnailPath = NULL; + char* number = NULL; + + std::unique_ptr<__Group> currentGroup; + std::unique_ptr<__Person> pendedPerson; + contacts_query_h query = NULL; + + int ret = contacts_query_create(_contacts_person_number._uri, &query); + WPRET_M(ret != CONTACTS_ERROR_NONE, "contacts_query_create() Failed(%d)", ret); + + ret = contacts_query_set_projection(query, contacts_person_number_projection, sizeof(contacts_person_number_projection)/sizeof(int)); + if (CONTACTS_ERROR_NONE != ret) { + WERROR("contacts_query_set_projection() Failed(%d)", ret); + contacts_query_destroy(query); + return; + } + + ret = contacts_query_set_sort(query, _contacts_person_number.number, true); + if (CONTACTS_ERROR_NONE != ret) { + WERROR("contacts_query_set_sort() Failed(%d)", ret); + contacts_query_destroy(query); + return; + } + + contacts_record_h personRecord = NULL; + contacts_list_h personList = NULL; + ret = contacts_db_get_records_with_query(query, 0, 0, &personList); + if(CONTACTS_ERROR_NONE != ret) { + WERROR("contacts_db_get_records_with_query() Failed(%d)", ret); + contacts_query_destroy(query); + if(personList) + contacts_list_destroy(personList, true); + return; + } + + while(contacts_list_get_current_record_p(personList, &personRecord) == CONTACTS_ERROR_NONE) { + if (__canceled) + break; + + ret = contacts_record_get_int(personRecord, _contacts_person_number.type, &type); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + if (CONTACTS_NUMBER_TYPE_WORK & type || CONTACTS_NUMBER_TYPE_FAX & type) { + WDEBUG("type: %d", type); + contacts_list_next(personList); + continue; + } + + ret = contacts_record_get_int(personRecord, _contacts_person_number.person_id, &personId); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Failed(%d)", ret); + if (pendedPerson && pendedPerson->personId == personId) { + contacts_list_next(personList); + continue; + } + + auto iter = personInfoMap.find(personId); + if (iter == personInfoMap.end()) { // person info does not exist + contacts_list_next(personList); + continue; + } + + if (iter->second.grouped) { // already grouped + contacts_list_next(personList); + continue; + } + + if (iter->second.inSimAddressbook) { // sim contact + contacts_list_next(personList); + continue; + } + + ret = contacts_record_get_str_p(personRecord, _contacts_person_number.number, &number); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_str_p() Failed(%d)", ret); + if (number == NULL || strlen(number) == 0) { + contacts_list_next(personList); + continue; + } + + ret = contacts_record_get_str_p(personRecord, _contacts_person_number.display_name, &displayName); + + ctCommonRemoveNewline(displayName); + + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_str_p() Failed(%d)", ret); + if (displayName == NULL || strlen(displayName) == 0) { + contacts_list_next(personList); + continue; + } + + ret = contacts_record_get_str_p(personRecord, _contacts_person_number.image_thumbnail_path, &thumbnailPath); + WPWARN(CONTACTS_ERROR_NONE != ret, "contacts_record_get_str_p() Failed(%d)", ret); + + std::unique_ptr<__Person> newPerson(new __Person()); + + newPerson->personId = personId; + newPerson->addressbookId = personInfoMap[personId].addressbookId; + newPerson->addressbookMode = personInfoMap[personId].addressbookMode; + newPerson->mergeCount = personInfoMap[personId].mergeCount; + newPerson->displayName = displayName; + newPerson->label = number; + + if (thumbnailPath) + newPerson->thumbnail = thumbnailPath; + + if (currentGroup == NULL) { + + if (pendedPerson == NULL) { + pendedPerson = move(newPerson); + } + else { + if (newPerson->label == pendedPerson->label) { + personInfoMap[pendedPerson->personId].grouped = true; + personInfoMap[newPerson->personId].grouped = true; + + std::unique_ptr<__Group> newGroup(new __Group); + + newGroup->label = newPerson->label; + newGroup->checkedCount = 0; + + pendedPerson->representative = true; + newGroup->members.push_back(move(pendedPerson)); + newGroup->members.push_back(move(newPerson)); + + currentGroup = move(newGroup); + } + else { + pendedPerson = move(newPerson); + } + } + } + else { + if (currentGroup->label == newPerson->label) { + personInfoMap[newPerson->personId].grouped = true; + currentGroup->members.push_back(move(newPerson)); + } + else { + pendedPerson = move(newPerson); + __appendGroup(move(currentGroup)); + } + } + contacts_list_next(personList); + } + + if (currentGroup) { + __appendGroup(move(currentGroup)); + } + + contacts_query_destroy(query); + contacts_list_destroy(personList, true); + + WHIT(); +} |