a02be8fc8c85a54a7fa0cd106c8c3cbe11cc5be8
[profile/ivi/wrt-plugins-tizen.git] / src / platform / Tizen / Calendar / Calendar.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <calendar-svc-provider.h>
19 #include <dpl/log/log.h>
20 #include <dpl/scoped_ptr.h>
21 #include "Calendar.h"
22 #include "CalendarManager.h"
23 #include "CalendarQuery.h"
24 #include "CalendarFilter.h"
25 #include "CalendarFilterValidator.h"
26 #include "API/Calendar/OnAddEventsChanged.h"
27 #include "API/Calendar/OnUpdateEventsChanged.h"
28 #include "API/Calendar/OnDeleteEventsChanged.h"
29 #include "API/Calendar/OnEventsChanged.h"
30 #include "API/Calendar/IEventWatchChanges.h"
31 #include "API/Calendar/IEventClearWatch.h"
32 #include "API/Calendar/EventId.h"
33 #include <API/Filter/IFilter.h>
34 #include <API/Filter/IFilterVisitor.h>
35 #include <sstream>
36
37 using namespace TizenApis::Api::Calendar;
38 using namespace WrtDeviceApis::Commons;
39
40 namespace TizenApis {
41 namespace Platform {
42 namespace Calendar {
43
44 Calendar::Calendar()
45 {
46     LogDebug("entered");
47 }
48
49 Calendar::~Calendar()
50 {
51     LogDebug("entered");
52 }
53
54 void Calendar::OnRequestReceived(const IEventAddEventPtr &event)
55 {
56     LogDebug("entered");
57     Try
58     {
59         if (!event->getEvent()) {
60             ThrowMsg(NullPointerException, "event parameter is NULL");
61         }
62         if (event->getEvent()->getIdIsSet()) {
63             LogWarning("adding event that is already added");
64             event->getEvent()->resetId();
65         }
66         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
67         event->getEvent()->setCalendarType(getType());
68         eventWrapper->convertAbstractEventToPlatformEvent();
69         if (event->checkCancelled()) {
70             event->setCancelAllowed(true);
71             event->setResult(true);
72             return;
73         }
74
75         // Set the account and calendar id before saving the item.
76         eventWrapper->setCalendarId(getId());
77         eventWrapper->setCalendarAccountId(getAccountId());
78         eventWrapper->saveEvent();
79         event->setResult(true);
80     }
81     catch (const Exception &ex)
82     {
83         LogError("Error during adding event" << ex.DumpToString());
84         event->setResult(false);
85         event->setExceptionCode(ExceptionCodes::UnknownException);
86     }
87     event->setCancelAllowed(false);
88 }
89
90 void Calendar::OnRequestReceived(const IEventAddEventsPtr &events)
91 {
92     LogDebug("entered");
93     Try
94     {
95         if (events->getEvents()->empty()) {
96             ThrowMsg(NullPointerException, "event vector parameter is empty");
97         }
98
99         // Save the vector of events iteratively
100         bool failedAdding = false;
101         for(unsigned int i=0; i<events->getEvents()->size(); i++)
102         {
103             if (events->getEvents()->at(i)->getIdIsSet()) {
104                 LogWarning("adding event that is already added: index " << i);
105                 events->getEvents()->at(i)->resetId();
106             }
107             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(events->getEvents()->at(i), getType()));
108             events->getEvents()->at(i)->setCalendarType(getType());
109             eventWrapper->convertAbstractEventToPlatformEvent();
110             if (events->checkCancelled()) {
111                 events->setCancelAllowed(true);
112                 events->setResult(true);
113                 return;
114             }
115
116             try {
117                 // Set the account and calendar id before saving the item.
118                 eventWrapper->setCalendarId(getId());
119                 eventWrapper->setCalendarAccountId(getAccountId());
120                 eventWrapper->saveEvent();
121             } catch (const Exception &saveException) {
122                 LogInfo("Error during saving an event " << saveException.DumpToString());
123                 failedAdding = true;
124             }
125             //getAddEmitter()->emit(eventPtr);
126         }
127
128         if( false==failedAdding ) {
129             events->setResult(true);
130         } else {
131             events->setResult(false);
132         }
133     }
134     catch (const Exception &ex)
135     {
136         LogError("Error during adding events" << ex.DumpToString());
137         events->setResult(false);
138         events->setExceptionCode(ExceptionCodes::UnknownException);
139     }
140     events->setCancelAllowed(false);
141 }
142
143 void Calendar::OnRequestReceived(const IEventUpdateEventPtr &event)
144 {
145     LogDebug("entered");
146     Try
147     {
148         if (!event->getEvent()) {
149             ThrowMsg(NullPointerException, "event parameter is NULL");
150         }
151         if (!event->getEvent()->getIdIsSet()) {
152             ThrowMsg(
153                 InvalidArgumentException,
154                 "Cannot update non-existing event. Event needs adding or ID is wrong");
155         }
156         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
157         event->getEvent()->setCalendarType(getType());
158         eventWrapper->convertAbstractEventToPlatformEvent();
159         if (event->checkCancelled()) {
160             event->setCancelAllowed(true);
161             event->setResult(true);
162             return;
163         }
164
165         if ( event->getUpdateAllInstances() || NULL==event->getEvent()->getRecurrenceRule())
166         {
167             // Set the account and calendar id before saving the item.
168             eventWrapper->setCalendarId(getId());
169             eventWrapper->setCalendarAccountId(getAccountId());
170             eventWrapper->saveEvent();
171         }
172         else
173         {
174             LogDebug("Update the exception record");
175             DPL::ScopedPtr<EventWrapper> eventWrapperChild(new EventWrapper(event->getEvent(), getType()));
176             eventWrapperChild->convertAbstractEventToPlatformEvent();
177
178             if ( CAL_SUCCESS!=calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
179                 CAL_VALUE_INT_ORIGINAL_EVENT_ID, event->getEvent()->getId()) ) {
180                 ThrowMsg(PlatformException, "cannot save exception event");
181             }
182             if (CAL_SUCCESS!=calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
183                 CAL_VALUE_INT_REPEAT_TERM,0) ) {
184                 ThrowMsg(PlatformException, "cannot save exception event");
185             }
186             int childId = calendar_svc_insert(eventWrapperChild->getPlatformEvent());
187             if ( childId<0 ) {
188                 ThrowMsg(PlatformException, "cannot save exception event");
189             }
190
191             GList* list = NULL;
192             cal_value *value = calendar_svc_value_new(CAL_VALUE_LST_EXCEPTION_DATE);
193             if (CAL_SUCCESS!=calendar_svc_value_set_time(value, CAL_VALUE_GMT_EXCEPTION_DATE_TIME, CAL_TZ_FLAG_GMT, event->getEvent()->getStartTime()) ) {
194                 ThrowMsg(PlatformException, "cannot save the exception parent event");
195             }
196             if (CAL_SUCCESS!=calendar_svc_value_set_int(value,  CAL_VALUE_INT_EXCEPTION_DATE_ID, childId)) {
197                 ThrowMsg(PlatformException, "cannot save the exception parent event");
198             }
199             eventWrapper->loadEvent(event->getEvent()->getId());
200             calendar_svc_struct_get_list(eventWrapper->getPlatformEvent(), CAL_VALUE_LST_EXCEPTION_DATE, &list);
201             list = g_list_append(list, value);
202             if (CAL_SUCCESS!=calendar_svc_struct_store_list(eventWrapper->getPlatformEvent(), CAL_VALUE_LST_EXCEPTION_DATE, list)) {
203                 ThrowMsg(PlatformException, "cannot save the exception parent event");
204             }
205             calendar_svc_update(eventWrapper->getPlatformEvent());
206
207             event->getEvent()->setIsDetached(true);
208         }
209
210         event->setResult(true);
211     }
212     catch (const Exception &ex)
213     {
214         LogError("Error during updating event " << ex.DumpToString());
215         event->setResult(false);
216         event->setExceptionCode(ExceptionCodes::UnknownException);
217     }
218     event->setCancelAllowed(false);
219 }
220
221 void Calendar::OnRequestReceived(const IEventUpdateEventsPtr &events)
222 {
223     LogDebug("entered");
224     Try
225     {
226         if (events->getEvents()->empty()) {
227             ThrowMsg(NullPointerException, "event vector parameter is empty");
228         }
229
230         // Update the vector of events iteratively
231         bool failedUpdating = false;
232         for(unsigned int i=0; i<events->getEvents()->size(); i++)
233         {
234             CalendarEventPtr thisEvent = events->getEvents()->at(i);
235             if (!thisEvent->getIdIsSet()) {
236                 ThrowMsg(InvalidArgumentException,
237                     "Cannot update non-existing event. Event needs adding or ID is wrong");
238             }
239             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(thisEvent, getType()));
240             events->getEvents()->at(i)->setCalendarType(getType());
241             eventWrapper->convertAbstractEventToPlatformEvent();
242             if (events->checkCancelled()) {
243                 events->setCancelAllowed(true);
244                 events->setResult(true);
245                 return;
246             }
247
248             try {
249                 if (events->getUpdateAllInstances() || NULL==thisEvent->getRecurrenceRule())
250                 {
251                     // Set the account and calendar id before saving the item.
252                     eventWrapper->setCalendarId(getId());
253                     eventWrapper->setCalendarAccountId(getAccountId());
254                     eventWrapper->saveEvent();
255                 }
256                 else
257                 {
258                     LogDebug("Update the exception record");
259                     DPL::ScopedPtr<EventWrapper> eventWrapperChild(new EventWrapper(thisEvent, getType()));
260                     eventWrapperChild->convertAbstractEventToPlatformEvent();
261
262                     if ( CAL_SUCCESS!=calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
263                         CAL_VALUE_INT_ORIGINAL_EVENT_ID, thisEvent->getId()) ) {
264                         ThrowMsg(PlatformException, "cannot save exception event");
265                     }
266                     if (CAL_SUCCESS!=calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
267                         CAL_VALUE_INT_REPEAT_TERM,0) ) {
268                         ThrowMsg(PlatformException, "cannot save exception event");
269                     }
270                     int childId = calendar_svc_insert(eventWrapperChild->getPlatformEvent());
271                     if ( childId<0 ) {
272                         ThrowMsg(PlatformException, "cannot save exception event");
273                     }
274
275                     GList* list = NULL;
276                     cal_value *value = calendar_svc_value_new(CAL_VALUE_LST_EXCEPTION_DATE);
277                     if (CAL_SUCCESS!=calendar_svc_value_set_time(value, CAL_VALUE_GMT_EXCEPTION_DATE_TIME, CAL_TZ_FLAG_GMT, thisEvent->getStartTime()) ) {
278                         ThrowMsg(PlatformException, "cannot save the exception parent event");
279                     }
280                     if (CAL_SUCCESS!=calendar_svc_value_set_int(value,  CAL_VALUE_INT_EXCEPTION_DATE_ID, childId)) {
281                         ThrowMsg(PlatformException, "cannot save the exception parent event");
282                     }
283                     calendar_svc_struct_get_list(eventWrapper->getPlatformEvent(), CAL_VALUE_LST_EXCEPTION_DATE, &list);
284                     list = g_list_append(list, value);
285                     if (CAL_SUCCESS!=calendar_svc_struct_store_list(eventWrapper->getPlatformEvent(), CAL_VALUE_LST_EXCEPTION_DATE, list)) {
286                         ThrowMsg(PlatformException, "cannot save the exception parent event");
287                     }
288                     calendar_svc_update(eventWrapper->getPlatformEvent());
289
290                     thisEvent->setIsDetached(true);
291                 }
292             } catch (const Exception &updateException) {
293                 LogInfo("Error during updating an event " << updateException.DumpToString());
294                 failedUpdating = true;
295             }
296             //getUpdateEmitter()->emit(eventPtr);
297         }
298
299         if( false==failedUpdating ) {
300             events->setResult(true);
301         } else {
302             events->setResult(false);
303         }
304     }
305     catch (const Exception &ex)
306     {
307         LogError("Error during updating events " << ex.DumpToString());
308         events->setResult(false);
309         events->setExceptionCode(ExceptionCodes::UnknownException);
310     }
311     events->setCancelAllowed(false);
312 }
313
314 void Calendar::OnRequestReceived(const IEventDeleteEventPtr &event)
315 {
316     LogDebug("entered");
317     Try
318     {
319         if (!event->getEventId()) {
320             ThrowMsg(NullPointerException, "event Id parameter is NULL");
321         }
322
323         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
324         event->getEventId()->setCalendarType(getType());
325         std::istringstream stream(event->getEventId()->getUId());
326         int id = -1;
327         stream>>id;
328         //eventWrapper->getAbstractEvent()->setId(id);
329         eventWrapper->loadEvent(id);
330         LogDebug("event->getEventId()->getRecurrenceId() : " << event->getEventId()->getRecurrenceId());
331         eventWrapper->getAbstractEvent()->setRecurrenceId(event->getEventId()->getRecurrenceId());
332
333         if (event->checkCancelled()) {
334             event->setCancelAllowed(true);
335             event->setResult(true);
336             return;
337         }
338
339         eventWrapper->deleteEvent();
340         event->setResult(true);
341     }
342     catch (const NotFoundException &ex)
343     {
344         LogError("event doesn't exist");
345         event->setResult(false);
346         event->setExceptionCode(ExceptionCodes::NotFoundException);
347     }
348     catch (const Exception &ex)
349     {
350         LogError("Error during deleting event " << ex.DumpToString());
351         event->setResult(false);
352         event->setExceptionCode(ExceptionCodes::UnknownException);
353     }
354     event->setCancelAllowed(false);
355 }
356
357 void Calendar::OnRequestReceived(const IEventDeleteEventsPtr &events)
358 {
359     LogDebug("entered");
360     Try
361     {
362         if (events->getEventIds()->empty()) {
363             ThrowMsg(NullPointerException, "event vector parameter is empty");
364         }
365
366         // Delete the vector of events iteratively considering the recurrenceId
367         bool failedDeleting = false;
368         for(unsigned int i=0; i<events->getEventIds()->size(); i++)
369         {
370             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
371             events->getEventIds()->at(i)->setCalendarType(getType());
372             std::istringstream stream(events->getEventIds()->at(i)->getUId());
373             int id;
374             stream>>id;
375             eventWrapper->getAbstractEvent()->setId(id);
376             eventWrapper->getAbstractEvent()->setRecurrenceId(events->getEventIds()->at(i)->getRecurrenceId());
377             eventWrapper->convertAbstractEventToPlatformEvent();
378             if (events->checkCancelled()) {
379                 events->setCancelAllowed(true);
380                 events->setResult(true);
381                 return;
382             }
383
384             try {
385                 eventWrapper->deleteEvent();
386             } catch (const NotFoundException &ex) {
387                 LogInfo("Event not found during deleting an event.");
388                 events->setExceptionCode(ExceptionCodes::NotFoundException);
389                 failedDeleting = true;
390             } catch (const Exception &ex) {
391                 LogInfo("Exception occurred during deleting an event.");
392                 events->setExceptionCode(ExceptionCodes::PlatformException);
393                 failedDeleting = true;
394             }
395         }
396
397         if( false==failedDeleting ) {
398             events->setResult(true);
399         }
400         else {
401             events->setResult(false);
402         }
403     }
404     catch (const NotFoundException &ex)
405     {
406         LogError("event doesn't exist");
407         events->setResult(false);
408         events->setExceptionCode(ExceptionCodes::NotFoundException);
409     }
410     catch (const Exception &ex)
411     {
412         LogError("Error during deleting event " << ex.DumpToString());
413         events->setResult(false);
414         events->setExceptionCode(ExceptionCodes::UnknownException);
415     }
416     events->setCancelAllowed(false);
417 }
418
419 void Calendar::OnRequestReceived(const IEventFindEventsPtr &event)
420 {
421     LogDebug("entered");
422     bool useGenericFilter = true;
423     event->setResult(true);
424
425     // Tizen Generic filter
426     if ( useGenericFilter )
427     {
428         try
429         {
430             _db_init();
431
432             CalendarFilterPtr calendarFilter( new CalendarFilter() );
433
434             // Set the attributesOfInterest here if needed.
435             //std::string query ("SELECT " + calendarFilter.concatenateFilterAttributes() + " FROM schedule_table");
436             std::string query (std::string("SELECT ") + CAL_VALUE_INT_INDEX + " FROM schedule_table");
437             LogInfo("Default query statement: "<<query);
438
439                 TizenApis::Api::Tizen::IFilterVisitorPtr filterTraversal = DPL::StaticPointerCast<TizenApis::Api::Tizen::IFilterVisitor>(calendarFilter);
440
441                 if (event->getGenericFilterIsSet()) {
442                 TizenApis::Api::Tizen::FilterPtr genericFilter = event->getGenericFilter();
443
444                 TizenApis::Api::Tizen::FilterValidatorPtr validator = CalendarFilterValidatorFactory::getCalendarFilterValidator();
445                 bool success = genericFilter->validate(validator);
446                 if(!success) {
447                     ThrowMsg(InvalidArgumentException, "Invalid filter arguments.");
448                 } else {
449                     LogInfo("Filter validation has passed.");
450                 }
451
452                         genericFilter->travel(filterTraversal, 0);
453                         LogDebug("Traverse string [" << calendarFilter->getResult() << "]");
454                         query.append(calendarFilter->getResult());
455                 query.append(" AND is_deleted = 0;");
456                 } else {
457                 query.append(" WHERE is_deleted = 0;");
458                 }
459
460                 if (event->getSortModesIsSet()) {
461                         query.append(calendarFilter->makeQuerySortMode(event->getSortModes()));
462                 }
463
464                 LogDebug("Filter query [" << query << "]");
465
466                 calendarFilter->executeQuery(query, event->getEvents());
467
468             LogDebug("Result count [" << event->getEvents()->size() << "]");
469
470             _db_finish();
471
472             // Now load the full calendar item using the retrieved id.
473             for( unsigned int i=0; i<event->getEvents()->size(); i++) {
474                 // platformEvent is freed when the wrapper destructor is called.
475                 DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvents()->at(i), getType()));
476                 eventWrapper->loadEvent(event->getEvents()->at(i)->getId());
477             }
478         }
479         catch (const InvalidArgumentException &ex)
480         {
481             LogError("Exception: " << ex.DumpToString());
482             event->setResult(false);
483             event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
484         }
485         catch (const NotFoundException &ex)
486         {
487             LogError("Exception: " << ex.DumpToString());
488             event->setResult(false);
489             event->setExceptionCode(ExceptionCodes::NotFoundException);
490         }
491         catch (const Exception &ex)
492         {
493             LogError("Exception: " << ex.DumpToString());
494             event->setResult(false);
495             event->setExceptionCode(ExceptionCodes::UnknownException);
496         }
497     }
498     // WAC style filter
499     else
500     {
501         cal_iter *iter = NULL;
502         try
503         {
504             const EventFilterPtr filter = event->getFilter();
505             cal_struct *platformEvent = NULL;
506             bool isStartDateSet = false;
507
508             if (NULL==filter)
509             {
510                 LogInfo("Filter is not set.");
511                 const char *dataType;
512                 if(getType() == CalendarEvent::TASK_TYPE) {
513                     dataType = CAL_STRUCT_TODO;
514                 } else {
515                     dataType = CAL_STRUCT_SCHEDULE;
516                 }
517
518                 std::istringstream stream(getId());
519                 int calendarId = -1;
520                 stream>>calendarId;
521                 if (CAL_SUCCESS != calendar_svc_get_all(getAccountId(), calendarId, dataType, &iter)) {
522                         ThrowMsg(PlatformException, "Can't get all records");
523                 }
524             }
525             else
526             // Use the new calendar service search function with multiple type/value pairs.
527             {
528                 int filterCount = 0;
529                 const char *searchType[9];
530                 const void *searchValue[9];
531
532                 if(filter->getIdIsSet()) {
533                     // Platform supports integer type db index only.
534                     std::istringstream istream(filter->getIdFilter());
535                     int id;
536                     istream>>id;
537                     searchType[filterCount] = CAL_VALUE_INT_INDEX;
538                     searchValue[filterCount++] = (void*)(id);
539                 }
540                 if(filter->getSubjectIsSet()) {
541                     searchType[filterCount] = CAL_VALUE_TXT_SUMMARY;
542                     searchValue[filterCount++] = (void*)(filter->getSubjectFilter().c_str());
543                 }
544                 if(filter->getDescriptionIsSet()) {
545                     searchType[filterCount] = CAL_VALUE_TXT_DESCRIPTION;
546                     searchValue[filterCount++] = (void*)(filter->getDescriptionFilter().c_str());
547                 }
548                 if(filter->getLocationIsSet()) {
549                     searchType[filterCount] = CAL_VALUE_TXT_LOCATION;
550                     searchValue[filterCount++] = (void*)(filter->getLocationFilter().c_str());
551                 }
552                 if(filter->getCategoryIsSet()) {
553                     searchType[filterCount] = CAL_VALUE_TXT_MEETING_CATEGORY_DETAIL_NAME;
554                     searchValue[filterCount++] = (void*)(filter->getCategoryFilter().c_str());
555                 }
556                 if(filter->getStatusIsSet()) {
557                     std::stringstream ss;
558                     std::string status;
559                     for( unsigned int i=0; i<filter->getStatusFilter().size(); i++ ) {
560                         cal_status_type_t statusValue = CAL_STATUS_CONFIRM;
561                         switch(filter->getStatusFilter().at(i)) {
562                         case CalendarEvent::TENTATIVE_STATUS:
563                             statusValue = CAL_STATUS_TENTATIVE;
564                             break;
565                         case CalendarEvent::CANCELLED_STATUS:
566                             statusValue = CAL_STATUS_DENIED;
567                             break;
568                         case CalendarEvent::CONFIRMED_STATUS:
569                         default:
570                             statusValue = CAL_STATUS_CONFIRM;
571                             break;
572                         }
573                         ss<<statusValue;
574                     }
575                     searchType[filterCount] = CAL_VALUE_INT_MEETING_STATUS;
576                     status = ss.str();
577                     searchValue[filterCount++] = (void*)(status.c_str());
578                     LogInfo("status filter "<<status.c_str());
579                 }
580                 if(filter->getStartTimeMinIsSet()) {
581                     searchType[filterCount] = CAL_VALUE_GMT_START_DATE_TIME;
582                     searchValue[filterCount++] = (void*)(filter->getStartTimeMinFilter());
583                     isStartDateSet = true;
584                 }
585                 if(filter->getStartTimeMaxIsSet()) {
586                     searchType[filterCount] = CAL_VALUE_GMT_END_DATE_TIME;
587                     searchValue[filterCount++] = (void*)(filter->getStartTimeMaxFilter());
588                     isStartDateSet = true;
589                 }
590                 LogInfo("Filter is set: "<<filterCount);
591
592                 if(CAL_SUCCESS !=
593                     calendar_svc_find_event_list_by_filter(0, filterCount, searchType, searchValue, &iter)) {
594                     ThrowMsg(NotFoundException, "Can't find event list by filter.");
595                 }
596             }
597
598             while (CAL_SUCCESS == calendar_svc_iter_next(iter)) {
599                 event->tryCancelled();
600
601                 platformEvent = NULL;
602                 if (CAL_SUCCESS !=
603                     calendar_svc_iter_get_info(iter, &platformEvent)) {
604                     ThrowMsg(PlatformException, "Can't get event info.");
605                 }
606
607                 // platformEvent is freed when the wrapper destructor is called.
608                 DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(platformEvent, getType()));
609
610                 eventWrapper->convertPlatformEventToAbstractEvent()->setCalendarType(getType());
611                 event->addEvent(eventWrapper->getAbstractEvent());
612             }
613
614             // Process the recurring event cases here.
615             if ( isStartDateSet ) {
616                 LogInfo("Process the recurring evets");
617                 if(CAL_SUCCESS !=
618                     calendar_svc_find_recurring_event_list(0, &iter)) {
619                     ThrowMsg(PlatformException, "Can't find recurring event list.");
620                 }
621
622                 time_t startTime, endTime, nextStartTime, nextEndTime;
623                 if (filter->getStartTimeMinIsSet()) {
624                     startTime = filter->getStartTimeMinFilter();
625                 } else {
626                     startTime = 0;
627                 }
628                 if (filter->getStartTimeMaxIsSet()) {
629                     endTime = filter->getStartTimeMaxFilter();
630                 } else {
631                     endTime = INT_MAX; // about 60 years in 4 bytes system.
632                 }
633
634                 while (CAL_SUCCESS == calendar_svc_iter_next(iter)) {
635                     event->tryCancelled();
636
637                     nextStartTime = 0; // It's important to reset this before calling calendar_svc_util_next_valid_event.
638                     nextEndTime = 0;
639                     platformEvent = NULL;
640                     if (CAL_SUCCESS !=
641                         calendar_svc_iter_get_info(iter, &platformEvent)) {
642                         ThrowMsg(PlatformException, "Can't get event info.");
643                     }
644
645                     if ( CAL_SUCCESS ==
646                         calendar_svc_util_next_valid_event(platformEvent, startTime, endTime, &nextStartTime, &nextEndTime) ) {
647                         bool isDuplicated = false;
648                         for( unsigned int i=0; i<event->getEvents()->size(); i++ ) {
649                             if (calendar_svc_struct_get_int(platformEvent, CAL_VALUE_INT_INDEX)==event->getEvents()->at(i)->getId())
650                                 isDuplicated = true;
651                         }
652                         if (!isDuplicated) {
653                             LogInfo("Found a recurring event inbetween the start time period.");
654                             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(platformEvent, getType()));
655                             eventWrapper->convertPlatformEventToAbstractEvent()->setCalendarType(getType());
656                             event->addEvent(eventWrapper->getAbstractEvent());
657                         }
658                     }
659                 }
660             }
661         }
662         catch (const NotFoundException &ex)
663         {
664             LogError("Exception: " << ex.DumpToString());
665             event->setResult(false);
666             event->setExceptionCode(ExceptionCodes::NotFoundException);
667         }
668         catch (const Exception &ex)
669         {
670             LogError("Exception: " << ex.DumpToString());
671             event->setResult(false);
672             event->setExceptionCode(ExceptionCodes::UnknownException);
673         }
674
675         calendar_svc_iter_remove(&iter);
676     }
677 }
678
679 void Calendar::OnRequestReceived(const IEventCreateEventPtr &event)
680 {
681     LogDebug("entered");
682     Try
683     {
684         event->setEvent(CalendarEventPtr(new CalendarEvent()));
685         event->getEvent()->setCalendarType(getType());
686         event->setResult(event->getEvent().Get() != NULL);
687     }
688     catch (const Exception &ex)
689     {
690         LogError("Error during creating an event " << ex.DumpToString());
691         event->setResult(false);
692         event->setExceptionCode(ExceptionCodes::UnknownException);
693     }
694 }
695
696 void Calendar::OnRequestReceived(const IEventCreateEventFromStringPtr &event)
697 {
698     LogDebug("entered");
699     Try
700     {
701         if (event->checkCancelled()) {
702             event->setCancelAllowed(true);
703             event->setResult(true);
704             return;
705         }
706
707         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
708         eventWrapper->createEventFromString(event->getEventString());
709         event->setEvent(eventWrapper->convertPlatformEventToAbstractEvent());
710         event->getEvent()->setCalendarType(getType());
711         event->setResult(true);
712     }
713     catch (const Exception &ex)
714     {
715         LogError("Error during creating event from string" << ex.DumpToString());
716         LogInfo("eventString: " + event->getEventString());
717         event->setResult(false);
718         event->setExceptionCode(ExceptionCodes::UnknownException);
719     }
720     event->setCancelAllowed(false);
721 }
722
723 void Calendar::OnRequestReceived(const IEventExportEventToStringPtr &event)
724 {
725     LogDebug("entered");
726     Try
727     {
728         if (!event->getEvent()) {
729             ThrowMsg(NullPointerException, "event parameter is NULL");
730         }
731
732         if (event->checkCancelled()) {
733             event->setCancelAllowed(true);
734             event->setResult(true);
735             return;
736         }
737
738         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
739         event->getEvent()->setCalendarType(getType());
740         eventWrapper->convertAbstractEventToPlatformEvent();
741         event->setEventString(eventWrapper->exportEventToString());
742         event->setResult(true);
743     }
744     catch (const Exception &ex)
745     {
746         LogError("Error during creating string from event" << ex.DumpToString());
747         event->setResult(false);
748         event->setExceptionCode(ExceptionCodes::UnknownException);
749     }
750     event->setCancelAllowed(false);
751 }
752
753 static void eventChangedCb(void *user_data)
754 {
755     LogDebug("entered");
756
757     OnEventsChangedPtr eventPtr(new OnEventsChanged());
758     try
759     {
760         Calendar *thisCalendar = (Calendar*) user_data;
761
762         // Determine the status of event change.
763         cal_iter *iter = NULL;
764         cal_struct *platformEvent = NULL;
765         int index;
766         int syncStatus;
767
768         if( CAL_SUCCESS != calendar_svc_get_updated_event_list(thisCalendar->getAccountId(),
769                 thisCalendar->getLastChangeFetchTime(),
770                 &iter) ) {
771             ThrowMsg(PlatformException, "Can't get the updated event list.");
772         }
773         while( CAL_SUCCESS == calendar_svc_iter_next(iter) )
774         {
775             if ( CAL_SUCCESS != calendar_svc_iter_get_info(iter, &platformEvent) ) {
776                 ThrowMsg(PlatformException, "Can't get the calendar info.");
777             }
778
779             index = calendar_svc_struct_get_int(platformEvent, CAL_VALUE_INT_INDEX);
780             syncStatus = calendar_svc_struct_get_int(platformEvent, CAL_VALUE_INT_SYNC_STATUS);
781             LogDebug("index "<<index<<" , syncStatus "<<syncStatus);
782             if ( CAL_SYNC_STATUS_NEW==syncStatus ) {
783                 eventPtr->setStatus(OnEventsChanged::ON_ADD);
784             } else if ( CAL_SYNC_STATUS_UPDATED==syncStatus ) {
785                 eventPtr->setStatus(OnEventsChanged::ON_UPDATE);
786             } else if ( CAL_SYNC_STATUS_DELETED==syncStatus ) {
787                 eventPtr->setStatus(OnEventsChanged::ON_DELETE);
788             } else {
789                 if( platformEvent ) {
790                     calendar_svc_struct_free(&platformEvent);
791                 }
792                 calendar_svc_iter_remove(&iter);
793                 ThrowMsg(PlatformException, "Wrong syncStatus.");
794             }
795
796             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(thisCalendar->getType()));
797             eventWrapper->loadEvent(index);
798             eventPtr->addEvent(eventWrapper->getAbstractEvent());
799
800             if ( CAL_SUCCESS != calendar_svc_struct_free(&platformEvent) ) {
801                 ThrowMsg(PlatformException, "Can't free the platform event struct.");
802             }
803         }
804
805         if ( CAL_SUCCESS != calendar_svc_iter_remove(&iter) ) {
806             ThrowMsg(PlatformException, "Can't remove the iter.");
807         }
808
809         std::time_t localTime = time(NULL);
810         thisCalendar->setLastChangeFetchTime(localTime);
811         LogInfo("Last change fetch time: "<<thisCalendar->getLastChangeFetchTime());
812
813         eventPtr->setResult(true);
814
815         if( eventPtr->getEventList()->size() > 0 ) {
816             thisCalendar->m_changeEmitters.emit(eventPtr);
817         } else {
818             LogInfo("No actual changes. Skip signal emission.");
819         }
820     }
821     catch (const Exception &ex)
822     {
823         LogError("Error while emitting the change noti" << ex.DumpToString());
824     }
825 }
826
827 void Calendar::OnRequestReceived(const IEventWatchChangesPtr &event)
828 {
829     LogDebug("entered");
830     Try
831     {
832         // Subscribe the watch to the platform just once.
833         if( m_changeEmitters.size()==0 )
834         {
835             if( CAL_SUCCESS!=calendar_svc_subscribe_change(eventChangedCb, this) ) {
836                 ThrowMsg(PlatformException, "Can't subscribe the db change noti.");
837             } else {
838                 // Save the last change fetch time to start watching.
839                 std::time_t localTime = time(NULL);
840                 setLastChangeFetchTime(localTime);
841                 LogInfo("Last change fetch time: "<<getLastChangeFetchTime());
842             }
843         }
844
845         m_changeEmitters.attach(event->getEmitter());
846         event->setWatchId(event->getEmitter()->getId());
847         event->setResult(true);
848     }
849     catch (const Exception &ex)
850     {
851         LogError("Error during creating a watch " << ex.DumpToString());
852         event->setResult(false);
853         event->setExceptionCode(ExceptionCodes::UnknownException);
854     }
855 }
856
857 void Calendar::OnRequestReceived(const IEventClearWatchPtr &event)
858 {
859     LogDebug("entered");
860     Try
861     {
862         m_changeEmitters.detach(event->getWatchId());
863
864         if( m_changeEmitters.size()==0 ) {
865             if( CAL_SUCCESS!=calendar_svc_unsubscribe_change(eventChangedCb) ) {
866                 ThrowMsg(PlatformException, "Can't unsubscribe the db change noti.");
867             } else {
868                 LogDebug("Platform watch cleared successfully.");
869             }
870         }
871         event->setResult(true);
872     }
873     catch (const Exception &ex)
874     {
875         LogError("Error during clearing the watch " << ex.DumpToString());
876         event->setResult(false);
877         event->setExceptionCode(ExceptionCodes::UnknownException);
878     }
879 }
880
881 void Calendar::OnRequestReceived(const IEventExpandEventRecurrencePtr &event)
882 {
883     LogDebug("entered");
884     const CalendarEventPtr calEvent = event->getEvent();
885     const time_t startDate = event->getStartDate();
886     const time_t endDate = event->getEndDate();
887     event->setResult(true);
888
889     try {
890         if ( 0 >= calEvent->getRecurrenceRule()->getFrequency())
891         {
892             ThrowMsg(PlatformException, "This is not a recurring event.");
893         }
894
895         std::time_t nextStartTime = 0;
896         std::time_t nextEndTime = 0;
897
898         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
899         eventWrapper->convertAbstractEventToPlatformEvent();
900
901         event->tryCancelled();
902
903         while ( CAL_SUCCESS ==
904             calendar_svc_util_next_valid_event(eventWrapper->getPlatformEvent(), startDate, endDate, &nextStartTime, &nextEndTime) ) {
905             LogInfo("Found a next vaild event: "<<nextStartTime);
906             DPL::ScopedPtr<EventWrapper> recurringEventWrapper(new EventWrapper(getType()));
907             recurringEventWrapper->loadEvent(calEvent->getId());
908             recurringEventWrapper->getAbstractEvent()->setRecurrenceId(nextStartTime);
909             event->addExpandedEvent(recurringEventWrapper->getAbstractEvent());
910         }
911
912         LogInfo("Length of expanded events: "<<event->getExpandedEventList()->size());
913     }
914     catch (const Exception &ex)
915     {
916         LogError("Exception: " << ex.DumpToString());
917         event->setResult(false);
918         event->setExceptionCode(ExceptionCodes::UnknownException);
919     }
920
921     event->setCancelAllowed(true);
922 }
923
924 }
925 }
926 }