revise packaging
[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                         ERR("calloc() Fail");
109                         __ctsvc_result_destroy((contacts_record_h)out_data, true);
110                         return CONTACTS_ERROR_OUT_OF_MEMORY;
111                 }
112
113                 dest->property_id = src->property_id;
114                 dest->type = src->type;
115                 switch (src->type) {
116                 case CTSVC_VIEW_DATA_TYPE_BOOL:
117                         dest->value.b = src->value.b;
118                         break;
119                 case CTSVC_VIEW_DATA_TYPE_INT:
120                         dest->value.i = src->value.i;
121                         break;
122                 case CTSVC_VIEW_DATA_TYPE_LLI:
123                         dest->value.l = src->value.l;
124                         break;
125                 case CTSVC_VIEW_DATA_TYPE_STR:
126                         dest->value.s = SAFE_STRDUP(src->value.s);
127                         break;
128                 case CTSVC_VIEW_DATA_TYPE_DOUBLE:
129                         dest->value.d = src->value.d;
130                         break;
131                 default:
132                         break;
133                 }
134                 out_data->values = g_slist_append(out_data->values, (void*)dest);
135         }
136
137         int ret = ctsvc_record_copy_base(&(out_data->base), &(src_data->base));
138         if (CONTACTS_ERROR_NONE != ret) {
139                 ERR("ctsvc_record_copy_base() Fail");
140                 __ctsvc_result_destroy((contacts_record_h)out_data, true);
141                 return ret;
142         }
143
144         *out_record = (contacts_record_h)out_data;
145
146         return CONTACTS_ERROR_NONE;
147 }
148
149 static int __ctsvc_result_get_str_real(contacts_record_h record, unsigned int property_id,
150                 char **out_str, bool copy)
151 {
152         ctsvc_result_s *result = (ctsvc_result_s*)record;
153
154         GSList *cursor;
155
156         if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
157                 ERR("property_id is not str type.");
158                 return CONTACTS_ERROR_INVALID_PARAMETER;
159         }
160
161         for (cursor = result->values; cursor; cursor = cursor->next) {
162                 ctsvc_result_value_s *data = cursor->data;
163                 if (data->property_id == property_id) {
164                         *out_str = GET_STR(copy, data->value.s);
165                         return CONTACTS_ERROR_NONE;
166                 }
167         }
168
169         return CONTACTS_ERROR_NO_DATA;
170 }
171
172 static int __ctsvc_result_get_str_p(contacts_record_h record, unsigned int property_id, char **out_str)
173 {
174         return __ctsvc_result_get_str_real(record, property_id, out_str, false);
175 }
176
177 static int __ctsvc_result_get_str(contacts_record_h record, unsigned int property_id, char **out_str)
178 {
179         return __ctsvc_result_get_str_real(record, property_id, out_str, true);
180 }
181
182 static int __ctsvc_result_get_int(contacts_record_h record, unsigned int property_id, int *out_value)
183 {
184         ctsvc_result_s *result = (ctsvc_result_s*)record;
185
186         GSList *cursor;
187
188         if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
189                 ERR("property_id is not int type.");
190                 return CONTACTS_ERROR_INVALID_PARAMETER;
191         }
192
193         for (cursor = result->values; cursor; cursor = cursor->next) {
194                 ctsvc_result_value_s *data = cursor->data;
195                 if (data->property_id == property_id) {
196                         *out_value = data->value.i;
197                         return CONTACTS_ERROR_NONE;
198                 }
199         }
200
201         return CONTACTS_ERROR_NO_DATA;
202 }
203
204 static int __ctsvc_result_set_int(contacts_record_h record, unsigned int property_id, int value, bool *is_dirty)
205 {
206         ctsvc_result_s *result = (ctsvc_result_s*)record;
207         GSList *cursor;
208         ctsvc_result_value_s *data;
209
210         if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
211                 ERR("property_id is not int type.");
212                 return CONTACTS_ERROR_INVALID_PARAMETER;
213         }
214
215         for (cursor = result->values; cursor; cursor = cursor->next) {
216                 data = cursor->data;
217                 if (data->property_id == property_id) {
218 #ifdef _CONTACTS_IPC_SERVER
219                         if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
220                                         || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
221                                 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
222                                 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
223                         } else
224 #endif /* _CONTACTS_IPC_SERVER */
225                         {
226                                 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
227                                 data->value.i = value;
228                         }
229                         return CONTACTS_ERROR_NONE;
230                 }
231         }
232
233         data = calloc(1, sizeof(ctsvc_result_value_s));
234         if (NULL == data) {
235                 ERR("calloc() Fail");
236                 return CONTACTS_ERROR_OUT_OF_MEMORY;
237         }
238         data->property_id = property_id;
239         data->type = CTSVC_VIEW_DATA_TYPE_INT;
240 #ifdef _CONTACTS_IPC_SERVER
241         if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
242                         || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
243                 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
244                 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
245         } else
246 #endif /* _CONTACTS_IPC_SERVER */
247         {
248                 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
249                 data->value.i = value;
250         }
251         result->values = g_slist_append(result->values, (void*)data);
252         return CONTACTS_ERROR_NONE;
253 }
254
255 static int __ctsvc_result_set_bool(contacts_record_h record, unsigned int property_id, bool value, bool *is_dirty)
256 {
257         ctsvc_result_s *result = (ctsvc_result_s*)record;
258         GSList *cursor;
259         ctsvc_result_value_s *data;
260
261         /* TODO: check the value type of property_id is int */
262         for (cursor = result->values; cursor; cursor = cursor->next) {
263                 data = cursor->data;
264                 if (data->property_id == property_id) {
265                         if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
266                                 CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
267                                 data->value.b = value;
268                                 return CONTACTS_ERROR_NONE;
269                         } else {
270                                 ERR("use another get_type API, (type : %d)", data->type);
271                                 return CONTACTS_ERROR_INVALID_PARAMETER;
272                         }
273                 }
274         }
275
276         data = calloc(1, sizeof(ctsvc_result_value_s));
277         if (NULL == data) {
278                 ERR("calloc() Fail");
279                 return CONTACTS_ERROR_OUT_OF_MEMORY;
280         }
281         data->property_id = property_id;
282         data->type = CTSVC_VIEW_DATA_TYPE_BOOL;
283         CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
284         data->value.b = value;
285         result->values = g_slist_append(result->values, (void*)data);
286         return CONTACTS_ERROR_NONE;
287 }
288
289 static int __ctsvc_result_set_str(contacts_record_h record, unsigned int property_id, const char *str, bool *is_dirty)
290 {
291         ctsvc_result_s *result = (ctsvc_result_s*)record;
292         GSList *cursor;
293         ctsvc_result_value_s *data;
294         char *full_path = NULL;
295         int str_len;
296
297         if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
298                 ERR("property_id is not str type.");
299                 return CONTACTS_ERROR_INVALID_PARAMETER;
300         }
301
302         for (cursor = result->values; cursor; cursor = cursor->next) {
303                 data = cursor->data;
304                 if (data->property_id == property_id) {
305                         switch (property_id) {
306                         case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
307                         case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
308                                 if (str) {
309                                         str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
310                                         full_path = calloc(1, str_len);
311                                         if (NULL == full_path) {
312                                                 ERR("calloc() Fail");
313                                                 return CONTACTS_ERROR_OUT_OF_MEMORY;
314                                         }
315                                         snprintf(full_path, str_len, "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, str);
316                                 }
317                                 CHECK_DIRTY_STR(data->value.s, full_path, is_dirty);
318                                 free(data->value.s);
319                                 data->value.s = full_path;
320                                 return CONTACTS_ERROR_NONE;
321                         default:
322                                 CHECK_DIRTY_STR(data->value.s, str, is_dirty);
323                                 FREEandSTRDUP(data->value.s, str);
324                                 return CONTACTS_ERROR_NONE;
325                         }
326                 }
327         }
328
329         data = calloc(1, sizeof(ctsvc_result_value_s));
330         if (NULL == data) {
331                 ERR("calloc() Fail");
332                 return CONTACTS_ERROR_OUT_OF_MEMORY;
333         }
334         data->property_id = property_id;
335         data->type = CTSVC_VIEW_DATA_TYPE_STR;
336         switch (property_id) {
337         case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
338         case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
339                 if (str) {
340                         str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
341                         full_path = calloc(1, str_len);
342                         if (NULL == full_path) {
343                                 ERR("calloc() Fail");
344                                 free(data);
345                                 return CONTACTS_ERROR_OUT_OF_MEMORY;
346                         }
347                         snprintf(full_path, str_len, "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, str);
348                 }
349                 CHECK_DIRTY_STR(data->value.s, full_path, is_dirty);
350                 free(data->value.s);
351                 data->value.s = full_path;
352                 break;
353         default:
354                 CHECK_DIRTY_STR(data->value.s, str, is_dirty);
355                 data->value.s = SAFE_STRDUP(str);
356                 break;
357         }
358
359         result->values = g_slist_append(result->values, (void*)data);
360         return CONTACTS_ERROR_NONE;
361 }
362
363 static int __ctsvc_result_get_bool(contacts_record_h record, unsigned int property_id, bool *out_value)
364 {
365         ctsvc_result_s *result = (ctsvc_result_s*)record;
366         GSList *cursor;
367         for (cursor = result->values; cursor; cursor = cursor->next) {
368                 ctsvc_result_value_s *data = cursor->data;
369                 if (data->property_id == property_id) {
370                         if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
371                                 *out_value = data->value.b;
372                                 return CONTACTS_ERROR_NONE;
373                         } else {
374                                 ERR("use another get_type API, (type : %d)", data->type);
375                                 return CONTACTS_ERROR_INVALID_PARAMETER;
376                         }
377                 }
378         }
379
380         return CONTACTS_ERROR_NO_DATA;
381 }
382