37a3aedf849b0cb402d8c3fa94db8e40c5c49ed3
[framework/web/wrt-plugins-tizen.git] / src / Contact / ContactSearchEngine.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        ContactSearchEngine.cpp
20  * @author      Kisub Song (kisubs.song@samsung.com)
21  * @version     0.1
22  * @brief
23  */
24
25 #include "ContactSearchEngine.h"
26
27 #include <contacts.h>
28 #include <ctime>
29 #include <algorithm>
30 #include <limits>
31 #include <iomanip>
32 #include <Commons/Exception.h>
33 #include "Contact.h"
34 #include "ContactObjectP2AConverter.h"
35 #include "ContactUtility.h"
36 #include <Logger.h>
37
38 #define _CONTACTS_SVC_QUERY_FUNC_PREFIX(view_uri, query, filter) \
39         do { \
40                 if((errorCode = contacts_query_create(view_uri, &query)) != CONTACTS_ERROR_NONE) \
41                         ThrowMsg(PlatformException, "contacts_query_create error : " << errorCode << " (" << __FUNCTION__ << ")"); \
42                 if((errorCode = contacts_filter_create(view_uri, &filter)) != CONTACTS_ERROR_NONE) \
43                         ThrowMsg(PlatformException, "contacts_filter_create error : " << errorCode << " (" << __FUNCTION__ << ")"); \
44         } while(0)
45
46 #define _CONTACTS_SVC_QUERY_FUNC_SUFFIX(query, filter, list, property_contact_id, result) \
47         do { \
48                 if((errorCode = contacts_query_set_filter(query, filter)) != CONTACTS_ERROR_NONE) \
49                         ThrowMsg(PlatformException, "contacts_query_set_filter error : " << errorCode << " (" << __FUNCTION__ << ")"); \
50                 if((errorCode = contacts_db_get_records_with_query(query, 0, 0, &list)) != CONTACTS_ERROR_NONE) \
51                         ThrowMsg(PlatformException, "contacts_db_get_records_with_query error : " << errorCode << " (" << __FUNCTION__ << ")"); \
52                 unsigned int record_count = 0; \
53                 if((errorCode = contacts_list_get_count(list, &record_count)) != CONTACTS_ERROR_NONE) \
54                         ThrowMsg(PlatformException, "contacts_list_get_count error : " << errorCode << " (" << __FUNCTION__ << ")"); \
55                 contacts_list_first(list); \
56                 for(unsigned int i=0; i<record_count; i++) { \
57                         contacts_record_h record; \
58                         if((errorCode = contacts_list_get_current_record_p(list, &record)) != CONTACTS_ERROR_NONE) \
59                                 ThrowMsg(PlatformException, "contacts_list_get_current_record_p error : " << errorCode << " (" << __FUNCTION__ << ")"); \
60                         int value = 0; \
61                         if((errorCode = contacts_record_get_int(record, property_contact_id, &value)) != CONTACTS_ERROR_NONE) \
62                                 ThrowMsg(PlatformException, "contacts_record_get_int error : " << errorCode << " (" << __FUNCTION__ << ")"); \
63                         result->insert(value); \
64                         contacts_list_next(list); \
65                 } \
66                 if(list != NULL) \
67                         contacts_list_destroy(list, true); \
68                 if(filter != NULL) \
69                         contacts_filter_destroy(filter); \
70                 if(query != NULL) \
71                         contacts_query_destroy(query); \
72         } while(0)
73
74
75 namespace DeviceAPI {
76 namespace Contact {
77
78 using namespace WrtDeviceApis::Commons;
79 using namespace DeviceAPI::Tizen;
80 using namespace std;
81
82 ContactSearchEngine::AttributePropertiesMap ContactSearchEngine::attributePropertiesMap = {
83                 {"id",                      { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.id, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_String } },
84                 {"personId",                { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.person_id, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_String } },
85                 {"addressBookId",           { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.address_book_id, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_String } },
86                 {"lastUpdated",             { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.changed_time, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_Time } },
87                 {"isFavorite",              { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.is_favorite, ContactSearchEngine::ContactSvcPrimitiveType_Boolean, PrimitiveType_Boolean } },
88                 {"name.prefix",             { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.prefix, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
89                 {"name.suffix",             { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.suffix, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
90                 {"name.firstName",          { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.first, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
91                 {"name.middleName",         { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.addition, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
92                 {"name.lastName",           { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.last, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
93                 {"name.nicknames",          { _contacts_nickname._uri, _contacts_nickname.contact_id, _contacts_nickname.name, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
94                 {"name.phoneticFirstName",  { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.phonetic_first, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
95                 {"name.phoneticLastName",   { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.phonetic_last, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
96                 {"name.displayName",        { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.display_name, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
97                 {"addresses.country",       { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.country, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
98                 {"addresses.region",        { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.region, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
99                 {"addresses.city",          { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.locality, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
100                 {"addresses.streetAddress", { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.street, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
101                 {"addresses.additionalInformation", { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.extended, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
102                 {"addresses.postalCode",    { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.postal_code, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
103                 {"addresses.isDefault",     { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.is_default, ContactSearchEngine::ContactSvcPrimitiveType_Boolean, PrimitiveType_Boolean } },
104                 {"addresses.types",         { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.type, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_Long } },
105                 {"photoURI",                { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.image_thumbnail_path, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
106                 {"phoneNumbers.number",     { _contacts_number._uri, _contacts_number.contact_id, _contacts_number.number, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
107                 {"phoneNumbers.isDefault",  { _contacts_number._uri, _contacts_number.contact_id, _contacts_number.is_default, ContactSearchEngine::ContactSvcPrimitiveType_Boolean, PrimitiveType_Boolean } },
108                 {"phoneNumbers.types",      { _contacts_number._uri, _contacts_number.contact_id, _contacts_number.type, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_Long } },
109                 {"emails.email",            { _contacts_email._uri, _contacts_email.contact_id, _contacts_email.email, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
110                 {"emails.isDefault",        { _contacts_email._uri, _contacts_email.contact_id, _contacts_email.is_default, ContactSearchEngine::ContactSvcPrimitiveType_Boolean, PrimitiveType_Boolean } },
111                 {"emails.types",            { _contacts_email._uri, _contacts_email.contact_id, _contacts_email.type, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_Long } },
112                 {"birthday",                { _contacts_event._uri, _contacts_event.contact_id, _contacts_event.date, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_Long } },
113                 {"anniversaries.date",      { _contacts_event._uri, _contacts_event.contact_id, _contacts_event.date, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
114                 {"anniversaries.label",     { _contacts_event._uri, _contacts_event.contact_id, _contacts_event.label, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
115                 {"organizations.name",      { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.name, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
116                 {"organizations.department",{ _contacts_company._uri, _contacts_company.contact_id, _contacts_company.department, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
117                 {"organizations.title",     { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.job_title, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
118                 {"organizations.role",      { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.role, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
119                 {"organizations.logoURI",   { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.logo, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
120                 {"notes",                   { _contacts_note._uri, _contacts_note.contact_id, _contacts_note.note, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
121                 {"urls.url",                { _contacts_url._uri, _contacts_url.contact_id, _contacts_url.url, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
122                 {"urls.type",               { _contacts_url._uri, _contacts_url.contact_id, _contacts_url.type, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_Long } },
123                 {"ringtoneURI",             { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.ringtone_path, ContactSearchEngine::ContactSvcPrimitiveType_String, PrimitiveType_String } },
124                 {"groupIds",                { _contacts_group_relation._uri, _contacts_group_relation.contact_id, _contacts_group_relation.group_id, ContactSearchEngine::ContactSvcPrimitiveType_Int, PrimitiveType_Long } }
125 };
126
127 ContactSearchEngine::ContactSearchEngine() :
128                 m_addressBookId(0),
129                 m_isAddressBookIdSet(false),
130                 m_isFilterSet(false),
131                 m_isSortModeSet(false),
132                 m_sortOrder(ASCENDING_SORT_ORDER)
133 {
134 }
135
136 ContactSearchEngine::~ContactSearchEngine()
137 {
138 }
139
140 void ContactSearchEngine::setAddressBookId(int id)
141 {
142         m_addressBookId = id;
143         m_isAddressBookIdSet = true;
144 }
145
146 void ContactSearchEngine::setCondition(FilterPtr filter)
147 {
148         if(!filter)
149                 return;
150
151         IFilterVisitorPtr filterQuery = DPL::StaticPointerCast<IFilterVisitor>(SharedFromThis());
152         filter->travel(filterQuery);
153
154         if(m_filteredContactIds != NULL)
155                 m_isFilterSet = true;
156 }
157
158 void ContactSearchEngine::setSortMode(SortModePtr attr)
159 {
160         if(!attr)
161                 return;
162
163         m_sortOrder = attr->getOrder();
164         m_attributeNameForSort = attr->getAttributeName();
165
166         AttributePropertiesMap::iterator iter =
167                         attributePropertiesMap.find(m_attributeNameForSort);
168         if(iter == attributePropertiesMap.end())
169                 ThrowMsg(NotFoundException, "There is no attribute name for sorting : " << m_attributeNameForSort);
170
171         m_isSortModeSet = true;
172 }
173
174 ContactArrayPtr ContactSearchEngine::getContactSearchResult()
175 {
176         ContactArrayPtr result(NULL);
177         unsigned int length = 0;
178
179         LoggerD("entered");
180         if(m_isFilterSet)
181         {
182                 if(m_isSortModeSet)
183                 {
184                         ContactIdArrayPtr ids = ContactIdArrayPtr(new ContactIdArray());
185
186                         AttributePropertiesMap::iterator iter =
187                                         attributePropertiesMap.find(m_attributeNameForSort);
188                         AttributeProperties &property = iter->second;
189
190                         length = m_filteredContactIds->size();
191                         LoggerD("length : " << length);
192
193                         if(length != 0)
194                         {
195                                 if(m_sortOrder == ASCENDING_SORT_ORDER)
196                                         sortContacts(property, ids, true, m_filteredContactIds);
197                                 else
198                                         sortContacts(property, ids, false, m_filteredContactIds);
199
200                                 result = getContacts(ids);
201                         }else{
202                                 ContactArrayPtr contacts(new ContactArray());
203                                 result = contacts;
204                         }
205                 }
206                 else
207                 {
208                         length = m_filteredContactIds->size();
209                         LoggerD("length : " << length);
210                         if(length != 0)
211                         {
212                         result = getContacts(m_filteredContactIds);
213                         }else{
214                                 ContactArrayPtr contacts(new ContactArray());
215                                 result = contacts;
216                         }
217                 }
218         }
219         else
220         {
221                 if(m_isSortModeSet)
222                 {
223                         AttributePropertiesMap::iterator iter =
224                                         attributePropertiesMap.find(m_attributeNameForSort);
225                         AttributeProperties &property = iter->second;
226
227                         if(m_sortOrder == ASCENDING_SORT_ORDER)
228                                 result = getAllContactsSorted(property, true);
229                         else
230                                 result = getAllContactsSorted(property, false);
231                 }
232                 else
233                 {
234                         result = getAllContacts();
235                 }
236         }
237         LoggerD("End");
238
239         return result;
240 }
241
242 void ContactSearchEngine::visitPreComposite(FilterType& type, int depth)
243 {
244         ContactIdSetArrayPtr idSets = ContactIdSetArrayPtr(new ContactIdSetArray());
245
246         m_contactIdSetArrayStack.push(idSets);
247 }
248
249 void ContactSearchEngine::visitInComposite(FilterType& type, int depth)
250 {
251         // Nothing to do
252 }
253
254 void ContactSearchEngine::visitPostComposite(FilterType& type, int depth)
255 {
256         ContactIdSetArrayPtr idSets = m_contactIdSetArrayStack.top();
257         m_contactIdSetArrayStack.pop();
258
259         ContactIdSetPtr idSet = ContactIdSetPtr(new ContactIdSet());
260
261         if(type == UNION_FILTER)
262                 getUnion(idSets, idSet);
263         else if(type == INTERSECTION_FILTER)
264                 getIntersection(idSets, idSet);
265
266         if(depth == 0)
267         {
268                 m_filteredContactIds = idSet;
269         }
270         else
271         {
272                 if(idSet != NULL)
273                 {
274                         ContactIdSetArrayPtr parentIdSets = m_contactIdSetArrayStack.top();
275                         parentIdSets->push_back(idSet);
276                 }
277         }
278 }
279
280 void ContactSearchEngine::visitAttribute(string& attrName, MatchFlag& matchFlag, AnyPtr& matchValue, int depth)
281 {
282         ContactIdSetPtr idSet = ContactIdSetPtr(new ContactIdSet());
283
284         if(attrName == "id")
285         {
286                 string value = matchValue->getString();
287                 idSet->insert(ContactUtility::strToInt(value));
288
289                 if(depth == 0)
290                         m_filteredContactIds = idSet;
291                 else
292                 {
293                         ContactIdSetArrayPtr parentIdSets = m_contactIdSetArrayStack.top();
294                         parentIdSets->push_back(idSet);
295                 }
296
297                 return;
298         }
299         else if(attrName == "addresses.types" ||
300                         attrName == "emails.types" ||
301                         attrName == "phoneNumbers.types" ||
302                         attrName == "urls.type")
303         {
304                 if(depth == 0)
305                         m_filteredContactIds = ContactIdSetPtr(NULL);
306
307                 return;
308         }
309
310         AttributePropertiesMap::iterator iter =
311                         attributePropertiesMap.find(attrName);
312         if(iter == attributePropertiesMap.end())
313                 ThrowMsg(NotFoundException, "There is no attribute name for filter : " << attrName);
314         AttributeProperties &properties = iter->second;
315
316         if(properties.type == ContactSvcPrimitiveType_Boolean)
317         {
318                 bool value = matchValue->getBool();
319
320                 queryAttributeBool(properties, idSet, value);
321         }
322         else if(properties.type == ContactSvcPrimitiveType_String)
323         {
324                 string value = matchValue->getString();
325                 contacts_match_str_flag_e flag = CONTACTS_MATCH_EXISTS;
326
327                 if(matchFlag == MATCH_EXACTLY)
328                         flag = CONTACTS_MATCH_EXACTLY;
329                 else if(matchFlag == MATCH_FULLSTRING)
330                         flag = CONTACTS_MATCH_FULLSTRING;
331                 else if(matchFlag == MATCH_CONTAINS)
332                         flag = CONTACTS_MATCH_CONTAINS;
333                 else if(matchFlag == MATCH_STARTSWITH)
334                         flag = CONTACTS_MATCH_STARTSWITH;
335                 else if(matchFlag == MATCH_ENDSWITH)
336                         flag = CONTACTS_MATCH_ENDSWITH;
337                 else if(matchFlag == MATCH_EXISTS)
338                         flag = CONTACTS_MATCH_EXISTS;
339
340                 queryAttributeString(properties, idSet, flag, value.c_str());
341         }
342         else if(properties.type == ContactSvcPrimitiveType_Int)
343         {
344                 int value;
345
346                 if(attrName == "id")
347                         value = ContactUtility::strToInt(matchValue->getString());
348                 else
349                         value = matchValue->getLong();
350
351                 contacts_match_int_flag_e flag;
352                 if(matchFlag == MATCH_EXISTS)
353                 {
354                         flag = CONTACTS_MATCH_GREATER_THAN_OR_EQUAL;
355                         value = 0;
356                 }else{
357                         flag = CONTACTS_MATCH_EQUAL;
358                 }
359
360                 queryAttributeInt(properties, idSet, flag, value);
361         }
362
363         if(depth == 0)
364         {
365                 m_filteredContactIds = idSet;
366         }
367         else
368         {
369                 if(idSet != NULL)
370                 {
371                         ContactIdSetArrayPtr parentIdSets = m_contactIdSetArrayStack.top();
372                         parentIdSets->push_back(idSet);
373                 }
374         }
375 }
376
377 void ContactSearchEngine::visitAttributeRange(string& attrName, AnyPtr& initialValue, AnyPtr& endValue, int depth)
378 {
379         ContactIdSetPtr idSet = ContactIdSetPtr(new ContactIdSet());
380
381         bool initialValueIsSet = false;
382         bool endValueIsSet = false;
383
384         if(initialValue != NULL || initialValue->isNullOrUndefined())
385                 initialValueIsSet = false;
386
387         if(endValue != NULL || endValue->isNullOrUndefined())
388                 endValueIsSet = false;
389
390         if(!initialValueIsSet && !endValueIsSet)
391         {
392                 if(depth == 0)
393                         m_filteredContactIds = ContactIdSetPtr(NULL);
394
395                 return;
396         }
397
398         if(attrName == "id")
399         {
400                 if(depth == 0)
401                         m_filteredContactIds = idSet;
402                 else
403                 {
404                         ContactIdSetArrayPtr parentIdSets = m_contactIdSetArrayStack.top();
405                         parentIdSets->push_back(idSet);
406                 }
407
408                 return;
409         }
410         else if(attrName == "addresses.types" ||
411                         attrName == "emails.types" ||
412                         attrName == "phoneNumbers.types" ||
413                         attrName == "urls.type")
414         {
415                 if(depth == 0)
416                         m_filteredContactIds = ContactIdSetPtr(NULL);
417
418                 return;
419         }
420
421         AttributePropertiesMap::iterator iter =
422                         attributePropertiesMap.find(attrName);
423         if(iter == attributePropertiesMap.end())
424                 ThrowMsg(NotFoundException, "There is no attribute name for filter : " << attrName);
425         AttributeProperties &properties = iter->second;
426
427         if(properties.type == ContactSvcPrimitiveType_Boolean)
428         {
429                 bool initialValueBool = false;
430                 bool endValueBool = false;
431
432                 if(initialValueIsSet)
433                         initialValueBool = initialValue->getBool();
434                 if(endValueIsSet)
435                         endValueBool = endValue->getBool();
436
437                 queryAttributeRangeBool(properties, idSet, initialValueIsSet, initialValueBool, endValueIsSet, endValueBool);
438         }
439         else if(properties.type == ContactSvcPrimitiveType_String)
440         {
441                 const char *initialValueCStr = NULL;
442                 const char *endValueCStr = NULL;
443
444                 string initialValueStr;
445                 string endValueStr;
446
447                 if(initialValueIsSet)
448                 {
449                         initialValueStr = initialValue->getString();
450                         initialValueCStr = initialValueStr.c_str();
451                 }
452                 if(endValueIsSet)
453                 {
454                         endValueStr = endValue->getString();
455                         endValueCStr = endValueStr.c_str();
456                 }
457
458                 queryAttributeRangeString(properties, idSet, initialValueCStr, endValueCStr);
459         }
460         else if(properties.type == ContactSvcPrimitiveType_Int)
461         {
462                 int initialValueInt = 0;
463                 int endValueInt = 0;
464
465                 if(attrName == "id")
466                 {
467                         if(initialValueIsSet)
468                                 initialValueInt = ContactUtility::strToInt(initialValue->getString());
469                         if(endValueIsSet)
470                                 endValueInt = ContactUtility::strToInt(endValue->getString());
471                 }
472                 else
473                 {
474                         if(initialValueIsSet)
475                                 initialValueInt = initialValue->getLong();
476                         if(endValueIsSet)
477                                 endValueInt = endValue->getLong();
478                 }
479
480                 queryAttributeRangeInt(properties, idSet, initialValueIsSet, initialValueInt, endValueIsSet, endValueInt);
481         }
482
483         if(depth == 0)
484         {
485                 m_filteredContactIds = idSet;
486         }
487         else
488         {
489                 ContactIdSetArrayPtr parentIdSets = m_contactIdSetArrayStack.top();
490                 parentIdSets->push_back(idSet);
491         }
492 }
493
494 ContactArrayPtr ContactSearchEngine::getAllContactsSorted(AttributeProperties& attributeProperties, bool is_ascending)
495 {
496         ContactArrayPtr contacts = ContactArrayPtr(new ContactArray());
497
498         ContactArrayPtr allContacts = getAllContacts();
499         ContactIdArrayPtr sortedIds = ContactIdArrayPtr(new ContactIdArray());
500
501         sortContacts(attributeProperties, sortedIds, is_ascending);
502
503         map<int,ContactPtr> contactMap;
504
505         ContactArray::iterator citer;
506         for(citer=allContacts->begin(); citer!=allContacts->end(); citer++)
507         {
508                 ContactPtr contact = *citer;
509                 int id = ContactUtility::strToInt(contact->getId());
510                 contactMap.insert(pair<int,ContactPtr>(id, contact));
511         }
512
513         ContactIdArray::iterator iter;
514         for(iter=sortedIds->begin(); iter!=sortedIds->end(); iter++)
515         {
516                 int id = *iter;
517
518                 map<int,ContactPtr>::iterator idPair = contactMap.find(id);
519                 if(idPair == contactMap.end())
520                 {
521                         LoggerW("no contact id : " << id);
522                         continue;
523                 }
524                 contacts->push_back(idPair->second);
525         }
526
527         return contacts;
528 }
529
530 ContactArrayPtr ContactSearchEngine::getAllContacts()
531 {
532         int errorCode = 0;
533
534         ContactArrayPtr contacts(new ContactArray());
535         contacts_list_h list = NULL;
536
537         if(!m_isAddressBookIdSet)
538         {
539                 errorCode = contacts_db_get_all_records(_contacts_contact._uri, 0, 0, &list);
540                 if(errorCode != CONTACTS_ERROR_NONE)
541                         ThrowMsg(PlatformException, "contacts_db_get_all_records error : " << errorCode << " (" << __FUNCTION__ << ")");
542         }
543         else
544         {
545                 contacts_query_h query = NULL;
546                 contacts_filter_h filter = NULL;
547
548                 errorCode = contacts_query_create(_contacts_contact._uri, &query);
549                 if(errorCode != CONTACTS_ERROR_NONE)
550                         ThrowMsg(PlatformException, "Fail to get contacts_query_create (ret:" << errorCode << ")");
551
552                 errorCode = contacts_filter_create(_contacts_contact._uri, &filter);
553                 if(errorCode != CONTACTS_ERROR_NONE)
554                         ThrowMsg(PlatformException, "Fail to get contacts_filter_create (ret:" << errorCode << ")");
555
556                 errorCode = contacts_filter_add_int(filter, _contacts_contact.address_book_id, CONTACTS_MATCH_EQUAL, m_addressBookId);
557                 if(errorCode != CONTACTS_ERROR_NONE)
558                         ThrowMsg(PlatformException, "Fail to get contacts_filter_add_int (ret:" << errorCode << ")");
559
560                 errorCode = contacts_query_set_filter(query, filter);
561                 if(errorCode != CONTACTS_ERROR_NONE)
562                         ThrowMsg(PlatformException, "Fail to get contacts_query_set_filter (ret:" << errorCode << ")");
563
564                 errorCode = contacts_db_get_records_with_query(query, 0, 0, &list);
565                 if(errorCode != CONTACTS_ERROR_NONE)
566                         ThrowMsg(PlatformException, "Fail to get contacts_db_get_records_with_query (ret:" << errorCode << ")");
567
568                 errorCode = contacts_filter_destroy(filter);
569                 if(errorCode != CONTACTS_ERROR_NONE)
570                         ThrowMsg(PlatformException, "Fail to get contacts_filter_destroy (ret:" << errorCode << ")");
571
572                 errorCode = contacts_query_destroy(query);
573                 if(errorCode != CONTACTS_ERROR_NONE)
574                         ThrowMsg(PlatformException, "Fail to get contacts_query_destroy (ret:" << errorCode << ")");
575         }
576
577         unsigned int record_count = 0;
578         errorCode = contacts_list_get_count(list, &record_count);
579         if(errorCode != CONTACTS_ERROR_NONE)
580                 ThrowMsg(PlatformException, "Fail to get contacts_list_get_count : " << errorCode << " (" << __FUNCTION__ << ")");
581         LoggerD("END: pure contact-svc");
582
583         contacts_list_first(list);
584         for(unsigned int i=0; i<record_count; i++)
585         {
586                 contacts_record_h record;
587                 errorCode = contacts_list_get_current_record_p(list, &record);
588                 if(errorCode != CONTACTS_ERROR_NONE || record == NULL)
589                 {
590                         LoggerW("contacts_list_get_current_record_p error : " << errorCode << " (" << __FUNCTION__ << ")");
591                         continue;
592                 }
593
594                 ContactPtr contact(NULL);
595                 Try
596                 {
597                         ContactObjectP2AConverterPtr contactObjConverter(
598                                         new ContactObjectP2AConverter(record, false));
599
600                         contact = contactObjConverter->getAbstractContact();
601                 }
602                 Catch(Exception)
603                 {
604                         LoggerW("fail to convert contact");
605                         continue;
606                 }
607
608                 contacts->push_back(contact);
609
610                 contacts_list_next(list);
611         }
612
613         if(list != NULL)
614                 contacts_list_destroy(list, true);
615
616         LoggerD("END: convertToPlugin Objects");
617
618         return contacts;
619 }
620
621 ContactArrayPtr ContactSearchEngine::getContacts(ContactIdArrayPtr& ids)
622 {
623         ContactArrayPtr contacts(new ContactArray());
624
625         ContactIdArray::iterator iter;
626         for(iter=ids->begin(); iter!=ids->end(); iter++)
627         {
628                 Try
629                 {
630                         ContactPtr contact = getContact(*iter);
631                         if(contact != NULL)
632                                 contacts->push_back(contact);
633                 }
634                 Catch(Exception)
635                 {
636                         LoggerW(_rethrown_exception.GetMessage());
637                         continue;
638                 }
639         }
640
641         return contacts;
642 }
643
644 ContactArrayPtr ContactSearchEngine::getContacts(ContactIdSetPtr& ids)
645 {
646         ContactArrayPtr contacts(new ContactArray());
647
648         ContactIdSet::iterator iter;
649         for(iter=ids->begin(); iter!=ids->end(); iter++)
650         {
651                 Try
652                 {
653                         ContactPtr contact = getContact(*iter);
654                         if(contact != NULL)
655                                 contacts->push_back(contact);
656                 }
657                 Catch(Exception)
658                 {
659                         LoggerW(_rethrown_exception.GetMessage());
660                         continue;
661                 }
662         }
663         return contacts;
664 }
665
666 ContactPtr ContactSearchEngine::getContact(int id)
667 {
668         int errorCode = 0;
669         contacts_record_h record = NULL;
670
671         errorCode = contacts_db_get_record(_contacts_contact._uri, id, &record);
672         if(errorCode != CONTACTS_ERROR_NONE)
673         {
674                 LoggerE("No contact 1 : " << errorCode << " (" << __FUNCTION__ << ")");
675                 return ContactPtr(NULL);
676         }
677
678         if(m_isAddressBookIdSet)
679         {
680                 int addressBookId = 0;
681
682                 errorCode = contacts_record_get_int(record, _contacts_contact.address_book_id, &addressBookId);
683                 if(errorCode != CONTACTS_ERROR_NONE)
684                 {
685                         LoggerE("No contact 2 : " << errorCode << " (" << __FUNCTION__ << ")");
686                         return ContactPtr(NULL);
687                 }
688
689                 if(addressBookId != m_addressBookId)
690                         return ContactPtr(NULL);
691         }
692
693         ContactObjectP2AConverterPtr contactObjConverter(
694                         new ContactObjectP2AConverter(record, false));
695         ContactPtr contact = contactObjConverter->getAbstractContact();
696
697         return contact;
698 }
699
700 void ContactSearchEngine::queryAttributeBool(AttributeProperties& attributeProperties, ContactIdSetPtr& result,
701                 bool match_value)
702 {
703         const char* view_uri = attributeProperties.viewUri;
704         unsigned int property_contact_id = attributeProperties.propertyContactId;
705         unsigned int property_id = attributeProperties.propertyId;
706
707         int errorCode = 0;
708         contacts_query_h query = NULL;
709         contacts_filter_h filter = NULL;
710         contacts_list_h list = NULL;
711
712         _CONTACTS_SVC_QUERY_FUNC_PREFIX(view_uri, query, filter);
713
714         errorCode = contacts_filter_add_bool(filter, property_id, match_value);
715         if(errorCode != CONTACTS_ERROR_NONE)
716         {
717                 ThrowMsg(PlatformException, "contacts_filter_add_bool error : " << errorCode << " (" << __FUNCTION__ << ")");
718         }
719
720         _CONTACTS_SVC_QUERY_FUNC_SUFFIX(query, filter, list, property_contact_id, result);
721 }
722
723 void ContactSearchEngine::queryAttributeInt(AttributeProperties& attributeProperties, ContactIdSetPtr& result,
724                 contacts_match_int_flag_e match, int match_value)
725 {
726         const char* view_uri = attributeProperties.viewUri;
727         unsigned int property_contact_id = attributeProperties.propertyContactId;
728         unsigned int property_id = attributeProperties.propertyId;
729
730         int errorCode = 0;
731         contacts_query_h query = NULL;
732         contacts_filter_h filter = NULL;
733         contacts_list_h list = NULL;
734
735         _CONTACTS_SVC_QUERY_FUNC_PREFIX(view_uri, query, filter);
736
737         errorCode = contacts_filter_add_int(filter, property_id, match, match_value);
738         if(errorCode != CONTACTS_ERROR_NONE)
739         {
740                 ThrowMsg(PlatformException, "contacts_filter_add_int error : " << errorCode << " (" << __FUNCTION__ << ")");
741         }
742
743         _CONTACTS_SVC_QUERY_FUNC_SUFFIX(query, filter, list, property_contact_id, result);
744 }
745
746 void ContactSearchEngine::queryAttributeString(AttributeProperties& attributeProperties, ContactIdSetPtr& result,
747                 contacts_match_str_flag_e match, const char* match_value)
748 {
749         const char* view_uri = attributeProperties.viewUri;
750         unsigned int property_contact_id = attributeProperties.propertyContactId;
751         unsigned int property_id = attributeProperties.propertyId;
752
753         int errorCode = 0;
754         contacts_query_h query = NULL;
755         contacts_filter_h filter = NULL;
756         contacts_list_h list = NULL;
757
758         _CONTACTS_SVC_QUERY_FUNC_PREFIX(view_uri, query, filter);
759
760         errorCode = contacts_filter_add_str(filter, property_id, match, match_value);
761         if(errorCode != CONTACTS_ERROR_NONE)
762         {
763                 ThrowMsg(PlatformException, "contacts_filter_add_int error : " << errorCode << " (" << __FUNCTION__ << ")");
764         }
765
766         _CONTACTS_SVC_QUERY_FUNC_SUFFIX(query, filter, list, property_contact_id, result);
767 }
768
769 void ContactSearchEngine::queryAttributeRangeBool(AttributeProperties& attributeProperties, ContactIdSetPtr& result,
770                 bool initial_value_is_set, bool initial_value, bool end_value_is_set, bool end_value)
771 {
772         const char* view_uri = attributeProperties.viewUri;
773         unsigned int property_contact_id = attributeProperties.propertyContactId;
774         unsigned int property_id = attributeProperties.propertyId;
775
776         int errorCode = 0;
777         contacts_query_h query = NULL;
778         contacts_filter_h filter = NULL;
779         contacts_list_h list = NULL;
780
781         _CONTACTS_SVC_QUERY_FUNC_PREFIX(view_uri, query, filter);
782
783         if(initial_value_is_set && end_value_is_set)
784         {
785                 if(initial_value == end_value)
786                 {
787                         if(initial_value == true)
788                                 errorCode = contacts_filter_add_bool(filter, property_id, true);
789                         else if(end_value == false)
790                                 errorCode = contacts_filter_add_bool(filter, property_id, false);
791                 }
792         }
793         else if(initial_value_is_set)
794         {
795                 if(initial_value == true)
796                         errorCode = contacts_filter_add_bool(filter, property_id, true);
797         }
798         else if(end_value_is_set)
799         {
800                 if(end_value == false)
801                         errorCode = contacts_filter_add_bool(filter, property_id, false);
802         }
803
804         _CONTACTS_SVC_QUERY_FUNC_SUFFIX(query, filter, list, property_contact_id, result);
805 }
806
807 void ContactSearchEngine::queryAttributeRangeInt(AttributeProperties& attributeProperties, ContactIdSetPtr& result,
808                 bool initial_value_is_set, int initial_value, bool end_value_is_set, int end_value)
809 {
810         const char* view_uri = attributeProperties.viewUri;
811         unsigned int property_contact_id = attributeProperties.propertyContactId;
812         unsigned int property_id = attributeProperties.propertyId;
813
814         int errorCode = 0;
815         contacts_query_h query = NULL;
816         contacts_filter_h filter = NULL;
817         contacts_list_h list = NULL;
818
819         _CONTACTS_SVC_QUERY_FUNC_PREFIX(view_uri, query, filter);
820
821         if(initial_value_is_set && end_value_is_set)
822         {
823                 contacts_filter_h sub_filter = NULL;
824
825                 errorCode = contacts_filter_create(_contacts_person._uri, &sub_filter);
826
827                 errorCode = contacts_filter_add_int(sub_filter, property_id,
828                                 CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value);
829
830                 contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
831
832                 errorCode = contacts_filter_add_int(sub_filter, property_id,
833                                 CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value);
834
835                 errorCode = contacts_filter_add_filter(filter, sub_filter);
836         }
837         else if(initial_value_is_set)
838         {
839                 errorCode = contacts_filter_add_int(filter, property_id,
840                                 CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value);
841         }
842         else if(end_value_is_set)
843         {
844                 errorCode = contacts_filter_add_int(filter, property_id,
845                                 CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value);
846         }
847
848         _CONTACTS_SVC_QUERY_FUNC_SUFFIX(query, filter, list, property_contact_id, result);
849 }
850
851 void ContactSearchEngine::queryAttributeRangeString(AttributeProperties& attributeProperties, ContactIdSetPtr& result,
852                 const char* initial_value, const char* end_value)
853
854 {
855         const char* view_uri = attributeProperties.viewUri;
856         unsigned int property_contact_id = attributeProperties.propertyContactId;
857         unsigned int property_id = attributeProperties.propertyId;
858         LoggerD("entered");
859
860         int errorCode = 0;
861         contacts_query_h query = NULL;
862         contacts_filter_h filter = NULL;
863         contacts_list_h list = NULL;
864
865         _CONTACTS_SVC_QUERY_FUNC_PREFIX(view_uri, query, filter);
866
867         if(initial_value != NULL && end_value != NULL)
868         {
869                 contacts_filter_h sub_filter = NULL;
870
871                 errorCode = contacts_filter_create(view_uri, &sub_filter);
872
873                 // TODO To be supported start
874                 errorCode = contacts_filter_add_str(sub_filter, property_id,
875                                 CONTACTS_MATCH_STARTSWITH, initial_value);
876
877                 contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
878
879                 errorCode = contacts_filter_add_str(sub_filter, property_id,
880                                 CONTACTS_MATCH_ENDSWITH, end_value);
881
882                 errorCode = contacts_filter_add_filter(filter, sub_filter);
883         }
884         else if(initial_value != NULL)
885         {
886                 errorCode = contacts_filter_add_str(filter, property_id,
887                                 CONTACTS_MATCH_STARTSWITH, initial_value);
888         }
889         else if(end_value != NULL)
890         {
891                 errorCode = contacts_filter_add_str(filter, property_id,
892                                 CONTACTS_MATCH_ENDSWITH, end_value);
893         }
894
895         _CONTACTS_SVC_QUERY_FUNC_SUFFIX(query, filter, list, property_contact_id, result);
896         LoggerD("end");
897 }
898
899 #if 0
900 void ContactSearchEngine::sortContacts(AttributeProperties& attributeProperties, ContactIdArrayPtr& result,
901                 bool is_ascending, ContactIdSetPtr& idSet)
902 {
903         const char* view_uri = attributeProperties.viewUri;
904         unsigned int property_contact_id = attributeProperties.propertyContactId;
905         unsigned int property_id = attributeProperties.propertyId;
906
907         LogDebug("entered");
908
909         int errorCode = 0;
910         contacts_query_h query = NULL;
911         contacts_list_h list = NULL;
912
913         errorCode = contacts_query_create(view_uri, &query);
914         if(errorCode != CONTACTS_ERROR_NONE)
915                 ThrowMsg(PlatformException, "contacts_query_create error : " << errorCode << " (" << __FUNCTION__ << ")");
916
917         errorCode = contacts_query_set_sort(query, property_id, is_ascending);
918         if(errorCode != CONTACTS_ERROR_NONE)
919                 ThrowMsg(PlatformException, "contacts_query_set_sort error : " << errorCode << " (" << __FUNCTION__ << ")");
920
921         errorCode = contacts_db_get_records_with_query(query, 0, 0, &list);
922         if(errorCode != CONTACTS_ERROR_NONE)
923                 ThrowMsg(PlatformException, "contacts_db_get_records_with_query error : " << errorCode << " (" << __FUNCTION__ << ")");
924
925         unsigned int record_count = 0;
926         errorCode = contacts_list_get_count(list, &record_count);
927         if(errorCode != CONTACTS_ERROR_NONE)
928                 ThrowMsg(PlatformException, "contacts_list_get_count error : " << errorCode << " (" << __FUNCTION__ << ")");
929
930         std::set<int>::iterator it;
931
932         contacts_list_first(list);
933         for(unsigned int i=0; i<record_count; i++)
934         {
935                 contacts_record_h record;
936                 errorCode = contacts_list_get_current_record_p(list, &record);
937                 if(errorCode != CONTACTS_ERROR_NONE)
938                         ThrowMsg(PlatformException, "contacts_list_get_current_record_p error : " << errorCode << " (" << __FUNCTION__ << ")");
939
940                 int value = 0;
941                 errorCode = contacts_record_get_int(record, property_contact_id, &value);
942                 if(errorCode  != CONTACTS_ERROR_NONE)
943                         ThrowMsg(PlatformException, "contacts_record_get_int error : " << errorCode << " (" << __FUNCTION__ << ")");
944
945                 it = idSet->find(value);
946                 if(it != idSet->end())
947                         result->push_back(value);
948
949                 contacts_list_next(list);
950         }
951
952         if(list != NULL)
953                 contacts_list_destroy(list, true);
954
955         if(query != NULL)
956                 contacts_query_destroy(query);
957
958         LogDebug("end");
959 }
960 #endif
961
962 void ContactSearchEngine::sortContacts(AttributeProperties& attributeProperties, ContactIdArrayPtr& result,
963                 bool is_ascending, ContactIdSetPtr& idSet)
964 {
965         const char* view_uri = attributeProperties.viewUri;
966         unsigned int property_contact_id = attributeProperties.propertyContactId;
967         unsigned int property_id = attributeProperties.propertyId;
968
969         LoggerD("entered");
970
971         int errorCode = 0;
972         contacts_query_h query = NULL;
973         contacts_filter_h filter = NULL;
974         contacts_list_h list = NULL;
975
976         errorCode = contacts_query_create(view_uri, &query);
977         if(errorCode != CONTACTS_ERROR_NONE)
978                 ThrowMsg(PlatformException, "contacts_query_create error : " << errorCode << " (" << __FUNCTION__ << ")");
979
980         errorCode = contacts_filter_create(view_uri, &filter);
981         if(errorCode != CONTACTS_ERROR_NONE)
982                 ThrowMsg(PlatformException, "contacts_filter_create error : " << errorCode << " (" << __FUNCTION__ << ")");
983
984         ContactIdSet::iterator iter = idSet->begin();
985         if(iter != idSet->end())
986         {
987                 errorCode = contacts_filter_add_int(filter, property_contact_id, CONTACTS_MATCH_EQUAL, *iter);
988                 for(; iter!=idSet->end(); iter++)
989                 {
990                         errorCode = contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_OR);
991                         if(errorCode != CONTACTS_ERROR_NONE)
992                                 ThrowMsg(PlatformException, "contacts_filter_add_operator error : " << errorCode << " (" << __FUNCTION__ << ")");
993
994                         errorCode = contacts_filter_add_int(filter, property_contact_id, CONTACTS_MATCH_EQUAL, *iter);
995                         if(errorCode != CONTACTS_ERROR_NONE)
996                                 ThrowMsg(PlatformException, "contacts_query_create error : " << errorCode << " (" << __FUNCTION__ << ")");
997                 }
998         }
999
1000         errorCode = contacts_query_set_sort(query, property_id, is_ascending);
1001         if(errorCode != CONTACTS_ERROR_NONE)
1002                 ThrowMsg(PlatformException, "contacts_query_set_sort error : " << errorCode << " (" << __FUNCTION__ << ")");
1003
1004         errorCode = contacts_query_set_filter(query, filter);
1005         if(errorCode != CONTACTS_ERROR_NONE)
1006                 ThrowMsg(PlatformException, "contacts_query_set_filter error : " << errorCode << " (" << __FUNCTION__ << ")");
1007
1008         errorCode = contacts_db_get_records_with_query(query, 0, 0, &list);
1009         if(errorCode != CONTACTS_ERROR_NONE)
1010                 ThrowMsg(PlatformException, "contacts_db_get_records_with_query error : " << errorCode << " (" << __FUNCTION__ << ")");
1011
1012         unsigned int record_count = 0;
1013         errorCode = contacts_list_get_count(list, &record_count);
1014         if(errorCode != CONTACTS_ERROR_NONE)
1015                 ThrowMsg(PlatformException, "contacts_list_get_count error : " << errorCode << " (" << __FUNCTION__ << ")");
1016
1017         ContactIdSet overlappingIds;
1018
1019         contacts_list_first(list);
1020         for(unsigned int i=0; i<record_count; i++)
1021         {
1022                 contacts_record_h record;
1023                 errorCode = contacts_list_get_current_record_p(list, &record);
1024                 if(errorCode != CONTACTS_ERROR_NONE)
1025                         ThrowMsg(PlatformException, "contacts_list_get_current_record_p error : " << errorCode << " (" << __FUNCTION__ << ")");
1026
1027                 int value = 0;
1028                 errorCode = contacts_record_get_int(record, property_contact_id, &value);
1029                 if(errorCode  != CONTACTS_ERROR_NONE)
1030                         ThrowMsg(PlatformException, "contacts_record_get_int error : " << errorCode << " (" << __FUNCTION__ << ")");
1031
1032                 if(overlappingIds.find(value) == overlappingIds.end())
1033                 {
1034                         result->push_back(value);
1035                         overlappingIds.insert(value);
1036                 }
1037
1038                 contacts_list_next(list);
1039         }
1040
1041         if(list != NULL)
1042                 contacts_list_destroy(list, true);
1043
1044         if(filter != NULL)
1045                 contacts_filter_destroy(filter);
1046
1047         if(query != NULL)
1048                 contacts_query_destroy(query);
1049
1050         LoggerD("end");
1051 }
1052
1053 void ContactSearchEngine::sortContacts(AttributeProperties& attributeProperties, ContactIdArrayPtr& result,
1054                 bool is_ascending)
1055 {
1056         const char* view_uri = attributeProperties.viewUri;
1057         unsigned int property_contact_id = attributeProperties.propertyContactId;
1058         unsigned int property_id = attributeProperties.propertyId;
1059
1060         int errorCode = 0;
1061         contacts_query_h query = NULL;
1062         contacts_list_h list = NULL;
1063
1064         errorCode = contacts_query_create(view_uri, &query);
1065         if(errorCode != CONTACTS_ERROR_NONE)
1066                 ThrowMsg(PlatformException, "contacts_query_create error : " << errorCode << " (" << __FUNCTION__ << ")");
1067
1068         errorCode = contacts_query_set_sort(query, property_id, is_ascending);
1069         if(errorCode != CONTACTS_ERROR_NONE)
1070                 ThrowMsg(PlatformException, "contacts_query_set_sort error : " << errorCode << " (" << __FUNCTION__ << ")");
1071
1072         errorCode = contacts_db_get_records_with_query(query, 0, 0, &list);
1073         if(errorCode != CONTACTS_ERROR_NONE)
1074                 ThrowMsg(PlatformException, "contacts_db_get_records_with_query error : " << errorCode << " (" << __FUNCTION__ << ")");
1075
1076         unsigned int record_count = 0;
1077         errorCode = contacts_list_get_count(list, &record_count);
1078         if(errorCode != CONTACTS_ERROR_NONE)
1079                 ThrowMsg(PlatformException, "contacts_list_get_count error : " << errorCode << " (" << __FUNCTION__ << ")");
1080
1081         ContactIdSet overlappingIds;
1082
1083         contacts_list_first(list);
1084         for(unsigned int i=0; i<record_count; i++)
1085         {
1086                 contacts_record_h record;
1087                 errorCode = contacts_list_get_current_record_p(list, &record);
1088                 if(errorCode != CONTACTS_ERROR_NONE)
1089                         ThrowMsg(PlatformException, "contacts_list_get_current_record_p error : " << errorCode << " (" << __FUNCTION__ << ")");
1090
1091                 int value = 0;
1092                 errorCode = contacts_record_get_int(record, property_contact_id, &value);
1093                 if(errorCode  != CONTACTS_ERROR_NONE)
1094                         ThrowMsg(PlatformException, "contacts_record_get_int error : " << errorCode << " (" << __FUNCTION__ << ")");
1095
1096                 if(overlappingIds.find(value) == overlappingIds.end())
1097                 {
1098                         result->push_back(value);
1099                         overlappingIds.insert(value);
1100                 }
1101
1102                 contacts_list_next(list);
1103         }
1104
1105         if(list != NULL)
1106                 contacts_list_destroy(list, true);
1107
1108         if(query != NULL)
1109                 contacts_query_destroy(query);
1110 }
1111
1112 void ContactSearchEngine::getIntersection(ContactIdSetArrayPtr& idSets, ContactIdSetPtr& result)
1113 {
1114         ContactIdSetArray::iterator i;
1115
1116         if(idSets->size() == 0)
1117         {
1118                 result = ContactIdSetPtr(NULL);
1119                 return;
1120         }
1121         else if(idSets->size() == 1)
1122         {
1123                 *result = **idSets->begin();
1124                 return;
1125         }
1126
1127         ContactIdSetArray::iterator minIter;
1128         ContactIdSetArray::size_type minSize =
1129                         numeric_limits<ContactIdSetArray::size_type>::max();
1130
1131         for(i=idSets->begin(); i!=idSets->end(); i++)
1132         {
1133                 ContactIdSetPtr idSet = *i;
1134                 ContactIdSetArray::size_type size = idSet->size();
1135                 if(minSize > size)
1136                 {
1137                         minSize = size;
1138                         minIter = i;
1139                 }
1140         }
1141
1142         ContactIdSetPtr p = *minIter;
1143         ContactIdSetArrayPtr sa = ContactIdSetArrayPtr(new ContactIdSetArray());
1144         for(i=idSets->begin(); i!=idSets->end(); i++)
1145         {
1146                 if(minIter != i)
1147                 {
1148                         sa->push_back(*i);
1149                 }
1150         }
1151
1152         ContactIdSet::iterator iter;
1153         for(iter=p->begin(); iter!=p->end(); iter++)
1154         {
1155                 bool excluded = false;
1156                 int value = *iter;
1157
1158                 for(i=sa->begin(); i!=sa->end(); i++)
1159                 {
1160                         ContactIdSetPtr idSet = *i;
1161                         if(idSet->find(value) == idSet->end())
1162                         {
1163                                 excluded = true;
1164                                 break;
1165                         }
1166                 }
1167
1168                 if(excluded == false)
1169                 {
1170                         result->insert(value);
1171                 }
1172         }
1173 }
1174
1175 void ContactSearchEngine::getUnion(ContactIdSetArrayPtr& idSets, ContactIdSetPtr& result)
1176 {
1177         ContactIdSetArray::iterator i;
1178
1179         if(idSets->size() == 0)
1180         {
1181                 result = ContactIdSetPtr(NULL);
1182                 return;
1183         }
1184         else if(idSets->size() == 1)
1185         {
1186                 *result = **idSets->begin();
1187                 return;
1188         }
1189
1190         for(i=idSets->begin(); i!=idSets->end(); i++)
1191         {
1192                 ContactIdSetPtr ids = *i;
1193                 ContactIdSet::iterator j;
1194                 for(j=ids->begin(); j!=ids->end(); j++)
1195                 {
1196                         result->insert(*j);
1197                 }
1198         }
1199 }
1200
1201 } // Contact
1202 } // DeviceAPI