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