wrt-plugins-tizen_0.4.23
[framework/web/wrt-plugins-tizen.git] / src / Contact / PersonSearchEngine.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        PersonSearchEngine.cpp
20  * @author      Kisub Song (kisubs.song@samsung.com)
21  * @version     0.1
22  * @brief
23  */
24
25 #include "PersonSearchEngine.h"
26
27 #include <ctime>
28 #include <algorithm>
29 #include <Commons/Exception.h>
30 #include "Person.h"
31 #include "ContactUtility.h"
32 #include "ContactsSvcObjectConverter.h"
33 #include <Logger.h>
34
35 namespace DeviceAPI {
36 namespace Contact {
37
38 using namespace WrtDeviceApis::Commons;
39 using namespace DeviceAPI::Tizen;
40 using namespace std;
41
42 map<string, PersonSearchEngine::FilterPropertyStruct> PersonSearchEngine::attrEnumMap = {
43                 {"id",                                          { _contacts_person.id,                  PrimitiveType_Long } },
44                 {"displayName",                         { _contacts_person.display_name,        PrimitiveType_String } },
45                 {"contactCount",                        { _contacts_person.link_count,          PrimitiveType_Long } },
46                 {"hasPhoneNumber",                      { _contacts_person.has_phonenumber,     PrimitiveType_Boolean } },
47                 {"hasEmail",                            { _contacts_person.has_email,           PrimitiveType_Boolean } },
48                 {"isFavorite",                          { _contacts_person.is_favorite,         PrimitiveType_Boolean } },
49                 {"photoURI",                            { _contacts_person.image_thumbnail_path,PrimitiveType_String } },
50                 {"ringtoneURI",                         { _contacts_person.ringtone_path,       PrimitiveType_String } },
51                 {"displayContactId",            { _contacts_person.display_contact_id,  PrimitiveType_String } },
52 };
53
54 PersonSearchEngine::PersonSearchEngine() :
55                 m_query(NULL),
56                 m_filter(NULL)
57 {
58         contacts_query_create(_contacts_person._uri, &m_query);
59 }
60
61 PersonSearchEngine::~PersonSearchEngine()
62 {
63         if(m_filter != NULL)
64                 contacts_filter_destroy(m_filter);
65
66         if(m_query != NULL)
67                 contacts_query_destroy(m_query);
68 }
69
70 void PersonSearchEngine::setCondition(FilterPtr filter)
71 {
72         if(!filter)
73                 return;
74
75         IFilterVisitorPtr filterQuery = DPL::StaticPointerCast<IFilterVisitor>(SharedFromThis());
76         filter->travel(filterQuery);
77
78         contacts_query_set_filter(m_query, m_filter);
79 }
80
81 void PersonSearchEngine::setSortMode(SortModePtr attr)
82 {
83         if(attr == NULL)
84                 return;
85
86         string attrName = attr->getAttributeName();
87
88         map<string, PersonSearchEngine::FilterPropertyStruct>::iterator iter = attrEnumMap.find(attrName);
89         if(iter == attrEnumMap.end())
90         {
91                 ThrowMsg(InvalidArgumentException, "SortMode don't support " << attrName);
92         }
93
94         FilterPropertyStruct property = iter->second;
95
96         bool is_ascending;
97         if(attr->getOrder() == ASCENDING_SORT_ORDER)
98                 is_ascending = true;
99         else
100                 is_ascending = false;
101
102         contacts_query_set_sort(m_query, property.propertyId, is_ascending);
103 }
104
105 PersonArrayPtr PersonSearchEngine::getResult()
106 {
107         int errorCode = 0;
108         contacts_list_h person_list = NULL;
109
110         PersonArrayPtr persons = PersonArrayPtr(new PersonArray());
111
112         errorCode = contacts_db_get_records_with_query(m_query, 0, 0, &person_list);
113         if(errorCode != CONTACTS_ERROR_NONE)
114                 ThrowMsg(PlatformException, "Fail to get contacts_db_get_records_with_query (ret:" << errorCode << ")");
115
116         unsigned int record_count = 0;
117         errorCode = contacts_list_get_count(person_list, &record_count);
118         if(errorCode != CONTACTS_ERROR_NONE)
119                 ThrowMsg(PlatformException, "Fail to get contacts_list_get_count (ret:" << errorCode << ")");
120
121         contacts_list_first(person_list);
122         for(unsigned int i=0; i<record_count; i++)
123         {
124                 contacts_record_h contacts_record;
125                 errorCode = contacts_list_get_current_record_p(person_list, &contacts_record);
126                 if(errorCode != CONTACTS_ERROR_NONE || contacts_record == NULL)
127                 {
128                         LoggerW("Fail to get group record (ret:" << errorCode << ")");
129                         continue;
130                 }
131
132                 PersonPtr person = PersonPtr(new Person());
133
134                 ContactsSvcObjectConverter::convertToAbstract(contacts_record, person);
135
136                 persons->push_back(person);
137
138                 contacts_list_next(person_list);
139         }
140
141         if(person_list != NULL)
142                 contacts_list_destroy(person_list, true);
143
144         return persons;
145 }
146
147 void PersonSearchEngine::visitPreComposite(FilterType& type, int depth)
148 {
149         int errorCode = 0;
150         contacts_filter_h filter = NULL;
151
152         errorCode = contacts_filter_create(_contacts_person._uri, &filter);
153
154         m_filterStack.push(filter);
155         if(depth == 0)
156         {
157                 m_filter = filter;
158         }
159 }
160
161 void PersonSearchEngine::visitInComposite(FilterType& type, int depth)
162 {
163         int errorCode = 0;
164
165         contacts_filter_h filter = NULL;
166         contacts_filter_operator_e operator_type = CONTACTS_FILTER_OPERATOR_OR;
167
168         filter = m_filterStack.top();
169
170         if(type == UNION_FILTER)
171                 operator_type = CONTACTS_FILTER_OPERATOR_OR;
172         else if(type == INTERSECTION_FILTER)
173                 operator_type = CONTACTS_FILTER_OPERATOR_AND;
174
175         errorCode = contacts_filter_add_operator(filter, operator_type);
176 }
177
178 void PersonSearchEngine::visitPostComposite(FilterType& type, int depth)
179 {
180         int errorCode = 0;
181         contacts_filter_h filter = NULL;
182
183         filter = m_filterStack.top();
184         m_filterStack.pop();
185
186         if(depth != 0)
187         {
188                 contacts_filter_h parent_filter = NULL;
189                 parent_filter = m_filterStack.top();
190                 errorCode = contacts_filter_add_filter(parent_filter, filter);
191         }
192 }
193
194 void PersonSearchEngine::visitAttribute(string& attrName, MatchFlag& matchFlag, AnyPtr& matchValue, int depth)
195 {
196         int errorCode = 0;
197         contacts_filter_h filter = NULL;
198
199         if(depth != 0)
200         {
201                 filter = m_filterStack.top();
202         }
203         else
204         {
205                 errorCode = contacts_filter_create(_contacts_person._uri, &filter);
206                 m_filterStack.push(filter);
207                 m_filter = filter;
208         }
209
210         FilterPropertyStruct property = attrEnumMap[attrName];
211
212         if(property.type == PrimitiveType_Long)
213         {
214                 int value = 0;
215                 if(attrName == "id")
216                 {
217                         string valueStr = matchValue->getString();
218                         value = ContactUtility::strToInt(valueStr);
219                 }
220                 else
221                         value = matchValue->getLong();
222
223                 contacts_match_int_flag_e flag;
224                 if(matchFlag == MATCH_EXISTS)
225                         flag = CONTACTS_MATCH_NONE;
226                 else
227                         flag = CONTACTS_MATCH_EQUAL;
228
229                 errorCode = contacts_filter_add_int(filter, property.propertyId, flag, value);
230         }
231         else if(property.type == PrimitiveType_String)
232         {
233                 string value = matchValue->getString();
234
235                 contacts_match_str_flag_e flag = CONTACTS_MATCH_EXISTS;
236                 if(matchFlag == MATCH_EXACTLY)
237                         flag = CONTACTS_MATCH_EXACTLY;
238                 else if(matchFlag == MATCH_FULLSTRING)
239                         flag = CONTACTS_MATCH_FULLSTRING;
240                 else if(matchFlag == MATCH_CONTAINS)
241                         flag = CONTACTS_MATCH_CONTAINS;
242                 else if(matchFlag == MATCH_STARTSWITH)
243                         flag = CONTACTS_MATCH_STARTSWITH;
244                 else if(matchFlag == MATCH_ENDSWITH)
245                         flag = CONTACTS_MATCH_ENDSWITH;
246                 else if(matchFlag == MATCH_EXISTS)
247                         flag = CONTACTS_MATCH_EXISTS;
248
249                 contacts_filter_add_str(filter, property.propertyId, flag, value.c_str());
250         }
251         else if(property.type == PrimitiveType_Boolean)
252         {
253                 bool value = false;
254                 value = matchValue->getBool();
255
256                 // TODO MATCH_EXISTS
257 //              if(matchFlag == MATCH_EXISTS)
258 //              else
259
260                 errorCode = contacts_filter_add_bool(filter, property.propertyId, value);
261         }
262 }
263
264 void PersonSearchEngine::visitAttributeRange(string& attrName, AnyPtr& initialValue, AnyPtr& endValue, int depth)
265 {
266         int errorCode = 0;
267         contacts_filter_h filter = NULL;
268
269         if(depth != 0)
270         {
271                 filter = m_filterStack.top();
272         }
273         else
274         {
275                 errorCode = contacts_filter_create(_contacts_person._uri, &filter);
276                 m_filterStack.push(filter);
277                 m_filter = filter;
278         }
279
280         FilterPropertyStruct property = attrEnumMap[attrName];
281
282         if(property.type == PrimitiveType_Long)
283         {
284                 int initialValueInt = 0;
285                 int endValueInt = 0;
286
287                 bool initialValueExists = false;
288                 bool endValueExists = false;
289
290                 if(!initialValue->isNullOrUndefined())
291                 {
292                         if(attrName == "id")
293                         {
294                                 string valueStr = initialValue->getString();
295                                 initialValueInt = ContactUtility::strToInt(valueStr);
296                         }
297                         else
298                                 initialValueInt = initialValue->getLong();
299
300                         initialValueExists = true;
301                 }
302
303                 if(!endValue->isNullOrUndefined())
304                 {
305                         if(attrName == "id")
306                         {
307                                 string valueStr = endValue->getString();
308                                 endValueInt = ContactUtility::strToInt(valueStr);
309                         }
310                         else
311                                 endValueInt = endValue->getLong();
312
313                         endValueExists = true;
314                 }
315
316
317                 if(initialValueExists && endValueExists)
318                 {
319                         contacts_filter_h sub_filter = NULL;
320                         if(depth != 0)
321                         {
322                                 errorCode = contacts_filter_create(_contacts_person._uri, &sub_filter);
323                         }
324                         else
325                         {
326                                 sub_filter = filter;
327                         }
328
329                         errorCode = contacts_filter_add_int(sub_filter, property.propertyId,
330                                         CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initialValueInt);
331
332                         contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
333
334                         errorCode = contacts_filter_add_int(sub_filter, property.propertyId,
335                                         CONTACTS_MATCH_LESS_THAN_OR_EQUAL, endValueInt);
336
337                         if(depth != 0)
338                         {
339                                 errorCode = contacts_filter_add_filter(filter, sub_filter);
340                         }
341                 }
342                 else if(initialValueExists)
343                 {
344                         errorCode = contacts_filter_add_int(filter, property.propertyId,
345                                         CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initialValueInt);
346                 }
347                 else if(endValueExists)
348                 {
349                         errorCode = contacts_filter_add_int(filter, property.propertyId,
350                                         CONTACTS_MATCH_LESS_THAN_OR_EQUAL, endValueInt);
351                 }
352         }
353         else if(property.type == PrimitiveType_String)
354         {
355                 string initialValueStr = 0;
356                 string endValueStr = 0;
357
358                 bool initialValueExists = false;
359                 bool endValueExists = false;
360
361                 if(!initialValue->isNullOrUndefined())
362                 {
363                         initialValueStr = initialValue->getLong();
364                         initialValueExists = true;
365                 }
366
367                 if(!endValue->isNullOrUndefined())
368                 {
369                         endValueStr = endValue->getLong();
370                         endValueExists = true;
371                 }
372
373
374                 if(initialValueExists && endValueExists)
375                 {
376                         contacts_filter_h sub_filter = NULL;
377                         if(depth != 0)
378                         {
379                                 errorCode = contacts_filter_create(_contacts_person._uri, &sub_filter);
380                         }
381                         else
382                         {
383                                 sub_filter = filter;
384                         }
385
386                         errorCode = contacts_filter_add_str(sub_filter, property.propertyId,
387                                         CONTACTS_MATCH_STARTSWITH, initialValueStr.c_str());
388
389                         contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
390
391                         errorCode = contacts_filter_add_str(sub_filter, property.propertyId,
392                                         CONTACTS_MATCH_ENDSWITH, endValueStr.c_str());
393
394                         if(depth != 0)
395                         {
396                                 errorCode = contacts_filter_add_filter(filter, sub_filter);
397                         }
398                 }
399                 else if(initialValueExists)
400                 {
401                         errorCode = contacts_filter_add_str(filter, property.propertyId,
402                                         CONTACTS_MATCH_STARTSWITH, initialValueStr.c_str());
403                 }
404                 else if(endValueExists)
405                 {
406                         errorCode = contacts_filter_add_str(filter, property.propertyId,
407                                         CONTACTS_MATCH_ENDSWITH, endValueStr.c_str());
408                 }
409         }
410         else if(property.type == PrimitiveType_Boolean)
411         {
412                 bool initialValueBool = 0;
413                 bool endValueBool = 0;
414
415                 bool initialValueExists = false;
416                 bool endValueExists = false;
417
418                 if(!initialValue->isNullOrUndefined())
419                 {
420                         initialValueBool = initialValue->getBool();
421                         initialValueExists = true;
422                 }
423
424                 if(!endValue->isNullOrUndefined())
425                 {
426                         endValueBool = endValue->getBool();
427                         endValueExists = true;
428                 }
429
430
431                 if(initialValueExists && endValueExists)
432                 {
433                         if(initialValueBool == endValueBool)
434                         {
435                                 if(initialValueBool == true)
436                                         errorCode = contacts_filter_add_bool(filter, property.propertyId, true);
437                                 else if(endValueBool == false)
438                                         errorCode = contacts_filter_add_bool(filter, property.propertyId, false);
439                         }
440                 }
441                 else if(initialValueExists)
442                 {
443                         if(initialValueBool == true)
444                                 errorCode = contacts_filter_add_bool(filter, property.propertyId, true);
445                 }
446                 else if(endValueExists)
447                 {
448                         if(endValueBool == false)
449                                 errorCode = contacts_filter_add_bool(filter, property.propertyId, false);
450                 }
451         }
452 }
453
454 } // Contact
455 } // DeviceAPI