change the path of socket & inotify file
[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         r_type = ctsvc_view_get_record_type(view_uri);
213         RETVM_IF(CTSVC_RECORD_INVALID == r_type, CONTACTS_ERROR_INVALID_PARAMETER,
214                         "view_uri(%s)", view_uri);
215
216         plugin_cb = __ctsvc_record_get_plugin_cb(r_type);
217         if (plugin_cb && plugin_cb->create) {
218                 ret = plugin_cb->create(out_record);
219                 if (CONTACTS_ERROR_NONE == ret)
220                         CTSVC_RECORD_INIT_BASE((ctsvc_record_s*)*out_record, r_type, plugin_cb, ctsvc_view_get_uri(view_uri));
221
222                 return ret;
223         }
224
225         __INVALID_PARAMETER_ERROR_HANDLING();
226 }
227
228 EXPORT_API int contacts_record_destroy(contacts_record_h record, bool delete_child)
229 {
230         ctsvc_record_s *s_record;
231
232         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
233         s_record = (ctsvc_record_s*)record;
234
235         if (s_record && s_record->plugin_cbs && s_record->plugin_cbs->destroy)
236                 return s_record->plugin_cbs->destroy(record, delete_child);
237
238         __INVALID_PARAMETER_ERROR_HANDLING();
239 }
240
241 EXPORT_API int contacts_record_clone(contacts_record_h record, contacts_record_h *out_record)
242 {
243         ctsvc_record_s *s_record;
244
245         RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
246         *out_record = NULL;
247
248         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
249         s_record = (ctsvc_record_s*)record;
250
251         if (s_record->plugin_cbs && s_record->plugin_cbs->clone)
252                 return s_record->plugin_cbs->clone(record, out_record);
253
254         __INVALID_PARAMETER_ERROR_HANDLING();
255 }
256
257 EXPORT_API int contacts_record_get_uri_p(contacts_record_h record, const char **out_str)
258 {
259         int ret = CONTACTS_ERROR_NONE;
260
261         ctsvc_record_s *temp = (ctsvc_record_s*)(record);
262
263         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
264         RETV_IF(NULL == out_str, CONTACTS_ERROR_INVALID_PARAMETER);
265
266         *out_str = (temp->view_uri);
267
268         return ret;
269 }
270
271 /* Record get/set int,str, etc.. */
272 EXPORT_API int contacts_record_get_str(contacts_record_h record, unsigned int property_id, char **out_str)
273 {
274         ctsvc_record_s *s_record;
275
276         RETV_IF(NULL == out_str, CONTACTS_ERROR_INVALID_PARAMETER);
277         *out_str = NULL;
278
279         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
280         s_record = (ctsvc_record_s*)record;
281
282         __CHECK_PROJECTED_PROPERTY();
283
284         if (s_record->plugin_cbs && s_record->plugin_cbs->get_str)
285                 return s_record->plugin_cbs->get_str(record, property_id, out_str);
286
287         __INVALID_PARAMETER_ERROR_HANDLING();
288 }
289
290 EXPORT_API int contacts_record_get_lli(contacts_record_h record, unsigned int property_id, long long int *value)
291 {
292         ctsvc_record_s *s_record;
293
294         RETV_IF(NULL == value, CONTACTS_ERROR_INVALID_PARAMETER);
295         *value = 0;
296
297         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
298         s_record = (ctsvc_record_s*)record;
299
300         __CHECK_PROJECTED_PROPERTY();
301
302         if (s_record->plugin_cbs && s_record->plugin_cbs->get_lli)
303                 return s_record->plugin_cbs->get_lli(record, property_id, value);
304
305         __INVALID_PARAMETER_ERROR_HANDLING();
306 }
307
308 EXPORT_API int contacts_record_get_double(contacts_record_h record, unsigned int property_id, double *value)
309 {
310         ctsvc_record_s *s_record;
311
312         RETV_IF(NULL == value, CONTACTS_ERROR_INVALID_PARAMETER);
313         *value = 0;
314
315         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
316         s_record = (ctsvc_record_s*)record;
317
318         __CHECK_PROJECTED_PROPERTY();
319
320         if (s_record->plugin_cbs && s_record->plugin_cbs->get_double)
321                 return s_record->plugin_cbs->get_double(record, property_id, value);
322
323         __INVALID_PARAMETER_ERROR_HANDLING();
324 }
325
326 EXPORT_API int contacts_record_get_str_p(contacts_record_h record, unsigned int property_id, char **out_str)
327 {
328         ctsvc_record_s *s_record;
329
330         RETV_IF(NULL == out_str, CONTACTS_ERROR_INVALID_PARAMETER);
331         *out_str = NULL;
332
333         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
334         s_record = (ctsvc_record_s*)record;
335
336         __CHECK_PROJECTED_PROPERTY();
337
338         if (s_record->plugin_cbs && s_record->plugin_cbs->get_str_p)
339                 return s_record->plugin_cbs->get_str_p(record, property_id, out_str);
340
341         __INVALID_PARAMETER_ERROR_HANDLING();
342 }
343
344 EXPORT_API int contacts_record_get_int(contacts_record_h record, unsigned int property_id, int *out_value)
345 {
346         ctsvc_record_s *s_record;
347
348         RETV_IF(NULL == out_value, CONTACTS_ERROR_INVALID_PARAMETER);
349         *out_value = 0;
350
351         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
352         s_record = (ctsvc_record_s*)record;
353
354         __CHECK_PROJECTED_PROPERTY();
355
356         if (s_record->plugin_cbs && s_record->plugin_cbs->get_int)
357                 return s_record->plugin_cbs->get_int(record, property_id, out_value);
358
359         __INVALID_PARAMETER_ERROR_HANDLING();
360 }
361
362 EXPORT_API int contacts_record_set_str(contacts_record_h record, unsigned int property_id, const char *value)
363 {
364         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
365
366         __CHECK_READ_ONLY_PROPERTY();
367
368         return ctsvc_record_set_str(record, property_id, value);
369 }
370
371 int ctsvc_record_set_str(contacts_record_h record, unsigned int property_id, const char *value)
372 {
373         char *str;
374         ctsvc_record_s *s_record;
375         int ret;
376
377         s_record = (ctsvc_record_s*)record;
378         __CHECK_PROJECTED_PROPERTY();
379
380         if (value && *value)
381                 str = (char *)value;
382         else
383                 str = NULL;
384
385         if (s_record->plugin_cbs && s_record->plugin_cbs->set_str) {
386                 bool is_dirty = false;
387                 ret = s_record->plugin_cbs->set_str(record, property_id, str, &is_dirty);
388                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
389                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
390
391                 return ret;
392         }
393
394         __INVALID_PARAMETER_ERROR_HANDLING();
395 }
396
397 EXPORT_API int contacts_record_get_bool(contacts_record_h record,
398                 unsigned int property_id, bool *value)
399 {
400         ctsvc_record_s *s_record;
401
402         RETV_IF(NULL == value, CONTACTS_ERROR_INVALID_PARAMETER);
403         *value = false;
404
405         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
406         s_record = (ctsvc_record_s*)record;
407
408         __CHECK_PROJECTED_PROPERTY();
409
410         if (s_record->plugin_cbs && s_record->plugin_cbs->get_bool)
411                 return s_record->plugin_cbs->get_bool(record, property_id, value);
412
413         __INVALID_PARAMETER_ERROR_HANDLING();
414 }
415
416 EXPORT_API int contacts_record_set_bool(contacts_record_h record,
417                 unsigned int property_id, bool value)
418 {
419         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
420
421         __CHECK_READ_ONLY_PROPERTY();
422
423         return ctsvc_record_set_bool(record, property_id, value);
424 }
425
426 int ctsvc_record_set_bool(contacts_record_h record, unsigned int property_id, bool value)
427 {
428         int ret;
429         ctsvc_record_s *s_record;
430         s_record = (ctsvc_record_s*)record;
431         __CHECK_PROJECTED_PROPERTY();
432
433         if (s_record->plugin_cbs && s_record->plugin_cbs->set_bool) {
434                 bool is_dirty = false;
435                 ret = s_record->plugin_cbs->set_bool(record, property_id, value, &is_dirty);
436                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
437                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
438                 return ret;
439         }
440
441         __INVALID_PARAMETER_ERROR_HANDLING();
442 }
443
444 EXPORT_API int contacts_record_set_int(contacts_record_h record, unsigned int property_id,
445                 int value)
446 {
447         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
448
449         __CHECK_READ_ONLY_PROPERTY();
450
451 #ifdef _CONTACTS_IPC_CLIENT
452         if (CTSVC_RECORD_RESULT == ((ctsvc_record_s*)record)->r_type) {
453                 ERR("Can not set int to result record");
454                 return CONTACTS_ERROR_INVALID_PARAMETER;
455         }
456 #endif
457         return ctsvc_record_set_int(record, property_id, value);
458 }
459
460 int ctsvc_record_set_int(contacts_record_h record, unsigned int property_id, int value)
461 {
462         int ret;
463         ctsvc_record_s *s_record;
464         s_record = (ctsvc_record_s*)record;
465         __CHECK_PROJECTED_PROPERTY();
466
467         if (s_record->plugin_cbs && s_record->plugin_cbs->set_int) {
468                 bool is_dirty = false;
469                 ret = s_record->plugin_cbs->set_int(record, property_id, value, &is_dirty);
470                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
471                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
472                 return ret;
473         }
474         __INVALID_PARAMETER_ERROR_HANDLING();
475 }
476
477 EXPORT_API int contacts_record_set_lli(contacts_record_h record, unsigned int property_id,
478                 long long int value)
479 {
480         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
481
482         __CHECK_READ_ONLY_PROPERTY();
483
484         return ctsvc_record_set_lli(record, property_id, value);
485 }
486
487 int ctsvc_record_set_lli(contacts_record_h record, unsigned int property_id,
488                 long long int value)
489 {
490         int ret;
491         ctsvc_record_s *s_record;
492         s_record = (ctsvc_record_s*)record;
493         __CHECK_PROJECTED_PROPERTY();
494
495         if (s_record->plugin_cbs && s_record->plugin_cbs->set_lli) {
496                 bool is_dirty = false;
497                 ret = s_record->plugin_cbs->set_lli(record, property_id, value, &is_dirty);
498                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
499                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
500                 return ret;
501         }
502
503         __INVALID_PARAMETER_ERROR_HANDLING();
504 }
505
506 EXPORT_API int contacts_record_set_double(contacts_record_h record, unsigned int property_id,
507                 double value)
508 {
509         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
510
511         __CHECK_READ_ONLY_PROPERTY();
512
513         return ctsvc_record_set_double(record, property_id, value);
514 }
515
516 int ctsvc_record_set_double(contacts_record_h record, unsigned int property_id,
517                 double value)
518 {
519         int ret;
520         ctsvc_record_s *s_record;
521
522         s_record = (ctsvc_record_s*)record;
523         __CHECK_PROJECTED_PROPERTY();
524
525         if (s_record->plugin_cbs && s_record->plugin_cbs->set_double) {
526                 bool is_dirty = false;
527                 ret = s_record->plugin_cbs->set_double(record, property_id, value, &is_dirty);
528                 if (CONTACTS_ERROR_NONE == ret && is_dirty)
529                         ctsvc_record_set_property_flag(s_record, property_id, CTSVC_PROPERTY_FLAG_DIRTY);
530                 return ret;
531         }
532
533         __INVALID_PARAMETER_ERROR_HANDLING();
534 }
535
536 /* Record get/set child records */
537 EXPORT_API int contacts_record_add_child_record(contacts_record_h record,
538                 unsigned int property_id, contacts_record_h child_record)
539 {
540         ctsvc_record_s *s_record;
541
542         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
543         RETV_IF(NULL == child_record, CONTACTS_ERROR_INVALID_PARAMETER);
544         s_record = (ctsvc_record_s*)record;
545
546         if (s_record->plugin_cbs && s_record->plugin_cbs->add_child_record)
547                 return s_record->plugin_cbs->add_child_record(record, property_id, child_record);
548
549         __INVALID_PARAMETER_ERROR_HANDLING();
550 }
551
552 EXPORT_API int contacts_record_remove_child_record(contacts_record_h record,
553                 unsigned int property_id, contacts_record_h child_record)
554 {
555         ctsvc_record_s *s_record;
556
557         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
558         RETV_IF(NULL == child_record, CONTACTS_ERROR_INVALID_PARAMETER);
559         s_record = (ctsvc_record_s*)record;
560
561         if (s_record->plugin_cbs && s_record->plugin_cbs->remove_child_record)
562                 return s_record->plugin_cbs->remove_child_record(record, property_id, child_record);
563
564         __INVALID_PARAMETER_ERROR_HANDLING();
565 }
566
567 EXPORT_API int contacts_record_get_child_record_count(contacts_record_h record,
568                 unsigned int property_id, int *count)
569 {
570         ctsvc_record_s *s_record;
571
572         RETV_IF(NULL == count, CONTACTS_ERROR_INVALID_PARAMETER);
573         *count = 0;
574
575         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
576         s_record = (ctsvc_record_s*)record;
577
578         if (s_record->plugin_cbs && s_record->plugin_cbs->get_child_record_count)
579                 return s_record->plugin_cbs->get_child_record_count(record, property_id, count);
580
581         __INVALID_PARAMETER_ERROR_HANDLING();
582 }
583
584 EXPORT_API int contacts_record_get_child_record_at_p(contacts_record_h record,
585                 unsigned int property_id, int index, contacts_record_h *out_record)
586 {
587         ctsvc_record_s *s_record;
588
589         RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
590         *out_record = NULL;
591
592         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
593         s_record = (ctsvc_record_s*)record;
594
595         if (s_record->plugin_cbs && s_record->plugin_cbs->get_child_record_at_p)
596                 return s_record->plugin_cbs->get_child_record_at_p(record, property_id, index, out_record);
597
598         __INVALID_PARAMETER_ERROR_HANDLING();
599 }
600
601 EXPORT_API int contacts_record_clone_child_record_list(contacts_record_h record,
602                 unsigned int property_id, contacts_list_h *out_list)
603 {
604         ctsvc_record_s *s_record;
605
606         RETV_IF(NULL == out_list, CONTACTS_ERROR_INVALID_PARAMETER);
607         *out_list = NULL;
608
609         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
610         s_record = (ctsvc_record_s*)record;
611
612         if (s_record->plugin_cbs && s_record->plugin_cbs->clone_child_record_list)
613                 return s_record->plugin_cbs->clone_child_record_list(record, property_id, out_list);
614
615         __INVALID_PARAMETER_ERROR_HANDLING();
616 }
617
618 int ctsvc_record_set_projection_flags(contacts_record_h record,
619                 const unsigned int *projection,
620                 const unsigned int projection_count,
621                 const unsigned int property_max_count)
622 {
623         int i;
624
625         RETV_IF(record == NULL, CONTACTS_ERROR_INVALID_PARAMETER);
626
627         ctsvc_record_s *_record = (ctsvc_record_s*)record;
628
629         free(_record->properties_flags);
630         _record->properties_flags = NULL;
631
632         _record->properties_flags = calloc(property_max_count, sizeof(char));
633         if (NULL == _record->properties_flags) {
634                 /* LCOV_EXCL_START */
635                 ERR("calloc fail");
636                 return CONTACTS_ERROR_OUT_OF_MEMORY;
637                 /* LCOV_EXCL_STOP */
638         }
639
640         _record->property_max_count = property_max_count;
641
642         if (CTSVC_RECORD_RESULT == _record->r_type) {
643                 _record->property_flag |= CTSVC_PROPERTY_FLAG_PROJECTION;
644         } else {
645                 for (i = 0; i < projection_count; i++)
646                         ctsvc_record_set_property_flag(_record, projection[i], CTSVC_PROPERTY_FLAG_PROJECTION);
647         }
648
649         return CONTACTS_ERROR_NONE;
650 }
651