wrt-plugins-tizen_0.4.23
[framework/web/wrt-plugins-tizen.git] / src / Calendar / Calendar.cpp
1 //
2 // Tizen Web Device API
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 <calendar2.h>
19 #include <dpl/scoped_ptr.h>
20 #include "Calendar.h"
21 #include "CalendarManager.h"
22 #include "CalendarFilter.h"
23 #include "CalendarFilterValidator.h"
24 #include "CalendarUtility.h"
25 #include "OnEventsChanged.h"
26 #include "IEventWatchChanges.h"
27 #include "IEventClearWatch.h"
28 #include "EventId.h"
29 #include <IFilter.h>
30 #include <IFilterVisitor.h>
31 #include <sstream>
32 #include <algorithm>
33 #include <Logger.h>
34
35 using namespace WrtDeviceApis::Commons;
36
37 namespace DeviceAPI {
38 namespace Calendar {
39
40 Calendar::Calendar()
41 {
42 }
43
44 Calendar::~Calendar()
45 {
46 }
47
48 void Calendar::OnRequestReceived(const IEventAddEventPtr &event)
49 {
50     Try
51     {
52         if (!event->getEvent()) {
53             ThrowMsg(NullPointerException, "Item parameter is NULL.");
54         }
55         if (event->getEvent()->getIdIsSet()) {
56             LoggerW("Non-null item id.");
57             event->getEvent()->resetId();
58         }
59
60         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
61
62                 if(getIsUnified()) {
63                         LoggerD("Set the default calendar id for a unified calendar item.");
64                         event->getEvent()->setCalendarId(DEFAULT_EVENT_CALENDAR_BOOK_ID);
65                 } else {
66                         std::stringstream ss(getId());
67                         int calendarId;
68                         ss>>calendarId;
69                         event->getEvent()->setCalendarId(calendarId);
70                 }
71
72         eventWrapper->convertAbstractEventToPlatformEvent();
73
74         eventWrapper->saveEvent();
75
76         event->setResult(true);
77     }
78     Catch (Exception)
79     {
80         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
81         event->setResult(false);
82         event->setExceptionCode(ExceptionCodes::UnknownException);
83     }
84 }
85
86 void Calendar::OnRequestReceived(const IEventAddEventsPtr &event)
87 {
88     calendar_list_h listForAdd = NULL;
89
90     Try
91     {
92         if (event->getEvents()->empty()) {
93             ThrowMsg(NullPointerException, "Item array is empty.");
94         }
95
96         int ret, count = 0;
97         calendar_record_h record = NULL;
98         int* ids = NULL;
99
100         ret = calendar_list_create(&listForAdd);
101         if (CALENDAR_ERROR_NONE != ret) {
102             ThrowMsg(PlatformException, "Can't create a list: "<<ret);
103         }
104
105         for(unsigned int i=0; i<event->getEvents()->size(); i++) {
106                         CalendarEventPtr theItem = event->getEvents()->at(i);
107             if (theItem->getIdIsSet()) {
108                 LoggerW("Item has index: " << i << ". Resetting it.");
109                 theItem->resetId();
110             }
111             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(theItem, getType()));
112
113                         if(getIsUnified()) {
114                                 LoggerD("Set the default calendar id for a unified calendar item.");
115                                 theItem->setCalendarId(DEFAULT_EVENT_CALENDAR_BOOK_ID);
116                         } else {
117                                 std::stringstream ss(getId());
118                                 int calendarId;
119                                 ss>>calendarId;
120                                 theItem->setCalendarId(calendarId);
121                         }
122
123             eventWrapper->convertAbstractEventToPlatformEvent();
124
125             // Clone the record because the platform event will be freed by destructor.
126             record = NULL;
127             ret = calendar_record_clone(eventWrapper->getPlatformEvent(), &record);
128             if(CALENDAR_ERROR_NONE!=ret) {
129                 ThrowMsg(PlatformException, "Clonning failed: "<<ret);
130             }
131
132             ret = calendar_list_add(listForAdd, record);
133             if (CALENDAR_ERROR_NONE != ret) {
134                 ThrowMsg(PlatformException, "Can't add the item to the list: "<<ret);
135             }
136         }
137
138         ret = calendar_db_insert_records(listForAdd, &ids, &count);
139         if (CALENDAR_ERROR_NONE != ret) {
140             ThrowMsg(PlatformException, "Can't insert the item list: "<<ret);
141         } else {
142             LoggerD("Add records requst done with count: "<<count);
143         }
144
145         for(int i=0; i<count; i++) {
146             event->getEvents()->at(i)->setId(ids[i]);
147         }
148
149                 if(ids) {
150                         free(ids);
151                 }
152
153         event->setResult(true);
154     }
155     Catch (Exception)
156     {
157         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
158         event->setResult(false);
159         event->setExceptionCode(ExceptionCodes::UnknownException);
160     }
161
162     if(listForAdd) {
163         calendar_list_destroy(listForAdd, true);
164     }
165 }
166
167 void Calendar::OnRequestReceived(const IEventUpdateEventPtr &event)
168 {
169     calendar_query_h query = NULL;
170     calendar_filter_h filter = NULL;
171
172     Try
173     {
174         if (!event->getEvent()) {
175             ThrowMsg(NullPointerException, "Item object is NULL.");
176         }
177
178         CalendarEventPtr theItem = event->getEvent();
179         if (!theItem->getIdIsSet()) {
180             ThrowMsg(InvalidArgumentException, "Item id is not set.");
181         }
182
183         int ret;
184
185         const char *dataType;
186         if(getType() == CalendarEvent::TASK_TYPE) {
187             dataType = _calendar_todo._uri;
188         } else {
189             dataType = _calendar_event._uri;
190         }
191
192         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(theItem, getType()));
193         eventWrapper->convertAbstractEventToPlatformEvent(true);
194
195         if ( event->getUpdateAllInstances() || 0>=theItem->getRecurrenceRule()->getFrequency() || UNDEFINED_TIME==theItem->getRecurrenceId()) {
196             // Platform detects the detached events and uptates all instances.
197             eventWrapper->saveEvent();
198         } else {
199             LoggerD("Update the exdate for a recurring parent event and add a new child event.");
200
201             // First update the parent event.
202             EventRecurrenceRulePtr rrule = theItem->getRecurrenceRule();
203             (*rrule->getExceptions()).push_back(theItem->getRecurrenceId());
204
205             std::string exdate = "";
206             for( unsigned int i=0; i<rrule->getExceptions()->size(); i++ ) {
207                 std::stringstream ss;
208                 ss<<rrule->getExceptions()->at(i);
209                 exdate.append(ss.str());
210                 if(i!=rrule->getExceptions()->size()-1) {
211                     exdate.append(",");
212                 }
213             }
214             ret = calendar_record_set_str(eventWrapper->getPlatformEvent(), _calendar_event.exdate, exdate.c_str());
215             if(ret!=CALENDAR_ERROR_NONE) {
216                 ThrowMsg(PlatformException, "Can't update the exdate: "<<ret);
217             } else {
218                 LoggerD("Set the exdate for the parent event: "<<exdate);
219             }
220
221             // Don't set the recurrence id for the parent event.
222             ret = calendar_record_set_str(eventWrapper->getPlatformEvent(), _calendar_event.recurrence_id, NULL);
223             if (CALENDAR_ERROR_NONE != ret) {
224                 ThrowMsg(PlatformException, "Can't set recurrence id.");
225             }
226
227             eventWrapper->saveEvent();
228
229             // Now add the detached child event.
230             EventRecurrenceRulePtr emptyRRule( new EventRecurrenceRule() );
231             // Detached event should not have rrule set.
232             theItem->setRecurrenceRule(emptyRRule);
233
234             theItem->setParentId(theItem->getId());
235
236             // Convert the modified child event.
237             eventWrapper->convertAbstractEventToPlatformEvent();
238
239             // Reset id for record insertion.
240             theItem->resetId();
241             eventWrapper->saveEvent();
242
243             theItem->setIsDetached(true);
244         }
245
246         event->setResult(true);
247     }
248     Catch (Exception)
249     {
250         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
251         event->setResult(false);
252         event->setExceptionCode(ExceptionCodes::UnknownException);
253     }
254
255     if(query) {
256         calendar_query_destroy(query);
257     }
258     if(filter) {
259         calendar_filter_destroy(filter);
260     }
261 }
262
263 void Calendar::OnRequestReceived(const IEventUpdateEventsPtr &event)
264 {
265     calendar_list_h listForUpdate = NULL;
266     calendar_list_h listForAdd = NULL;
267     calendar_query_h query =   NULL;
268     calendar_filter_h filter = NULL;
269
270     Try
271     {
272         if (event->getEvents()->empty()) {
273             ThrowMsg(NullPointerException, "Item array is empty.");
274         }
275
276         int ret, count = -1;
277         calendar_record_h record = NULL;
278
279         const char *dataType;
280         if(getType() == CalendarEvent::TASK_TYPE) {
281             dataType = _calendar_todo._uri;
282         } else {
283             dataType = _calendar_event._uri;
284         }
285
286         ret = calendar_list_create(&listForUpdate);
287         if (CALENDAR_ERROR_NONE != ret) {
288             ThrowMsg(PlatformException, "Can't create a list for update: "<<ret);
289         }
290         ret = calendar_list_create(&listForAdd);
291         if (CALENDAR_ERROR_NONE != ret) {
292             ThrowMsg(PlatformException, "Can't create a list for add: "<<ret);
293         }
294
295         for(unsigned int i=0; i<event->getEvents()->size(); i++) {
296             CalendarEventPtr thisEvent = event->getEvents()->at(i);
297             if (!thisEvent->getIdIsSet()) {
298                 ThrowMsg(InvalidArgumentException, "Item id is not set.");
299             }
300
301             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(thisEvent, getType()));
302             eventWrapper->convertAbstractEventToPlatformEvent(true);
303
304             if( true==thisEvent->getIsDetached() ) {
305                 // Treat the detached event same as the parent event.
306                 record = NULL;
307                 ret = calendar_record_clone(eventWrapper->getPlatformEvent(), &record);
308                 if(CALENDAR_ERROR_NONE!=ret) {
309                     ThrowMsg(PlatformException, "Clonning failed: "<<ret);
310                 }
311
312                 ret = calendar_list_add(listForUpdate, record);
313                 if (CALENDAR_ERROR_NONE != ret) {
314                     ThrowMsg(PlatformException, "Can't add the detached item to the list: "<<ret);
315                     } else {
316                     LoggerD("Added the detached event to the update list: "<<thisEvent->getId());
317                     }
318             } else if (event->getUpdateAllInstances() || 0>=thisEvent->getRecurrenceRule()->getFrequency() || UNDEFINED_TIME==thisEvent->getRecurrenceId()) {
319                 // Platform detects the detached events and uptates all instances.
320                 record = NULL;
321                 ret = calendar_record_clone(eventWrapper->getPlatformEvent(), &record);
322                 if(CALENDAR_ERROR_NONE!=ret) {
323                         ThrowMsg(PlatformException, "Clonning failed: "<<ret);
324                 }
325
326                 ret = calendar_list_add(listForUpdate, record);
327                 if (CALENDAR_ERROR_NONE != ret) {
328                     ThrowMsg(PlatformException, "Can't add the item to the list: "<<ret);
329                 }
330             } else {
331                 LoggerD("Update the exdate for a recurring parent event and add a new child event.");
332                 DPL::ScopedPtr<EventWrapper> eventWrapperChild(new EventWrapper(thisEvent, getType()));
333                 eventWrapperChild->convertAbstractEventToPlatformEvent(true);
334
335                 std::stringstream ss;
336                 ss<<thisEvent->getRecurrenceId();
337                 ret = calendar_record_set_str(eventWrapperChild->getPlatformEvent(), _calendar_event.recurrence_id, ss.str().c_str());
338                 if (CALENDAR_ERROR_NONE != ret) {
339                     ThrowMsg(PlatformException, "Cannot set event recurrence id: "<<ret);
340                 } else {
341                     LoggerD("Saved the rid for the child: "<<thisEvent->getRecurrenceId());
342                 }
343
344                 ret = calendar_record_set_int(eventWrapperChild->getPlatformEvent(), _calendar_event.original_event_id, thisEvent->getId());
345                 if (CALENDAR_ERROR_NONE != ret) {
346                     ThrowMsg(PlatformException, "Cannot set the parent id: "<<ret);
347                 }
348
349                 ret = calendar_record_set_int(eventWrapperChild->getPlatformEvent(), _calendar_event.freq, CALENDAR_RECURRENCE_NONE);
350                 if (CALENDAR_ERROR_NONE != ret) {
351                     ThrowMsg(PlatformException, "Cannot set the frequency: "<<ret);
352                 }
353
354                 record = NULL;
355                 ret = calendar_record_clone(eventWrapperChild->getPlatformEvent(), &record);
356                 if(CALENDAR_ERROR_NONE!=ret) {
357                     ThrowMsg(PlatformException, "Clonning the child event failed: "<<ret);
358                 }
359
360                 ret = calendar_list_add(listForAdd, record);
361                 if (CALENDAR_ERROR_NONE != ret) {
362                     ThrowMsg(PlatformException, "Can't add the item to the add list: "<<ret);
363                 }
364
365                 thisEvent->setIsDetached(true);
366
367                 // Now update the parent event.
368                 EventRecurrenceRulePtr rrule = thisEvent->getRecurrenceRule();
369                 (*rrule->getExceptions()).push_back(thisEvent->getRecurrenceId());
370
371                 std::string exdate = "";
372                 for( unsigned int j=0; j<rrule->getExceptions()->size(); j++ ) {
373                     std::stringstream ss;
374                     ss<<rrule->getExceptions()->at(j);
375                     exdate.append(ss.str());
376                     if(j!=rrule->getExceptions()->size()-1) {
377                         exdate.append(",");
378                     }
379                 }
380                 ret = calendar_record_set_str(eventWrapper->getPlatformEvent(), _calendar_event.exdate, exdate.c_str());
381                 if(ret!=CALENDAR_ERROR_NONE) {
382                     ThrowMsg(PlatformException, "Can't update the exdate: "<<ret);
383                 } else {
384                     LoggerD("Set the exdate for the parent event: "<<exdate);
385                 }
386
387                 record = NULL;
388                 ret = calendar_record_clone(eventWrapper->getPlatformEvent(), &record);
389                 if(CALENDAR_ERROR_NONE!=ret) {
390                     ThrowMsg(PlatformException, "Clonning the child event failed: "<<ret);
391                 }
392
393                 ret = calendar_list_add(listForUpdate, record);
394                 if (CALENDAR_ERROR_NONE != ret) {
395                     ThrowMsg(PlatformException, "Can't add the item to the update list: "<<ret);
396                 }
397             }
398         }
399
400         // Perform the platform operations.
401         count = -1;
402         ret = calendar_list_get_count(listForAdd, &count);
403         if(CALENDAR_ERROR_NONE!=ret){
404             ThrowMsg(PlatformException, "Getting list count failed: "<<ret);
405         } else {
406             LoggerD("Final list count for add: "<<count);
407         }
408         if(count>0) {
409             ret = calendar_db_insert_records(listForAdd, NULL, NULL);
410             if (CALENDAR_ERROR_NONE != ret) {
411                 ThrowMsg(PlatformException, "Can't insert the item list: "<<ret);
412             } else {
413                 LoggerD("Add records requst done for update batch operation.");
414             }
415         }
416
417         count = -1;
418         ret = calendar_list_get_count(listForUpdate, &count);
419         if(CALENDAR_ERROR_NONE!=ret){
420             ThrowMsg(PlatformException, "Getting list count failed: "<<ret);
421         } else {
422             LoggerD("Final list count for update: "<<count);
423         }
424         if(count>0) {
425             ret = calendar_db_update_records(listForUpdate);
426             if (CALENDAR_ERROR_NONE != ret) {
427                 ThrowMsg(PlatformException, "Can't update the item list: "<<ret);
428             } else {
429                 LoggerD("Update records requst done for update batch operation.");
430             }
431         }
432
433         event->setResult(true);
434     }
435     Catch (Exception)
436     {
437         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
438         event->setResult(false);
439         event->setExceptionCode(ExceptionCodes::UnknownException);
440     }
441
442     if(listForAdd) {
443         calendar_list_destroy(listForAdd, true);
444     }
445     if(listForUpdate) {
446         calendar_list_destroy(listForUpdate, true);
447     }
448     if(query) {
449         calendar_query_destroy(query);
450     }
451     if(filter) {
452         calendar_filter_destroy(filter);
453     }
454 }
455
456 void Calendar::OnRequestReceived(const IEventDeleteEventPtr &event)
457 {
458     Try
459     {
460         if (!event->getEventId()) {
461             ThrowMsg(NullPointerException, "Item id is not set.");
462         }
463
464         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
465         event->getEventId()->setCalendarType(getType());
466         std::istringstream stream(event->getEventId()->getUId());
467         int id = -1;
468         stream>>id;
469         eventWrapper->getAbstractEvent()->setId(id);
470
471         std::stringstream ss(event->getEventId()->getRecurrenceId());
472         long long int rid;
473         ss>>rid;
474
475         LoggerD("id: " << id << ", rid: " << rid);
476
477         eventWrapper->loadEvent(id);
478
479         // recurrence id is reset while loading the platform event.
480         eventWrapper->getAbstractEvent()->setRecurrenceId(rid);
481
482         eventWrapper->deleteEvent();
483         event->setResult(true);
484     }
485     Catch (NotFoundException)
486     {
487         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
488         event->setResult(false);
489         event->setExceptionCode(ExceptionCodes::NotFoundException);
490     }
491     Catch (Exception)
492     {
493         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
494         event->setResult(false);
495         event->setExceptionCode(ExceptionCodes::UnknownException);
496     }
497 }
498
499 void Calendar::OnRequestReceived(const IEventGetPtr &event)
500 {
501     Try
502     {
503         if (!event->getItemId()) {
504             ThrowMsg(NullPointerException, "Id parameter is NULL");
505         }
506
507         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
508         std::stringstream ss(event->getItemId()->getUId());
509         int id = -1;
510         ss>>id;
511
512         eventWrapper->loadEvent(id);
513
514         event->setItem(eventWrapper->getAbstractEvent());
515         event->setResult(true);
516     }
517     Catch (NotFoundException)
518     {
519         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
520         event->setResult(false);
521         event->setExceptionCode(ExceptionCodes::NotFoundException);
522     }
523     Catch (Exception)
524     {
525         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
526         event->setResult(false);
527         event->setExceptionCode(ExceptionCodes::UnknownException);
528     }
529 }
530
531 void Calendar::OnRequestReceived(const IEventDeleteEventsPtr &event)
532 {
533     calendar_list_h listForUpdate = NULL;
534     calendar_query_h query = NULL;
535     calendar_filter_h filter = NULL;
536
537     Try
538     {
539         if (event->getEventIds()->empty()) {
540             ThrowMsg(NullPointerException, "Item id array is empty.");
541         }
542
543         std::vector<int> listForDelete;
544         std::vector<int> listForDetached;
545         std::vector<int> listForDetachedParent;
546
547         int ret, id, count;
548         long long int rid;
549         calendar_record_h item, record;
550         const char *dataType = NULL;
551
552         ret = calendar_list_create(&listForUpdate);
553         if (CALENDAR_ERROR_NONE != ret) {
554             ThrowMsg(PlatformException, "Can't create a list for update: "<<ret);
555         }
556
557         for(unsigned int i=0; i<event->getEventIds()->size(); i++) {
558             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
559             event->getEventIds()->at(i)->setCalendarType(getType());
560
561             std::istringstream stream(event->getEventIds()->at(i)->getUId());
562             stream>>id;
563             eventWrapper->getAbstractEvent()->setId(id);
564
565             eventWrapper->loadEvent(id);
566             item = eventWrapper->getPlatformEvent();
567
568             std::stringstream ss(event->getEventIds()->at(i)->getRecurrenceId());
569             ss>>rid;
570             eventWrapper->getAbstractEvent()->setRecurrenceId(rid);
571
572             // If the recurrenceId is set, delete the instance of recurring event only.
573             LoggerD("id to delete: " << id << ", rid: " << rid << ", type: " << getType());
574
575             dataType = NULL;
576             if(getType() == CalendarEvent::TASK_TYPE) {
577                 dataType = _calendar_todo._uri;
578             } else {
579                 dataType = _calendar_event._uri;
580             }
581
582             /* Platform detects the detached events and deletes them automatically.
583                         But if both parent and detached ids are added to the list, platform error is returned. */
584             if ( 0>=rid ) {
585                 listForDelete.push_back(id);
586             } else if (true==eventWrapper->getAbstractEvent()->getIsDetached() ) {
587                 listForDetached.push_back(id);
588
589                 int parentId;
590                 ret = calendar_record_get_int(eventWrapper->getPlatformEvent(), _calendar_event.original_event_id, &parentId);
591                 if (CALENDAR_ERROR_NONE != ret) {
592                     ThrowMsg(PlatformException, "Can't get the parent id: "<<ret);
593                 }
594                 listForDetachedParent.push_back(parentId);
595                 LoggerD("Added the detached event id: "<<id<<", parent id: "<<parentId);
596             } else {
597                 EventRecurrenceRulePtr rrule = eventWrapper->getAbstractEvent()->getRecurrenceRule();
598                 (*rrule->getExceptions()).push_back(rid);
599
600                 std::string exdate = "";
601                 for( unsigned int i=0; i<rrule->getExceptions()->size(); i++ ) {
602                     std::stringstream ss;
603                     ss<<rrule->getExceptions()->at(i);
604                     exdate.append(ss.str());
605                     if(i!=rrule->getExceptions()->size()-1) {
606                         exdate.append(",");
607                     }
608                 }
609                 ret = calendar_record_set_str(item, _calendar_event.exdate, exdate.c_str());
610                 if(ret!=CALENDAR_ERROR_NONE) {
611                     ThrowMsg(PlatformException, "Can't delete the instance: "<<ret);
612                 } else {
613                     LoggerD("Set the exdate: "<<exdate);
614                 }
615
616                 record = NULL;
617                 ret = calendar_record_clone(item, &record);
618                 if(CALENDAR_ERROR_NONE!=ret) {
619                     ThrowMsg(PlatformException, "Clonning failed: "<<ret);
620                 }
621
622                 ret = calendar_list_add(listForUpdate, record);
623                 if (CALENDAR_ERROR_NONE != ret) {
624                     ThrowMsg(PlatformException, "Can't add the item to the list: "<<ret);
625                 }
626                 LoggerD("Calendar item instance added for update.");
627             }
628         }
629
630         // Perform the platform operations.
631         // Uptate operatoin should be done first not to update records after deletion.
632         count = -1;
633         ret = calendar_list_get_count(listForUpdate, &count);
634         if(CALENDAR_ERROR_NONE!=ret){
635             LoggerW("Getting list count for update failed: "<<ret);
636         } else {
637             LoggerD("Final list count for update: "<<count);
638         }
639         if(count>0) {
640             ret = calendar_db_update_records(listForUpdate);
641             if (CALENDAR_ERROR_NONE != ret) {
642                 ThrowMsg(PlatformException, "Can't update the item list: "<<ret);
643             } else {
644                 LoggerD("Update records requst done for update batch operation.");
645             }
646         }
647
648         // Merge the detached event id list if the parent is not included in the delete list.
649         count = listForDetached.size();
650         LoggerD("Number of detached events: "<<count);
651         while(count--) {
652             std::vector<int>::iterator it;
653             it = std::find(listForDelete.begin(), listForDelete.end(), listForDetachedParent.at(count));
654             if(listForDelete.end()==it) {
655                 listForDelete.push_back(listForDetached.at(count));
656                 LoggerD("Add the detached event id to the delete list: "<<listForDetached.at(count));
657             } else {
658                 LoggerD("The parent id is already included to the delete list: "<<listForDetachedParent.at(count));
659             }
660         }
661         count = listForDelete.size();
662
663         LoggerD("Final list count for deletion: "<<count);
664         if(count>0) {
665             ret = calendar_db_delete_records(dataType, &listForDelete[0], count);
666             if (CALENDAR_ERROR_NONE != ret) {
667                 ThrowMsg(PlatformException, "Can't delete the records: "<<ret);
668             } else {
669                 LoggerD("Delete records requst done for delete batch operation.");
670             }
671         }
672
673         event->setResult(true);
674     }
675     Catch (NotFoundException)
676     {
677         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
678         event->setResult(false);
679         event->setExceptionCode(ExceptionCodes::NotFoundException);
680     }
681     Catch (Exception)
682     {
683         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
684         event->setResult(false);
685         event->setExceptionCode(ExceptionCodes::UnknownException);
686     }
687
688     if(query) {
689         calendar_query_destroy(query);
690     }
691     if(filter) {
692         calendar_filter_destroy(filter);
693     }
694     if(listForUpdate) {
695         calendar_list_destroy(listForUpdate, true);
696     }
697 }
698
699 void Calendar::OnRequestReceived(const IEventFindEventsPtr &event)
700 {
701     Try
702     {
703         CalendarFilterPtr calendarFilter( new CalendarFilter() );
704
705         calendarFilter->setType(getType());
706         LoggerD("Default filter created with type "<<getType());
707
708                 DeviceAPI::Tizen::IFilterVisitorPtr filterTraversal = DPL::StaticPointerCast<DeviceAPI::Tizen::IFilterVisitor>(calendarFilter);
709
710         int calendarId;
711         std::stringstream ss(getId());
712         ss>>calendarId;
713                 if (event->getGenericFilterIsSet()) {
714             DeviceAPI::Tizen::FilterPtr genericFilter = event->getGenericFilter();
715
716             DeviceAPI::Tizen::FilterValidatorPtr validator = CalendarFilterValidatorFactory::getCalendarFilterValidator();
717             bool success = genericFilter->validate(validator);
718             if(!success) {
719                 ThrowMsg(InvalidArgumentException, "Invalid filter arguments.");
720             } else {
721                 LoggerD("Filter validation has passed.");
722             }
723
724                         genericFilter->travel(filterTraversal, 0);
725
726                         if(getIsUnified()) {
727                                 LoggerD("Set all calendars flag for a unified calendar.");
728                                 calendarFilter->setCalendarId(CALENDAR_BOOK_FILTER_ALL, true);
729                         } else {
730                                 LoggerD("Set additional calendar id: "<<calendarId);
731                 calendarFilter->setCalendarId(calendarId, true);
732                         }
733                 } else {
734                         if(getIsUnified()) {
735                                 LoggerD("Set all calendars flag for a unified calendar.");
736                                 calendarFilter->setCalendarId(CALENDAR_BOOK_FILTER_ALL, false);
737                         } else {
738                     LoggerD("Set calendar id: "<<calendarId);
739                 calendarFilter->setCalendarId(calendarId, false);
740                         }
741                 }
742
743                 if (event->getSortModesIsSet()) {
744                         calendarFilter->setSortMode(event->getSortModes());
745                 }
746
747                 calendarFilter->executeQuery();
748
749                 LoggerD("Return the query result after conversion.");
750
751         calendar_list_h resultList = calendarFilter->getResultRecordList();
752         int ret;
753         int count = calendarFilter->getResultRecordCount();
754         calendar_record_h currentRecord = NULL;
755
756         calendar_list_first(resultList);
757
758         while(count--) {
759             currentRecord = NULL;
760             ret = calendar_list_get_current_record_p(resultList, &currentRecord);
761             if ( CALENDAR_ERROR_NONE != ret ) {
762                 ThrowMsg(PlatformException, "Can't get current record: "<<ret);
763             }
764
765             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(currentRecord, getType()));
766             event->addEvent(eventWrapper->convertPlatformEventToAbstractEvent());
767
768             calendar_list_next(resultList);
769         }
770         LoggerD("Length of found items: "<<event->getEvents()->size());
771
772                 // Handle the recurring event range filter corner case.
773                 int id = -1, parentCount = -1;
774                 bool found = false;
775         resultList = calendarFilter->getNormalInstanceResultRecordList();
776         count = calendarFilter->getNormalInstanceResultRecordCount();
777                 LoggerD("Number of found normal instances: "<<count);
778
779         currentRecord = NULL;
780         calendar_list_first(resultList);
781         while(count--) {
782             currentRecord = NULL;
783             ret = calendar_list_get_current_record_p(resultList, &currentRecord);
784             if ( CALENDAR_ERROR_NONE != ret ) {
785                 ThrowMsg(PlatformException, "Can't get a current record: "<<ret);
786             }
787
788                         id = -1;
789                         ret = calendar_record_get_int(currentRecord, _calendar_instance_normal_calendar_book.event_id, &id);
790                         if (CALENDAR_ERROR_NONE != ret) {
791                                 ThrowMsg(PlatformException, "Can't get the normal instance parent id: "<<ret);
792                         }
793
794                         // Skip if the parent event is already found.
795                         parentCount = event->getEvents()->size();
796                         found = false;
797                         while(parentCount--) {
798                                 if(id==event->getEvents()->at(parentCount)->getId()) {
799                                         LoggerD("Found the id: "<<id<<", thus skip this.");
800                                         found = true;
801                                         break;
802                                 }
803                         }
804
805                         if(false==found) {
806                                 LoggerD("Add the normal instance parent: "<<id);
807                     DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
808                                 eventWrapper->loadEvent(id);
809                     event->addEvent(eventWrapper->convertPlatformEventToAbstractEvent());
810                         }
811
812             calendar_list_next(resultList);
813         }
814         LoggerD("Length of found items including normal instances: "<<event->getEvents()->size());
815
816         resultList = calendarFilter->getAlldayInstanceResultRecordList();
817         count = calendarFilter->getAlldayInstanceResultRecordCount();
818                 LoggerD("Number of found allday instances: "<<count);
819
820         currentRecord = NULL;
821         calendar_list_first(resultList);
822         while(count--) {
823             currentRecord = NULL;
824             ret = calendar_list_get_current_record_p(resultList, &currentRecord);
825             if ( CALENDAR_ERROR_NONE != ret ) {
826                 ThrowMsg(PlatformException, "Can't get a current record: "<<ret);
827             }
828
829                         id = -1;
830                         ret = calendar_record_get_int(currentRecord, _calendar_instance_allday_calendar_book.event_id, &id);
831                         if (CALENDAR_ERROR_NONE != ret) {
832                                 ThrowMsg(PlatformException, "Can't get the allday instance parent id: "<<ret);
833                         }
834
835                         // Skip if the parent event is already found.
836                         parentCount = event->getEvents()->size();
837                         found = false;
838                         while(parentCount--) {
839                                 if(id==event->getEvents()->at(parentCount)->getId()) {
840                                         LoggerD("Found the id: "<<id<<", thus skip this.");
841                                         found = true;
842                                         break;
843                                 }
844                         }
845
846                         if(false==found) {
847                                 LoggerD("Add the allday instance parent: "<<id);
848                     DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
849                                 eventWrapper->loadEvent(id);
850                     event->addEvent(eventWrapper->convertPlatformEventToAbstractEvent());
851                         }
852
853             calendar_list_next(resultList);
854         }
855         LoggerD("Length of found items including allday instances: "<<event->getEvents()->size());
856
857         event->setResult(true);
858     }
859     Catch (InvalidArgumentException)
860     {
861         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
862         event->setResult(false);
863         event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
864     }
865     Catch (NotFoundException)
866     {
867         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
868         event->setResult(false);
869         event->setExceptionCode(ExceptionCodes::NotFoundException);
870     }
871     Catch (Exception)
872     {
873         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
874         event->setResult(false);
875         event->setExceptionCode(ExceptionCodes::UnknownException);
876     }
877 }
878
879 void Calendar::OnRequestReceived(const IEventCreateEventFromStringPtr &event)
880 {
881     Try
882     {
883         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
884         eventWrapper->createEventFromString(event->getEventString());
885         event->setEvent(eventWrapper->convertPlatformEventToAbstractEvent());
886         event->getEvent()->setCalendarType(getType());
887         event->setResult(true);
888     }
889     Catch(PlatformException)
890     {
891                 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
892         LoggerD("eventString: " + event->getEventString());
893         event->setResult(false);
894         event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
895     }
896     Catch (Exception)
897     {
898         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
899         LoggerD("eventString: " + event->getEventString());
900         event->setResult(false);
901         event->setExceptionCode(ExceptionCodes::UnknownException);
902     }
903 }
904
905 void Calendar::OnRequestReceived(const IEventExportEventToStringPtr &event)
906 {
907     Try
908     {
909         if (!event->getEvent()) {
910             ThrowMsg(NullPointerException, "event parameter is NULL");
911         }
912
913         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
914         event->getEvent()->setCalendarType(getType());
915         eventWrapper->convertAbstractEventToPlatformEvent();
916         event->setEventString(eventWrapper->exportEventToString());
917         event->setResult(true);
918     }
919     Catch (Exception)
920     {
921         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
922         event->setResult(false);
923         event->setExceptionCode(ExceptionCodes::UnknownException);
924     }
925 }
926
927 static void eventChangedCb(const char *view_uri, void *user_data)
928 {
929     LoggerD("Items change cb with view_uri: "<<view_uri);
930
931     OnEventsChangedPtr eventPtr(new OnEventsChanged());
932     calendar_list_h list = NULL;
933
934     Try
935     {
936         if (user_data == NULL) {
937             LoggerD("user_data is NULL.");
938                 return;
939         }
940
941         Calendar *thisCalendar = (Calendar*) user_data;
942
943         int ret, id, type, updatedVersion, calendarId, count = 0;
944
945
946                 if(thisCalendar->getIsUnified()) {
947                         LoggerD("Set the all calendar id for a unified calendar.");
948                         calendarId = CALENDAR_BOOK_FILTER_ALL;
949                 } else {
950                 std::stringstream ss(thisCalendar->getId());
951             ss>>calendarId;
952                 }
953
954         LoggerD("Getting items with calendar id: "<<calendarId<<", version: "<<thisCalendar->getLastChangedVersion()<<", type: "<<thisCalendar->getType());
955         if (CalendarEvent::TASK_TYPE==thisCalendar->getType()) {
956             ret = calendar_db_get_changes_by_version(_calendar_todo._uri, calendarId, thisCalendar->getLastChangedVersion(), &list, &updatedVersion);
957         } else {
958             ret = calendar_db_get_changes_by_version(_calendar_event._uri, calendarId, thisCalendar->getLastChangedVersion(), &list, &updatedVersion);
959         }
960         if( CALENDAR_ERROR_NONE!=ret ) {
961             ThrowMsg(PlatformException, "Can't get the updated item list: "<<ret);
962         }
963
964         ret = calendar_list_get_count(list, &count);
965         if( CALENDAR_ERROR_NONE!=ret ) {
966             ThrowMsg(PlatformException, "Can't get the item count: "<<ret);
967         } else {
968             LoggerD("Item count: "<<count);
969         }
970
971         calendar_list_first(list);
972
973         calendar_record_h currentRecord = NULL;
974         while(count--)
975         {
976             currentRecord = NULL;
977             ret = calendar_list_get_current_record_p(list, &currentRecord);
978             if ( CALENDAR_ERROR_NONE != ret ) {
979                 ThrowMsg(PlatformException, "Can't get current record: "<<ret);
980             }
981
982             ret = calendar_record_get_int(currentRecord, _calendar_updated_info.id ,&id);
983             if ( CALENDAR_ERROR_NONE != ret ) {
984                 ThrowMsg(PlatformException, "Can't get updated info id: "<<ret);
985             }
986
987             ret = calendar_record_get_int(currentRecord, _calendar_updated_info.modified_status ,&type);
988             if ( CALENDAR_ERROR_NONE != ret ) {
989                 ThrowMsg(PlatformException, "Can't get updated info modified status: "<<ret);
990             }
991
992             LoggerD("id "<<id<<", type "<<type);
993             if ( CALENDAR_EVENT_MODIFIED_STATUS_INSERTED==type ) {
994                 eventPtr->setStatus(OnEventsChanged::ON_ADD);
995             } else if ( CALENDAR_EVENT_MODIFIED_STATUS_UPDATED==type ) {
996                 eventPtr->setStatus(OnEventsChanged::ON_UPDATE);
997             } else if ( CALENDAR_EVENT_MODIFIED_STATUS_DELETED==type ) {
998                 eventPtr->setStatus(OnEventsChanged::ON_DELETE);
999             } else {
1000                 LoggerW("Wrong change type.");
1001                 calendar_list_next(list);
1002                 continue;
1003             }
1004
1005             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(thisCalendar->getType()));
1006             Try {
1007                 eventWrapper->loadEvent(id);
1008             } Catch (NotFoundException){
1009                 LoggerD("Handling deleted event with index: "<<id);
1010             }
1011             eventPtr->addEvent(eventWrapper->getAbstractEvent());
1012
1013             calendar_list_next(list);
1014         }
1015
1016         ret = calendar_db_get_current_version(&updatedVersion);
1017         if( CALENDAR_ERROR_NONE!=ret ) {
1018             ThrowMsg(PlatformException, "Can't get new version: "<<ret);
1019         }
1020
1021         thisCalendar->setLastChangedVersion(updatedVersion);
1022         LoggerD("Last change fetch version: "<<thisCalendar->getLastChangedVersion());
1023
1024         eventPtr->setResult(true);
1025         eventPtr->setCalendarType(thisCalendar->getType());
1026
1027         if( eventPtr->getEventList()->size() > 0 ) {
1028             thisCalendar->m_changeEmitters.emit(eventPtr);
1029         } else {
1030             LoggerD("No actual changes. Skip signal emission.");
1031         }
1032     }
1033     Catch (Exception)
1034     {   
1035         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
1036     }
1037
1038         if( list ) {
1039             calendar_list_destroy(list, true);
1040         }
1041 }
1042
1043 void Calendar::OnRequestReceived(const IEventWatchChangesPtr &event)
1044 {
1045     Try
1046     {
1047         // Subscribe the watch to the platform just once.
1048         int ret;
1049         if( m_changeEmitters.size()==0 )
1050         {
1051             const char *dataType;
1052             if(getType() == CalendarEvent::TASK_TYPE) {
1053                 dataType = _calendar_todo._uri;
1054             } else {
1055                 dataType = _calendar_event._uri;
1056             }
1057
1058             ret = calendar_db_add_changed_cb(dataType, eventChangedCb, this);
1059             if( CALENDAR_ERROR_NONE!=ret ) {
1060                 ThrowMsg(PlatformException, "Can't add db changed cb: "<<ret);
1061             } else {
1062                 // Save the last change fetch version to start watching.
1063                 int version;
1064                 ret = calendar_db_get_current_version(&version);
1065                 if( CALENDAR_ERROR_NONE!=ret ) {
1066                     ThrowMsg(PlatformException, "Can't get version: "<<ret);
1067                 } else {
1068                     setLastChangedVersion(version);
1069                     LoggerD("Last change fetch version: "<<getLastChangedVersion());
1070                 }
1071             }
1072         }
1073
1074         m_changeEmitters.attach(event->getEmitter());
1075         event->setWatchId(event->getEmitter()->getId());
1076         event->setResult(true);
1077     }
1078     Catch (Exception)
1079     {
1080         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
1081         event->setResult(false);
1082         event->setExceptionCode(ExceptionCodes::UnknownException);
1083     }
1084 }
1085
1086 void Calendar::OnRequestReceived(const IEventClearWatchPtr &event)
1087 {
1088     Try
1089     {
1090         if( m_changeEmitters.detach(event->getWatchId()) ) {
1091             if( m_changeEmitters.size()==0 ) {
1092                 const char *dataType;
1093                 if(getType() == CalendarEvent::TASK_TYPE) {
1094                     dataType = _calendar_todo._uri;
1095                 } else {
1096                     dataType = _calendar_event._uri;
1097                 }
1098
1099                 if( CALENDAR_ERROR_NONE!=calendar_db_remove_changed_cb(dataType, eventChangedCb, this) ) {
1100                     ThrowMsg(PlatformException, "Can't remove change cb.");
1101                 } else {
1102                     LoggerD("Platform watch cleared successfully.");
1103                 }
1104             }
1105             event->setResult(true);
1106         } else {
1107             LoggerD("Wrong watch Id.");
1108             event->setResult(false);
1109         }
1110     }
1111     Catch (Exception)
1112     {
1113         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
1114         event->setResult(false);
1115         event->setExceptionCode(ExceptionCodes::UnknownException);
1116     }
1117 }
1118
1119 void Calendar::OnRequestReceived(const IEventExpandEventRecurrencePtr &event)
1120 {
1121     const CalendarEventPtr calEvent = event->getEvent();
1122     const long long int startDate = event->getStartDate();
1123     const long long int endDate = event->getEndDate();
1124     bool isAllDay = calEvent->getIsAllDay();
1125
1126     calendar_query_h query =   NULL;
1127     calendar_filter_h filter = NULL;
1128     calendar_list_h list = NULL;
1129
1130     Try {
1131         if ( 0 >= calEvent->getRecurrenceRule()->getFrequency()) {
1132             ThrowMsg(InvalidArgumentException, "This is not a recurring event.");
1133         }
1134
1135         calendar_record_h currentRecord = NULL;
1136         int ret, currentRecordIndex, count=0;
1137
1138         calendar_time_s st, et;
1139                 if( true==isAllDay ) {
1140                         st.type = CALENDAR_TIME_LOCALTIME;
1141                         st.time.date = CalendarUtility::LLIToCalTime(calEvent->getTimeZone().c_str(), startDate).time.date;
1142
1143                         et.type = CALENDAR_TIME_LOCALTIME;
1144                         et.time.date = CalendarUtility::LLIToCalTime(calEvent->getTimeZone().c_str(), endDate).time.date;
1145                 } else {
1146                 st.type = CALENDAR_TIME_UTIME;
1147                 st.time.utime = startDate;
1148
1149                 et.type = CALENDAR_TIME_UTIME;
1150                 et.time.utime = endDate;
1151                 }
1152
1153         if( true==isAllDay ) {
1154             ret = calendar_query_create(_calendar_instance_allday_calendar_book._uri, &query);
1155         } else {
1156             ret = calendar_query_create(_calendar_instance_normal_calendar_book._uri, &query);
1157         }
1158         if( CALENDAR_ERROR_NONE!=ret ) {
1159             ThrowMsg(PlatformException, "Creating a query failed: "<<ret);
1160         }
1161
1162         if( true==isAllDay ) {
1163             ret = calendar_filter_create(_calendar_instance_allday_calendar_book._uri, &filter);
1164         } else {
1165             ret = calendar_filter_create(_calendar_instance_normal_calendar_book._uri, &filter);
1166         }
1167         if( CALENDAR_ERROR_NONE!=ret ) {
1168             ThrowMsg(PlatformException, "Creating a filter failed: "<<ret);
1169         }
1170
1171         if( true==isAllDay ) {
1172             ret = calendar_filter_add_caltime(filter, _calendar_instance_allday_calendar_book.start_time, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL, st);
1173         } else {
1174             ret = calendar_filter_add_caltime(filter, _calendar_instance_normal_calendar_book.start_time, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL, st);
1175         }
1176         if( CALENDAR_ERROR_NONE!=ret ) {
1177             ThrowMsg(PlatformException, "Adding a caltime filter failed: "<<ret);
1178         }
1179
1180         ret = calendar_filter_add_operator(filter, CALENDAR_FILTER_OPERATOR_AND);
1181         if( CALENDAR_ERROR_NONE!=ret ) {
1182             ThrowMsg(PlatformException, "Adding a filter operator failed: "<<ret);
1183         }
1184
1185         if( true==isAllDay ) {
1186             ret = calendar_filter_add_caltime(filter, _calendar_instance_allday_calendar_book.end_time, CALENDAR_MATCH_LESS_THAN_OR_EQUAL, et);
1187         } else {
1188             ret = calendar_filter_add_caltime(filter, _calendar_instance_normal_calendar_book.end_time, CALENDAR_MATCH_LESS_THAN_OR_EQUAL, et);
1189         }
1190         if( CALENDAR_ERROR_NONE!=ret ) {
1191             ThrowMsg(PlatformException, "Adding a caltime filter failed: "<<ret);
1192         }
1193
1194         ret = calendar_query_set_filter(query, filter);
1195         if( CALENDAR_ERROR_NONE!=ret ) {
1196             ThrowMsg(PlatformException, "Setting a filter: "<<ret);
1197         }
1198
1199         ret = calendar_db_get_records_with_query(query, 0, 0, &list);
1200         if( CALENDAR_ERROR_NONE!=ret ) {
1201             ThrowMsg(PlatformException, "Getting event instances failed: "<<ret);
1202         }
1203
1204         ret = calendar_list_get_count(list, &count);
1205         if( CALENDAR_ERROR_NONE!=ret ) {
1206             ThrowMsg(PlatformException, "Can't get the item count: "<<ret);
1207         } else {
1208             LoggerD("Item count: "<<count<<", isAllDay: "<<isAllDay);
1209         }
1210
1211         calendar_list_first(list);
1212
1213         while(count--)
1214         {
1215             currentRecord = NULL;
1216             ret = calendar_list_get_current_record_p(list, &currentRecord);
1217             if ( CALENDAR_ERROR_NONE != ret ) {
1218                 ThrowMsg(PlatformException, "Can't get current record: "<<ret);
1219             }
1220
1221             if( true==isAllDay ) {
1222                 ret = calendar_record_get_int(currentRecord, _calendar_instance_allday_calendar_book.event_id, &currentRecordIndex);
1223             } else {
1224             ret = calendar_record_get_int(currentRecord, _calendar_instance_normal_calendar_book.event_id, &currentRecordIndex);
1225             }
1226             if ( CALENDAR_ERROR_NONE != ret ) {
1227                 ThrowMsg(PlatformException, "Can't get current record id: "<<ret);
1228             }
1229
1230             if(currentRecordIndex==calEvent->getId()) {
1231                 DPL::ScopedPtr<EventWrapper> recurringEventWrapper(new EventWrapper(getType()));
1232                 recurringEventWrapper->loadEvent(calEvent->getId());
1233
1234                 // Set distintive attributes of each instance.
1235                 if( true==isAllDay ) {
1236                     ret = calendar_record_get_caltime(currentRecord, _calendar_instance_allday_calendar_book.start_time, &st);
1237
1238                                         recurringEventWrapper->getAbstractEvent()->setRecurrenceId(CalendarUtility::calTimeToLLI(calEvent->getTimeZone().c_str(), st));
1239                                         recurringEventWrapper->getAbstractEvent()->setStartTime(CalendarUtility::calTimeToLLI(calEvent->getTimeZone().c_str(), st));
1240                 } else {
1241                 ret = calendar_record_get_caltime(currentRecord, _calendar_instance_normal_calendar_book.start_time, &st);
1242
1243                         recurringEventWrapper->getAbstractEvent()->setRecurrenceId(st.time.utime);
1244                         recurringEventWrapper->getAbstractEvent()->setStartTime(st.time.utime);
1245                 }
1246                 if ( CALENDAR_ERROR_NONE != ret ) {
1247                     ThrowMsg(PlatformException, "Can't get current record start time: "<<ret);
1248                 }
1249
1250                 if( true==isAllDay ) {
1251                     ret = calendar_record_get_caltime(currentRecord, _calendar_instance_allday_calendar_book.end_time, &et);
1252
1253                                         recurringEventWrapper->getAbstractEvent()->setEndTime(CalendarUtility::calTimeToLLI(calEvent->getTimeZone().c_str(), et));
1254                 } else {
1255                 ret = calendar_record_get_caltime(currentRecord, _calendar_instance_normal_calendar_book.end_time, &et);
1256
1257                                         recurringEventWrapper->getAbstractEvent()->setEndTime(et.time.utime);
1258                 }
1259                 if ( CALENDAR_ERROR_NONE != ret ) {
1260                     ThrowMsg(PlatformException, "Can't get current record end time: "<<ret);
1261                 }
1262
1263                 LoggerD("Found a valid event instance with rid: "<<recurringEventWrapper->getAbstractEvent()->getRecurrenceId());
1264
1265                 event->addExpandedEvent(recurringEventWrapper->getAbstractEvent());
1266                         } else {
1267                                 LoggerD("Skip unmatched instance with event_id: "<<currentRecordIndex<<" and parent id: "<<calEvent->getId());
1268                         }
1269
1270             calendar_list_next(list);
1271         }
1272         LoggerD("Length of expanded events from parent: "<<event->getExpandedEventList()->size());
1273
1274         if(query) {
1275             calendar_query_destroy(query);
1276             query = NULL;
1277         }
1278         if(filter) {
1279             calendar_filter_destroy(filter);
1280             filter = NULL;
1281         }
1282         if( list ) {
1283             calendar_list_destroy(list, true);
1284             list = NULL;
1285         }
1286
1287         // Consider the detached events also.
1288         currentRecord = NULL;
1289         int parentId = event->getEvent()->getId();
1290
1291         ret = calendar_query_create(_calendar_event._uri, &query);
1292         if( CALENDAR_ERROR_NONE!=ret ) {
1293             ThrowMsg(PlatformException, "Creating a query failed: "<<ret);
1294         }
1295
1296         ret = calendar_filter_create(_calendar_event._uri, &filter);
1297         if( CALENDAR_ERROR_NONE!=ret ) {
1298             ThrowMsg(PlatformException, "Creating a filter failed: "<<ret);
1299         }
1300
1301         ret = calendar_filter_add_int(filter, _calendar_event.original_event_id, CALENDAR_MATCH_EQUAL, parentId);
1302         if( CALENDAR_ERROR_NONE!=ret ) {
1303             ThrowMsg(PlatformException, "Adding an int filter failed: "<<ret);
1304         }
1305
1306         ret = calendar_query_set_filter(query, filter);
1307         if( CALENDAR_ERROR_NONE!=ret ) {
1308             ThrowMsg(PlatformException, "Setting a filter: "<<ret);
1309         }
1310
1311         ret = calendar_db_get_records_with_query(query, 0, 0, &list);
1312         if(CALENDAR_ERROR_NONE!=ret) {
1313             ThrowMsg(PlatformException, "Finding detached instances failed: "<<ret);
1314         }
1315
1316         ret = calendar_list_get_count(list, &count);
1317         if( CALENDAR_ERROR_NONE!=ret ) {
1318             ThrowMsg(PlatformException, "Can't get the item count: "<<ret);
1319         } else {
1320             LoggerD("Item count: "<<count);
1321         }
1322
1323         calendar_list_first(list);
1324
1325         while(count--)
1326         {
1327             currentRecord = NULL;
1328             ret = calendar_list_get_current_record_p(list, &currentRecord);
1329             if ( CALENDAR_ERROR_NONE != ret ) {
1330                 ThrowMsg(PlatformException, "Can't get current record: "<<ret);
1331             }
1332
1333             ret = calendar_record_get_int(currentRecord, _calendar_event.id, &currentRecordIndex);
1334             if ( CALENDAR_ERROR_NONE != ret ) {
1335                 ThrowMsg(PlatformException, "Can't get current record id: "<<ret);
1336             }
1337
1338             st = {CALENDAR_TIME_UTIME, {0}};
1339             ret = calendar_record_get_caltime(currentRecord, _calendar_event.start_time, &st);
1340             if ( CALENDAR_ERROR_NONE != ret ) {
1341                 ThrowMsg(PlatformException, "Can't get current record start time: "<<ret);
1342             }
1343
1344             et = {CALENDAR_TIME_UTIME, {0}};
1345             ret = calendar_record_get_caltime(currentRecord, _calendar_event.end_time, &et);
1346             if ( CALENDAR_ERROR_NONE != ret ) {
1347                 ThrowMsg(PlatformException, "Can't get current record end time: "<<ret);
1348             }
1349
1350             if (st.time.utime>=startDate && et.time.utime<=endDate) {
1351                 LoggerD("Found a valid detached event: "<<st.time.utime);
1352                 DPL::ScopedPtr<EventWrapper> detachedEventWrapper(new EventWrapper(getType()));
1353                 detachedEventWrapper->loadEvent(currentRecordIndex);
1354
1355                 // Set the same parent uid to each instances
1356                 detachedEventWrapper->getAbstractEvent()->setId(parentId);
1357                 // Set distintive attributes of each instance.
1358                 detachedEventWrapper->getAbstractEvent()->setRecurrenceId(st.time.utime);
1359                 detachedEventWrapper->getAbstractEvent()->setStartTime(st.time.utime);
1360                 detachedEventWrapper->getAbstractEvent()->setEndTime(et.time.utime);
1361
1362                 event->addExpandedEvent(detachedEventWrapper->getAbstractEvent());
1363             }
1364
1365             calendar_list_next(list);
1366         }
1367
1368         LoggerD("Length of total expanded events: "<<event->getExpandedEventList()->size());
1369
1370         event->setResult(true);
1371
1372         if(query) {
1373             calendar_query_destroy(query);
1374             query = NULL;
1375         }
1376         if(filter) {
1377             calendar_filter_destroy(filter);
1378             filter = NULL;
1379         }
1380         if( list ) {
1381             calendar_list_destroy(list, true);
1382             list = NULL;
1383         }
1384     }
1385     Catch (InvalidArgumentException)
1386     {
1387         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
1388         event->setResult(false);
1389         event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
1390     }
1391     Catch (Exception)
1392     {
1393         LoggerW("Exception: "<<_rethrown_exception.GetMessage());
1394         event->setResult(false);
1395         event->setExceptionCode(ExceptionCodes::UnknownException);
1396     }
1397
1398     if(query) {
1399         calendar_query_destroy(query);
1400     }
1401     if(filter) {
1402         calendar_filter_destroy(filter);
1403     }
1404     if( list ) {
1405         calendar_list_destroy(list, true);
1406     }
1407 }
1408
1409 }
1410 }