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