Update change log and spec for wrt-plugins-tizen_0.4.50
[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_Long } },
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(matchValue == NULL || matchValue->isNullOrUndefined())
200                 matchFlag = MATCH_EXISTS;
201
202         if(depth != 0)
203         {
204                 filter = m_filterStack.top();
205         }
206         else
207         {
208                 errorCode = contacts_filter_create(_contacts_person._uri, &filter);
209                 m_filterStack.push(filter);
210                 m_filter = filter;
211         }
212
213         FilterPropertyStruct property = attrEnumMap[attrName];
214
215         if(property.type == PrimitiveType_Long)
216         {
217                 int value = 0;
218                 if(attrName == "id" || attrName == "displayContactId")
219                 {
220                         if(matchFlag != MATCH_EXISTS){
221                                 string valueStr = matchValue->getString();
222                                 value = ContactUtility::strToInt(valueStr);
223                         }
224                 }
225                 else{
226                         if(matchFlag != MATCH_EXISTS)
227                                 value = matchValue->getLong();
228                 }
229
230                 contacts_match_int_flag_e flag;
231                 if(matchFlag == MATCH_EXISTS)
232                 {
233                         flag = CONTACTS_MATCH_GREATER_THAN_OR_EQUAL;
234                         value = 0;
235                 }else if(matchFlag == MATCH_STARTSWITH || matchFlag == MATCH_CONTAINS){
236                         flag = CONTACTS_MATCH_GREATER_THAN_OR_EQUAL;
237                 }else if(matchFlag == MATCH_ENDSWITH){
238                         flag = CONTACTS_MATCH_LESS_THAN_OR_EQUAL;
239                 }else{
240                         flag = CONTACTS_MATCH_EQUAL;
241                 }
242
243                 errorCode = contacts_filter_add_int(filter, property.propertyId, flag, value);
244         }
245         else if(property.type == PrimitiveType_String)
246         {
247                 string value;
248                 if(matchFlag != MATCH_EXISTS){
249                         if(attrName == "photoURI" || attrName == "ringtoneURI")
250                                 value = ContactUtility::convertUriToPath(matchValue->getString());
251                         else
252                                 value = matchValue->getString();
253                 }else
254                         value = "";
255
256                 contacts_match_str_flag_e flag = CONTACTS_MATCH_EXISTS;
257                 if(matchFlag == MATCH_EXACTLY)
258                         flag = CONTACTS_MATCH_EXACTLY;
259                 else if(matchFlag == MATCH_FULLSTRING)
260                         flag = CONTACTS_MATCH_FULLSTRING;
261                 else if(matchFlag == MATCH_CONTAINS)
262                         flag = CONTACTS_MATCH_CONTAINS;
263                 else if(matchFlag == MATCH_STARTSWITH)
264                         flag = CONTACTS_MATCH_STARTSWITH;
265                 else if(matchFlag == MATCH_ENDSWITH)
266                         flag = CONTACTS_MATCH_ENDSWITH;
267                 else if(matchFlag == MATCH_EXISTS)
268                         flag = CONTACTS_MATCH_EXISTS;
269
270                 contacts_filter_add_str(filter, property.propertyId, flag, value.c_str());
271         }
272         else if(property.type == PrimitiveType_Boolean)
273         {
274                 bool value = true;
275                 if(matchFlag != MATCH_EXISTS)
276                         value = matchValue->getBool();
277
278                 errorCode = contacts_filter_add_bool(filter, property.propertyId, value);
279         }
280 }
281
282 void PersonSearchEngine::visitAttributeRange(string& attrName, AnyPtr& initialValue, AnyPtr& endValue, int depth)
283 {
284         int errorCode = 0;
285         contacts_filter_h filter = NULL;
286
287         if(depth != 0)
288         {
289                 filter = m_filterStack.top();
290         }
291         else
292         {
293                 errorCode = contacts_filter_create(_contacts_person._uri, &filter);
294                 m_filterStack.push(filter);
295                 m_filter = filter;
296         }
297
298         FilterPropertyStruct property = attrEnumMap[attrName];
299
300         if(property.type == PrimitiveType_Long)
301         {
302                 int initialValueInt = 0;
303                 int endValueInt = 0;
304
305                 bool initialValueExists = false;
306                 bool endValueExists = false;
307
308                 if(!initialValue->isNullOrUndefined())
309                 {
310                         if(attrName == "id")
311                         {
312                                 string valueStr = initialValue->getString();
313                                 initialValueInt = ContactUtility::strToInt(valueStr);
314                         }
315                         else
316                                 initialValueInt = initialValue->getLong();
317
318                         initialValueExists = true;
319                 }
320
321                 if(!endValue->isNullOrUndefined())
322                 {
323                         if(attrName == "id")
324                         {
325                                 string valueStr = endValue->getString();
326                                 endValueInt = ContactUtility::strToInt(valueStr);
327                         }
328                         else
329                                 endValueInt = endValue->getLong();
330
331                         endValueExists = true;
332                 }
333
334
335                 if(initialValueExists && endValueExists)
336                 {
337                         contacts_filter_h sub_filter = NULL;
338                         if(depth != 0)
339                         {
340                                 errorCode = contacts_filter_create(_contacts_person._uri, &sub_filter);
341                         }
342                         else
343                         {
344                                 sub_filter = filter;
345                         }
346
347                         errorCode = contacts_filter_add_int(sub_filter, property.propertyId,
348                                         CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initialValueInt);
349
350                         contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
351
352                         errorCode = contacts_filter_add_int(sub_filter, property.propertyId,
353                                         CONTACTS_MATCH_LESS_THAN_OR_EQUAL, endValueInt);
354
355                         if(depth != 0)
356                         {
357                                 errorCode = contacts_filter_add_filter(filter, sub_filter);
358                         }
359                 }
360                 else if(initialValueExists)
361                 {
362                         errorCode = contacts_filter_add_int(filter, property.propertyId,
363                                         CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initialValueInt);
364                 }
365                 else if(endValueExists)
366                 {
367                         errorCode = contacts_filter_add_int(filter, property.propertyId,
368                                         CONTACTS_MATCH_LESS_THAN_OR_EQUAL, endValueInt);
369                 }
370         }
371         else if(property.type == PrimitiveType_String)
372         {
373                 string initialValueStr = 0;
374                 string endValueStr = 0;
375
376                 bool initialValueExists = false;
377                 bool endValueExists = false;
378
379                 if(!initialValue->isNullOrUndefined())
380                 {
381                         initialValueStr = initialValue->getLong();
382                         initialValueExists = true;
383                 }
384
385                 if(!endValue->isNullOrUndefined())
386                 {
387                         endValueStr = endValue->getLong();
388                         endValueExists = true;
389                 }
390
391
392                 if(initialValueExists && endValueExists)
393                 {
394                         contacts_filter_h sub_filter = NULL;
395                         if(depth != 0)
396                         {
397                                 errorCode = contacts_filter_create(_contacts_person._uri, &sub_filter);
398                         }
399                         else
400                         {
401                                 sub_filter = filter;
402                         }
403
404                         errorCode = contacts_filter_add_str(sub_filter, property.propertyId,
405                                         CONTACTS_MATCH_STARTSWITH, initialValueStr.c_str());
406
407                         contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
408
409                         errorCode = contacts_filter_add_str(sub_filter, property.propertyId,
410                                         CONTACTS_MATCH_ENDSWITH, endValueStr.c_str());
411
412                         if(depth != 0)
413                         {
414                                 errorCode = contacts_filter_add_filter(filter, sub_filter);
415                         }
416                 }
417                 else if(initialValueExists)
418                 {
419                         errorCode = contacts_filter_add_str(filter, property.propertyId,
420                                         CONTACTS_MATCH_STARTSWITH, initialValueStr.c_str());
421                 }
422                 else if(endValueExists)
423                 {
424                         errorCode = contacts_filter_add_str(filter, property.propertyId,
425                                         CONTACTS_MATCH_ENDSWITH, endValueStr.c_str());
426                 }
427         }
428         else if(property.type == PrimitiveType_Boolean)
429         {
430                 bool initialValueBool = 0;
431                 bool endValueBool = 0;
432
433                 bool initialValueExists = false;
434                 bool endValueExists = false;
435
436                 if(!initialValue->isNullOrUndefined())
437                 {
438                         initialValueBool = initialValue->getBool();
439                         initialValueExists = true;
440                 }
441
442                 if(!endValue->isNullOrUndefined())
443                 {
444                         endValueBool = endValue->getBool();
445                         endValueExists = true;
446                 }
447
448
449                 if(initialValueExists && endValueExists)
450                 {
451                         if(initialValueBool == endValueBool)
452                         {
453                                 if(initialValueBool == true)
454                                         errorCode = contacts_filter_add_bool(filter, property.propertyId, true);
455                                 else if(endValueBool == false)
456                                         errorCode = contacts_filter_add_bool(filter, property.propertyId, false);
457                         }
458                 }
459                 else if(initialValueExists)
460                 {
461                         if(initialValueBool == true)
462                                 errorCode = contacts_filter_add_bool(filter, property.propertyId, true);
463                 }
464                 else if(endValueExists)
465                 {
466                         if(endValueBool == false)
467                                 errorCode = contacts_filter_add_bool(filter, property.propertyId, false);
468                 }
469         }
470 }
471
472 } // Contact
473 } // DeviceAPI