ac8ba8c55745fcb35bd53f871734ff9765c0dcde
[platform/core/system/sync-agent.git] / src / fw-plugins / common-public / calendar / src / plugin_interface.c
1 /*
2  * sync-agent
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <stdio.h>
19 #include <glib.h>
20 #include <pthread.h>
21 #include <calendar2.h>
22 #include <account.h>
23
24 #include "extern_info.h"
25 #include "item_change_info.h"
26 #include "ext_datastore_info_calendar.h"
27 #include "in_datastore_info_calendar.h"
28
29 /* for log */
30 #include "utility/sync_util.h"
31 #include "utility/fw_async_queue.h"
32 #include "plugin/data_connector_interface.h"
33 #include "data-adapter/agent_handler_manager.h"
34
35 #ifndef EXPORT_API
36 #define EXPORT_API __attribute__ ((visibility("default")))
37 #endif
38
39 #ifndef SYNC_AGENT_LOG
40 #undef LOG_TAG
41 #define LOG_TAG "PLUGIN_DA_CALENDAR"
42 #endif
43
44 #define FW_CALENDAR     1       /* plugIn-Id */
45 #define EXTYPE_UPDATE_KEYWORD                   "X-EXTYPE:2"
46
47 static sync_agent_util_async_queue_s *queue;
48 static int latest_calendar_version = 0;
49 static pthread_mutex_t lockx;
50 static int is_noti_from_me = 0;
51 static int is_storage_changed = 0;
52
53 static sync_agent_add_item_cb_plugin callback_add_item;
54 static sync_agent_del_item_cb_plugin callback_del_item;
55 static sync_agent_update_item_cb_plugin callback_update_item;
56 static sync_agent_get_account_id_list_cb_plugin callback_get_account_id_list;
57 static sync_agent_del_child_item_cb_plugin callback_delete_child_item;
58
59 static void _set_is_noti_from_me(int set_flag);
60 static int __get_is_noti_from_me(void);
61 static char * _get_value_by_token(const char *src, const char *token, const char *end_of_token);
62 static void _process_calendar_change(const char *view_uri, void *user_data);
63 static void *_rutine_calendar_change(void *);
64 static sync_agent_da_return_e _convert_service_error_to_common_error(int err);
65 static bool _get_account_id(account_h account, void *user_data);
66 static bool __is_calendar_id(const char* capability_type, account_capability_state_e capability_value, void *user_data);
67 static sync_agent_da_return_e _get_service_folder_list_by_account_id(int account_id, calendar_list_h * item_list, int *count);
68 static int _get_deleted_exdate_item_count(calendar_query_h query);
69 static int _add_updated_exdate_item(int service_account_id, int index, char *parent_service_item_id, char *service_folder_id);
70 static sync_agent_da_return_e _process_exdate_item(calendar_record_h calendar_record);
71 static sync_agent_da_return_e _get_service_event_list_by_folder_id(int folder_id, calendar_list_h * item_list, int *count);
72
73 typedef struct account_id {
74         int account_id;
75         struct account_id *next;
76 } account_id_s;
77
78 static sync_agent_da_return_e _get_service_event_list_by_folder_id(int folder_id, calendar_list_h * item_list, int *count)
79 {
80         _INNER_FUNC_ENTER;
81
82         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
83         int service_ret = CALENDAR_ERROR_NONE;
84
85         unsigned int ids[1];
86         calendar_query_h query = NULL;
87         calendar_filter_h filter = NULL;
88         calendar_list_h list = NULL;
89
90         // start pre condition
91         service_ret = calendar_query_create(_calendar_event._uri, &query);
92         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_create() Fail!: err[%d]", service_ret);
93
94         service_ret = calendar_filter_create(_calendar_event._uri, &filter);
95         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_create() Fail!: err[%d]", service_ret);
96
97         service_ret = calendar_filter_add_int(filter, _calendar_event.calendar_book_id, CALENDAR_MATCH_EQUAL, folder_id);
98         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_add_int() Fail!: err[%d]", service_ret);
99         // end pre condition
100
101         service_ret = calendar_query_set_filter(query, filter);
102         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_set_filter() Fail!: err[%d]", service_ret);
103
104         ids[0] = _calendar_event.id;
105         service_ret = calendar_query_set_projection(query, ids, 1);
106         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_set_projection() Fail!: err[%d]", service_ret);
107
108         service_ret = calendar_db_get_records_with_query(query, 0, 0, &list);
109         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_db_get_records_with_query() Fail!: err[%d]", service_ret);
110
111         service_ret = calendar_list_get_count(list, count);
112         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_get_count() Fail!: err[%d]", service_ret);
113
114         _DEBUG_INFO("count(%d)", *count);
115
116         service_ret = calendar_list_first(list);
117         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_first() Fail!: err[%d]", service_ret);
118
119  return_part:
120         ret = _convert_service_error_to_common_error(service_ret);
121         calendar_filter_destroy(filter);
122         calendar_query_destroy(query);
123
124         *item_list = list;
125         _INNER_FUNC_EXIT;
126         return ret;
127 }
128
129 static sync_agent_da_return_e _get_service_folder_list_by_account_id(int account_id, calendar_list_h * item_list, int *count)
130 {
131         _INNER_FUNC_ENTER;
132
133         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
134         int service_ret = 0;
135
136         unsigned int ids[1];
137         calendar_query_h query = NULL;
138         calendar_filter_h filter = NULL;
139         calendar_list_h list = NULL;
140
141         // start pre condition
142         service_ret = calendar_query_create(_calendar_book._uri, &query);
143         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_create() Fail!: err[%d]", service_ret);
144
145         service_ret = calendar_filter_create(_calendar_book._uri, &filter);
146         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_create() Fail!: err[%d]", service_ret);
147
148         service_ret = calendar_filter_add_int(filter, _calendar_book.account_id, CALENDAR_MATCH_EQUAL, account_id);
149         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_add_int() Fail!: err[%d]", service_ret);
150         // end pre condition
151
152         service_ret = calendar_query_set_filter(query, filter);
153         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_set_filter() Fail!: err[%d]", service_ret);
154
155         ids[0] = _calendar_book.id;
156         service_ret = calendar_query_set_projection(query, ids, 1);
157         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_set_projection() Fail!: err[%d]", service_ret);
158
159         service_ret = calendar_db_get_records_with_query(query, 0, 0, &list);
160         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_db_get_records_with_query() Fail!: err[%d]", service_ret);
161
162         service_ret = calendar_list_get_count(list, count);
163         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_get_count() Fail!: err[%d]", service_ret);
164         _DEBUG_INFO("count(%d)", *count);
165
166         service_ret = calendar_list_first(list);
167         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_first() Fail!: err[%d]", service_ret);
168
169  return_part:
170         ret = _convert_service_error_to_common_error(service_ret);
171         calendar_filter_destroy(filter);
172         calendar_query_destroy(query);
173
174         *item_list = list;
175         _INNER_FUNC_EXIT;
176         return ret;
177 }
178
179 static int _get_deleted_exdate_item_count(calendar_query_h query)
180 {
181         _EXTERN_FUNC_ENTER;
182         retvm_if(query == NULL, 0, "query is NULL");
183
184         calendar_filter_h filter = NULL;
185         calendar_list_h list = NULL;
186         calendar_record_h calendar_record = NULL;
187         int exdate_count = 0;
188         int service_ret = CALENDAR_ERROR_NONE;
189
190         service_ret = calendar_db_get_records_with_query(query, 0, 0, &list);
191         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_db_get_records_with_query() Fail!: err[%d]", service_ret);
192
193         service_ret = calendar_list_first(list);
194         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_first() Fail!: err[%d]", service_ret);
195
196         int index = 0;
197         do
198         {
199                 service_ret = calendar_list_get_current_record_p(list, &calendar_record);
200                 if (service_ret != CALENDAR_ERROR_NONE || calendar_record == NULL) {
201                         _DEBUG_ERROR("calendar_list_get_current_record_p() failed");
202                         continue;
203                 }
204
205                 char *exdate = NULL;
206                 service_ret = calendar_record_get_str(calendar_record, _calendar_event.exdate, &exdate);
207                 goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_get_str() Fail!: err[%d]", service_ret);
208
209                 _DEBUG_INFO("index = %d, exdate = %s", index, exdate);
210                 index++;
211
212                 gchar **array_exdate = g_strsplit(exdate, ",", -1);
213                 goto_if(array_exdate == NULL, "array_exdate is NULL");
214
215                 int array_length = 0;
216                 array_length = g_strv_length(array_exdate);
217                 _DEBUG_INFO("array_length = %d", array_length);
218
219                 exdate_count += array_length;
220
221                 int exdate_index = 0;
222                 for (exdate_index = 0; array_exdate[exdate_index] != NULL; exdate_index++)
223                         _DEBUG_INFO("exdate_index = %d, one_exdate = %s", exdate_index, array_exdate[exdate_index]);
224                 g_strfreev(array_exdate);
225         } while (calendar_list_next(list) != CALENDAR_ERROR_NO_DATA);
226
227 return_part:
228         _DEBUG_INFO("total exdate_count = %d", exdate_count);
229         calendar_list_destroy(list, false);
230         calendar_filter_destroy(filter);
231         _EXTERN_FUNC_EXIT;
232         return exdate_count;
233 }
234
235 EXPORT_API sync_agent_da_return_e sync_agent_plugin_open_service(void)
236 {
237         _EXTERN_FUNC_ENTER;
238
239         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
240         int err = calendar_connect_on_thread();
241
242         if (err != CALENDAR_ERROR_NONE) {
243                 _DEBUG_ERROR("[calendar] calendar_connect Fail!\n");
244                 ret = _convert_service_error_to_common_error(err);
245         } else {
246                 _DEBUG_INFO("[calendar] calendar_connect Success!\n");
247         }
248
249         _EXTERN_FUNC_EXIT;
250         return ret;
251 }
252
253 EXPORT_API sync_agent_da_return_e sync_agent_plugin_close_service(void)
254 {
255         _EXTERN_FUNC_ENTER;
256
257         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
258         int err = calendar_disconnect_on_thread();
259
260         if (err != CALENDAR_ERROR_NONE) {
261                 _DEBUG_ERROR("[calendar] calendar_disconnect Fail!\n");
262                 ret = _convert_service_error_to_common_error(err);
263         } else {
264                 _DEBUG_INFO("[calendar] calendar_disconnect Success!\n");
265         }
266
267         _EXTERN_FUNC_EXIT;
268         return ret;
269 }
270
271 EXPORT_API sync_agent_da_return_e sync_agent_plugin_begin_transaction(void)
272 {
273         _EXTERN_FUNC_ENTER;
274
275         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
276         _DEBUG_INFO("[calendar] not anymore need to transaction");
277         _set_is_noti_from_me(1);
278
279         _EXTERN_FUNC_EXIT;
280         return ret;
281 }
282
283 EXPORT_API int sync_agent_plugin_end_transaction(int is_success)
284 {
285         _EXTERN_FUNC_ENTER;
286
287         _DEBUG_INFO("[calendar] SLP Calendar Service is not supported Rollback Operation!\n");
288
289         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
290         _DEBUG_INFO("[calendar] in calendar Success!\n");
291         if (is_storage_changed == 0) {
292                 _DEBUG_INFO("calendar storaged was not Changed!!");
293                 _set_is_noti_from_me(0);
294         }
295         is_storage_changed = 0;
296         _DEBUG_INFO("[calendar] not anymore need to transaction, is_success : [%d]", is_success);
297         _EXTERN_FUNC_EXIT;
298
299         return ret;
300 }
301
302 EXPORT_API sync_agent_da_return_e sync_agent_plugin_add_item(int account_id, char *folder_id, void *data, char **item_id)
303 {
304         _EXTERN_FUNC_ENTER;
305
306         retvm_if(folder_id == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "folder_id is NULL. FAIL !!!");
307
308         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
309         int service_ret = 0;
310
311         calendar_record_h item = (calendar_record_h) data;
312
313         int un_type = 0;
314         memcpy(&un_type, item, 4);
315         int int_folder_id = atoi(folder_id);
316         _DEBUG_INFO("[calendar] calendar type %d, in %d, folder id [%d]", un_type, item, int_folder_id);
317
318         /* setting folder id */
319         service_ret = calendar_record_set_int(item, _calendar_event.calendar_book_id, int_folder_id);
320         if (service_ret != CALENDAR_ERROR_NONE) {
321                 _DEBUG_ERROR("calendar_record_set_int() Fail! : err = %d", service_ret);
322                 ret = SYNC_AGENT_DA_ERRORS;
323                 goto DACI_FINISH;
324         }
325         _DEBUG_INFO("[calendar] calendar_svc_struct_set_int(folder %d) return [%d]!\n", atoi(folder_id), service_ret);
326
327         /* add item */
328         int slp_cal_info_id = 0;
329         service_ret = calendar_db_insert_record(item, &slp_cal_info_id);
330         if (service_ret != CALENDAR_ERROR_NONE) {
331                 _DEBUG_ERROR("calendar_db_insert_record() Fail! : err = %d", service_ret);
332                 ret = _convert_service_error_to_common_error(service_ret);
333                 *item_id = 0;
334                 goto DACI_FINISH;
335         } else {
336                 _DEBUG_INFO("[calendar] calendar_svc_insert() Success!");
337                 _DEBUG_INFO("calendar_svc_insert() Success!: id = %d", slp_cal_info_id);
338                 *item_id = g_strdup_printf("%d", slp_cal_info_id);
339                 is_storage_changed = 1;
340         }
341  DACI_FINISH:
342         service_ret = calendar_record_destroy(item, false);
343         if (service_ret != CALENDAR_ERROR_NONE) {
344                 _DEBUG_ERROR("calendar_record_destroy() Fail! : err = %d", service_ret);
345         }
346         item = NULL;
347         _EXTERN_FUNC_EXIT;
348         return ret;
349 }
350
351 EXPORT_API sync_agent_da_return_e sync_agent_plugin_update_item(int account_id, char *folder_id, char *item_id, void *data)
352 {
353         _EXTERN_FUNC_ENTER;
354
355         retvm_if(folder_id == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "folder_id is NULL. FAIL !!!");
356         retvm_if(item_id == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "item_id is NULL. FAIL !!!");
357         retvm_if(data == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "data is NULL. FAIL !!!");
358
359         calendar_record_h item = (calendar_record_h) data;
360         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
361         int service_ret = CALENDAR_ERROR_NONE;
362         int int_folder_id = atoi(folder_id);
363
364         // exception handler for EXDATE item
365         if(_process_exdate_item(item) == SYNC_AGENT_DA_ERR_ITEM_READ_ONLY) {
366                 _DEBUG_INFO("this is a updated exdate item. it should be not done calendar_db_update_record(). so just return.");
367                 goto return_part;
368         }
369
370         service_ret = calendar_record_set_int(item, _calendar_event.calendar_book_id, int_folder_id);
371         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_set_int() Fail!: err[%d]", service_ret);
372
373         service_ret = calendar_db_update_record(item);
374         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_db_update_record() Fail!: err[%d]", service_ret);
375
376         _DEBUG_INFO("[calendar] calendar_svc_update() Success!");
377         is_storage_changed = 1;
378
379 return_part:
380         ret = _convert_service_error_to_common_error(service_ret);
381         if (item != NULL) {
382                 service_ret = calendar_record_destroy(item, false);
383                 if (service_ret != CALENDAR_ERROR_NONE) {
384                         _DEBUG_ERROR("calendar_record_destroy() Fail! : service_ret = %d", service_ret);
385                 }
386                 item = NULL;
387         }
388         _EXTERN_FUNC_EXIT;
389         return ret;
390 }
391
392 EXPORT_API sync_agent_da_return_e sync_agent_plugin_delete_item(int account_id, char *folder_id, char *item_id)
393 {
394         _EXTERN_FUNC_ENTER;
395
396         retvm_if(item_id == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "item_id is NULL. FAIL !!!");
397
398         /*  delete item  */
399         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
400         int err = calendar_db_delete_record(_calendar_event._uri, atoi(item_id));
401
402         if (err != CALENDAR_ERROR_NONE) {
403                 _DEBUG_INFO("[calendar] calendar_svc_delete() Fail!");
404                 ret = _convert_service_error_to_common_error(err);
405         } else {
406                 _DEBUG_INFO("[calendar] calendar_svc_delete() Success!");
407                 is_storage_changed = 1;
408         }
409
410         _EXTERN_FUNC_EXIT;
411
412         return ret;
413 }
414
415 EXPORT_API sync_agent_da_return_e sync_agent_plugin_delete_all_items(int account_id)
416 {
417         _EXTERN_FUNC_ENTER;
418
419         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
420         int err = 1;
421
422         int folder_id_list_cnt = 0;
423         int *folder_type_list;
424         char **folder_id_list = 0;
425         int service_ret = 0;
426
427         int item_id = 0;
428         calendar_list_h event_list = NULL;
429
430         /* get folder id list for account id */
431         folder_id_list = sync_agent_plugin_get_folder_id_list(account_id, &folder_id_list_cnt, &folder_type_list);
432         if (folder_id_list == NULL || folder_id_list_cnt == 0) {
433                 _DEBUG_INFO("[calendar] folder id list cnt : %d", folder_id_list_cnt);
434                 if (folder_type_list != NULL) {
435                         cfree(folder_type_list);
436                         folder_type_list = NULL;
437                 }
438                 if (folder_id_list != NULL) {
439                         free(folder_id_list);
440                         folder_id_list = NULL;
441                 }
442                 return SYNC_AGENT_DA_ERR_NO_DATA;
443         }
444
445         int folder_iter = 0;
446         for (; folder_iter < folder_id_list_cnt; folder_iter++) {
447                 int int_folder_id = atoi(folder_id_list[folder_iter]);
448                 _DEBUG_INFO("[calendar] folder id : %d\n", int_folder_id);
449                 int event_count = 0;
450                 ret = _get_service_event_list_by_folder_id(int_folder_id, &event_list, &event_count);
451                 if (ret != SYNC_AGENT_DA_SUCCESS) {
452                         _DEBUG_ERROR("_get_service_folder_list_by_account_id failed !!!");
453                         continue;
454                 } else if (event_count == 0) {
455                         _DEBUG_INFO("_get_service_folder_list_by_account_id no list");
456                         continue;
457                 }
458
459                 int event_list_count = 0;
460                 service_ret = calendar_list_get_count(event_list, &event_list_count);
461                 if (service_ret != CALENDAR_ERROR_NONE) {
462                         _DEBUG_ERROR("calendar_list_get_count() Fail! : err = %d", service_ret);
463                         continue;
464                 }
465                 _DEBUG_TRACE("recode list count = %d", event_list_count);
466                 if (event_list_count == 0) {
467                         continue;
468                 }
469
470                 do {
471                         calendar_record_h event = NULL;
472
473                         item_id = -1;
474                         event = NULL;
475                         service_ret = calendar_list_get_current_record_p(event_list, &event);
476                         if (service_ret != CALENDAR_ERROR_NONE) {
477                                 _DEBUG_ERROR("[calendar] in calendar_list_get_current_record_p Fail!\n");
478                                 ret = _convert_service_error_to_common_error(service_ret);
479                                 continue;
480                         }
481                         service_ret = calendar_record_get_int(event, _calendar_event.id, &item_id);
482                         if (service_ret != CALENDAR_ERROR_NONE) {
483                                 _DEBUG_ERROR("[calendar] in calendar_record_get_int Fail!\n");
484                                 ret = _convert_service_error_to_common_error(service_ret);
485                                 continue;
486                         }
487                         _DEBUG_INFO("[calendar] item id : %d\n", item_id);
488
489                         err = calendar_db_delete_record(_calendar_event._uri, item_id);
490                         if (err != CALENDAR_ERROR_NONE) {
491                                 _DEBUG_ERROR("[calendar] calendar_svc_delete(%d) Fail!\n", item_id);
492                                 ret = _convert_service_error_to_common_error(err);
493                                 goto DACI_FINISH;
494                         } else {
495                                 _DEBUG_INFO("[calendar] calendar_svc_delete(%d) Success!\n", item_id);
496                                 is_storage_changed = 1;
497                         }
498
499                 } while (calendar_list_next(event_list) != CALENDAR_ERROR_NO_DATA);
500
501                 if (event_list != NULL) {
502                         err = calendar_list_destroy(event_list, true);
503                         if (err != CALENDAR_ERROR_NONE) {
504                                 _DEBUG_ERROR("calendar_list_destroy() Fail! : err = %d", err);
505                         }
506                         event_list = NULL;
507                 }
508         }
509
510  DACI_FINISH:
511         if (event_list != NULL) {
512                 err = calendar_list_destroy(event_list, true);
513                 if (err != CALENDAR_ERROR_NONE) {
514                         _DEBUG_ERROR("calendar_list_destroy() Fail! : err = %d", err);
515                 }
516                 event_list = NULL;
517         }
518         if (folder_id_list != NULL) {
519                 int cnt = 0;
520                 for (cnt = 0; cnt < folder_id_list_cnt; cnt++) {
521                         if (folder_id_list[cnt] != NULL) {
522                                 free(folder_id_list[cnt]);
523                                 _DEBUG_INFO("[calendar] folder id free !! \n");
524                         }
525                 }
526                 cfree(folder_id_list);
527                 _DEBUG_INFO("[calendar] folder id list free !! \n");
528         }
529         if (folder_type_list != NULL) {
530                 cfree(folder_type_list);
531                 folder_type_list = NULL;
532         }
533
534         _EXTERN_FUNC_EXIT;
535         return ret;
536 }
537
538 EXPORT_API sync_agent_da_return_e sync_agent_plugin_get_item(int account_id, char *folder_id, char *item_id, void **data)
539 {
540         _EXTERN_FUNC_ENTER;
541
542         retvm_if(item_id == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "item_id is NULL. FAIL !!!");
543
544         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
545         int err = 0;
546         calendar_record_h item = 0;
547
548         /* get item */
549         err = calendar_db_get_record(_calendar_event._uri, atoi(item_id), &item);
550         if (err != CALENDAR_ERROR_NONE) {
551                 _DEBUG_INFO("[calendar] calendar_db_get_record() Fail!\n");
552                 ret = _convert_service_error_to_common_error(err);
553                 *data = 0;
554         } else {
555                 _DEBUG_INFO("[calendar] calendar_svc_get() Success!\n");
556                 *data = (void *)item;
557         }
558
559         _EXTERN_FUNC_EXIT;
560
561         return ret;
562 }
563
564 EXPORT_API sync_agent_da_return_e sync_agent_plugin_add_folder(int account_id, char *folder_name, int folder_type, char **folder_id)
565 {
566         _EXTERN_FUNC_ENTER;
567
568         retvm_if(folder_name == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "folder_name is NULL. FAIL !!!");
569
570         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
571         int service_ret = CALENDAR_ERROR_NONE;
572         calendar_record_h folder = 0;
573
574         /* new service struct */
575         int result_calendar_record_create = 0;
576         result_calendar_record_create = calendar_record_create(_calendar_book._uri, &folder);
577         if(result_calendar_record_create != CALENDAR_ERROR_NONE) {
578                 _DEBUG_INFO("[task] calendar_svc_struct_new() Fail! result_calendar_record_create[%d]\n", result_calendar_record_create);
579                 *folder_id = 0;
580                 return SYNC_AGENT_DA_ERRORS;
581         }
582         if (folder == NULL) {
583                 _DEBUG_INFO("[calendar] calendar_svc_struct_new() Fail!\n");
584                 *folder_id = 0;
585                 return SYNC_AGENT_DA_ERRORS;
586         }
587
588         /* setting folder data */
589         service_ret = calendar_record_set_int(folder, _calendar_book.account_id, account_id);
590         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_set_int() Fail!: err[%d]", service_ret);
591
592         service_ret = calendar_record_set_int(folder, _calendar_book.visibility, 1);
593         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_set_int() Fail!: err[%d]", service_ret);
594
595         service_ret = calendar_record_set_str(folder, _calendar_book.name, folder_name);
596         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_set_str() Fail!: err[%d]", service_ret);
597
598         /* add folder */
599         int service_folder_item_id = 0;
600         service_ret = calendar_db_insert_record(folder, &service_folder_item_id);
601         if (service_ret != CALENDAR_ERROR_NONE) {
602                 _DEBUG_INFO("[calendar] calendar_svc_insert() Fail!\n");
603                 *folder_id = 0;
604         } else {
605                 _DEBUG_INFO("[calendar] calendar_svc_insert() Success!");
606                 *folder_id = g_strdup_printf("%d", service_folder_item_id);
607                 is_storage_changed = 1;
608         }
609
610 return_part:
611         ret = _convert_service_error_to_common_error(service_ret);
612         if (folder != NULL) {
613                 calendar_record_destroy(folder, false);
614                 if (service_ret != CALENDAR_ERROR_NONE) {
615                         _DEBUG_ERROR("calendar_record_destroy() Fail! : service_ret = %d", service_ret);
616                 }
617                 folder = NULL;
618         }
619         _EXTERN_FUNC_EXIT;
620
621         return ret;
622 }
623
624 EXPORT_API sync_agent_da_return_e sync_agent_plugin_delete_folder(int account_id, char *folder_id)
625 {
626         _EXTERN_FUNC_ENTER;
627
628         retvm_if(folder_id == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "folder_id is NULL. FAIL !!!");
629
630         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
631         int err = 0;
632
633         /* delete folder */
634         err = calendar_db_delete_record(_calendar_book._uri, atoi(folder_id));
635         if (err != CALENDAR_ERROR_NONE) {
636                 _DEBUG_INFO("[calendar] calendar_db_delete_record() Fail, err[%d]", err);
637                 ret = _convert_service_error_to_common_error(err);
638         } else {
639                 _DEBUG_INFO("[calendar] calendar_svc_delete() Success!\n");
640                 calendar_db_clean_after_sync(atoi(folder_id), 0);
641                 is_storage_changed = 1;
642         }
643
644         _EXTERN_FUNC_EXIT;
645
646         return ret;
647 }
648
649 EXPORT_API sync_agent_da_return_e sync_agent_plugin_get_folder(int account_id, char *folder_id, char **out_folder_name, int *out_folder_type)
650 {
651         _EXTERN_FUNC_ENTER;
652
653         retvm_if(folder_id == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "folder_id is NULL. FAIL !!!");
654
655         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
656         int err = 0;
657         calendar_record_h folder = 0;
658         int task_folder_id = atoi(folder_id);
659         _DEBUG_INFO("[calendar] task_folder_id : %d\n", task_folder_id);
660
661         err = calendar_db_get_record(_calendar_book._uri, task_folder_id, &folder);
662         if (err != CALENDAR_ERROR_NONE) {
663                 _DEBUG_INFO("[calendar] contacts_svc_get_addressbook() Fail!\n");
664                 ret = _convert_service_error_to_common_error(err);
665                 *out_folder_name = 0;
666                 *out_folder_type = -1;
667                 goto return_part;
668         }
669
670         _DEBUG_INFO("[calendar] contacts_svc_get_addressbook() Success!\n");
671
672         *out_folder_name = 0;
673         err = calendar_record_get_str(folder, _calendar_book.name, out_folder_name);
674         if (err != CALENDAR_ERROR_NONE) {
675                 _DEBUG_INFO("[calendar] calendar_record_get_str() Fail!\n");
676                 ret = _convert_service_error_to_common_error(err);
677                 *out_folder_name = 0;
678                 *out_folder_type = -1;
679                 goto return_part;
680         }
681
682         *out_folder_type = DEFAULT_CALENDAR_FOLDER;
683
684 return_part:
685         if (folder != NULL) {
686                 calendar_record_destroy(folder, false);
687                 if (err != CALENDAR_ERROR_NONE) {
688                         _DEBUG_ERROR("calendar_record_destroy() Fail! : err = %d", err);
689                 }
690                 folder = NULL;
691         }
692         _EXTERN_FUNC_EXIT;
693         return ret;
694 }
695
696 EXPORT_API sync_agent_da_return_e sync_agent_plugin_execute(int account_ID, const char *execute_key, void *execute_values, void **result)
697 {
698         _EXTERN_FUNC_ENTER;
699
700         _DEBUG_INFO("[calendar] service is not supported execute. \n");
701         *result = 0;
702
703         _EXTERN_FUNC_EXIT;
704
705         return SYNC_AGENT_DA_SUCCESS;
706 }
707
708 EXPORT_API int sync_agent_plugin_get_used_item_count()
709 {
710         _EXTERN_FUNC_ENTER;
711
712         int used_cnt = 0;
713         int deleted_exdate_count = 0;
714
715         int err = calendar_db_get_count(_calendar_event._uri, &used_cnt);
716         if (err != CALENDAR_ERROR_NONE) {
717                 _DEBUG_INFO("[calendar] calendar_db_get_count() Fail\n");
718         } else {
719                 _DEBUG_INFO("[calendar] used_count = %d\n", used_cnt);
720                 deleted_exdate_count = sync_agent_plugin_get_deleted_exdate_item_count();
721                 used_cnt += deleted_exdate_count;
722         }
723
724         _DEBUG_INFO("[calendar] used_count = %d\n", used_cnt);
725         _EXTERN_FUNC_EXIT;
726         return used_cnt;
727 }
728
729 EXPORT_API int sync_agent_plugin_get_deleted_exdate_item_count()
730 {
731         _EXTERN_FUNC_ENTER;
732
733         calendar_filter_h filter = NULL;
734         calendar_query_h query = NULL;
735
736         int exdate_parent_count = 0;
737         int deleted_exdate_count = 0;
738         int service_ret = CALENDAR_ERROR_NONE;
739
740         // check exdate count
741         service_ret = calendar_query_create(_calendar_event._uri, &query);
742         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_create() Fail!: err[%d]", service_ret);
743
744         service_ret = calendar_filter_create(_calendar_event._uri, &filter);
745         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_create() Fail!: err[%d]", service_ret);
746
747         service_ret = calendar_filter_add_str(filter, _calendar_event.exdate, CALENDAR_MATCH_EXISTS, "");
748         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_add_str() Fail!: err[%d]", service_ret);
749
750         service_ret = calendar_query_set_filter(query, filter);
751         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_set_filter() Fail!: err[%d]", service_ret);
752
753         service_ret = calendar_db_get_count_with_query(query, &exdate_parent_count);
754         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_db_get_count_with_query() Fail!: err[%d]", service_ret);
755
756         _DEBUG_INFO("exdate_parent_count = %d\n", exdate_parent_count);
757         // if exdate:delete exist, get deleted exdate count
758         if (exdate_parent_count > 0) {
759                 deleted_exdate_count = _get_deleted_exdate_item_count(query);
760                 _DEBUG_INFO("deleted_exdate_count = %d\n", deleted_exdate_count);
761         }
762
763 return_part:
764         calendar_filter_destroy(filter);
765         calendar_query_destroy(query);
766         _EXTERN_FUNC_EXIT;
767         return deleted_exdate_count;
768 }
769
770 EXPORT_API sync_agent_da_return_e sync_agent_plugin_is_exist_exdate_item(const char *fw_parent_id, const char *child_vcalendar)
771 {
772         _EXTERN_FUNC_ENTER;
773         retvm_if(fw_parent_id == NULL, SYNC_AGENT_DA_ERRORS, "fw_parent_id is NULL. FAIL !!!");
774         retvm_if(child_vcalendar == NULL, SYNC_AGENT_DA_ERRORS, "child_vcalendar is NULL. FAIL !!!");
775         _DEBUG_INFO("fw_parent_id = %s", fw_parent_id);
776
777         const char *updated_exdate_token = "\r\nX-EXTYPE:2\r\nEXDATE:";
778         const char *exdate_token = "EXDATE:";
779         char *temp = NULL;
780         char *updated_exdate = NULL;
781         int ret = SYNC_AGENT_DA_ERRORS;
782         int service_ret = CALENDAR_ERROR_NONE;
783         calendar_filter_h filter = NULL;
784         calendar_query_h query = NULL;
785
786         temp = strstr(child_vcalendar, updated_exdate_token);
787         goto_if(temp == NULL, "this vcalendar has not exdate data");
788
789         updated_exdate = _get_value_by_token(temp + strlen(updated_exdate_token) - strlen(exdate_token), exdate_token, "\r\n");
790         _DEBUG_INFO("updated_exdate = %s", updated_exdate);
791         goto_if(updated_exdate == NULL, "updated_exdate is null");
792
793         int matched_count = 0;
794         service_ret = calendar_query_create(_calendar_event._uri, &query);
795         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_create() Fail!: err[%d]", service_ret);
796
797         service_ret = calendar_filter_create(_calendar_event._uri, &filter);
798         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_create() Fail!: err[%d]", service_ret);
799
800         service_ret = calendar_filter_add_str(filter, _calendar_event.recurrence_id, CALENDAR_MATCH_EXACTLY, updated_exdate);
801         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_add_str() Fail!: err[%d]", service_ret);
802
803         ret = calendar_filter_add_operator(filter, CALENDAR_FILTER_OPERATOR_AND);
804         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_add_operator() Fail!: err[%d]", service_ret);
805
806         service_ret = calendar_filter_add_int(filter, _calendar_event.original_event_id, CALENDAR_MATCH_EQUAL, atoi(fw_parent_id));
807         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_filter_add_str() Fail!: err[%d]", service_ret);
808
809         service_ret = calendar_query_set_filter(query, filter);
810         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_query_set_filter() Fail!: err[%d]", service_ret);
811
812         service_ret = calendar_db_get_count_with_query(query, &matched_count);
813         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_db_get_count_with_query() Fail!: err[%d]", service_ret);
814         _DEBUG_INFO("matched_count = %d", matched_count);
815
816         if (matched_count > 0) {
817                 _DEBUG_INFO("this item already exist");
818                 ret = SYNC_AGENT_DA_ERR_ALREADY_EXIST;
819                 goto return_part;
820         }
821         _DEBUG_INFO("this item is not exist. it's a new item.");
822         ret = SYNC_AGENT_DA_SUCCESS;
823
824 return_part:
825         if(updated_exdate) {
826                 free(updated_exdate);
827                 updated_exdate = NULL;
828         }
829         calendar_filter_destroy(filter);
830         calendar_query_destroy(query);
831         _EXTERN_FUNC_EXIT;
832         return ret;
833 }
834
835 EXPORT_API void sync_agent_plugin_construct_exdate_parent_item(char *parent_service_id)
836 {
837         _EXTERN_FUNC_ENTER;
838         retm_if(parent_service_id == NULL, "parent_service_id is NULL. FAIL !!!");
839         _DEBUG_INFO("parent_service_id = %s", parent_service_id);
840
841         calendar_record_h item = 0;
842         int service_ret = CALENDAR_ERROR_NONE;
843
844         service_ret = calendar_db_get_record(_calendar_event._uri, atoi(parent_service_id), &item);
845         goto_if(service_ret != CALENDAR_ERROR_NONE, "[claendar] calendar_db_get_record() Fail!: err[%d]", service_ret);
846
847         service_ret = calendar_db_update_record(item);
848         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_db_update_record() Fail!: err[%d]", service_ret);
849         _DEBUG_INFO("[calendar] calendar_svc_update() Success!");
850
851 return_part:
852         _EXTERN_FUNC_EXIT;
853         return;
854 }
855
856 EXPORT_API int sync_agent_plugin_get_used_item_count_for_folder(int account_id, char *folder_id)
857 {
858         _EXTERN_FUNC_ENTER;
859
860         retvm_if(folder_id == NULL, SYNC_AGENT_DA_ERR_INVALID_CONTENT, "folder_id is NULL. FAIL !!!");
861
862         calendar_filter_h filter = NULL;
863         calendar_query_h query = NULL;
864         int service_ret = CALENDAR_ERROR_NONE;
865
866         service_ret = calendar_query_create(_calendar_event._uri, &query);
867         service_ret = calendar_filter_create(_calendar_event._uri, &filter);
868         service_ret = calendar_filter_add_int(filter, _calendar_event.calendar_book_id, CALENDAR_MATCH_EQUAL, atoi(folder_id));
869         service_ret = calendar_query_set_filter(query, filter);
870
871         int used_cnt = 0;
872         service_ret = calendar_db_get_count_with_query(query, &used_cnt);
873         if (service_ret != CALENDAR_ERROR_NONE) {
874                 _DEBUG_ERROR("[calendar] calendar_db_get_count() Fail\n");
875         } else {
876                 _DEBUG_INFO("[calendar] calendar_db_get_count() Success\n");
877                 _DEBUG_INFO("[calendar] used_count = %d\n", used_cnt);
878         }
879
880         if (filter != NULL)
881                 calendar_filter_destroy(filter);
882         if (query != NULL)
883                 calendar_query_destroy(query);
884
885         _EXTERN_FUNC_EXIT;
886         return used_cnt;
887 }
888
889 EXPORT_API char **sync_agent_plugin_get_folder_id_list(int account_id, int *folder_count, int **folder_type_list)
890 {
891         _EXTERN_FUNC_ENTER;
892
893         char **folder_id_list = NULL;
894         int count = 0;
895         calendar_list_h service_folder_list = 0;
896         int err = 0;
897         int i = 0;
898         *folder_count = 0;
899
900         _DEBUG_INFO("account_id [%d]", account_id);
901
902         err = _get_service_folder_list_by_account_id(account_id, &service_folder_list, &count);
903         if (err != SYNC_AGENT_DA_SUCCESS || count == 0) {
904                 _DEBUG_ERROR("_get_service_folder_list_by_account_id failed !!!");
905                 folder_id_list = NULL;
906                 goto return_part;
907         }
908
909         if (count > 0) {
910                 folder_id_list = (char **)calloc(count, sizeof(char *));
911                 if (folder_id_list == NULL) {
912                         _DEBUG_ERROR("CALLOC failed !!!");
913                         goto return_part;
914                 }
915                 *folder_type_list = (int *)calloc(count, sizeof(int));
916                 if (*folder_type_list == NULL) {
917                         _DEBUG_ERROR("CALLOC failed !!!");
918                         if (folder_id_list) {
919                                 free(folder_id_list);
920                                 folder_id_list = NULL;
921                         }
922                         goto return_part;
923                 }
924
925                 do {
926                         int int_folder_id = 0;
927                         calendar_record_h event = NULL;
928                         err = calendar_record_create(_calendar_event._uri, &event);
929                         if ((err != CALENDAR_ERROR_NONE) && (event == NULL)) {
930                                 _DEBUG_ERROR("calendar_record_create() Fail! : err = %d", err);
931                                 break;
932                         }
933
934                         err = calendar_record_get_int(event, _calendar_event.calendar_book_id, &int_folder_id);
935                         if (err != CALENDAR_ERROR_NONE) {
936                                 _DEBUG_ERROR("calendar_record_get_int() Fail! : err = %d", err);
937                                 break;
938                         }
939
940                         folder_id_list[i] = g_strdup_printf("%d", int_folder_id);
941                         (*folder_type_list)[i] = DEFAULT_CALENDAR_FOLDER;
942                         i++;
943                         *folder_count = i;
944                 } while (calendar_list_next(service_folder_list) != CALENDAR_ERROR_NO_DATA);
945         }
946
947 return_part:
948         _DEBUG_INFO("return_part");
949         if (service_folder_list != NULL) {
950                 err = calendar_list_destroy(service_folder_list, true);
951                 if (err != CALENDAR_ERROR_NONE) {
952                         _DEBUG_ERROR("calendar_list_destroy() Fail! : err = %d", err);
953                 }
954                 service_folder_list = NULL;
955         }
956         _EXTERN_FUNC_EXIT;
957         return folder_id_list;
958 }
959
960 EXPORT_API int *sync_agent_plugin_get_account_id_list(int *count)
961 {
962         _EXTERN_FUNC_ENTER;
963
964         _DEBUG_INFO("[calendar] start!!\n");
965
966         int error_code = account_connect();
967
968         account_id_s *account_info_list = (account_id_s *) calloc(1, sizeof(account_id_s));
969         if (account_info_list == NULL) {
970                 _DEBUG_ERROR("CALLOC failed !!!");
971                 return NULL;
972         }
973         account_info_list->account_id = -1;
974         account_info_list->next = 0;
975
976         account_foreach_account_from_db(_get_account_id, account_info_list);
977
978         *count = 0;
979         account_id_s *cursor_ptr = account_info_list;
980         while (cursor_ptr != 0) {
981                 cursor_ptr = cursor_ptr->next;
982                 (*count)++;
983         }
984
985         int *id_list = 0;
986
987         if ((*count) > 0) {
988                 id_list = (int *)calloc(*count, sizeof(int));
989                 if (id_list == NULL) {
990                         _DEBUG_ERROR("CALLOC failed !!!");
991                         if (account_info_list) {
992                                 free(account_info_list);
993                                 account_info_list = NULL;
994                         }
995                         _EXTERN_FUNC_EXIT;
996                         return NULL;
997                 }
998                 cursor_ptr = account_info_list;
999                 int i = 0;
1000                 while (cursor_ptr != 0) {
1001                         id_list[i] = cursor_ptr->account_id;
1002                         cursor_ptr = cursor_ptr->next;
1003                         i++;
1004                 }
1005         }
1006
1007         free(account_info_list);
1008
1009         error_code = account_disconnect();
1010
1011         _DEBUG_INFO("[calendar] end!!\n");
1012
1013         _EXTERN_FUNC_EXIT;
1014
1015         return id_list;
1016 }
1017
1018 EXPORT_API sync_agent_plugin_item_node_s *sync_agent_plugin_get_changed_item_for_folder_add(int account_id, const char *folder_id, int changepoint, int *changeCount)
1019 {
1020         _EXTERN_FUNC_ENTER;
1021
1022         _DEBUG_INFO("[calendar] account_id : %d\n", account_id);
1023         _DEBUG_INFO("[calendar] folder_id : %s\n", folder_id);
1024         _DEBUG_INFO("[calendar] changepoint : %d\n", changepoint);
1025
1026         int calendarTimeStamp = changepoint;
1027         int current_change_point = 0;
1028         int temp_folder_id = atoi(folder_id);
1029         int service_ret = CALENDAR_ERROR_NONE;
1030
1031         sync_agent_plugin_item_node_s *root_ptr = 0;
1032         sync_agent_plugin_item_node_s *cursor_ptr = 0;
1033         int chagned_count = 0;
1034
1035         calendar_list_h service_changed_list = 0;
1036         calendar_record_h changed_event = NULL;
1037
1038         service_ret = calendar_db_get_changes_by_version(_calendar_event._uri, temp_folder_id, calendarTimeStamp, &service_changed_list, &current_change_point);
1039         _DEBUG_INFO("[calendar] calendar_db_get_changes_by_version service_ret : %d, input folder id [%d], current change point [%d]", service_ret, temp_folder_id, current_change_point);
1040         goto_if((service_ret != CALENDAR_ERROR_NONE) && (service_changed_list == NULL), "[calendar] calendar_db_get_changes_by_version() Fail!: err[%d]", service_ret);
1041
1042         int list_count = 0;
1043         service_ret = calendar_list_get_count(service_changed_list, &list_count);
1044         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_get_count() Fail!: err[%d]", service_ret);
1045
1046         _DEBUG_INFO("[calendar] in calendar_list_get_count [%d]!", list_count);
1047         if (list_count <= 0) {
1048                 goto return_part;
1049         }
1050
1051         service_ret = calendar_list_first(service_changed_list);
1052         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_first() Fail!: err[%d]", service_ret);
1053
1054         _DEBUG_INFO("[calendar] calendar_svc_iter_next service_ret : %d\n", service_ret);
1055
1056         do {
1057                 _DEBUG_INFO("while start");
1058
1059                 service_ret = calendar_list_get_current_record_p(service_changed_list, &changed_event);
1060                 goto_if((service_ret != CALENDAR_ERROR_NONE) && (changed_event == NULL), "[calendar] calendar_list_get_current_record_p() Fail!: err[%d]", service_ret);
1061
1062                 int type = 0;
1063                 service_ret = calendar_record_get_int(changed_event, _calendar_updated_info.modified_status, &type);
1064                 if (service_ret != CALENDAR_ERROR_NONE) {
1065                         _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1066                         break;
1067                 }
1068
1069                 _DEBUG_INFO("[calendar] type is [%d]", type);
1070                 if (type == CALENDAR_EVENT_MODIFIED_STATUS_INSERTED) {
1071                         int calendar_id = 0;
1072                         service_ret = calendar_record_get_int(changed_event, _calendar_updated_info.id, &calendar_id);
1073                         if (service_ret != CALENDAR_ERROR_NONE) {
1074                                 _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1075                                 break;
1076                         }
1077                         _DEBUG_INFO("[calendar] calendar id is [%d]", calendar_id);
1078                         char *calendar_id_str = g_strdup_printf("%d", calendar_id);
1079                         _DEBUG_INFO("[calendar] CALS_UPDATED_TYPE_INSERTED : [%s]\n", calendar_id_str);
1080
1081                         if (root_ptr == NULL) {
1082                                 root_ptr = (sync_agent_plugin_item_node_s *) calloc(1, sizeof(sync_agent_plugin_item_node_s));
1083                                 if (root_ptr == NULL) {
1084                                         _DEBUG_ERROR("CALLOC failed !!!");
1085                                         if (service_changed_list != NULL) {
1086                                                 calendar_list_destroy(service_changed_list, true);
1087                                                 service_changed_list = NULL;
1088                                         }
1089                                         return NULL;
1090                                 }
1091                                 root_ptr->item_id = calendar_id_str;
1092                                 root_ptr->next = 0;
1093                                 cursor_ptr = root_ptr;
1094                         } else {
1095                                 cursor_ptr->next = (sync_agent_plugin_item_node_s *) calloc(1, sizeof(sync_agent_plugin_item_node_s));
1096                                 if (cursor_ptr->next == NULL) {
1097                                         _DEBUG_ERROR("CALLOC failed !!!");
1098                                         if (service_changed_list != NULL) {
1099                                                 calendar_list_destroy(service_changed_list, true);
1100                                                 service_changed_list = NULL;
1101                                         }
1102                                         if (root_ptr) {
1103                                                 free(root_ptr);
1104                                                 root_ptr = NULL;
1105                                         }
1106                                         return NULL;
1107                                 }
1108                                 cursor_ptr->next->item_id = calendar_id_str;
1109                                 cursor_ptr->next->next = 0;
1110                                 cursor_ptr = cursor_ptr->next;
1111                         }
1112
1113                         chagned_count++;
1114
1115                 }
1116         } while (calendar_list_next(service_changed_list) != CALENDAR_ERROR_NO_DATA);
1117
1118  return_part:
1119         if (service_changed_list != NULL) {
1120                 calendar_list_destroy(service_changed_list, true);
1121                 service_changed_list = NULL;
1122         }
1123
1124         *changeCount = chagned_count;
1125
1126         _EXTERN_FUNC_EXIT;
1127         return root_ptr;
1128 }
1129
1130 EXPORT_API sync_agent_plugin_item_node_s *sync_agent_plugin_get_changed_item_for_folder_delete(int account_id, const char *folder_id, int change_point, int *change_count)
1131 {
1132         _EXTERN_FUNC_ENTER;
1133
1134         _DEBUG_INFO("[calendar] account_id : %d\n", account_id);
1135         _DEBUG_INFO("[calendar] folder_id : %s\n", folder_id);
1136         _DEBUG_INFO("[calendar] changepoint : %d\n", change_point);
1137         int current_change_point = 0;
1138         int calendar_time_stamp = change_point;
1139         int temp_folder_id = atoi(folder_id);
1140         int service_ret = CALENDAR_ERROR_NONE;
1141
1142         sync_agent_plugin_item_node_s *root_ptr = 0;
1143         sync_agent_plugin_item_node_s *cursor_ptr = 0;
1144         int chagned_count = 0;
1145
1146         calendar_list_h service_changed_list = 0;
1147         calendar_record_h changed_event = NULL;
1148
1149         service_ret = calendar_db_get_changes_by_version(_calendar_event._uri, temp_folder_id, calendar_time_stamp, &service_changed_list, &current_change_point);
1150         _DEBUG_INFO("[calendar] calendar_db_get_changes_by_version service_ret : %d, input folder id [%d], current change point [%d]", service_ret, temp_folder_id, current_change_point);
1151         goto_if((service_ret != CALENDAR_ERROR_NONE) && (service_changed_list == NULL), "[calendar] calendar_db_get_changes_by_version() Fail!: err[%d]", service_ret);
1152
1153         int list_count = 0;
1154         service_ret = calendar_list_get_count(service_changed_list, &list_count);
1155         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_get_count() Fail!: err[%d]", service_ret);
1156
1157         _DEBUG_INFO("[calendar] in calendar_list_get_count [%d]!", list_count);
1158         if (list_count <= 0) {
1159                 goto return_part;
1160         }
1161
1162         service_ret = calendar_list_first(service_changed_list);
1163         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_first() Fail!: err[%d]", service_ret);
1164
1165         do {
1166
1167                 service_ret = calendar_list_get_current_record_p(service_changed_list, &changed_event);
1168                 goto_if((service_ret != CALENDAR_ERROR_NONE) && (changed_event == NULL), "[calendar] calendar_list_get_current_record_p() Fail!: err[%d]", service_ret);
1169
1170                 int type = 0;
1171                 service_ret = calendar_record_get_int(changed_event, _calendar_updated_info.modified_status, &type);
1172                 if (service_ret != CALENDAR_ERROR_NONE) {
1173                         _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1174                         break;
1175                 }
1176                 if (type == CALENDAR_EVENT_MODIFIED_STATUS_DELETED) {
1177                         int calendar_id = 0;
1178                         service_ret = calendar_record_get_int(changed_event, _calendar_updated_info.id, &calendar_id);
1179                         if (service_ret != CALENDAR_ERROR_NONE) {
1180                                 _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1181                                 break;
1182                         }
1183                         char *calendar_id_str = g_strdup_printf("%d", calendar_id);
1184                         _DEBUG_INFO("[calendar] CALS_UPDATED_TYPE_DELETED : [%s]\n", calendar_id_str);
1185
1186                         if (root_ptr == NULL) {
1187                                 root_ptr = (sync_agent_plugin_item_node_s *) calloc(1, sizeof(sync_agent_plugin_item_node_s));
1188                                 if (root_ptr == NULL) {
1189                                         _DEBUG_ERROR("CALLOC failed !!!");
1190                                         if (service_changed_list != NULL) {
1191                                                 calendar_list_destroy(service_changed_list, true);
1192                                                 service_changed_list = NULL;
1193                                         }
1194                                         return NULL;
1195                                 }
1196                                 root_ptr->item_id = calendar_id_str;
1197                                 root_ptr->next = 0;
1198                                 cursor_ptr = root_ptr;
1199                         } else {
1200                                 cursor_ptr->next = (sync_agent_plugin_item_node_s *) calloc(1, sizeof(sync_agent_plugin_item_node_s));
1201                                 if (cursor_ptr->next == NULL) {
1202                                         _DEBUG_ERROR("CALLOC failed !!!");
1203                                         if (service_changed_list != NULL) {
1204                                                 calendar_list_destroy(service_changed_list, true);
1205                                                 service_changed_list = NULL;
1206                                         }
1207                                         if (root_ptr) {
1208                                                 free(root_ptr);
1209                                                 root_ptr = NULL;
1210                                         }
1211                                         return NULL;
1212                                 }
1213                                 cursor_ptr->next->item_id = calendar_id_str;
1214                                 cursor_ptr->next->next = 0;
1215                                 cursor_ptr = cursor_ptr->next;
1216                         }
1217
1218                         chagned_count++;
1219                 }
1220         } while (calendar_list_next(service_changed_list) != CALENDAR_ERROR_NO_DATA);
1221
1222  return_part:
1223         if (service_changed_list != NULL) {
1224                 calendar_list_destroy(service_changed_list, true);
1225                 service_changed_list = NULL;
1226         }
1227         *change_count = chagned_count;
1228         _EXTERN_FUNC_EXIT;
1229         return root_ptr;
1230 }
1231
1232 EXPORT_API sync_agent_plugin_item_node_s *sync_agent_plugin_get_changed_item_for_folder_update(int account_id, const char *folder_id, int change_point, int *change_count)
1233 {
1234         _EXTERN_FUNC_ENTER;
1235
1236         _DEBUG_INFO("\n[calendar] account_id : %d\n", account_id);
1237         _DEBUG_INFO("[calendar] folder_id : %s\n", folder_id);
1238         _DEBUG_INFO("[calendar] changepoint : %d\n", change_point);
1239
1240         int calendar_time_stamp = change_point;
1241         int temp_folder_id = atoi(folder_id);
1242         int service_ret = CALENDAR_ERROR_NONE;
1243
1244         calendar_list_h service_changed_list = 0;
1245         calendar_record_h changed_event = NULL;
1246
1247         sync_agent_plugin_item_node_s *root_ptr = NULL;
1248         sync_agent_plugin_item_node_s *cursor_ptr = NULL;
1249         int chagned_count = 0;
1250         int current_change_point = 0;
1251         service_ret = calendar_db_get_changes_by_version(_calendar_event._uri, temp_folder_id, calendar_time_stamp, &service_changed_list, &current_change_point);
1252         _DEBUG_INFO("[calendar] calendar_db_get_changes_by_version service_ret : %d, input folder id [%d], current change point [%d]", service_ret, temp_folder_id, current_change_point);
1253         goto_if((service_ret != CALENDAR_ERROR_NONE) && (service_changed_list == NULL), "[calendar] calendar_db_get_changes_by_version() Fail!: err[%d]", service_ret);
1254
1255         int list_count = 0;
1256         service_ret = calendar_list_get_count(service_changed_list, &list_count);
1257         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_list_get_count() Fail!: err[%d]", service_ret);
1258
1259         _DEBUG_INFO("[calendar] in calendar_list_get_count [%d]!", list_count);
1260         if (list_count <= 0) {
1261                 goto return_part;
1262         }
1263
1264         service_ret = calendar_list_first(service_changed_list);
1265         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_get_child_record_count() Fail!: err[%d]", service_ret);
1266
1267         _DEBUG_INFO("[calendar] service_ret : %d\n", service_ret);
1268
1269         do {
1270                 service_ret = calendar_list_get_current_record_p(service_changed_list, &changed_event);
1271                 goto_if((service_ret != CALENDAR_ERROR_NONE) && (changed_event == NULL), "[calendar] calendar_record_get_child_record_count() Fail!: err[%d]", service_ret);
1272
1273                 int type = 0;
1274                 service_ret = calendar_record_get_int(changed_event, _calendar_updated_info.modified_status, &type);
1275                 if (service_ret != CALENDAR_ERROR_NONE) {
1276                         _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1277                         break;
1278                 }
1279
1280                 if (type == CALENDAR_EVENT_MODIFIED_STATUS_UPDATED) {
1281                         int calendar_id = 0;
1282                         service_ret = calendar_record_get_int(changed_event, _calendar_updated_info.id, &calendar_id);
1283                         if (service_ret != CALENDAR_ERROR_NONE) {
1284                                 _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1285                                 break;
1286                         }
1287                         char *calendar_id_str = g_strdup_printf("%d", calendar_id);
1288                         _DEBUG_INFO("[calendar] CALS_UPDATED_TYPE_MODIFIED : [%s]\n", calendar_id_str);
1289
1290                         if (root_ptr == NULL) {
1291                                 root_ptr = (sync_agent_plugin_item_node_s *) calloc(1, sizeof(sync_agent_plugin_item_node_s));
1292                                 if (root_ptr == NULL) {
1293                                         _DEBUG_ERROR("CALLOC failed !!!");
1294                                         if (service_changed_list != NULL) {
1295                                                 calendar_list_destroy(service_changed_list, true);
1296                                                 service_changed_list = NULL;
1297                                         }
1298                                         return NULL;
1299                                 }
1300                                 root_ptr->item_id = calendar_id_str;
1301                                 root_ptr->next = NULL;
1302                                 cursor_ptr = root_ptr;
1303                         } else {
1304                                 cursor_ptr->next = (sync_agent_plugin_item_node_s *) calloc(1, sizeof(sync_agent_plugin_item_node_s));
1305                                 if (cursor_ptr->next == NULL) {
1306                                         _DEBUG_ERROR("CALLOC failed !!!");
1307                                         if (service_changed_list != NULL) {
1308                                                 calendar_list_destroy(service_changed_list, true);
1309                                                 service_changed_list = NULL;
1310                                         }
1311                                         if (root_ptr) {
1312                                                 free(root_ptr);
1313                                                 root_ptr = NULL;
1314                                         }
1315                                         return NULL;
1316                                 }
1317                                 cursor_ptr->next->item_id = calendar_id_str;
1318                                 cursor_ptr->next->next = NULL;
1319                                 cursor_ptr = cursor_ptr->next;
1320                         }
1321                         chagned_count++;
1322                         // end of normal calendar
1323
1324                         // Check whether this calendar have updated exdate child
1325                         calendar_record_h cal_record = NULL;
1326                         unsigned int updated_exdate_count = 0;
1327                         service_ret = calendar_db_get_record(_calendar_event._uri, calendar_id, &cal_record);
1328                         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_db_get_record() Fail!: err[%d]", service_ret);
1329
1330                         service_ret = calendar_record_get_child_record_count(cal_record, _calendar_event.exception, &updated_exdate_count);
1331                         goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_get_child_record_count() Fail!: err[%d]", service_ret);
1332                         _DEBUG_INFO("updated_exdate_count(%d)", updated_exdate_count);
1333
1334                         if (updated_exdate_count > 0) {
1335                                 cursor_ptr->parent_item_id = g_strdup("-1"); // parent_item_id of the parent item should be set to "-1"
1336                         }
1337
1338                         int index = 0;
1339                         for (index = 0; index < updated_exdate_count; index++) {
1340                                 calendar_record_h updated_exdate_record = NULL;
1341                                 int child_service_id = 0;
1342                                 int original_event_id = 0;
1343                                 char *recurrence_id = NULL;
1344
1345                                 service_ret = calendar_record_get_child_record_at_p(cal_record, _calendar_event.exception, index, &updated_exdate_record);
1346                                 goto_if(service_ret != CALENDAR_ERROR_NONE || updated_exdate_record == NULL, "[calendar] calendar_record_get_child_record_at_p() Fail!: err[%d]", service_ret);
1347
1348                                 service_ret = calendar_record_get_int(updated_exdate_record, _calendar_event.id, &child_service_id);
1349                                 goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_get_int() Fail!: err[%d]", service_ret);
1350                                 _DEBUG_INFO("child_service_id = %d", child_service_id);
1351
1352                                 service_ret = calendar_record_get_int(updated_exdate_record, _calendar_event.original_event_id, &original_event_id);
1353                                 goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_get_int() Fail!: err[%d]", service_ret);
1354                                 _DEBUG_INFO("original_event_id = %d", original_event_id);
1355
1356                                 service_ret = calendar_record_get_str(updated_exdate_record, _calendar_event.recurrence_id, &recurrence_id);
1357                                 goto_if(service_ret != CALENDAR_ERROR_NONE, "[calendar] calendar_record_get_str() Fail!: err[%d]", service_ret);
1358                                 _DEBUG_INFO("recurrence_id = %s", recurrence_id);
1359
1360                                 service_ret = calendar_record_set_str(updated_exdate_record, _calendar_event.exdate, NULL);
1361                                 goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_set_str() Fail!: err[%d]", service_ret);
1362
1363                                 if (original_event_id >= 0 && recurrence_id != NULL && strlen(recurrence_id) > 0) {
1364                                         cursor_ptr->next = (sync_agent_plugin_item_node_s *) calloc(1, sizeof(sync_agent_plugin_item_node_s));
1365                                         if (cursor_ptr->next == NULL) {
1366                                                 _DEBUG_ERROR("CALLOC failed !!!");
1367                                                 if (service_changed_list != NULL) {
1368                                                         calendar_list_destroy(service_changed_list, true);
1369                                                         service_changed_list = NULL;
1370                                                 }
1371                                                 if (root_ptr) {
1372                                                         free(root_ptr);
1373                                                         root_ptr = NULL;
1374                                                 }
1375                                                 return NULL;
1376                                         }
1377                                         cursor_ptr->next->item_id = g_strdup_printf("%d", child_service_id);
1378                                         cursor_ptr->next->parent_item_id = g_strdup_printf("%d", original_event_id);
1379                                         cursor_ptr->next->next = NULL;
1380                                         cursor_ptr = cursor_ptr->next;
1381                                         chagned_count++;
1382                                 }
1383                         }
1384                         // end of child calendar
1385                 }
1386         } while (calendar_list_next(service_changed_list) != CALENDAR_ERROR_NO_DATA);
1387
1388  return_part:
1389         if (service_changed_list != NULL) {
1390                 calendar_list_destroy(service_changed_list, true);
1391                 service_changed_list = NULL;
1392         }
1393         *change_count = chagned_count;
1394         _EXTERN_FUNC_EXIT;
1395         return root_ptr;
1396 }
1397
1398 EXPORT_API int sync_agent_plugin_get_last_change_point(void)
1399 {
1400         _EXTERN_FUNC_ENTER;
1401
1402         int calendar_db_version = 0;
1403         int service_ret = calendar_db_get_current_version(&calendar_db_version);
1404         if (service_ret != CALENDAR_ERROR_NONE) {
1405                 _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1406         }
1407         _EXTERN_FUNC_EXIT;
1408
1409         return calendar_db_version;
1410 }
1411
1412 EXPORT_API void sync_agent_plugin_start_listening_change_noti(void *data)
1413 {
1414         _EXTERN_FUNC_ENTER;
1415
1416         int service_ret = calendar_db_add_changed_cb(_calendar_event._uri, _process_calendar_change, NULL);
1417         if (service_ret != CALENDAR_ERROR_NONE) {
1418                 _DEBUG_ERROR("calendar_db_add_changed_cb() Fail!: err = %d", service_ret);
1419         }
1420
1421         latest_calendar_version = sync_agent_plugin_get_last_change_point();
1422         _DEBUG_INFO("Current Latest Calendar Version : %d", latest_calendar_version);
1423
1424         pthread_t thread_process_change_id;
1425         if (pthread_create(&thread_process_change_id, 0, _rutine_calendar_change, 0) < 0) {
1426                 _DEBUG_ERROR("Calendar Change Noti Handling Thread Create Error");
1427         }
1428
1429         _EXTERN_FUNC_EXIT;
1430 }
1431
1432 EXPORT_API void sync_agent_plugin_set_callback_add_item(sync_agent_add_item_cb_plugin callback)
1433 {
1434         _EXTERN_FUNC_ENTER;
1435
1436         callback_add_item = callback;
1437
1438         _EXTERN_FUNC_EXIT;
1439 }
1440
1441 EXPORT_API void sync_agent_plugin_set_callback_delete_item(sync_agent_del_item_cb_plugin callback)
1442 {
1443         _EXTERN_FUNC_ENTER;
1444
1445         callback_del_item = callback;
1446
1447         _EXTERN_FUNC_EXIT;
1448 }
1449
1450 EXPORT_API void sync_agent_plugin_set_callback_update_item(sync_agent_update_item_cb_plugin callback)
1451 {
1452         _EXTERN_FUNC_ENTER;
1453
1454         callback_update_item = callback;
1455
1456         _EXTERN_FUNC_EXIT;
1457 }
1458
1459 EXPORT_API void sync_agent_plugin_set_callback_get_account_id_list(sync_agent_get_account_id_list_cb_plugin callback)
1460 {
1461         _EXTERN_FUNC_ENTER;
1462
1463         callback_get_account_id_list = callback;
1464
1465         _EXTERN_FUNC_EXIT;
1466 }
1467
1468 EXPORT_API void sync_agent_plugin_set_callback_delete_child_item(sync_agent_del_child_item_cb_plugin callback)
1469 {
1470         _EXTERN_FUNC_ENTER;
1471         callback_delete_child_item = callback;
1472         _EXTERN_FUNC_EXIT;
1473 }
1474
1475 EXPORT_API int sync_agent_plugin_get_max_item_count(int folder_type)
1476 {
1477         _EXTERN_FUNC_ENTER;
1478
1479         _EXTERN_FUNC_EXIT;
1480
1481         return MAX_ITEM_COUNT_CALENDAR;
1482 }
1483
1484 EXPORT_API int sync_agent_plugin_get_max_field_length(int field_name, int child_field_name)
1485 {
1486         _EXTERN_FUNC_ENTER;
1487
1488         switch (field_name) {
1489         case CALENDAR_FIELD_SUMMARY:
1490                 _EXTERN_FUNC_EXIT;
1491                 return MAX_LEN_SUMMARY;
1492         case CALENDAR_FIELD_DESCRIPTION:
1493                 _EXTERN_FUNC_EXIT;
1494                 return MAX_LEN_DESCRIPTION;
1495         case CALENDAR_FIELD_LOCATOIN:
1496                 _EXTERN_FUNC_EXIT;
1497                 return MAX_LEN_LOCATION;
1498         case CALENDAR_FIELD_MEMO:
1499                 _EXTERN_FUNC_EXIT;
1500                 return MAX_LEN_MEMO;
1501         default:
1502                 _EXTERN_FUNC_EXIT;
1503                 return -1;
1504         }
1505 }
1506
1507 EXPORT_API int sync_agent_plugin_get_max_field_count(int field_name, int child_field_name)
1508 {
1509         _EXTERN_FUNC_ENTER;
1510
1511         _EXTERN_FUNC_EXIT;
1512
1513         return -1;
1514 }
1515
1516 EXPORT_API int sync_agent_plugin_get_field_value(int field_name, int child_field_name, char **str_val, int *num_val1, int *num_val2)
1517 {
1518         _EXTERN_FUNC_ENTER;
1519
1520         switch (field_name) {
1521         case CALENDAR_FIELD_YEAR:
1522                 *num_val1 = MIN_PERIOD_YEAR;
1523                 *num_val2 = MAX_PERIOD_YEAR;
1524                 _EXTERN_FUNC_EXIT;
1525                 return 1;
1526         case CALENDAR_FIELD_TYPE_MODEL:
1527                 *str_val = VAL_TYPE_MODEL;
1528                 _EXTERN_FUNC_EXIT;
1529                 return 1;
1530         case CALENDAR_FIELD_DB_INDEX:
1531                 switch (child_field_name) {
1532                 case CALENDAR_FEATURE_APPOINTMENT:
1533                         *num_val1 = VAL_DB_INDEX_APPOINTMENT;
1534                         _EXTERN_FUNC_EXIT;
1535                         return 1;
1536                 case CALENDAR_FEATURE_ANNIVERSARY:
1537                         *num_val1 = VAL_DB_INDEX_ANNIVERSARY;
1538                         _EXTERN_FUNC_EXIT;
1539                         return 1;
1540                 case CALENDAR_FEATURE_HOLIDAY:
1541                         *num_val1 = VAL_DB_INDEX_HOLIDAY;
1542                         _EXTERN_FUNC_EXIT;
1543                         return 1;
1544                 case CALENDAR_FEATURE_IMPORTANT:
1545                         *num_val1 = VAL_DB_INDEX_IMPORTANT;
1546                         _EXTERN_FUNC_EXIT;
1547                         return 1;
1548                 case CALENDAR_FEATURE_PRIVATE:
1549                         *num_val1 = VAL_DB_INDEX_PRIVATE;
1550                         _EXTERN_FUNC_EXIT;
1551                         return 1;
1552                 case CALENDAR_FEATURE_MISCELLANEOUS:
1553                         *num_val1 = VAL_DB_INDEX_MISCELLANEOUS;
1554                         _EXTERN_FUNC_EXIT;
1555                         return 1;
1556                 case CALENDAR_FEATURE_TASK:
1557                         *num_val1 = VAL_DB_INDEX_TASK;
1558                         _EXTERN_FUNC_EXIT;
1559                         return 1;
1560                 case CALENDAR_FEATURE_MEMO:
1561                         *num_val1 = VAL_DB_INDEX_MEMO;
1562                         _EXTERN_FUNC_EXIT;
1563                         return 1;
1564                 default:
1565                         return -1;
1566                 }
1567         case CALENDAR_FIELD_TIMEZONE:
1568                 switch (child_field_name) {
1569                 case CALENDAR_CHILD_FIELD_BIAS:
1570                         *num_val1 = (int)VAL_TZ_BIAS;
1571                         _EXTERN_FUNC_EXIT;
1572                         return 1;
1573                 case CALENDAR_CHILD_FIELD_DAYLIGHT:
1574                         *num_val1 = (int)VAL_TZ_DAYLIGHT;
1575                         _EXTERN_FUNC_EXIT;
1576                         return 1;
1577                 case CALENDAR_CHILD_FIELD_DAYLIGHT_BIAS:
1578                         *num_val1 = (int)VAL_TZ_DAYLIGHT_BIAS;
1579                         _EXTERN_FUNC_EXIT;
1580                         return 1;
1581                 case CALENDAR_CHILD_FIELD_DAYLIGHT_BEGIN:
1582                         *str_val = VAL_TZ_DAYLIGHT_BEGIN;
1583                         _EXTERN_FUNC_EXIT;
1584                         return 1;
1585                 case CALENDAR_CHILD_FIELD_DAYLIGHT_END:
1586                         *str_val = VAL_TZ_DAYLIGHT_END;
1587                         _EXTERN_FUNC_EXIT;
1588                         return 1;
1589                 case CALENDAR_CHILD_FIELD_STANDARD_TIMENAME:
1590                         *str_val = VAL_TZ_STANDARD_TIMENAME;
1591                         _EXTERN_FUNC_EXIT;
1592                         return 1;
1593                 case CALENDAR_CHILD_FIELD_DAYLIGHT_TIMENAME:
1594                         *str_val = VAL_TZ_DAYLIGHT_TIMENAME;
1595                         _EXTERN_FUNC_EXIT;
1596                         return 1;
1597                 default:
1598                         return -1;
1599                 }
1600         default:
1601                 return -1;
1602         }
1603 }
1604
1605 EXPORT_API int sync_agent_plugin_get_is_support_feature(int feature)
1606 {
1607         _EXTERN_FUNC_ENTER;
1608
1609         switch (feature) {
1610         case CALENDAR_FEATURE_APPOINTMENT:
1611                 _EXTERN_FUNC_EXIT;
1612                 return IF_SUPPORT_APPOINTMENT;
1613         case CALENDAR_FEATURE_ANNIVERSARY:
1614                 _EXTERN_FUNC_EXIT;
1615                 return IF_SUPPORT_ANNIVERSARY;
1616         case CALENDAR_FEATURE_HOLIDAY:
1617                 _EXTERN_FUNC_EXIT;
1618                 return IF_SUPPORT_HOLIDAY;
1619         case CALENDAR_FEATURE_IMPORTANT:
1620                 _EXTERN_FUNC_EXIT;
1621                 return IF_SUPPORT_IMPORTANT;
1622         case CALENDAR_FEATURE_PRIVATE:
1623                 _EXTERN_FUNC_EXIT;
1624                 return IF_SUPPORT_PRIVATE;
1625         case CALENDAR_FEATURE_MISCELLANEOUS:
1626                 _EXTERN_FUNC_EXIT;
1627                 return IF_SUPPORT_MISCELLANEOUS;
1628         case CALENDAR_FEATURE_TASK:
1629                 _EXTERN_FUNC_EXIT;
1630                 return IF_SUPPORT_TASK;
1631         case CALENDAR_FEATURE_MEMO:
1632                 _EXTERN_FUNC_EXIT;
1633                 return IF_SUPPORT_MEMO;
1634         default:
1635                 return -1;
1636         }
1637 }
1638
1639 /********************************** static function *******************************************/
1640
1641 static void _set_is_noti_from_me(int set_flag)
1642 {
1643         _INNER_FUNC_ENTER;
1644
1645         if (pthread_mutex_lock(&lockx)) {
1646                 _DEBUG_ERROR("[calendar] pthread_mutex_lock error");
1647         }
1648
1649         is_noti_from_me = set_flag;
1650
1651         if (pthread_mutex_unlock(&lockx)) {
1652                 _DEBUG_ERROR("[calendar] pthread_mutex_unlock error");
1653         }
1654
1655         _INNER_FUNC_EXIT;
1656 }
1657
1658 static int __get_is_noti_from_me(void)
1659 {
1660         _INNER_FUNC_ENTER;
1661
1662         _INNER_FUNC_EXIT;
1663
1664         return is_noti_from_me;
1665 }
1666
1667 static char * _get_value_by_token(const char *src, const char *token, const char *end_of_token)
1668 {
1669         _INNER_FUNC_ENTER;
1670         if (src == NULL || strlen(src) <= 0) {
1671                 _DEBUG_ERROR("src is null");
1672                 return NULL;
1673         }
1674
1675         char *token_loc = NULL;
1676         char *str_output = NULL;
1677
1678         if ((token_loc = strstr(src, token)) != NULL) {
1679                 char *str_temp = strstr(token_loc, end_of_token);
1680                 if (str_temp != NULL) {
1681                         int ret_str_length = strlen(token_loc) - strlen(token) - strlen(str_temp);
1682                         if (ret_str_length <= 0) {
1683                                 _DEBUG_ERROR("token_loc = %s", token_loc);
1684                                 _DEBUG_ERROR("token = %s", token);
1685                                 _DEBUG_ERROR("str_temp = %s", str_temp);
1686                                 _DEBUG_ERROR("ret_str_length(%d) <= 0", ret_str_length);
1687                                 goto return_part;
1688                         }
1689                         str_output = (char *)calloc(ret_str_length, sizeof(char));
1690                         goto_if(str_output == NULL, "str_output is NULL");
1691
1692                         memcpy(str_output, token_loc + strlen(token), ret_str_length);
1693                 }
1694         }
1695
1696 return_part:
1697         _INNER_FUNC_EXIT;
1698         return str_output;
1699 }
1700
1701 void _process_calendar_change(const char *view_uri, void *user_data)
1702 {
1703         _INNER_FUNC_ENTER;
1704         _DEBUG_TRACE("[calendar] detected calendar storage changed\n");
1705
1706         int from_Me = __get_is_noti_from_me();
1707         if (from_Me == 1) {
1708                 _set_is_noti_from_me(0);
1709                 _DEBUG_TRACE("[calendar] This noti is from Me!! so will be ignored!!\n");
1710                 return;
1711         }
1712
1713         int *calendarVersion = (int *)calloc(1, sizeof(int));
1714         if (calendarVersion == NULL) {
1715                 _DEBUG_ERROR("CALLOC failed !!!");
1716                 return;
1717         }
1718         *calendarVersion = latest_calendar_version;
1719         latest_calendar_version++;
1720
1721         _DEBUG_INFO("fw_async_queue_length = %d", sync_agent_async_queue_length(queue));
1722         if (sync_agent_async_queue_length(queue) < 1) {
1723                 sync_agent_send_msg_async_queue(queue, (void *)calendarVersion);
1724                 _DEBUG_INFO("fw_async_queue_length = %d", sync_agent_async_queue_length(queue));
1725         } else {
1726                 _DEBUG_INFO("send_msg_failed... sync_agent_async_queue_length(queue) >= 1");
1727                 if(calendarVersion != NULL) {
1728                         free(calendarVersion);
1729                         calendarVersion = NULL;
1730                 }
1731         }
1732
1733         _INNER_FUNC_EXIT;
1734 }
1735
1736 static void *_rutine_calendar_change(void *data)
1737 {
1738         _INNER_FUNC_ENTER;
1739
1740         _DEBUG_TRACE("[calendar] Start __rutine_Calendar_Change (create thread)\n");
1741
1742         /*
1743          * Create Queue
1744          */
1745         queue = sync_agent_alloc_async_queue();
1746         if (queue == NULL) {
1747                 _DEBUG_ERROR("Failed to call fw_async_queue_alloc()");
1748                 return 0;
1749         }
1750
1751         calendar_list_h folder_list = NULL;
1752         calendar_list_h record_list = NULL;
1753         int service_ret = 0;
1754
1755         // open calendar service
1756         sync_agent_plugin_open_service();
1757
1758         while (1) {
1759                 _DEBUG_TRACE("fw_async_queue_length = %d", sync_agent_async_queue_length(queue));
1760                 int *temp_calendar_version = sync_agent_receive_msg_async_queue(queue);
1761                 int calendar_version = *temp_calendar_version;
1762                 free(temp_calendar_version);
1763
1764                 _DEBUG_TRACE("Detected Change calendarVersion : %d", calendar_version);
1765
1766                 int account_list_count;
1767                 int *account_list = callback_get_account_id_list(FW_CALENDAR, &account_list_count);
1768                 if (account_list == NULL)
1769                         return 0;
1770
1771                 int i = 0;
1772                 for (; i < account_list_count; i++) {
1773                         int calendar_account_id = account_list[i];
1774                         _DEBUG_TRACE("[calendar] calendar_account_id : %d, count : %d\n", calendar_account_id, account_list_count);
1775                         _DEBUG_TRACE("[calendar] Before calendar_svc_event_get_changes : %d\n", calendar_version);
1776
1777                         /*get folder id */
1778                         int folder_list_count = 0;
1779                         service_ret = _get_service_folder_list_by_account_id(calendar_account_id, &folder_list, &folder_list_count);
1780                         if (service_ret != SYNC_AGENT_DA_SUCCESS || folder_list == NULL) {
1781                                 _DEBUG_ERROR("calendar_list_get_count() Fail! : err = %d", service_ret);
1782                                 break;
1783                         }
1784                         _DEBUG_TRACE("[calendar] folder_list_count : %d", folder_list_count);
1785
1786                         do {
1787
1788                                 calendar_record_h folder = NULL;
1789                                 service_ret = calendar_list_get_current_record_p(folder_list, &folder);
1790                                 if ((service_ret != CALENDAR_ERROR_NONE) && (folder == NULL)) {
1791                                         _DEBUG_ERROR("calendar_list_get_current_record_p() Fail! : err = %d", service_ret);
1792                                         break;
1793                                 }
1794
1795                                 int calendar_folder_id = 0;
1796                                 service_ret = calendar_record_get_int(folder, _calendar_book.id, &calendar_folder_id);
1797                                 if (service_ret != CALENDAR_ERROR_NONE) {
1798                                         _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1799                                         break;
1800                                 }
1801
1802                                 int current_cal_db_ver = 0;
1803                                 service_ret = calendar_db_get_changes_by_version(_calendar_event._uri, calendar_folder_id, calendar_version, &record_list, &current_cal_db_ver);
1804                                 if (service_ret != CALENDAR_ERROR_NONE || record_list == NULL) {
1805                                         _DEBUG_ERROR("calendar_db_get_changes_by_version() Fail!: calendar_folder_id = %d, err = %d", calendar_folder_id, service_ret);
1806                                         continue;
1807                                 }
1808                                 _DEBUG_TRACE("calendar_db_get_changes_by_version() Success, calendar_folderId = %d", calendar_folder_id);
1809
1810                                 service_ret = calendar_list_first(record_list);
1811                                 if (service_ret != CALENDAR_ERROR_NONE) {
1812                                         _DEBUG_ERROR("calendar_list_first() Fail! : err = %d", service_ret);
1813                                         break;
1814                                 }
1815                                 int recode_count = 0;
1816                                 service_ret = calendar_list_get_count(record_list, &recode_count);
1817                                 if (service_ret != CALENDAR_ERROR_NONE) {
1818                                         _DEBUG_ERROR("calendar_list_get_count() Fail! : err = %d", service_ret);
1819                                         break;
1820                                 }
1821                                 _DEBUG_TRACE("recode list count = %d", recode_count);
1822                                 if (recode_count == 0) {
1823                                         continue;
1824                                 }
1825
1826                                 do {
1827                                         calendar_record_h row_event = NULL;
1828                                         service_ret = calendar_list_get_current_record_p(record_list, &row_event);
1829                                         if ((service_ret != CALENDAR_ERROR_NONE) && (row_event == NULL)) {
1830                                                 _DEBUG_ERROR("calendar_list_get_current_record_p() Fail! : err = %d", service_ret);
1831                                                 break;
1832                                         }
1833
1834                                         int calendar_id = 0;
1835                                         service_ret = calendar_record_get_int(row_event, _calendar_updated_info.id, &calendar_id);
1836                                         if (service_ret != CALENDAR_ERROR_NONE) {
1837                                                 _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1838                                                 break;
1839                                         }
1840
1841                                         _DEBUG_TRACE("recode list count = %d", recode_count);
1842                                         char calendar_id_str[12];
1843                                         snprintf(calendar_id_str, sizeof(calendar_id_str), "%d", calendar_id);
1844
1845                                         int type = 0;
1846                                         service_ret = calendar_record_get_int(row_event, _calendar_updated_info.modified_status, &type);
1847                                         if (service_ret != CALENDAR_ERROR_NONE) {
1848                                                 _DEBUG_ERROR("calendar_record_get_int() Fail!: err = %d", service_ret);
1849                                                 break;
1850                                         }
1851                                         switch (type) {
1852                                         case CALENDAR_EVENT_MODIFIED_STATUS_INSERTED:
1853                                                 {
1854                                                         _DEBUG_INFO("[calendar] Calendar Inserted!\n");
1855                                                         char calendar_folder_id_str[12];
1856                                                         snprintf(calendar_folder_id_str, sizeof(calendar_folder_id_str), "%d", calendar_folder_id);
1857
1858                                                         _DEBUG_INFO("[calendar] calendar folder id : %s\n", calendar_folder_id_str);
1859                                                         int result = callback_add_item(account_list[i], i, calendar_id_str, NULL, FW_CALENDAR, calendar_folder_id_str, 0);
1860                                                         if (!result)
1861                                                                 _DEBUG_ERROR("[calendar] Failed to call SA_EH_Add_Item() \n");
1862                                                 }
1863                                                 break;
1864                                         case CALENDAR_EVENT_MODIFIED_STATUS_UPDATED:
1865                                                 {
1866                                                         _DEBUG_INFO("[calendar] Calendar Updated!\n");
1867                                                         char *parend_id = NULL;
1868                                                         int exdate_count = 0;
1869                                                         char calendar_folder_id_str[12];
1870
1871                                                         snprintf(calendar_folder_id_str, sizeof(calendar_folder_id_str), "%d", calendar_folder_id);
1872                                                         _DEBUG_INFO("[calendar] calendar folder id : %s\n", calendar_folder_id_str);
1873
1874                                                         exdate_count = _add_updated_exdate_item(account_list[i], i, calendar_id_str, calendar_folder_id_str);
1875                                                         if (exdate_count > 0) {
1876                                                                 parend_id = g_strdup("-1");
1877                                                         }
1878
1879                                                         int result = callback_update_item(account_list[i], i, calendar_id_str, parend_id, FW_CALENDAR);
1880                                                         if (!result)
1881                                                                 _DEBUG_ERROR("[calendar] Failed to call callback_update_item() \n");
1882                                                 }
1883                                                 break;
1884                                         case CALENDAR_EVENT_MODIFIED_STATUS_DELETED:
1885                                                 {
1886                                                         _DEBUG_INFO("[calendar] Calendar Deleted!\n");
1887                                                         int result = callback_del_item(account_list[i], i, calendar_id_str, FW_CALENDAR);
1888                                                         if (!result)
1889                                                                 _DEBUG_ERROR("[calendar] Failed to call callback_del_item() \n");
1890                                                 }
1891                                                 break;
1892                                         default:
1893                                                 _DEBUG_INFO("[calendar] cached Another Calendar Change Noti!\n");
1894                                                 break;
1895                                         }
1896                                 } while (calendar_list_next(record_list) != CALENDAR_ERROR_NO_DATA);
1897
1898                                 if (record_list != NULL) {
1899                                         service_ret = calendar_list_destroy(record_list, true);
1900                                         if (service_ret != CALENDAR_ERROR_NONE) {
1901                                                 _DEBUG_ERROR("calendar_list_destroy() Fail! : err = %d", service_ret);
1902                                         }
1903                                         record_list = NULL;
1904                                 }
1905                         } while (calendar_list_next(folder_list) != CALENDAR_ERROR_NO_DATA);
1906
1907                         _DEBUG_TRACE("folder list free");
1908                         if (folder_list != NULL) {
1909                                 service_ret = calendar_list_destroy(folder_list, true);
1910                                 if (service_ret != CALENDAR_ERROR_NONE) {
1911                                         _DEBUG_ERROR("calendar_list_destroy() Fail! : err = %d", service_ret);
1912                                 }
1913                                 folder_list = NULL;
1914                         }
1915                 }
1916                 _DEBUG_TRACE("account list free");
1917                 if (account_list != NULL) {
1918                         free(account_list);
1919                 }
1920         }
1921
1922         sync_agent_plugin_close_service();
1923         _DEBUG_TRACE("[calendar] End __rutine_Calendar_Change (create thread)\n");
1924         _INNER_FUNC_EXIT;
1925         return 0;
1926 }
1927
1928 static sync_agent_da_return_e _convert_service_error_to_common_error(int err)
1929 {
1930         _INNER_FUNC_ENTER;
1931
1932         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
1933         _DEBUG_TRACE("[calendar] Error Code : %d\n", err);
1934
1935         switch (err) {
1936         case CALENDAR_ERROR_NONE:
1937                 ret = SYNC_AGENT_DA_SUCCESS;
1938                 break;
1939
1940         case CALENDAR_ERROR_INVALID_PARAMETER:  /* -4 */
1941                 ret = SYNC_AGENT_DA_ERR_INVALID_CONTENT;
1942                 break;
1943
1944         default:
1945                 ret = SYNC_AGENT_DA_ERRORS;
1946                 break;
1947         }
1948
1949         _INNER_FUNC_EXIT;
1950         return ret;
1951 }
1952
1953 static bool _get_account_id(account_h account, void *user_data)
1954 {
1955         _INNER_FUNC_ENTER;
1956
1957         account_id_s *account_info_list = user_data;
1958
1959         bool has_contact = FALSE;
1960
1961         account_get_capability_all(account, __is_calendar_id, &has_contact);
1962
1963         if (has_contact == FALSE) {
1964                 /* DO Nothing */
1965                 _DEBUG_INFO("has_contact is false");
1966         } else {
1967                 char *domain_name = NULL;
1968                 account_error_e error_code = account_get_domain_name(account, &domain_name);
1969                 if (error_code != ACCOUNT_ERROR_NONE) {
1970                         _DEBUG_ERROR("Failed to call account_get_domain_name()");
1971                         return has_contact;
1972                 }
1973
1974                 /*local service id already in id list so pass */
1975                 _DEBUG_INFO("domain_name = %s", domain_name);
1976                 if (strcmp(domain_name, "Gmail") && strcmp(domain_name, "exchange")) {
1977                         _DEBUG_TRACE("domain is [%s] is not gmail&exchange");
1978                         return has_contact;
1979                 }
1980
1981                 account_id_s *account_info = (account_id_s *) calloc(1, sizeof(account_id_s));
1982                 if (account_info == NULL) {
1983                         _DEBUG_ERROR("CALLOC failed !!!");
1984                         return FALSE;
1985                 }
1986                 account_get_account_id(account, &(account_info->account_id));
1987                 _DEBUG_TRACE("Getted accont id : %d", account_info->account_id);
1988                 account_info->next = 0;
1989
1990                 account_id_s *cursor_ptr = account_info_list;
1991                 while (cursor_ptr->next != 0) {
1992                         cursor_ptr = cursor_ptr->next;
1993                 }
1994
1995                 cursor_ptr->next = account_info;
1996         }
1997
1998         _INNER_FUNC_EXIT;
1999
2000         return has_contact;
2001 }
2002
2003 static bool __is_calendar_id(const char* capability_type, account_capability_state_e capability_value, void *user_data)
2004 {
2005         _INNER_FUNC_ENTER;
2006         retvm_if(capability_type == NULL, FALSE, "capability_type is NULL !!");
2007
2008         bool *has_contact = user_data;
2009         if (strncmp(capability_type, ACCOUNT_SUPPORTS_CAPABILITY_CALENDAR, strlen(capability_type)) == 0) {
2010                 *has_contact = TRUE;
2011                 _INNER_FUNC_EXIT;
2012                 return FALSE;
2013         }
2014         _INNER_FUNC_EXIT;
2015         return TRUE;
2016 }
2017
2018 static int _add_updated_exdate_item(int service_account_id, int index, char *parent_service_item_id, char *service_folder_id)
2019 {
2020         _EXTERN_FUNC_ENTER;
2021         retvm_if(parent_service_item_id == NULL, 0, "parent_service_item_id is NULL !!");
2022
2023         // Check whether this calendar have updated exdate child
2024         calendar_record_h cal_record = NULL;
2025         unsigned int exception_count = 0;
2026         int result = 0;
2027         int service_ret = 0;
2028         int updated_exdate_count = 0;
2029
2030         service_ret = calendar_db_get_record(_calendar_event._uri, atoi(parent_service_item_id), &cal_record);
2031         goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_db_get_record() Fail!: err[%d]", service_ret);
2032
2033         service_ret = calendar_record_get_child_record_count(cal_record, _calendar_event.exception, &exception_count);
2034         goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_child_record_count() Fail!: err[%d]", service_ret);
2035
2036         _DEBUG_INFO("exception_count = %d, parent_service_item_id = %s", exception_count, parent_service_item_id);
2037         goto_if(exception_count <= 0, "exception_count <= 0");
2038
2039         // All child item of parent item whose has original_event_id as service_id field should be deleted before callback_add_item()
2040         // Requesting by Calendar Svc  Team (2013-03-26 tw123.kim & iamjs.kim)
2041         result = callback_delete_child_item(parent_service_item_id, NULL);
2042         if (!result)
2043                 _DEBUG_ERROR("Failed to call callback_delete_child_item() \n");
2044
2045         int exdate_index = 0;
2046         for (exdate_index = 0; exdate_index < exception_count; exdate_index++) {
2047                 calendar_record_h updated_exdate_record = NULL;
2048                 int child_service_id = 0;
2049                 int original_event_id = 0;
2050                 char *recurrence_id = NULL;
2051
2052                 service_ret = calendar_record_get_child_record_at_p(cal_record, _calendar_event.exception, exdate_index, &updated_exdate_record);
2053                 goto_if(service_ret != CALENDAR_ERROR_NONE || updated_exdate_record == NULL, "calendar_record_get_child_record_at_p() Fail!: err[%d]", service_ret);
2054
2055                 service_ret = calendar_record_get_int(updated_exdate_record, _calendar_event.id, &child_service_id);
2056                 goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_int() Fail!: err[%d]", service_ret);
2057
2058                 char *child_id = g_strdup_printf("%d", child_service_id);
2059                 _DEBUG_INFO("child_id = %s", child_id);
2060
2061                 service_ret = calendar_record_get_int(updated_exdate_record, _calendar_event.original_event_id, &original_event_id);
2062                 goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_int() Fail!: err[%d]", service_ret);
2063                 _DEBUG_INFO("original_event_id = %d", original_event_id);
2064
2065                 service_ret = calendar_record_get_str(updated_exdate_record, _calendar_event.recurrence_id, &recurrence_id);
2066                 goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_str() Fail!: err[%d]", service_ret);
2067                 _DEBUG_INFO("recurrence_id = %s", recurrence_id);
2068
2069                 service_ret = calendar_record_set_str(updated_exdate_record, _calendar_event.exdate, NULL);
2070                 goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_set_str() Fail!: err[%d]", service_ret);
2071
2072                 if (original_event_id >= 0 && recurrence_id != NULL && strlen(recurrence_id) > 0) {
2073                         char *parent_id = strdup(parent_service_item_id);
2074                         result = callback_add_item(service_account_id, index, child_id, parent_id, FW_CALENDAR, service_folder_id, 0);
2075                         if (!result)
2076                                 _DEBUG_ERROR("Failed to call SA_EH_Add_Item() \n");
2077                         else {
2078                                 _DEBUG_INFO("Success to call SA_EH_Add_Item() \n");
2079                                 updated_exdate_count++;
2080                         }
2081                 }
2082         }
2083
2084 return_part:
2085         _DEBUG_INFO("updated_exdate_count = %d", updated_exdate_count);
2086         _INNER_FUNC_EXIT;
2087         return updated_exdate_count;
2088 }
2089
2090 static sync_agent_da_return_e _process_exdate_item(calendar_record_h calendar_record)
2091 {
2092         _INNER_FUNC_ENTER;
2093         retvm_if(calendar_record == NULL, SYNC_AGENT_DA_ERRORS, "calendar_record is NULL !!");
2094
2095         sync_agent_da_return_e ret = SYNC_AGENT_DA_SUCCESS;
2096         int service_ret = CALENDAR_ERROR_NONE;
2097         gchar **array_delete_exdate = NULL;
2098         GList *matched_item_list = NULL;
2099
2100         // case 1 : updated exdate item doesn't need to calendar_db_update_record(), so just return this API
2101         char *check_exdate_update = NULL;
2102         service_ret = calendar_record_get_str(calendar_record, _calendar_event.recurrence_id, &check_exdate_update);
2103         goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_str() Fail!: err[%d]", service_ret);
2104
2105         if (check_exdate_update != NULL && g_strcmp0(check_exdate_update, EXTYPE_UPDATE_KEYWORD) == 0) {
2106                 // this is a updated exdate item. it should be not done calendar_db_update_record(). so just return
2107                 ret = SYNC_AGENT_DA_ERR_ITEM_READ_ONLY;
2108                 goto return_part;
2109         }
2110
2111         // case 2 : the parent item which has updated exdate items, it should be got DB changing callback function
2112         unsigned int exception_count = 0;
2113         service_ret = calendar_record_get_child_record_count(calendar_record, _calendar_event.exception, &exception_count);
2114         goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_child_record_count() Fail!: err[%d]", service_ret);
2115         _DEBUG_INFO("exception_count(%d)", exception_count);
2116
2117         if (exception_count <= 0) {
2118                 _DEBUG_INFO("this record has not updated exdate item. so just return");
2119                 goto return_part;
2120         }
2121
2122         _DEBUG_INFO("this is a parent item of updated exdate items. it should be got DB changing callback function");
2123         _set_is_noti_from_me(0);
2124
2125         // case 3 : updated exdate items which exist at the same date of deleted exdate items, should be deleted
2126         // 3-1 : get the deleted exdate items
2127         char *exdate = NULL;
2128         service_ret = calendar_record_get_str(calendar_record, _calendar_event.exdate, &exdate);
2129         goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_str() Fail!: err[%d]", service_ret);
2130
2131         _DEBUG_INFO("exdate = %s", exdate);
2132         if (exdate == NULL) {
2133                 goto return_part;
2134         }
2135
2136         array_delete_exdate = g_strsplit(exdate, ",", -1);
2137         goto_if(array_delete_exdate == NULL, "array_delete_exdate is NULL");
2138
2139         // 3-2 : get the updated exdate items, After that check whether same date exist, or not.
2140         int updated_index = 0;
2141         for (updated_index = 0; updated_index < exception_count; updated_index++) {
2142                 calendar_record_h updated_exdate_record = NULL;
2143                 char *recurrence_id = NULL;
2144                 int deleted_index = 0;
2145
2146                 service_ret = calendar_record_get_child_record_at_p(calendar_record, _calendar_event.exception, updated_index, &updated_exdate_record);
2147                 goto_if(service_ret != CALENDAR_ERROR_NONE || updated_exdate_record == NULL, "calendar_record_get_child_record_at_p() Fail!: err[%d]", service_ret);
2148
2149                 service_ret = calendar_record_get_str(updated_exdate_record, _calendar_event.recurrence_id, &recurrence_id);
2150                 goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_str() Fail!: err[%d]", service_ret);
2151                 _DEBUG_INFO("updated_index = %d, recurrence_id = %s", updated_index, recurrence_id);
2152
2153                 for (deleted_index = 0; array_delete_exdate[deleted_index] != NULL; deleted_index++) {
2154                         _DEBUG_INFO("one_exdate = %s, deleted_index = %d", array_delete_exdate[deleted_index], deleted_index);
2155                         if (strcmp(recurrence_id, array_delete_exdate[deleted_index]) == 0) {
2156                                 _DEBUG_INFO("matched date = %s", array_delete_exdate[deleted_index]);
2157                                 matched_item_list = g_list_append(matched_item_list, updated_exdate_record);
2158                         }
2159                 }
2160         }
2161
2162         // 3-3 : delete the matched items
2163         int parent_service_item_id = 0;
2164         service_ret = calendar_record_get_int(calendar_record, _calendar_event.id, &parent_service_item_id);
2165         goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_int() Fail!: err[%d]", service_ret);
2166
2167         char *parent_id = g_strdup_printf("%d", parent_service_item_id);
2168         _DEBUG_INFO("parent_service_item_id = %s", parent_id);
2169
2170         int matched_count = g_list_length(matched_item_list);
2171         _DEBUG_INFO("matched_count = %d", matched_count);
2172
2173         int matched_index = 0;
2174         for (matched_index = 0; matched_index < matched_count; matched_index++) {
2175                 calendar_record_h record = (calendar_record_h)g_list_nth_data(matched_item_list, matched_index);
2176                 int child_service_id = 0;
2177
2178                 service_ret = calendar_record_remove_child_record(calendar_record, _calendar_event.exception, record);
2179                 goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_remove_child_record() Fail!: err[%d]", service_ret);
2180
2181                 service_ret = calendar_record_get_int(record, _calendar_event.id, &child_service_id);
2182                 goto_if(service_ret != CALENDAR_ERROR_NONE, "calendar_record_get_int() Fail!: err[%d]", service_ret);
2183
2184                 char *child_id = g_strdup_printf("%d", child_service_id);
2185                 _DEBUG_INFO("child_id for deleting = %s, index = %d", child_id, matched_index);
2186
2187                 ret = callback_delete_child_item(parent_id, child_id);
2188                 if (!ret)
2189                         _DEBUG_ERROR("Failed to call callback_delete_child_item() \n");
2190         }
2191
2192 return_part:
2193         if(array_delete_exdate) {
2194                 g_strfreev(array_delete_exdate);
2195                 array_delete_exdate = NULL;
2196         }
2197         if(matched_item_list) {
2198                 g_list_free(matched_item_list);
2199                 matched_item_list = NULL;
2200         }
2201         _INNER_FUNC_EXIT;
2202         return ret;
2203 }