Beta merge 2
[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 IEventGetPtr &event)
358 {
359     LogDebug("entered");
360     Try
361     {
362         if (!event->getItemId()) {
363             ThrowMsg(NullPointerException, "Id parameter is NULL");
364         }
365
366         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
367         event->getItemId()->setCalendarType(getType());
368         std::stringstream ss(event->getItemId()->getUId());
369         int id = -1;
370         ss>>id;
371         eventWrapper->loadEvent(id);
372
373         event->setItem(eventWrapper->convertPlatformEventToAbstractEvent());
374         event->getItem()->setCalendarType(getType());
375         event->setResult(true);
376     }
377     catch (const NotFoundException &ex)
378     {
379         LogError("Item doesn't exist");
380         event->setResult(false);
381         event->setExceptionCode(ExceptionCodes::NotFoundException);
382     }
383     catch (const Exception &ex)
384     {
385         LogError("Error during getting an item " << ex.DumpToString());
386         event->setResult(false);
387         event->setExceptionCode(ExceptionCodes::UnknownException);
388     }
389     event->setCancelAllowed(false);
390 }
391
392 void Calendar::OnRequestReceived(const IEventDeleteEventsPtr &events)
393 {
394     LogDebug("entered");
395     Try
396     {
397         if (events->getEventIds()->empty()) {
398             ThrowMsg(NullPointerException, "event vector parameter is empty");
399         }
400
401         // Delete the vector of events iteratively considering the recurrenceId
402         bool failedDeleting = false;
403         for(unsigned int i=0; i<events->getEventIds()->size(); i++)
404         {
405             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
406             events->getEventIds()->at(i)->setCalendarType(getType());
407             std::istringstream stream(events->getEventIds()->at(i)->getUId());
408             int id;
409             stream>>id;
410             eventWrapper->getAbstractEvent()->setId(id);
411             eventWrapper->getAbstractEvent()->setRecurrenceId(events->getEventIds()->at(i)->getRecurrenceId());
412             eventWrapper->convertAbstractEventToPlatformEvent();
413             if (events->checkCancelled()) {
414                 events->setCancelAllowed(true);
415                 events->setResult(true);
416                 return;
417             }
418
419             try {
420                 eventWrapper->deleteEvent();
421             } catch (const NotFoundException &ex) {
422                 LogInfo("Event not found during deleting an event.");
423                 events->setExceptionCode(ExceptionCodes::NotFoundException);
424                 failedDeleting = true;
425             } catch (const Exception &ex) {
426                 LogInfo("Exception occurred during deleting an event.");
427                 events->setExceptionCode(ExceptionCodes::PlatformException);
428                 failedDeleting = true;
429             }
430         }
431
432         if( false==failedDeleting ) {
433             events->setResult(true);
434         }
435         else {
436             events->setResult(false);
437         }
438     }
439     catch (const NotFoundException &ex)
440     {
441         LogError("event doesn't exist");
442         events->setResult(false);
443         events->setExceptionCode(ExceptionCodes::NotFoundException);
444     }
445     catch (const Exception &ex)
446     {
447         LogError("Error during deleting event " << ex.DumpToString());
448         events->setResult(false);
449         events->setExceptionCode(ExceptionCodes::UnknownException);
450     }
451     events->setCancelAllowed(false);
452 }
453
454 void Calendar::OnRequestReceived(const IEventFindEventsPtr &event)
455 {
456     LogDebug("entered");
457     bool useGenericFilter = true;
458     event->setResult(true);
459
460     // Tizen Generic filter
461     if ( useGenericFilter )
462     {
463         try
464         {
465             _db_init();
466
467             CalendarFilterPtr calendarFilter( new CalendarFilter() );
468
469             // Set the attributesOfInterest here if needed.
470             //std::string query ("SELECT " + calendarFilter.concatenateFilterAttributes() + " FROM schedule_table");
471             std::string query (std::string("SELECT ") + CAL_VALUE_INT_INDEX + " FROM schedule_table");
472             LogInfo("Default query statement: "<<query);
473
474                 TizenApis::Api::Tizen::IFilterVisitorPtr filterTraversal = DPL::StaticPointerCast<TizenApis::Api::Tizen::IFilterVisitor>(calendarFilter);
475
476                 if (event->getGenericFilterIsSet()) {
477                 TizenApis::Api::Tizen::FilterPtr genericFilter = event->getGenericFilter();
478
479                 TizenApis::Api::Tizen::FilterValidatorPtr validator = CalendarFilterValidatorFactory::getCalendarFilterValidator();
480                 bool success = genericFilter->validate(validator);
481                 if(!success) {
482                     ThrowMsg(InvalidArgumentException, "Invalid filter arguments.");
483                 } else {
484                     LogInfo("Filter validation has passed.");
485                 }
486
487                         genericFilter->travel(filterTraversal, 0);
488                         LogDebug("Traverse string [" << calendarFilter->getResult() << "]");
489                         query.append(calendarFilter->getResult());
490                 query.append(" AND is_deleted = 0;");
491                 } else {
492                 query.append(" WHERE is_deleted = 0;");
493                 }
494
495                 if (event->getSortModesIsSet()) {
496                         query.append(calendarFilter->makeQuerySortMode(event->getSortModes()));
497                 }
498
499                 LogDebug("Filter query [" << query << "]");
500
501                 calendarFilter->executeQuery(query, event->getEvents());
502
503             LogDebug("Result count [" << event->getEvents()->size() << "]");
504
505             _db_finish();
506
507             // Now load the full calendar item using the retrieved id.
508             for( unsigned int i=0; i<event->getEvents()->size(); i++) {
509                 // platformEvent is freed when the wrapper destructor is called.
510                 DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvents()->at(i), getType()));
511                 eventWrapper->loadEvent(event->getEvents()->at(i)->getId());
512             }
513         }
514         catch (const InvalidArgumentException &ex)
515         {
516             LogError("Exception: " << ex.DumpToString());
517             event->setResult(false);
518             event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
519         }
520         catch (const NotFoundException &ex)
521         {
522             LogError("Exception: " << ex.DumpToString());
523             event->setResult(false);
524             event->setExceptionCode(ExceptionCodes::NotFoundException);
525         }
526         catch (const Exception &ex)
527         {
528             LogError("Exception: " << ex.DumpToString());
529             event->setResult(false);
530             event->setExceptionCode(ExceptionCodes::UnknownException);
531         }
532     }
533     // WAC style filter
534     else
535     {
536         cal_iter *iter = NULL;
537         try
538         {
539             const EventFilterPtr filter = event->getFilter();
540             cal_struct *platformEvent = NULL;
541             bool isStartDateSet = false;
542
543             if (NULL==filter)
544             {
545                 LogInfo("Filter is not set.");
546                 const char *dataType;
547                 if(getType() == CalendarEvent::TASK_TYPE) {
548                     dataType = CAL_STRUCT_TODO;
549                 } else {
550                     dataType = CAL_STRUCT_SCHEDULE;
551                 }
552
553                 std::istringstream stream(getId());
554                 int calendarId = -1;
555                 stream>>calendarId;
556                 if (CAL_SUCCESS != calendar_svc_get_all(getAccountId(), calendarId, dataType, &iter)) {
557                         ThrowMsg(PlatformException, "Can't get all records");
558                 }
559             }
560             else
561             // Use the new calendar service search function with multiple type/value pairs.
562             {
563                 int filterCount = 0;
564                 const char *searchType[9];
565                 const void *searchValue[9];
566
567                 if(filter->getIdIsSet()) {
568                     // Platform supports integer type db index only.
569                     std::istringstream istream(filter->getIdFilter());
570                     int id;
571                     istream>>id;
572                     searchType[filterCount] = CAL_VALUE_INT_INDEX;
573                     searchValue[filterCount++] = (void*)(id);
574                 }
575                 if(filter->getSubjectIsSet()) {
576                     searchType[filterCount] = CAL_VALUE_TXT_SUMMARY;
577                     searchValue[filterCount++] = (void*)(filter->getSubjectFilter().c_str());
578                 }
579                 if(filter->getDescriptionIsSet()) {
580                     searchType[filterCount] = CAL_VALUE_TXT_DESCRIPTION;
581                     searchValue[filterCount++] = (void*)(filter->getDescriptionFilter().c_str());
582                 }
583                 if(filter->getLocationIsSet()) {
584                     searchType[filterCount] = CAL_VALUE_TXT_LOCATION;
585                     searchValue[filterCount++] = (void*)(filter->getLocationFilter().c_str());
586                 }
587                 if(filter->getCategoryIsSet()) {
588                     searchType[filterCount] = CAL_VALUE_TXT_MEETING_CATEGORY_DETAIL_NAME;
589                     searchValue[filterCount++] = (void*)(filter->getCategoryFilter().c_str());
590                 }
591                 if(filter->getStatusIsSet()) {
592                     std::stringstream ss;
593                     std::string status;
594                     for( unsigned int i=0; i<filter->getStatusFilter().size(); i++ ) {
595                         cal_status_type_t statusValue = CAL_STATUS_CONFIRM;
596                         switch(filter->getStatusFilter().at(i)) {
597                         case CalendarEvent::TENTATIVE_STATUS:
598                             statusValue = CAL_STATUS_TENTATIVE;
599                             break;
600                         case CalendarEvent::CANCELLED_STATUS:
601                             statusValue = CAL_STATUS_DENIED;
602                             break;
603                         case CalendarEvent::CONFIRMED_STATUS:
604                         default:
605                             statusValue = CAL_STATUS_CONFIRM;
606                             break;
607                         }
608                         ss<<statusValue;
609                     }
610                     searchType[filterCount] = CAL_VALUE_INT_MEETING_STATUS;
611                     status = ss.str();
612                     searchValue[filterCount++] = (void*)(status.c_str());
613                     LogInfo("status filter "<<status.c_str());
614                 }
615                 if(filter->getStartTimeMinIsSet()) {
616                     searchType[filterCount] = CAL_VALUE_GMT_START_DATE_TIME;
617                     searchValue[filterCount++] = (void*)(filter->getStartTimeMinFilter());
618                     isStartDateSet = true;
619                 }
620                 if(filter->getStartTimeMaxIsSet()) {
621                     searchType[filterCount] = CAL_VALUE_GMT_END_DATE_TIME;
622                     searchValue[filterCount++] = (void*)(filter->getStartTimeMaxFilter());
623                     isStartDateSet = true;
624                 }
625                 LogInfo("Filter is set: "<<filterCount);
626
627                 if(CAL_SUCCESS !=
628                     calendar_svc_find_event_list_by_filter(0, filterCount, searchType, searchValue, &iter)) {
629                     ThrowMsg(NotFoundException, "Can't find event list by filter.");
630                 }
631             }
632
633             while (CAL_SUCCESS == calendar_svc_iter_next(iter)) {
634                 event->tryCancelled();
635
636                 platformEvent = NULL;
637                 if (CAL_SUCCESS !=
638                     calendar_svc_iter_get_info(iter, &platformEvent)) {
639                     ThrowMsg(PlatformException, "Can't get event info.");
640                 }
641
642                 // platformEvent is freed when the wrapper destructor is called.
643                 DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(platformEvent, getType()));
644
645                 eventWrapper->convertPlatformEventToAbstractEvent()->setCalendarType(getType());
646                 event->addEvent(eventWrapper->getAbstractEvent());
647             }
648
649             // Process the recurring event cases here.
650             if ( isStartDateSet ) {
651                 LogInfo("Process the recurring evets");
652                 if(CAL_SUCCESS !=
653                     calendar_svc_find_recurring_event_list(0, &iter)) {
654                     ThrowMsg(PlatformException, "Can't find recurring event list.");
655                 }
656
657                 time_t startTime, endTime, nextStartTime, nextEndTime;
658                 if (filter->getStartTimeMinIsSet()) {
659                     startTime = filter->getStartTimeMinFilter();
660                 } else {
661                     startTime = 0;
662                 }
663                 if (filter->getStartTimeMaxIsSet()) {
664                     endTime = filter->getStartTimeMaxFilter();
665                 } else {
666                     endTime = INT_MAX; // about 60 years in 4 bytes system.
667                 }
668
669                 while (CAL_SUCCESS == calendar_svc_iter_next(iter)) {
670                     event->tryCancelled();
671
672                     nextStartTime = 0; // It's important to reset this before calling calendar_svc_util_next_valid_event.
673                     nextEndTime = 0;
674                     platformEvent = NULL;
675                     if (CAL_SUCCESS !=
676                         calendar_svc_iter_get_info(iter, &platformEvent)) {
677                         ThrowMsg(PlatformException, "Can't get event info.");
678                     }
679
680                     if ( CAL_SUCCESS ==
681                         calendar_svc_util_next_valid_event(platformEvent, startTime, endTime, &nextStartTime, &nextEndTime) ) {
682                         bool isDuplicated = false;
683                         for( unsigned int i=0; i<event->getEvents()->size(); i++ ) {
684                             if (calendar_svc_struct_get_int(platformEvent, CAL_VALUE_INT_INDEX)==event->getEvents()->at(i)->getId())
685                                 isDuplicated = true;
686                         }
687                         if (!isDuplicated) {
688                             LogInfo("Found a recurring event inbetween the start time period.");
689                             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(platformEvent, getType()));
690                             eventWrapper->convertPlatformEventToAbstractEvent()->setCalendarType(getType());
691                             event->addEvent(eventWrapper->getAbstractEvent());
692                         }
693                     }
694                 }
695             }
696         }
697         catch (const NotFoundException &ex)
698         {
699             LogError("Exception: " << ex.DumpToString());
700             event->setResult(false);
701             event->setExceptionCode(ExceptionCodes::NotFoundException);
702         }
703         catch (const Exception &ex)
704         {
705             LogError("Exception: " << ex.DumpToString());
706             event->setResult(false);
707             event->setExceptionCode(ExceptionCodes::UnknownException);
708         }
709
710         calendar_svc_iter_remove(&iter);
711     }
712 }
713
714 void Calendar::OnRequestReceived(const IEventCreateEventPtr &event)
715 {
716     LogDebug("entered");
717     Try
718     {
719         event->setEvent(CalendarEventPtr(new CalendarEvent()));
720         event->getEvent()->setCalendarType(getType());
721         event->setResult(event->getEvent().Get() != NULL);
722     }
723     catch (const Exception &ex)
724     {
725         LogError("Error during creating an event " << ex.DumpToString());
726         event->setResult(false);
727         event->setExceptionCode(ExceptionCodes::UnknownException);
728     }
729 }
730
731 void Calendar::OnRequestReceived(const IEventCreateEventFromStringPtr &event)
732 {
733     LogDebug("entered");
734     Try
735     {
736         if (event->checkCancelled()) {
737             event->setCancelAllowed(true);
738             event->setResult(true);
739             return;
740         }
741
742         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
743         eventWrapper->createEventFromString(event->getEventString());
744         event->setEvent(eventWrapper->convertPlatformEventToAbstractEvent());
745         event->getEvent()->setCalendarType(getType());
746         event->setResult(true);
747     }
748     catch (const Exception &ex)
749     {
750         LogError("Error during creating event from string" << ex.DumpToString());
751         LogInfo("eventString: " + event->getEventString());
752         event->setResult(false);
753         event->setExceptionCode(ExceptionCodes::UnknownException);
754     }
755     event->setCancelAllowed(false);
756 }
757
758 void Calendar::OnRequestReceived(const IEventExportEventToStringPtr &event)
759 {
760     LogDebug("entered");
761     Try
762     {
763         if (!event->getEvent()) {
764             ThrowMsg(NullPointerException, "event parameter is NULL");
765         }
766
767         if (event->checkCancelled()) {
768             event->setCancelAllowed(true);
769             event->setResult(true);
770             return;
771         }
772
773         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
774         event->getEvent()->setCalendarType(getType());
775         eventWrapper->convertAbstractEventToPlatformEvent();
776         event->setEventString(eventWrapper->exportEventToString());
777         event->setResult(true);
778     }
779     catch (const Exception &ex)
780     {
781         LogError("Error during creating string from event" << ex.DumpToString());
782         event->setResult(false);
783         event->setExceptionCode(ExceptionCodes::UnknownException);
784     }
785     event->setCancelAllowed(false);
786 }
787
788 static void eventChangedCb(void *user_data)
789 {
790     LogDebug("entered");
791
792     OnEventsChangedPtr eventPtr(new OnEventsChanged());
793     try
794     {
795         Calendar *thisCalendar = (Calendar*) user_data;
796
797         // Determine the status of event change.
798         cal_iter *iter = NULL;
799         cal_struct *platformEvent = NULL;
800         int index;
801         int syncStatus;
802
803         if( CAL_SUCCESS != calendar_svc_get_updated_event_list(thisCalendar->getAccountId(),
804                 thisCalendar->getLastChangeFetchTime(),
805                 &iter) ) {
806             ThrowMsg(PlatformException, "Can't get the updated event list.");
807         }
808         while( CAL_SUCCESS == calendar_svc_iter_next(iter) )
809         {
810             if ( CAL_SUCCESS != calendar_svc_iter_get_info(iter, &platformEvent) ) {
811                 ThrowMsg(PlatformException, "Can't get the calendar info.");
812             }
813
814             index = calendar_svc_struct_get_int(platformEvent, CAL_VALUE_INT_INDEX);
815             syncStatus = calendar_svc_struct_get_int(platformEvent, CAL_VALUE_INT_SYNC_STATUS);
816             LogDebug("index "<<index<<" , syncStatus "<<syncStatus);
817             if ( CAL_SYNC_STATUS_NEW==syncStatus ) {
818                 eventPtr->setStatus(OnEventsChanged::ON_ADD);
819             } else if ( CAL_SYNC_STATUS_UPDATED==syncStatus ) {
820                 eventPtr->setStatus(OnEventsChanged::ON_UPDATE);
821             } else if ( CAL_SYNC_STATUS_DELETED==syncStatus ) {
822                 eventPtr->setStatus(OnEventsChanged::ON_DELETE);
823             } else {
824                 if( platformEvent ) {
825                     calendar_svc_struct_free(&platformEvent);
826                 }
827                 calendar_svc_iter_remove(&iter);
828                 ThrowMsg(PlatformException, "Wrong syncStatus.");
829             }
830
831             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(thisCalendar->getType()));
832             eventWrapper->loadEvent(index);
833             eventPtr->addEvent(eventWrapper->getAbstractEvent());
834
835             if ( CAL_SUCCESS != calendar_svc_struct_free(&platformEvent) ) {
836                 ThrowMsg(PlatformException, "Can't free the platform event struct.");
837             }
838         }
839
840         if ( CAL_SUCCESS != calendar_svc_iter_remove(&iter) ) {
841             ThrowMsg(PlatformException, "Can't remove the iter.");
842         }
843
844         std::time_t localTime = time(NULL);
845         thisCalendar->setLastChangeFetchTime(localTime);
846         LogInfo("Last change fetch time: "<<thisCalendar->getLastChangeFetchTime());
847
848         eventPtr->setResult(true);
849
850         if( eventPtr->getEventList()->size() > 0 ) {
851             thisCalendar->m_changeEmitters.emit(eventPtr);
852         } else {
853             LogInfo("No actual changes. Skip signal emission.");
854         }
855     }
856     catch (const Exception &ex)
857     {
858         LogError("Error while emitting the change noti" << ex.DumpToString());
859     }
860 }
861
862 void Calendar::OnRequestReceived(const IEventWatchChangesPtr &event)
863 {
864     LogDebug("entered");
865     Try
866     {
867         // Subscribe the watch to the platform just once.
868         if( m_changeEmitters.size()==0 )
869         {
870             if( CAL_SUCCESS!=calendar_svc_subscribe_change(eventChangedCb, this) ) {
871                 ThrowMsg(PlatformException, "Can't subscribe the db change noti.");
872             } else {
873                 // Save the last change fetch time to start watching.
874                 std::time_t localTime = time(NULL);
875                 setLastChangeFetchTime(localTime);
876                 LogInfo("Last change fetch time: "<<getLastChangeFetchTime());
877             }
878         }
879
880         m_changeEmitters.attach(event->getEmitter());
881         event->setWatchId(event->getEmitter()->getId());
882         event->setResult(true);
883     }
884     catch (const Exception &ex)
885     {
886         LogError("Error during creating a watch " << ex.DumpToString());
887         event->setResult(false);
888         event->setExceptionCode(ExceptionCodes::UnknownException);
889     }
890 }
891
892 void Calendar::OnRequestReceived(const IEventClearWatchPtr &event)
893 {
894     LogDebug("entered");
895     Try
896     {
897         m_changeEmitters.detach(event->getWatchId());
898
899         if( m_changeEmitters.size()==0 ) {
900             if( CAL_SUCCESS!=calendar_svc_unsubscribe_change(eventChangedCb) ) {
901                 ThrowMsg(PlatformException, "Can't unsubscribe the db change noti.");
902             } else {
903                 LogDebug("Platform watch cleared successfully.");
904             }
905         }
906         event->setResult(true);
907     }
908     catch (const Exception &ex)
909     {
910         LogError("Error during clearing the watch " << ex.DumpToString());
911         event->setResult(false);
912         event->setExceptionCode(ExceptionCodes::UnknownException);
913     }
914 }
915
916 void Calendar::OnRequestReceived(const IEventExpandEventRecurrencePtr &event)
917 {
918     LogDebug("entered");
919     const CalendarEventPtr calEvent = event->getEvent();
920     const time_t startDate = event->getStartDate();
921     const time_t endDate = event->getEndDate();
922     event->setResult(true);
923
924     try {
925         if ( 0 >= calEvent->getRecurrenceRule()->getFrequency())
926         {
927             ThrowMsg(PlatformException, "This is not a recurring event.");
928         }
929
930         std::time_t nextStartTime = 0;
931         std::time_t nextEndTime = 0;
932
933         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
934         eventWrapper->convertAbstractEventToPlatformEvent();
935
936         event->tryCancelled();
937
938         while ( CAL_SUCCESS ==
939             calendar_svc_util_next_valid_event(eventWrapper->getPlatformEvent(), startDate, endDate, &nextStartTime, &nextEndTime) ) {
940             LogInfo("Found a next vaild event: "<<nextStartTime);
941             DPL::ScopedPtr<EventWrapper> recurringEventWrapper(new EventWrapper(getType()));
942             recurringEventWrapper->loadEvent(calEvent->getId());
943             recurringEventWrapper->getAbstractEvent()->setRecurrenceId(nextStartTime);
944             event->addExpandedEvent(recurringEventWrapper->getAbstractEvent());
945         }
946
947         LogInfo("Length of expanded events: "<<event->getExpandedEventList()->size());
948     }
949     catch (const Exception &ex)
950     {
951         LogError("Exception: " << ex.DumpToString());
952         event->setResult(false);
953         event->setExceptionCode(ExceptionCodes::UnknownException);
954     }
955
956     event->setCancelAllowed(true);
957 }
958
959 }
960 }
961 }