Rearrange contacts-service.service from default.target to delayed.target
[platform/core/pim/contacts-service.git] / common / ctsvc_filter.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <glib.h>
20
21 #include "contacts.h"
22 #include "ctsvc_internal.h"
23 #include "ctsvc_filter.h"
24
25 static inline bool _filter_property_check(const property_info_s *properties,
26                 int count, unsigned int property_id, int *type)
27 {
28         int i;
29         for (i = 0; i < count; i++) {
30                 property_info_s *p = (property_info_s*)&(properties[i]);
31                 if (property_id == p->property_id) {
32                         if (p->property_type == CTSVC_SEARCH_PROPERTY_ALL
33                                         || p->property_type == CTSVC_SEARCH_PROPERTY_FILTER) {
34                                 *type = (property_id & CTSVC_VIEW_DATA_TYPE_MASK);
35                                 return true;
36                         } else {
37                                 return false;
38                         }
39                 }
40         }
41         return false;
42 }
43
44 EXPORT_API int contacts_filter_create(const char *view_uri, contacts_filter_h *out_filter)
45 {
46         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
47         ctsvc_composite_filter_s *com_filter;
48
49         RETV_IF(NULL == out_filter, CONTACTS_ERROR_INVALID_PARAMETER);
50         *out_filter = NULL;
51
52         RETV_IF(NULL == view_uri, CONTACTS_ERROR_INVALID_PARAMETER);
53
54         com_filter = calloc(1, sizeof(ctsvc_composite_filter_s));
55         RETV_IF(NULL == com_filter, CONTACTS_ERROR_OUT_OF_MEMORY);
56
57 #ifdef _CONTACTS_IPC_CLIENT
58         ctsvc_view_uri_init();
59 #endif
60
61         com_filter->filter_type = CTSVC_FILTER_COMPOSITE;
62         com_filter->view_uri = strdup(view_uri);
63         com_filter->properties = (property_info_s*)ctsvc_view_get_all_property_infos(view_uri,
64                         &com_filter->property_count);
65         *out_filter = (contacts_filter_h)com_filter;
66         return CONTACTS_ERROR_NONE;
67 }
68
69 EXPORT_API int contacts_filter_add_operator(contacts_filter_h filter,
70                 contacts_filter_operator_e op)
71 {
72         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
73         ctsvc_composite_filter_s *com_filter;
74
75         RETV_IF(NULL == filter, CONTACTS_ERROR_INVALID_PARAMETER);
76
77         com_filter = (ctsvc_composite_filter_s*)filter;
78         RETVM_IF(g_slist_length(com_filter->filter_ops) != (g_slist_length(com_filter->filters)-1),
79                         CONTACTS_ERROR_INVALID_PARAMETER, "Please check the operator of filter");
80
81         com_filter->filter_ops = g_slist_append(com_filter->filter_ops, (void*)op);
82
83         return CONTACTS_ERROR_NONE;
84 }
85
86 EXPORT_API int contacts_filter_add_filter(contacts_filter_h filter1, contacts_filter_h filter2)
87 {
88         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
89         int ret;
90         ctsvc_composite_filter_s *s_filter1;
91         ctsvc_composite_filter_s *s_filter2;
92         contacts_filter_h new_filter;
93
94         RETV_IF(NULL == filter1 || NULL == filter2, CONTACTS_ERROR_INVALID_PARAMETER);
95         s_filter1 = (ctsvc_composite_filter_s*)filter1;
96         s_filter2 = (ctsvc_composite_filter_s*)filter2;
97
98         RETVM_IF(g_slist_length(s_filter1->filter_ops) != (g_slist_length(s_filter1->filters)),
99                         CONTACTS_ERROR_INVALID_PARAMETER, "Please check the operator of filter");
100         RETVM_IF(STRING_EQUAL != strcmp(s_filter1->view_uri, s_filter2->view_uri),
101                         CONTACTS_ERROR_INVALID_PARAMETER,
102                         "The filter view_uri is different (filter1:%s, filter2:%s)",
103                         s_filter1->view_uri, s_filter2->view_uri);
104
105         ret = ctsvc_filter_clone(filter2, &new_filter);
106         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_filter_clone is Fail(%d)", ret);
107         s_filter1->filters = g_slist_append(s_filter1->filters, new_filter);
108
109         return CONTACTS_ERROR_NONE;
110 }
111
112 static int _filter_create_attribute(ctsvc_composite_filter_s *com_filter,
113                 unsigned int property_id,
114                 int match,
115                 int filter_type,
116                 ctsvc_attribute_filter_s **out_filter)
117 {
118         ctsvc_attribute_filter_s *filter;
119         int type;
120         bool find = false;
121
122         RETVM_IF(g_slist_length(com_filter->filter_ops) != g_slist_length(com_filter->filters),
123                         CONTACTS_ERROR_INVALID_PARAMETER, "Please check the operator of filter");
124
125         find = _filter_property_check(com_filter->properties, com_filter->property_count, property_id, &type);
126         RETVM_IF(false == find, CONTACTS_ERROR_INVALID_PARAMETER,
127                         "property_id(%d) is not supported on view_uri(%s)", property_id, com_filter->view_uri);
128
129         if (type == CTSVC_VIEW_DATA_TYPE_INT && CTSVC_FILTER_INT != filter_type) {
130                 /* LCOV_EXCL_START */
131         ERR("use contacts_filter_add_int() (%d)", filter_type);
132                 return CONTACTS_ERROR_INVALID_PARAMETER;
133                 /* LCOV_EXCL_STOP */
134         }
135
136         if (type == CTSVC_VIEW_DATA_TYPE_STR && CTSVC_FILTER_STR != filter_type) {
137                 /* LCOV_EXCL_START */
138         ERR("use contacts_filter_add_str() (%d)", filter_type);
139                 return CONTACTS_ERROR_INVALID_PARAMETER;
140                 /* LCOV_EXCL_STOP */
141         }
142
143         if (type == CTSVC_VIEW_DATA_TYPE_BOOL && CTSVC_FILTER_BOOL != filter_type) {
144                 /* LCOV_EXCL_START */
145         ERR("use contacts_filter_add_bool() (%d)", filter_type);
146                 return CONTACTS_ERROR_INVALID_PARAMETER;
147                 /* LCOV_EXCL_STOP */
148         }
149
150         if (type == CTSVC_VIEW_DATA_TYPE_LLI && CTSVC_FILTER_LLI != filter_type) {
151                 /* LCOV_EXCL_START */
152         ERR("use contacts_filter_add_lli() (%d)", filter_type);
153                 return CONTACTS_ERROR_INVALID_PARAMETER;
154                 /* LCOV_EXCL_STOP */
155         }
156
157         if (type == CTSVC_VIEW_DATA_TYPE_DOUBLE && CTSVC_FILTER_DOUBLE != filter_type) {
158                 /* LCOV_EXCL_START */
159         ERR("use contacts_filter_add_double() (%d)", filter_type);
160                 return CONTACTS_ERROR_INVALID_PARAMETER;
161                 /* LCOV_EXCL_STOP */
162         }
163
164         filter = calloc(1, sizeof(ctsvc_attribute_filter_s));
165         if (NULL == filter) {
166                 /* LCOV_EXCL_START */
167                 ERR("calloc() Fail");
168                 return CONTACTS_ERROR_OUT_OF_MEMORY;
169                 /* LCOV_EXCL_STOP */
170         }
171         filter->filter_type = filter_type;
172         filter->property_id = property_id;
173         filter->match = match;
174
175         com_filter->filters = g_slist_append(com_filter->filters, filter);
176         *out_filter = filter;
177         return CONTACTS_ERROR_NONE;
178 }
179
180 EXPORT_API int contacts_filter_add_str(contacts_filter_h filter, unsigned int property_id,
181                 contacts_match_str_flag_e match, const char *match_value)
182 {
183         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
184         ctsvc_composite_filter_s *com_filter;
185         ctsvc_attribute_filter_s *str_filter;
186         int ret;
187
188         RETV_IF(NULL == filter || NULL == match_value, CONTACTS_ERROR_INVALID_PARAMETER);
189
190         com_filter = (ctsvc_composite_filter_s*)filter;
191         ret = _filter_create_attribute(com_filter, property_id, match,
192                         CTSVC_FILTER_STR, &str_filter);
193         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret,
194                         "The parameter is not proper (view_uri:%s, property_id:0x%x, match:%d)",
195                         com_filter->view_uri, property_id, match);
196
197         str_filter->value.s = SAFE_STRDUP(match_value);
198         return CONTACTS_ERROR_NONE;
199 }
200
201 EXPORT_API int contacts_filter_add_int(contacts_filter_h filter, unsigned int property_id,
202                 contacts_match_int_flag_e match, int match_value)
203 {
204         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
205         ctsvc_composite_filter_s *com_filter;
206         ctsvc_attribute_filter_s *int_filter;
207         int ret;
208
209         RETV_IF(NULL == filter, CONTACTS_ERROR_INVALID_PARAMETER);
210         RETVM_IF((CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
211                                         || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id)
212                         && (CONTACTS_MATCH_GREATER_THAN <= match
213                                         && match <= CONTACTS_MATCH_LESS_THAN_OR_EQUAL),
214                         CONTACTS_ERROR_INVALID_PARAMETER, "Not support this condition");
215
216         com_filter = (ctsvc_composite_filter_s*)filter;
217         ret = _filter_create_attribute(com_filter, property_id, match,
218                         CTSVC_FILTER_INT, &int_filter);
219         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret,
220                         "The parameter is not proper (view_uri:%s, property_id:0x%x, match:%d)",
221                         com_filter->view_uri, property_id, match);
222
223         int_filter->value.i = match_value;
224
225         return CONTACTS_ERROR_NONE;
226 }
227
228 EXPORT_API int contacts_filter_add_lli(contacts_filter_h filter, unsigned int property_id,
229                 contacts_match_int_flag_e match, long long int match_value)
230 {
231         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
232         ctsvc_composite_filter_s *com_filter;
233         ctsvc_attribute_filter_s *lli_filter;
234         int ret;
235
236         RETV_IF(NULL == filter, CONTACTS_ERROR_INVALID_PARAMETER);
237
238         com_filter = (ctsvc_composite_filter_s*)filter;
239         ret = _filter_create_attribute(com_filter, property_id, match,
240                         CTSVC_FILTER_LLI, &lli_filter);
241         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret,
242                         "The parameter is not proper (view_uri:, property_id:0x%x, match:%d)",
243                         property_id, match);
244
245         lli_filter->value.l = match_value;
246
247         return CONTACTS_ERROR_NONE;
248 }
249
250 EXPORT_API int contacts_filter_add_double(contacts_filter_h filter, unsigned int property_id,
251                 contacts_match_int_flag_e match, double match_value)
252 {
253         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
254         ctsvc_composite_filter_s *com_filter;
255         ctsvc_attribute_filter_s *double_filter;
256         int ret;
257
258         RETV_IF(NULL == filter, CONTACTS_ERROR_INVALID_PARAMETER);
259
260         com_filter = (ctsvc_composite_filter_s*)filter;
261         ret = _filter_create_attribute(com_filter, property_id, match,
262                         CTSVC_FILTER_DOUBLE, &double_filter);
263         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret,
264                         "The parameter is not proper (view_uri:, property_id:0x%x, match:%d)",
265                         property_id, match);
266
267         double_filter->value.d = match_value;
268
269         return CONTACTS_ERROR_NONE;
270 }
271
272 EXPORT_API int contacts_filter_add_bool(contacts_filter_h filter, unsigned int property_id,
273                 bool match_value)
274 {
275         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
276         ctsvc_composite_filter_s *com_filter;
277         ctsvc_attribute_filter_s *bool_filter;
278         int ret;
279
280         RETV_IF(NULL == filter, CONTACTS_ERROR_INVALID_PARAMETER);
281
282         com_filter = (ctsvc_composite_filter_s*)filter;
283         ret = _filter_create_attribute(com_filter, property_id, 0, CTSVC_FILTER_BOOL,
284                         &bool_filter);
285         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret,
286                         "The parameter is not proper (view_uri:, property_id:%d)",
287                         property_id);
288
289         bool_filter->value.b = match_value;
290
291         return CONTACTS_ERROR_NONE;
292 }
293
294 static int __ctsvc_composite_filter_destroy(ctsvc_composite_filter_s *com_filter)
295 {
296         CTS_FN_CALL;
297         GSList *cursor;
298
299         RETV_IF(NULL == com_filter, CONTACTS_ERROR_INVALID_PARAMETER);
300
301         for (cursor = com_filter->filters; cursor; cursor = cursor->next) {
302                 ctsvc_filter_s *sub_filter = cursor->data;
303
304                 if (sub_filter->filter_type == CTSVC_FILTER_COMPOSITE) {
305                         __ctsvc_composite_filter_destroy((ctsvc_composite_filter_s*)sub_filter);
306                 } else {
307                         ctsvc_attribute_filter_s *attr = (ctsvc_attribute_filter_s*)sub_filter;
308                         if (attr->filter_type == CTSVC_FILTER_STR)
309                                 free(attr->value.s);
310                         free(attr);
311                 }
312         }
313         g_slist_free(com_filter->filters);
314         g_slist_free(com_filter->filter_ops);
315
316         free(com_filter->view_uri);
317
318         free(com_filter);
319         return CONTACTS_ERROR_NONE;
320 }
321
322
323 EXPORT_API int contacts_filter_destroy(contacts_filter_h filter)
324 {
325         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
326         RETV_IF(NULL == filter, CONTACTS_ERROR_INVALID_PARAMETER);
327 #ifdef _CONTACTS_IPC_CLIENT
328         ctsvc_view_uri_deinit();
329 #endif
330         return __ctsvc_composite_filter_destroy((ctsvc_composite_filter_s*)filter);
331 }
332
333 static int __ctsvc_attribute_filter_clone(ctsvc_attribute_filter_s *src,
334                 ctsvc_attribute_filter_s **dest)
335 {
336         ctsvc_attribute_filter_s *out;
337         out = calloc(1, sizeof(ctsvc_attribute_filter_s));
338         if (NULL == out) {
339                 /* LCOV_EXCL_START */
340         ERR("calloc() Fail");
341                 return CONTACTS_ERROR_OUT_OF_MEMORY;
342                 /* LCOV_EXCL_STOP */
343         }
344         out->filter_type = src->filter_type;
345         out->property_id = src->property_id;
346         out->match = src->match;
347         if (src->filter_type == CTSVC_FILTER_STR)
348                 out->value.s = SAFE_STRDUP(src->value.s);
349         else if (src->filter_type == CTSVC_FILTER_INT)
350                 out->value.i = src->value.i;
351         else if (src->filter_type == CTSVC_FILTER_BOOL)
352                 out->value.b = src->value.b;
353         else if (src->filter_type == CTSVC_FILTER_LLI)
354                 out->value.l = src->value.l;
355         else if (src->filter_type == CTSVC_FILTER_DOUBLE)
356                 out->value.d = src->value.d;
357         else
358                 ERR("unknown type (%d)", src->filter_type);
359
360         *dest = out;
361         return CONTACTS_ERROR_NONE;
362 }
363
364 static int __ctsvc_composite_filter_clone(ctsvc_composite_filter_s * filter,
365                 ctsvc_composite_filter_s **out_filter)
366 {
367         GSList *cursor;
368         ctsvc_composite_filter_s *out;
369
370         RETV_IF(NULL == filter, CONTACTS_ERROR_INVALID_PARAMETER);
371         contacts_filter_create(filter->view_uri, (contacts_filter_h*)&out);
372
373         for (cursor = filter->filters; cursor; cursor = cursor->next) {
374                 ctsvc_filter_s *src = cursor->data;
375                 ctsvc_filter_s *dest = NULL;
376
377                 if (src->filter_type == CTSVC_FILTER_COMPOSITE) {
378                         __ctsvc_composite_filter_clone((ctsvc_composite_filter_s*)src,
379                                         (ctsvc_composite_filter_s **)&dest);
380                 } else {
381                         __ctsvc_attribute_filter_clone((ctsvc_attribute_filter_s*)src,
382                                         (ctsvc_attribute_filter_s **)&dest);
383                 }
384
385                 out->filters = g_slist_append(out->filters, dest);
386         }
387
388         out->filter_ops = g_slist_copy(filter->filter_ops);
389         *out_filter = out;
390
391         return CONTACTS_ERROR_NONE;
392 }
393
394 int ctsvc_filter_clone(contacts_filter_h filter, contacts_filter_h *out_filter)
395 {
396         RETV_IF(NULL == filter || NULL == out_filter, CONTACTS_ERROR_INVALID_PARAMETER);
397
398         return __ctsvc_composite_filter_clone((ctsvc_composite_filter_s*)filter,
399                         (ctsvc_composite_filter_s **)out_filter);
400 }