revise packaging
[platform/core/pim/contacts-service.git] / common / ctsvc_record.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
20 #include "contacts.h"
21 #include "ctsvc_internal.h"
22 #include "ctsvc_record.h"
23 #include "ctsvc_struct.h"
24 #include "ctsvc_view.h"
25
26 extern ctsvc_record_plugin_cb_s addressbook_plugin_cbs;
27 extern ctsvc_record_plugin_cb_s group_plugin_cbs;
28 extern ctsvc_record_plugin_cb_s person_plugin_cbs;
29 extern ctsvc_record_plugin_cb_s contact_plugin_cbs;
30 extern ctsvc_record_plugin_cb_s my_profile_plugin_cbs;
31 extern ctsvc_record_plugin_cb_s simple_contact_plugin_cbs;
32 extern ctsvc_record_plugin_cb_s updated_info_plugin_cbs;
33
34 extern ctsvc_record_plugin_cb_s name_plugin_cbs;
35 extern ctsvc_record_plugin_cb_s number_plugin_cbs;
36 extern ctsvc_record_plugin_cb_s address_plugin_cbs;
37 extern ctsvc_record_plugin_cb_s url_plugin_cbs;
38 extern ctsvc_record_plugin_cb_s event_plugin_cbs;
39 extern ctsvc_record_plugin_cb_s messenger_plugin_cbs;
40 extern ctsvc_record_plugin_cb_s activity_plugin_cbs;
41 extern ctsvc_record_plugin_cb_s activity_photo_plugin_cbs;
42 extern ctsvc_record_plugin_cb_s relationship_plugin_cbs;
43 extern ctsvc_record_plugin_cb_s image_plugin_cbs;
44 extern ctsvc_record_plugin_cb_s group_relation_plugin_cbs;
45 extern ctsvc_record_plugin_cb_s note_plugin_cbs;
46 extern ctsvc_record_plugin_cb_s company_plugin_cbs;
47 extern ctsvc_record_plugin_cb_s profile_plugin_cbs;
48 extern ctsvc_record_plugin_cb_s nickname_plugin_cbs;
49 extern ctsvc_record_plugin_cb_s email_plugin_cbs;
50 extern ctsvc_record_plugin_cb_s result_plugin_cbs;
51 extern ctsvc_record_plugin_cb_s sdn_plugin_cbs;
52 extern ctsvc_record_plugin_cb_s speeddial_plugin_cbs;
53 extern ctsvc_record_plugin_cb_s extension_plugin_cbs;
54 #ifdef ENABLE_LOG_FEATURE
55 extern ctsvc_record_plugin_cb_s phonelog_plugin_cbs;
56 #endif /* ENABLE_LOG_FEATURE */
57 extern ctsvc_record_plugin_cb_s sip_plugin_cbs;
58
59 static const ctsvc_record_plugin_cb_s *__ctsvc_record_get_plugin_cb(int r_type)
60 {
61         switch ((int)r_type) {
62         case CTSVC_RECORD_ADDRESSBOOK:
63                 return &addressbook_plugin_cbs;
64         case CTSVC_RECORD_GROUP:
65                 return &group_plugin_cbs;
66         case CTSVC_RECORD_PERSON:
67                 return &person_plugin_cbs;
68         case CTSVC_RECORD_CONTACT:
69                 return &contact_plugin_cbs;
70         case CTSVC_RECORD_MY_PROFILE:
71                 return &my_profile_plugin_cbs;
72         case CTSVC_RECORD_SIMPLE_CONTACT:
73                 return &simple_contact_plugin_cbs;
74         case CTSVC_RECORD_NAME:
75                 return &name_plugin_cbs;
76         case CTSVC_RECORD_COMPANY:
77                 return &company_plugin_cbs;
78         case CTSVC_RECORD_NOTE:
79                 return &note_plugin_cbs;
80         case CTSVC_RECORD_NUMBER:
81                 return &number_plugin_cbs;
82         case CTSVC_RECORD_EMAIL:
83                 return &email_plugin_cbs;
84         case CTSVC_RECORD_URL:
85                 return &url_plugin_cbs;
86         case CTSVC_RECORD_EVENT:
87                 return &event_plugin_cbs;
88         case CTSVC_RECORD_NICKNAME:
89                 return &nickname_plugin_cbs;
90         case CTSVC_RECORD_ADDRESS:
91                 return &address_plugin_cbs;
92         case CTSVC_RECORD_MESSENGER:
93                 return &messenger_plugin_cbs;
94         case CTSVC_RECORD_GROUP_RELATION:
95                 return &group_relation_plugin_cbs;
96         case CTSVC_RECORD_ACTIVITY:
97                 return &activity_plugin_cbs;
98         case CTSVC_RECORD_ACTIVITY_PHOTO:
99                 return &activity_photo_plugin_cbs;
100         case CTSVC_RECORD_PROFILE:
101                 return &profile_plugin_cbs;
102         case CTSVC_RECORD_RELATIONSHIP:
103                 return &relationship_plugin_cbs;
104         case CTSVC_RECORD_IMAGE:
105                 return &image_plugin_cbs;
106         case CTSVC_RECORD_EXTENSION:
107                 return &extension_plugin_cbs;
108 #ifdef ENABLE_LOG_FEATURE
109         case CTSVC_RECORD_PHONELOG:
110                 return &phonelog_plugin_cbs;
111 #endif /* ENABLE_LOG_FEATURE */
112         case CTSVC_RECORD_SPEEDDIAL:
113                 return &speeddial_plugin_cbs;
114         case CTSVC_RECORD_SDN:
115                 return &sdn_plugin_cbs;
116         case CTSVC_RECORD_UPDATED_INFO:
117                 return &updated_info_plugin_cbs;
118         case CTSVC_RECORD_RESULT:
119                 return &result_plugin_cbs;
120         case CTSVC_RECORD_SIP:
121                 return &sip_plugin_cbs;
122         default:
123                 return NULL;
124         }
125 }
126
127 #define __INVALID_PARAMETER_ERROR_HANDLING() \
128         ERR("Invalid parameter: Operation restricted."); \
129 return CONTACTS_ERROR_INVALID_PARAMETER;
130
131 /*
132  * This function is used for view_uri which is able to CRUD.
133  * The view_uri's property should be sequencial value because it is used to find index at the below logic.
134  */
135 bool ctsvc_record_check_property_flag(const ctsvc_record_s *s_record, unsigned int property_id, contacts_property_flag_e flag)
136 {
137         int index = property_id & 0x000000FF;
138
139         if (CTSVC_RECORD_RESULT == s_record->r_type)
140                 return true;
141
142         /*
143          * Check it when getting value of property
144          * property_flag and properties_flags is set when getting record with query
145          */
146         if (CTSVC_PROPERTY_FLAG_PROJECTION == flag) {
147                 /* all property get. */
148                 if (NULL == s_record->properties_flags)
149                         return true;
150                 /*
151                  * Or before inserting record from DB, just get after setting.
152                  * properties_flags is not NULL when just setting dirty
153                  */
154                 if (0 == (CTSVC_PROPERTY_FLAG_PROJECTION & s_record->property_flag))
155                         return true;
156         }
157
158         /* Check it when updating record */
159         if (CTSVC_PROPERTY_FLAG_DIRTY == flag) {
160                 /* all property is clean */
161                 if (NULL == s_record->properties_flags)
162                         return false;
163         }
164         return (s_record->properties_flags[index] & flag) ? true : false;
165 }
166
167 int ctsvc_record_set_property_flag(ctsvc_record_s *_record, int property_id, contacts_property_flag_e flag)
168 {
169         int index = property_id & 0x000000FF;
170
171         if (CTSVC_RECORD_RESULT == _record->r_type)
172                 return CONTACTS_ERROR_NONE;
173
174         if (NULL == _record->properties_flags) {
175                 unsigned int count = 0;
176                 ctsvc_view_get_all_property_infos(_record->view_uri, &count);
177                 RETVM_IF(count <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "ctsvc_view_get_all_property_infos() Fail");
178
179                 _record->properties_flags = calloc(count, sizeof(char));
180                 _record->property_max_count = count;
181                 RETVM_IF(NULL == _record->properties_flags, CONTACTS_ERROR_OUT_OF_MEMORY, "calloc() Fail");
182         }
183         _record->property_flag |= flag;
184         _record->properties_flags[index] |= flag;
185
186         return CONTACTS_ERROR_NONE;
187 }
188
189 #define __CHECK_READ_ONLY_PROPERTY() \
190         if (CTSVC_READ_ONLY_CHECK(property_id, CTSVC_READ_ONLY_PROPERTY)) { \
191                 ERR("Don't try to change read-only property.(0x%0x)", property_id); \
192                 return CONTACTS_ERROR_INVALID_PARAMETER; \
193         }
194
195 #define __CHECK_PROJECTED_PROPERTY() \
196         if (false == ctsvc_record_check_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_PROJECTION)) { \
197                 ERR("Don't try to get un-projected property(0x%0x).", property_id); \
198                 return CONTACTS_ERROR_INVALID_PARAMETER; \
199         }
200
201 /* Record constuct/destruct */
202 EXPORT_API int contacts_record_create(const char *view_uri, contacts_record_h *out_record)
203 {
204         int ret;
205         ctsvc_record_type_e r_type;
206         const ctsvc_record_plugin_cb_s *plugin_cb;
207
208         RETV_IF(NULL == view_uri, CONTACTS_ERROR_INVALID_PARAMETER);
209         RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
210         *out_record = NULL;
211
212 #ifdef _CONTACTS_IPC_CLIENT
213         ctsvc_view_uri_init();
214 #endif
215
216         r_type = ctsvc_view_get_record_type(view_uri);
217         RETVM_IF(CTSVC_RECORD_INVALID == r_type, CONTACTS_ERROR_INVALID_PARAMETER,
218                         "view_uri(%s)", view_uri);
219
220         plugin_cb = __ctsvc_record_get_plugin_cb(r_type);
221         if (plugin_cb && plugin_cb->create) {
222                 ret = plugin_cb->create(out_record);
223                 if (CONTACTS_ERROR_NONE == ret)
224                         CTSVC_RECORD_INIT_BASE((ctsvc_record_s*)*out_record, r_type, plugin_cb, ctsvc_view_get_uri(view_uri));
225
226                 return ret;
227         }
228 #ifdef _CONTACTS_IPC_CLIENT
229         ctsvc_view_uri_deinit();
230 #endif
231         __INVALID_PARAMETER_ERROR_HANDLING();
232 }
233
234 EXPORT_API int contacts_record_destroy(contacts_record_h record, bool delete_child)
235 {
236         ctsvc_record_s *s_record;
237
238         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
239         s_record = (ctsvc_record_s*)record;
240
241         if (s_record && s_record->plugin_cbs && s_record->plugin_cbs->destroy) {
242 #ifdef _CONTACTS_IPC_CLIENT
243                 ctsvc_view_uri_deinit();
244 #endif
245                 return s_record->plugin_cbs->destroy(record, delete_child);
246         }
247
248         __INVALID_PARAMETER_ERROR_HANDLING();
249 }
250
251 EXPORT_API int contacts_record_clone(contacts_record_h record, contacts_record_h *out_record)
252 {
253         ctsvc_record_s *s_record;
254
255         RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
256         *out_record = NULL;
257
258         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
259         s_record = (ctsvc_record_s*)record;
260
261         if (s_record->plugin_cbs && s_record->plugin_cbs->clone) {
262 #ifdef _CONTACTS_IPC_CLIENT
263                 ctsvc_view_uri_init();
264 #endif
265                 return s_record->plugin_cbs->clone(record, out_record);
266         }
267         __INVALID_PARAMETER_ERROR_HANDLING();
268 }
269
270 EXPORT_API int contacts_record_get_uri_p(contacts_record_h record, const char **out_str)
271 {
272         int ret = CONTACTS_ERROR_NONE;
273
274         ctsvc_record_s *temp = (ctsvc_record_s*)(record);
275
276         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
277         RETV_IF(NULL == out_str, CONTACTS_ERROR_INVALID_PARAMETER);
278
279         *out_str = (temp->view_uri);
280
281         return ret;
282 }
283
284 /* Record get/set int,str, etc.. */
285 EXPORT_API int contacts_record_get_str(contacts_record_h record, unsigned int property_id, char **out_str)
286 {
287         ctsvc_record_s *s_record;
288
289         RETV_IF(NULL == out_str, CONTACTS_ERROR_INVALID_PARAMETER);
290         *out_str = NULL;
291
292         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
293         s_record = (ctsvc_record_s*)record;
294
295         __CHECK_PROJECTED_PROPERTY();
296
297         if (s_record->plugin_cbs && s_record->plugin_cbs->get_str)
298                 return s_record->plugin_cbs->get_str(record, property_id, out_str);
299
300         __INVALID_PARAMETER_ERROR_HANDLING();
301 }
302
303 EXPORT_API int contacts_record_get_lli(contacts_record_h record, unsigned int property_id, long long int *value)
304 {
305         ctsvc_record_s *s_record;
306
307         RETV_IF(NULL == value, CONTACTS_ERROR_INVALID_PARAMETER);
308         *value = 0;
309
310         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
311         s_record = (ctsvc_record_s*)record;
312
313         __CHECK_PROJECTED_PROPERTY();
314
315         if (s_record->plugin_cbs && s_record->plugin_cbs->get_lli)
316                 return s_record->plugin_cbs->get_lli(record, property_id, value);
317
318         __INVALID_PARAMETER_ERROR_HANDLING();
319 }
320
321 EXPORT_API int contacts_record_get_double(contacts_record_h record, unsigned int property_id, double *value)
322 {
323         ctsvc_record_s *s_record;
324
325         RETV_IF(NULL == value, CONTACTS_ERROR_INVALID_PARAMETER);
326         *value = 0;
327
328         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
329         s_record = (ctsvc_record_s*)record;
330
331         __CHECK_PROJECTED_PROPERTY();
332
333         if (s_record->plugin_cbs && s_record->plugin_cbs->get_double)
334                 return s_record->plugin_cbs->get_double(record, property_id, value);
335
336         __INVALID_PARAMETER_ERROR_HANDLING();
337 }
338
339 EXPORT_API int contacts_record_get_str_p(contacts_record_h record, unsigned int property_id, char **out_str)
340 {
341         ctsvc_record_s *s_record;
342
343         RETV_IF(NULL == out_str, CONTACTS_ERROR_INVALID_PARAMETER);
344         *out_str = NULL;
345
346         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
347         s_record = (ctsvc_record_s*)record;
348
349         __CHECK_PROJECTED_PROPERTY();
350
351         if (s_record->plugin_cbs && s_record->plugin_cbs->get_str_p)
352                 return s_record->plugin_cbs->get_str_p(record, property_id, out_str);
353
354         __INVALID_PARAMETER_ERROR_HANDLING();
355 }
356
357 EXPORT_API int contacts_record_get_int(contacts_record_h record, unsigned int property_id, int *out_value)
358 {
359         ctsvc_record_s *s_record;
360
361         RETV_IF(NULL == out_value, CONTACTS_ERROR_INVALID_PARAMETER);
362         *out_value = 0;
363
364         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
365         s_record = (ctsvc_record_s*)record;
366
367         __CHECK_PROJECTED_PROPERTY();
368
369         if (s_record->plugin_cbs && s_record->plugin_cbs->get_int)
370                 return s_record->plugin_cbs->get_int(record, property_id, out_value);
371
372         __INVALID_PARAMETER_ERROR_HANDLING();
373 }
374
375 EXPORT_API int contacts_record_set_str(contacts_record_h record, unsigned int property_id, const char *value)
376 {
377         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
378
379         __CHECK_READ_ONLY_PROPERTY();
380
381         return ctsvc_record_set_str(record, property_id, value);
382 }
383
384 int ctsvc_record_set_str(contacts_record_h record, unsigned int property_id, const char *value)
385 {
386         char *str;
387         ctsvc_record_s *s_record;
388         int ret;
389
390         s_record = (ctsvc_record_s*)record;
391         __CHECK_PROJECTED_PROPERTY();
392
393         if (value && *value)
394                 str = (char *)value;
395         else
396                 str = NULL;
397
398         if (s_record->plugin_cbs && s_record->plugin_cbs->set_str) {
399                 bool is_dirty = false;
400                 ret = s_record->plugin_cbs->set_str(record, property_id, str, &is_dirty);
401                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
402                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
403
404                 return ret;
405         }
406
407         __INVALID_PARAMETER_ERROR_HANDLING();
408 }
409
410 EXPORT_API int contacts_record_get_bool(contacts_record_h record,
411                 unsigned int property_id, bool *value)
412 {
413         ctsvc_record_s *s_record;
414
415         RETV_IF(NULL == value, CONTACTS_ERROR_INVALID_PARAMETER);
416         *value = false;
417
418         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
419         s_record = (ctsvc_record_s*)record;
420
421         __CHECK_PROJECTED_PROPERTY();
422
423         if (s_record->plugin_cbs && s_record->plugin_cbs->get_bool)
424                 return s_record->plugin_cbs->get_bool(record, property_id, value);
425
426         __INVALID_PARAMETER_ERROR_HANDLING();
427 }
428
429 EXPORT_API int contacts_record_set_bool(contacts_record_h record,
430                 unsigned int property_id, bool value)
431 {
432         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
433
434         __CHECK_READ_ONLY_PROPERTY();
435
436         return ctsvc_record_set_bool(record, property_id, value);
437 }
438
439 int ctsvc_record_set_bool(contacts_record_h record, unsigned int property_id, bool value)
440 {
441         int ret;
442         ctsvc_record_s *s_record;
443         s_record = (ctsvc_record_s*)record;
444         __CHECK_PROJECTED_PROPERTY();
445
446         if (s_record->plugin_cbs && s_record->plugin_cbs->set_bool) {
447                 bool is_dirty = false;
448                 ret = s_record->plugin_cbs->set_bool(record, property_id, value, &is_dirty);
449                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
450                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
451                 return ret;
452         }
453
454         __INVALID_PARAMETER_ERROR_HANDLING();
455 }
456
457 EXPORT_API int contacts_record_set_int(contacts_record_h record, unsigned int property_id,
458                 int value)
459 {
460         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
461
462         __CHECK_READ_ONLY_PROPERTY();
463
464 #ifdef _CONTACTS_IPC_CLIENT
465         if (CTSVC_RECORD_RESULT == ((ctsvc_record_s*)record)->r_type) {
466                 ERR("Can not set int to result record");
467                 return CONTACTS_ERROR_INVALID_PARAMETER;
468         }
469 #endif
470         return ctsvc_record_set_int(record, property_id, value);
471 }
472
473 int ctsvc_record_set_int(contacts_record_h record, unsigned int property_id, int value)
474 {
475         int ret;
476         ctsvc_record_s *s_record;
477         s_record = (ctsvc_record_s*)record;
478         __CHECK_PROJECTED_PROPERTY();
479
480         if (s_record->plugin_cbs && s_record->plugin_cbs->set_int) {
481                 bool is_dirty = false;
482                 ret = s_record->plugin_cbs->set_int(record, property_id, value, &is_dirty);
483                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
484                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
485                 return ret;
486         }
487         __INVALID_PARAMETER_ERROR_HANDLING();
488 }
489
490 EXPORT_API int contacts_record_set_lli(contacts_record_h record, unsigned int property_id,
491                 long long int value)
492 {
493         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
494
495         __CHECK_READ_ONLY_PROPERTY();
496
497         return ctsvc_record_set_lli(record, property_id, value);
498 }
499
500 int ctsvc_record_set_lli(contacts_record_h record, unsigned int property_id,
501                 long long int value)
502 {
503         int ret;
504         ctsvc_record_s *s_record;
505         s_record = (ctsvc_record_s*)record;
506         __CHECK_PROJECTED_PROPERTY();
507
508         if (s_record->plugin_cbs && s_record->plugin_cbs->set_lli) {
509                 bool is_dirty = false;
510                 ret = s_record->plugin_cbs->set_lli(record, property_id, value, &is_dirty);
511                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
512                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
513                 return ret;
514         }
515
516         __INVALID_PARAMETER_ERROR_HANDLING();
517 }
518
519 EXPORT_API int contacts_record_set_double(contacts_record_h record, unsigned int property_id,
520                 double value)
521 {
522         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
523
524         __CHECK_READ_ONLY_PROPERTY();
525
526         return ctsvc_record_set_double(record, property_id, value);
527 }
528
529 int ctsvc_record_set_double(contacts_record_h record, unsigned int property_id,
530                 double value)
531 {
532         int ret;
533         ctsvc_record_s *s_record;
534
535         s_record = (ctsvc_record_s*)record;
536         __CHECK_PROJECTED_PROPERTY();
537
538         if (s_record->plugin_cbs && s_record->plugin_cbs->set_double) {
539                 bool is_dirty = false;
540                 ret = s_record->plugin_cbs->set_double(record, property_id, value, &is_dirty);
541                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
542                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
543                 return ret;
544         }
545
546         __INVALID_PARAMETER_ERROR_HANDLING();
547 }
548
549 /* Record get/set child records */
550 EXPORT_API int contacts_record_add_child_record(contacts_record_h record,
551                 unsigned int property_id, contacts_record_h child_record)
552 {
553         ctsvc_record_s *s_record;
554
555         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
556         RETV_IF(NULL == child_record, CONTACTS_ERROR_INVALID_PARAMETER);
557         s_record = (ctsvc_record_s*)record;
558
559         if (s_record->plugin_cbs && s_record->plugin_cbs->add_child_record)
560                 return s_record->plugin_cbs->add_child_record(record, property_id, child_record);
561
562         __INVALID_PARAMETER_ERROR_HANDLING();
563 }
564
565 EXPORT_API int contacts_record_remove_child_record(contacts_record_h record,
566                 unsigned int property_id, contacts_record_h child_record)
567 {
568         ctsvc_record_s *s_record;
569
570         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
571         RETV_IF(NULL == child_record, CONTACTS_ERROR_INVALID_PARAMETER);
572         s_record = (ctsvc_record_s*)record;
573
574         if (s_record->plugin_cbs && s_record->plugin_cbs->remove_child_record)
575                 return s_record->plugin_cbs->remove_child_record(record, property_id, child_record);
576
577         __INVALID_PARAMETER_ERROR_HANDLING();
578 }
579
580 EXPORT_API int contacts_record_get_child_record_count(contacts_record_h record,
581                 unsigned int property_id, int *count)
582 {
583         ctsvc_record_s *s_record;
584
585         RETV_IF(NULL == count, CONTACTS_ERROR_INVALID_PARAMETER);
586         *count = 0;
587
588         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
589         s_record = (ctsvc_record_s*)record;
590
591         if (s_record->plugin_cbs && s_record->plugin_cbs->get_child_record_count)
592                 return s_record->plugin_cbs->get_child_record_count(record, property_id, count);
593
594         __INVALID_PARAMETER_ERROR_HANDLING();
595 }
596
597 EXPORT_API int contacts_record_get_child_record_at_p(contacts_record_h record,
598                 unsigned int property_id, int index, contacts_record_h *out_record)
599 {
600         ctsvc_record_s *s_record;
601
602         RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
603         *out_record = NULL;
604
605         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
606         s_record = (ctsvc_record_s*)record;
607
608         if (s_record->plugin_cbs && s_record->plugin_cbs->get_child_record_at_p)
609                 return s_record->plugin_cbs->get_child_record_at_p(record, property_id, index, out_record);
610
611         __INVALID_PARAMETER_ERROR_HANDLING();
612 }
613
614 EXPORT_API int contacts_record_clone_child_record_list(contacts_record_h record,
615                 unsigned int property_id, contacts_list_h *out_list)
616 {
617         ctsvc_record_s *s_record;
618
619         RETV_IF(NULL == out_list, CONTACTS_ERROR_INVALID_PARAMETER);
620         *out_list = NULL;
621
622         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
623         s_record = (ctsvc_record_s*)record;
624
625         if (s_record->plugin_cbs && s_record->plugin_cbs->clone_child_record_list)
626                 return s_record->plugin_cbs->clone_child_record_list(record, property_id, out_list);
627
628         __INVALID_PARAMETER_ERROR_HANDLING();
629 }
630
631 int ctsvc_record_set_projection_flags(contacts_record_h record,
632                 const unsigned int *projection,
633                 const unsigned int projection_count,
634                 const unsigned int property_max_count)
635 {
636         int i;
637
638         RETV_IF(record == NULL, CONTACTS_ERROR_INVALID_PARAMETER);
639
640         ctsvc_record_s *_record = (ctsvc_record_s*)record;
641
642         free(_record->properties_flags);
643         _record->properties_flags = NULL;
644
645         _record->properties_flags = calloc(property_max_count, sizeof(char));
646         if (NULL == _record->properties_flags) {
647                 /* LCOV_EXCL_START */
648                 ERR("calloc fail");
649                 return CONTACTS_ERROR_OUT_OF_MEMORY;
650                 /* LCOV_EXCL_STOP */
651         }
652
653         _record->property_max_count = property_max_count;
654
655         if (CTSVC_RECORD_RESULT == _record->r_type) {
656                 _record->property_flag |= CTSVC_PROPERTY_FLAG_PROJECTION;
657         } else {
658                 for (i = 0; i < projection_count; i++)
659                         ctsvc_record_set_property_flag(_record, projection[i], CTSVC_PROPERTY_FLAG_PROJECTION);
660         }
661
662         return CONTACTS_ERROR_NONE;
663 }
664