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