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