301ba47eb51ffad322eb30890813de15cd35a037
[platform/core/pim/contacts-service.git] / common / ctsvc_record_result.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 "contacts.h"
20
21 #include "ctsvc_internal.h"
22 #include "ctsvc_record.h"
23 #include "ctsvc_view.h"
24 #include "ctsvc_notify.h"
25
26 #ifdef _CONTACTS_IPC_SERVER
27 #include "ctsvc_server_sim.h"
28 #endif /* _CONTACTS_IPC_SERVER */
29
30 static int __ctsvc_result_create(contacts_record_h *out_record);
31 static int __ctsvc_result_destroy(contacts_record_h record, bool delete_child);
32 static int __ctsvc_result_clone(contacts_record_h record, contacts_record_h *out_record);
33 static int __ctsvc_result_get_str_p(contacts_record_h record, unsigned int property_id, char **out_str);
34 static int __ctsvc_result_get_str(contacts_record_h record, unsigned int property_id, char **out_str);
35 static int __ctsvc_result_get_int(contacts_record_h record, unsigned int property_id, int *out_value);
36 static int __ctsvc_result_get_bool(contacts_record_h record, unsigned int property_id, bool *out_value);
37 static int __ctsvc_result_set_int(contacts_record_h record, unsigned int property_id, int value, bool *is_dirty);
38 static int __ctsvc_result_set_bool(contacts_record_h record, unsigned int property_id, bool value, bool *is_dirty);
39 static int __ctsvc_result_set_str(contacts_record_h record, unsigned int property_id, const char *str, bool *is_dirty);
40
41 ctsvc_record_plugin_cb_s result_plugin_cbs = {
42         .create = __ctsvc_result_create,
43         .destroy = __ctsvc_result_destroy,
44         .clone = __ctsvc_result_clone,
45         .get_str = __ctsvc_result_get_str,
46         .get_str_p = __ctsvc_result_get_str_p,
47         .get_int = __ctsvc_result_get_int,
48         .get_bool = __ctsvc_result_get_bool,
49         .get_lli = NULL,
50         .get_double = NULL,
51         .set_str = __ctsvc_result_set_str,
52         .set_int = __ctsvc_result_set_int,
53         .set_bool = __ctsvc_result_set_bool,
54         .set_lli = NULL,
55         .set_double = NULL,
56         .add_child_record = NULL,
57         .remove_child_record = NULL,
58         .get_child_record_count = NULL,
59         .get_child_record_at_p = NULL,
60         .clone_child_record_list = NULL,
61 };
62
63 static int __ctsvc_result_create(contacts_record_h *out_record)
64 {
65         ctsvc_result_s *result;
66         result = calloc(1, sizeof(ctsvc_result_s));
67         RETVM_IF(NULL == result, CONTACTS_ERROR_OUT_OF_MEMORY, "calloc() Fail");
68
69         *out_record = (contacts_record_h)result;
70         return CONTACTS_ERROR_NONE;
71 }
72
73 static int __ctsvc_result_destroy(contacts_record_h record, bool delete_child)
74 {
75         GSList *cursor;
76         ctsvc_result_s *result = (ctsvc_result_s*)record;
77
78         for (cursor = result->values; cursor; cursor = cursor->next) {
79                 ctsvc_result_value_s *data = cursor->data;
80                 if (data->type == CTSVC_VIEW_DATA_TYPE_STR)
81                         free(data->value.s);
82                 free(data);
83         }
84         g_slist_free(result->values);
85         result->base.plugin_cbs = NULL; /* help to find double destroy bug (refer to the contacts_record_destroy) */
86         free(result->base.properties_flags);
87
88         free(result);
89
90         return CONTACTS_ERROR_NONE;
91 }
92
93 static int __ctsvc_result_clone(contacts_record_h record, contacts_record_h *out_record)
94 {
95         ctsvc_result_s *out_data = NULL;
96         ctsvc_result_s *src_data = NULL;
97         GSList *cursor;
98
99         src_data = (ctsvc_result_s*)record;
100         out_data = calloc(1, sizeof(ctsvc_result_s));
101         RETVM_IF(NULL == out_data, CONTACTS_ERROR_OUT_OF_MEMORY,
102                         "Out of memeory : calloc(ctsvc_result_s) Fail(%d)", CONTACTS_ERROR_OUT_OF_MEMORY);
103
104         for (cursor = src_data->values; cursor; cursor = cursor->next) {
105                 ctsvc_result_value_s *src = cursor->data;
106                 ctsvc_result_value_s *dest = calloc(1, sizeof(ctsvc_result_value_s));
107                 if (NULL == dest) {
108                         /* LCOV_EXCL_START */
109                         ERR("calloc() Fail");
110                         __ctsvc_result_destroy((contacts_record_h)out_data, true);
111                         return CONTACTS_ERROR_OUT_OF_MEMORY;
112                         /* LCOV_EXCL_STOP */
113                 }
114
115 /* LCOV_EXCL_START */
116                 dest->property_id = src->property_id;
117                 dest->type = src->type;
118                 switch (src->type) {
119                 case CTSVC_VIEW_DATA_TYPE_BOOL:
120                         dest->value.b = src->value.b;
121                         break;
122                 case CTSVC_VIEW_DATA_TYPE_INT:
123                         dest->value.i = src->value.i;
124                         break;
125                 case CTSVC_VIEW_DATA_TYPE_LLI:
126                         dest->value.l = src->value.l;
127                         break;
128                 case CTSVC_VIEW_DATA_TYPE_STR:
129                         dest->value.s = SAFE_STRDUP(src->value.s);
130                         break;
131                 case CTSVC_VIEW_DATA_TYPE_DOUBLE:
132                         dest->value.d = src->value.d;
133                         break;
134                 default:
135                         break;
136                 }
137                 out_data->values = g_slist_append(out_data->values, (void*)dest);
138         }
139 /* LCOV_EXCL_STOP */
140
141         int ret = ctsvc_record_copy_base(&(out_data->base), &(src_data->base));
142         if (CONTACTS_ERROR_NONE != ret) {
143                 /* LCOV_EXCL_START */
144                 ERR("ctsvc_record_copy_base() Fail");
145                 __ctsvc_result_destroy((contacts_record_h)out_data, true);
146                 return ret;
147                 /* LCOV_EXCL_STOP */
148         }
149
150         *out_record = (contacts_record_h)out_data;
151
152         return CONTACTS_ERROR_NONE;
153 }
154
155 /* LCOV_EXCL_START */
156 static int __ctsvc_result_get_str_real(contacts_record_h record, unsigned int property_id,
157                 char **out_str, bool copy)
158 {
159         ctsvc_result_s *result = (ctsvc_result_s*)record;
160
161         GSList *cursor;
162
163         if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
164                 ERR("property_id is not str type.");
165                 return CONTACTS_ERROR_INVALID_PARAMETER;
166         }
167
168         for (cursor = result->values; cursor; cursor = cursor->next) {
169                 ctsvc_result_value_s *data = cursor->data;
170                 if (data->property_id == property_id) {
171                         *out_str = GET_STR(copy, data->value.s);
172                         return CONTACTS_ERROR_NONE;
173                 }
174         }
175
176         return CONTACTS_ERROR_NO_DATA;
177 }
178
179 static int __ctsvc_result_get_str_p(contacts_record_h record, unsigned int property_id, char **out_str)
180 {
181         return __ctsvc_result_get_str_real(record, property_id, out_str, false);
182 }
183
184 static int __ctsvc_result_get_str(contacts_record_h record, unsigned int property_id, char **out_str)
185 {
186         return __ctsvc_result_get_str_real(record, property_id, out_str, true);
187 }
188
189 static int __ctsvc_result_get_int(contacts_record_h record, unsigned int property_id, int *out_value)
190 {
191         ctsvc_result_s *result = (ctsvc_result_s*)record;
192
193         GSList *cursor;
194
195         if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
196                 ERR("property_id is not int type.");
197                 return CONTACTS_ERROR_INVALID_PARAMETER;
198         }
199
200         for (cursor = result->values; cursor; cursor = cursor->next) {
201                 ctsvc_result_value_s *data = cursor->data;
202                 if (data->property_id == property_id) {
203                         *out_value = data->value.i;
204                         return CONTACTS_ERROR_NONE;
205                 }
206         }
207
208         return CONTACTS_ERROR_NO_DATA;
209 }
210 /* LCOV_EXCL_STOP */
211
212 static int __ctsvc_result_set_int(contacts_record_h record, unsigned int property_id, int value, bool *is_dirty)
213 {
214         ctsvc_result_s *result = (ctsvc_result_s*)record;
215         GSList *cursor;
216         ctsvc_result_value_s *data;
217
218         if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
219                 ERR("property_id is not int type.");
220                 return CONTACTS_ERROR_INVALID_PARAMETER;
221         }
222
223         for (cursor = result->values; cursor; cursor = cursor->next) {
224                 data = cursor->data;
225                 if (data->property_id == property_id) {
226 #ifdef _CONTACTS_IPC_SERVER
227                         if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
228                                         || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
229                                 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
230                                 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
231                         } else
232 #endif /* _CONTACTS_IPC_SERVER */
233                         {
234                                 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
235                                 data->value.i = value;
236                         }
237                         return CONTACTS_ERROR_NONE;
238                 }
239         }
240
241         data = calloc(1, sizeof(ctsvc_result_value_s));
242         if (NULL == data) {
243                 /* LCOV_EXCL_START */
244                 ERR("calloc() Fail");
245                 return CONTACTS_ERROR_OUT_OF_MEMORY;
246                 /* LCOV_EXCL_STOP */
247         }
248         data->property_id = property_id;
249         data->type = CTSVC_VIEW_DATA_TYPE_INT;
250 #ifdef _CONTACTS_IPC_SERVER
251         if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
252                         || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
253                 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
254                 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
255         } else
256 #endif /* _CONTACTS_IPC_SERVER */
257         {
258                 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
259                 data->value.i = value;
260         }
261         result->values = g_slist_append(result->values, (void*)data);
262         return CONTACTS_ERROR_NONE;
263 }
264
265 /* LCOV_EXCL_START */
266 static int __ctsvc_result_set_bool(contacts_record_h record, unsigned int property_id, bool value, bool *is_dirty)
267 {
268         ctsvc_result_s *result = (ctsvc_result_s*)record;
269         GSList *cursor;
270         ctsvc_result_value_s *data;
271
272         /* TODO: check the value type of property_id is int */
273         for (cursor = result->values; cursor; cursor = cursor->next) {
274                 data = cursor->data;
275                 if (data->property_id == property_id) {
276                         if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
277                                 CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
278                                 data->value.b = value;
279                                 return CONTACTS_ERROR_NONE;
280                         } else {
281                                 /* LCOV_EXCL_START */
282                                 ERR("use another get_type API, (type : %d)", data->type);
283                                 return CONTACTS_ERROR_INVALID_PARAMETER;
284                                 /* LCOV_EXCL_STOP */
285                         }
286                 }
287         }
288
289         data = calloc(1, sizeof(ctsvc_result_value_s));
290         if (NULL == data) {
291                 /* LCOV_EXCL_START */
292                 ERR("calloc() Fail");
293                 return CONTACTS_ERROR_OUT_OF_MEMORY;
294                 /* LCOV_EXCL_STOP */
295         }
296         data->property_id = property_id;
297         data->type = CTSVC_VIEW_DATA_TYPE_BOOL;
298         CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
299         data->value.b = value;
300         result->values = g_slist_append(result->values, (void*)data);
301         return CONTACTS_ERROR_NONE;
302 }
303
304 static int __ctsvc_result_set_str(contacts_record_h record, unsigned int property_id, const char *str, bool *is_dirty)
305 {
306         ctsvc_result_s *result = (ctsvc_result_s*)record;
307         GSList *cursor;
308         ctsvc_result_value_s *data;
309         char *full_path = NULL;
310         int str_len;
311
312         if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
313                 ERR("property_id is not str type.");
314                 return CONTACTS_ERROR_INVALID_PARAMETER;
315         }
316
317         for (cursor = result->values; cursor; cursor = cursor->next) {
318                 data = cursor->data;
319                 if (data->property_id == property_id) {
320                         switch (property_id) {
321                         case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
322                         case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
323                                 if (str) {
324                                         str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
325                                         full_path = calloc(1, str_len);
326                                         if (NULL == full_path) {
327                                                 /* LCOV_EXCL_START */
328                                                 ERR("calloc() Fail");
329                                                 return CONTACTS_ERROR_OUT_OF_MEMORY;
330                                                 /* LCOV_EXCL_STOP */
331                                         }
332                                         snprintf(full_path, str_len, "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, str);
333                                 }
334                                 CHECK_DIRTY_STR(data->value.s, full_path, is_dirty);
335                                 free(data->value.s);
336                                 data->value.s = full_path;
337                                 return CONTACTS_ERROR_NONE;
338                         default:
339                                 CHECK_DIRTY_STR(data->value.s, str, is_dirty);
340                                 FREEandSTRDUP(data->value.s, str);
341                                 return CONTACTS_ERROR_NONE;
342                         }
343                 }
344         }
345
346         data = calloc(1, sizeof(ctsvc_result_value_s));
347         if (NULL == data) {
348                 /* LCOV_EXCL_START */
349                 ERR("calloc() Fail");
350                 return CONTACTS_ERROR_OUT_OF_MEMORY;
351                 /* LCOV_EXCL_STOP */
352         }
353         data->property_id = property_id;
354         data->type = CTSVC_VIEW_DATA_TYPE_STR;
355         switch (property_id) {
356         case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
357         case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
358                 if (str) {
359                         str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
360                         full_path = calloc(1, str_len);
361                         if (NULL == full_path) {
362                                 /* LCOV_EXCL_START */
363                                 ERR("calloc() Fail");
364                                 free(data);
365                                 return CONTACTS_ERROR_OUT_OF_MEMORY;
366                                 /* LCOV_EXCL_STOP */
367                         }
368                         snprintf(full_path, str_len, "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, str);
369                 }
370                 CHECK_DIRTY_STR(data->value.s, full_path, is_dirty);
371                 free(data->value.s);
372                 data->value.s = full_path;
373                 break;
374         default:
375                 CHECK_DIRTY_STR(data->value.s, str, is_dirty);
376                 data->value.s = SAFE_STRDUP(str);
377                 break;
378         }
379
380         result->values = g_slist_append(result->values, (void*)data);
381         return CONTACTS_ERROR_NONE;
382 }
383
384 static int __ctsvc_result_get_bool(contacts_record_h record, unsigned int property_id, bool *out_value)
385 {
386         ctsvc_result_s *result = (ctsvc_result_s*)record;
387         GSList *cursor;
388         for (cursor = result->values; cursor; cursor = cursor->next) {
389                 ctsvc_result_value_s *data = cursor->data;
390                 if (data->property_id == property_id) {
391                         if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
392                                 *out_value = data->value.b;
393                                 return CONTACTS_ERROR_NONE;
394                         } else {
395                                 /* LCOV_EXCL_START */
396                                 ERR("use another get_type API, (type : %d)", data->type);
397                                 return CONTACTS_ERROR_INVALID_PARAMETER;
398                                 /* LCOV_EXCL_STOP */
399                         }
400                 }
401         }
402
403         return CONTACTS_ERROR_NO_DATA;
404 }
405 /* LCOV_EXCL_STOP */