Update change log and spec for wrt-plugins-tizen_0.2.84
[framework/web/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/OnEventsChanged.h"
27 #include "API/Calendar/IEventWatchChanges.h"
28 #include "API/Calendar/IEventClearWatch.h"
29 #include "API/Calendar/EventId.h"
30 #include <API/Filter/IFilter.h>
31 #include <API/Filter/IFilterVisitor.h>
32 #include <sstream>
33
34 using namespace TizenApis::Api::Calendar;
35 using namespace WrtDeviceApis::Commons;
36
37 namespace TizenApis {
38 namespace Platform {
39 namespace Calendar {
40
41 Calendar::Calendar()
42 {
43     LogDebug("entered");
44 }
45
46 Calendar::~Calendar()
47 {
48     LogDebug("entered");
49 }
50
51 void Calendar::OnRequestReceived(const IEventAddEventPtr &event)
52 {
53     LogDebug("entered");
54     Try
55     {
56         if (!event->getEvent()) {
57             ThrowMsg(NullPointerException, "event parameter is NULL");
58         }
59         if (event->getEvent()->getIdIsSet()) {
60             LogWarning("adding event that is already added");
61             event->getEvent()->resetId();
62         }
63         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
64         event->getEvent()->setCalendarType(getType());
65         eventWrapper->convertAbstractEventToPlatformEvent();
66
67         // Set the account and calendar id before saving the item.
68         eventWrapper->setCalendarId(getId());
69         eventWrapper->setCalendarAccountId(getAccountId());
70         eventWrapper->saveEvent();
71         event->setResult(true);
72     }
73     Catch (Exception)
74     {
75         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
76         event->setResult(false);
77         event->setExceptionCode(ExceptionCodes::UnknownException);
78     }
79 }
80
81 void Calendar::OnRequestReceived(const IEventAddEventsPtr &events)
82 {
83     LogDebug("entered");
84
85     Try
86     {
87         if (events->getEvents()->empty()) {
88             ThrowMsg(NullPointerException, "Items array is empty.");
89         }
90
91         int returnValue = calendar_svc_begin_trans();
92         if(CAL_SUCCESS!=returnValue) {
93             ThrowMsg(PlatformException, "Begin transaction failed with error code: "<<returnValue);
94         } else {
95             LogInfo("Begin transaction succeeded.");
96         }
97
98         bool failedAdding = false;
99         for(unsigned int i=0; i<events->getEvents()->size(); i++)
100         {
101             if (events->getEvents()->at(i)->getIdIsSet()) {
102                 LogWarning("Item has index: " << i << ". Resetting it.");
103                 events->getEvents()->at(i)->resetId();
104             }
105             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(events->getEvents()->at(i), getType()));
106             events->getEvents()->at(i)->setCalendarType(getType());
107             eventWrapper->convertAbstractEventToPlatformEvent();
108
109             Try {
110                 eventWrapper->setCalendarId(getId());
111                 eventWrapper->setCalendarAccountId(getAccountId());
112                 eventWrapper->saveEvent();
113             } Catch (Exception) {
114                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
115                 failedAdding = true;
116             }
117         }
118
119         if( false==failedAdding ) {
120             events->setResult(true);
121
122             returnValue = calendar_svc_end_trans(true);
123             LogInfo("End transaction return value with true flag: "<<returnValue);
124         } else {
125             events->setResult(false);
126
127             returnValue = calendar_svc_end_trans(false);
128             LogInfo("End transaction return value with false flag: "<<returnValue);
129         }
130     }
131     Catch (Exception)
132     {
133         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
134         events->setResult(false);
135         events->setExceptionCode(ExceptionCodes::UnknownException);
136     }
137 }
138
139 void Calendar::OnRequestReceived(const IEventUpdateEventPtr &event)
140 {
141     LogDebug("entered");
142
143     cal_iter *iter = NULL;
144     Try
145     {
146         if (!event->getEvent()) {
147             ThrowMsg(NullPointerException, "Item object is NULL.");
148         }
149         if (!event->getEvent()->getIdIsSet()) {
150             ThrowMsg(InvalidArgumentException, "Item id is not set.");
151         }
152
153         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
154         event->getEvent()->setCalendarType(getType());
155         eventWrapper->convertAbstractEventToPlatformEvent();
156
157         if ( event->getUpdateAllInstances() || 0>=event->getEvent()->getRecurrenceRule()->getFrequency())
158         {
159             // Update all parent and child instances with the given uid.
160             int parentId = event->getEvent()->getId();
161
162             // First, the parent event.
163             eventWrapper->saveEvent();
164
165             // Next, all the detached instances.
166             cal_struct *platformEvent = NULL;
167             if(CAL_SUCCESS != calendar_svc_find_event_list(getAccountId(), CAL_VALUE_INT_ORIGINAL_EVENT_ID, (void*) parentId, &iter)) {
168                 LogInfo("No detached instances found.");
169             }
170
171             while (CAL_SUCCESS == calendar_svc_iter_next(iter)) {
172                 platformEvent = NULL;
173                 if (CAL_SUCCESS != calendar_svc_iter_get_info(iter, &platformEvent)) {
174                     ThrowMsg(PlatformException, "Can't get event info.");
175                 }
176
177                 int detachedEventId = calendar_svc_struct_get_int(platformEvent, CAL_VALUE_INT_INDEX);
178                 long long int detachedStartTime = calendar_svc_struct_get_lli(platformEvent, CALS_VALUE_LLI_DTSTART_UTIME);
179                 long long int detachedEndTime = calendar_svc_struct_get_lli(platformEvent, CALS_VALUE_LLI_DTEND_UTIME);
180
181                 DPL::ScopedPtr<EventWrapper> eventWrapperChild(new EventWrapper(event->getEvent(), getType()));
182                 eventWrapperChild->convertAbstractEventToPlatformEvent();
183                 if (CAL_SUCCESS != calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
184                                                                CAL_VALUE_INT_INDEX,
185                                                                detachedEventId)) {
186                     ThrowMsg(PlatformException, "Can't set event Id.");
187                 }
188                 if (CAL_SUCCESS != calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
189                                                                CAL_VALUE_INT_ORIGINAL_EVENT_ID,
190                                                                parentId)) {
191                     ThrowMsg(PlatformException, "Can't set parent Id.");
192                 }
193                 if (CAL_SUCCESS != calendar_svc_struct_set_lli(eventWrapperChild->getPlatformEvent(),
194                                                                CALS_VALUE_LLI_DTSTART_UTIME,
195                                                                detachedStartTime)) {
196                     ThrowMsg(PlatformException, "Can't set start time.");
197                 }
198                 if (CAL_SUCCESS != calendar_svc_struct_set_lli(eventWrapperChild->getPlatformEvent(),
199                                                                CALS_VALUE_LLI_DTEND_UTIME,
200                                                                detachedEndTime)) {
201                     ThrowMsg(PlatformException, "Can't set end time.");
202                 }
203                 if (CAL_SUCCESS != calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
204                                                                CALS_VALUE_INT_RRULE_FREQ,
205                                                                CAL_REPEAT_NONE)) {
206                     ThrowMsg(PlatformException, "Can't set repeat term.");
207                 }
208
209                 eventWrapperChild->saveEvent();
210                 LogDebug("Updated a detached event by id: "<<detachedEventId);
211             }
212         }
213         else
214         {
215             LogDebug("Update the exception record");
216             DPL::ScopedPtr<EventWrapper> eventWrapperChild(new EventWrapper(event->getEvent(), getType()));
217             eventWrapperChild->convertAbstractEventToPlatformEvent();
218             if ( CAL_SUCCESS!=calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
219                 CAL_VALUE_INT_ORIGINAL_EVENT_ID, event->getEvent()->getId()) ) {
220                 ThrowMsg(PlatformException, "cannot save exception event");
221             } 
222             // Use "CAL_VALUE_LLI_COMPLETED_TIME" as the recurrence id saving point.
223             if ( CAL_SUCCESS!=calendar_svc_struct_set_lli(eventWrapperChild->getPlatformEvent(),
224                 CAL_VALUE_LLI_COMPLETED_TIME, event->getEvent()->getRecurrenceId()) ) {
225                 ThrowMsg(PlatformException, "cannot save recurrence id");
226             } else {
227                 LogInfo("Saved the rid for the child: "<<event->getEvent()->getRecurrenceId());
228             }
229             if (CAL_SUCCESS!=calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
230                 CALS_VALUE_INT_RRULE_FREQ, CAL_REPEAT_NONE) ) {
231                 ThrowMsg(PlatformException, "cannot save exception event");
232             }
233             int childId = calendar_svc_insert(eventWrapperChild->getPlatformEvent());
234             if ( childId<0 ) {
235                 ThrowMsg(PlatformException, "cannot save exception event");
236             }
237
238             int error = calendar_svc_event_delete_normal_instance(event->getEvent()->getId(), event->getEvent()->getRecurrenceId());
239             if(error!=CAL_SUCCESS) {
240                 ThrowMsg(PlatformException, "Can't delete the instance. Error code " << error);
241             }
242
243             event->getEvent()->setIsDetached(true);
244         }
245
246         event->setResult(true);
247     }
248     Catch (Exception)
249     {
250         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
251         event->setResult(false);
252         event->setExceptionCode(ExceptionCodes::UnknownException);
253     }
254
255     if(iter) {
256         calendar_svc_iter_remove(&iter);
257     }
258 }
259
260 void Calendar::OnRequestReceived(const IEventUpdateEventsPtr &events)
261 {
262     LogDebug("entered");
263
264     cal_iter *iter = NULL;
265     Try
266     {
267         if (events->getEvents()->empty()) {
268             ThrowMsg(NullPointerException, "Item array is empty.");
269         }
270
271         int returnValue = calendar_svc_begin_trans();
272         if(CAL_SUCCESS!=returnValue) {
273             ThrowMsg(PlatformException, "Begin transaction failed with error code: "<<returnValue);
274         } else {
275             LogInfo("Begin transaction succeeded.");
276         }
277
278         bool failedUpdating = false;
279         for(unsigned int i=0; i<events->getEvents()->size(); i++)
280         {
281             CalendarEventPtr thisEvent = events->getEvents()->at(i);
282             if (!thisEvent->getIdIsSet()) {
283                 ThrowMsg(InvalidArgumentException, "Item id is not set.");
284             }
285             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(thisEvent, getType()));
286             events->getEvents()->at(i)->setCalendarType(getType());
287             eventWrapper->convertAbstractEventToPlatformEvent();
288
289             try {
290                 if (events->getUpdateAllInstances() || 0>=thisEvent->getRecurrenceRule()->getFrequency())
291                 {
292                     // Update all parent and child instances with the given uid.
293                     int parentId = thisEvent->getId();
294
295                     // First, the parent event.
296                     eventWrapper->saveEvent();
297                     
298                     // Next, all the detached instances.
299                     cal_struct *platformEvent = NULL;
300                     if(CAL_SUCCESS != calendar_svc_find_event_list(getAccountId(), CAL_VALUE_INT_ORIGINAL_EVENT_ID, (void*) parentId, &iter)) {
301                         LogInfo("No detached instances found.");
302                     }
303
304                     while (CAL_SUCCESS == calendar_svc_iter_next(iter)) {
305                         platformEvent = NULL;
306                         if (CAL_SUCCESS != calendar_svc_iter_get_info(iter, &platformEvent)) {
307                             ThrowMsg(PlatformException, "Can't get event info.");
308                         }
309
310                         int detachedEventId = calendar_svc_struct_get_int(platformEvent, CAL_VALUE_INT_INDEX);
311                         long long int detachedStartTime = calendar_svc_struct_get_lli(platformEvent,
312                                                                                     CALS_VALUE_LLI_DTSTART_UTIME);
313                         long long int detachedEndTime = calendar_svc_struct_get_lli(platformEvent,
314                                                                                     CALS_VALUE_LLI_DTEND_UTIME);
315
316                         DPL::ScopedPtr<EventWrapper> eventWrapperChild(new EventWrapper(thisEvent, getType()));
317                         eventWrapperChild->convertAbstractEventToPlatformEvent();
318                         if (CAL_SUCCESS != calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
319                                                                        CAL_VALUE_INT_INDEX,
320                                                                        detachedEventId)) {
321                             ThrowMsg(PlatformException, "Can't set event Id.");
322                         }
323                         if (CAL_SUCCESS != calendar_svc_struct_set_lli(eventWrapperChild->getPlatformEvent(),
324                                                                        CALS_VALUE_LLI_DTSTART_UTIME,
325                                                                        detachedStartTime)) {
326                             ThrowMsg(PlatformException, "Can't set start time.");
327                         }
328                         if (CAL_SUCCESS != calendar_svc_struct_set_lli(eventWrapperChild->getPlatformEvent(),
329                                                                        CALS_VALUE_LLI_DTEND_UTIME,
330                                                                        detachedEndTime)) {
331                             ThrowMsg(PlatformException, "Can't set end time.");
332                         }
333
334                         eventWrapper->saveEvent();
335                         LogDebug("Updated a detached event by id: "<<detachedEventId);
336                     }
337                 }
338                 else
339                 {
340                     LogDebug("Update the exception record");
341                     DPL::ScopedPtr<EventWrapper> eventWrapperChild(new EventWrapper(thisEvent, getType()));
342                     eventWrapperChild->convertAbstractEventToPlatformEvent();
343
344                     if ( CAL_SUCCESS!=calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
345                         CAL_VALUE_INT_ORIGINAL_EVENT_ID, thisEvent->getId()) ) {
346                         ThrowMsg(PlatformException, "cannot save parent id.");
347                     }
348                     // Use "CAL_VALUE_LLI_COMPLETED_TIME" as the recurrence id saving point.
349                     if ( CAL_SUCCESS!=calendar_svc_struct_set_lli(eventWrapperChild->getPlatformEvent(),
350                         CAL_VALUE_LLI_COMPLETED_TIME, thisEvent->getRecurrenceId()) ) {
351                         ThrowMsg(PlatformException, "cannot save recurrence id.");
352                     } else {
353                         LogInfo("Saved the rid for the child: "<<thisEvent->getRecurrenceId());
354                     }
355                     if (CAL_SUCCESS!=calendar_svc_struct_set_int(eventWrapperChild->getPlatformEvent(),
356                         CALS_VALUE_INT_RRULE_FREQ, CAL_REPEAT_NONE) ) {
357                         ThrowMsg(PlatformException, "cannot save repeat term.");
358                     }
359                     int childId = calendar_svc_insert(eventWrapperChild->getPlatformEvent());
360                     if ( childId<0 ) {
361                         ThrowMsg(PlatformException, "cannot save exception event");
362                     }
363
364                     int error = calendar_svc_event_delete_normal_instance(thisEvent->getId(), thisEvent->getRecurrenceId());
365                     if(error!=CAL_SUCCESS) {
366                         ThrowMsg(PlatformException, "Can't delete the instance. Error code " << error);
367                     }
368
369                     thisEvent->setIsDetached(true);
370                 }
371             } Catch (Exception) {
372                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
373                 failedUpdating = true;
374             }
375             //getUpdateEmitter()->emit(eventPtr);
376         }
377
378         if( false==failedUpdating ) {
379             events->setResult(true);
380
381             returnValue = calendar_svc_end_trans(true);
382             LogInfo("End transaction return value with true flag: "<<returnValue);
383         } else {
384             events->setResult(false);
385
386             returnValue = calendar_svc_end_trans(false);
387             LogInfo("End transaction return value with false flag: "<<returnValue);
388         }
389     }
390     Catch (Exception)
391     {
392         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
393         events->setResult(false);
394         events->setExceptionCode(ExceptionCodes::UnknownException);
395     }
396
397     if(iter) {
398         calendar_svc_iter_remove(&iter);
399     }
400 }
401
402 void Calendar::OnRequestReceived(const IEventDeleteEventPtr &event)
403 {
404     LogDebug("entered");
405     Try
406     {
407         if (!event->getEventId()) {
408             ThrowMsg(NullPointerException, "Item id is not set.");
409         }
410
411         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
412         event->getEventId()->setCalendarType(getType());
413         std::istringstream stream(event->getEventId()->getUId());
414         int id = -1;
415         stream>>id;
416         eventWrapper->getAbstractEvent()->setId(id);
417
418         std::stringstream ss(event->getEventId()->getRecurrenceId());
419         long long int rid;
420         ss>>rid;
421         eventWrapper->getAbstractEvent()->setRecurrenceId(rid);
422
423         LogDebug("id: " << id << ", rid: " << rid);
424
425         eventWrapper->convertAbstractEventToPlatformEvent();
426
427         eventWrapper->setCalendarId(getId());
428         eventWrapper->setCalendarAccountId(getAccountId());
429         eventWrapper->deleteEvent();
430         event->setResult(true);
431     }
432     Catch (NotFoundException)
433     {
434         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
435         event->setResult(false);
436         event->setExceptionCode(ExceptionCodes::NotFoundException);
437     }
438     Catch (Exception)
439     {
440         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
441         event->setResult(false);
442         event->setExceptionCode(ExceptionCodes::UnknownException);
443     }
444 }
445
446 void Calendar::OnRequestReceived(const IEventGetPtr &event)
447 {
448     LogDebug("entered");
449     Try
450     {
451         if (!event->getItemId()) {
452             ThrowMsg(NullPointerException, "Id parameter is NULL");
453         }
454
455         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
456         std::stringstream ss(event->getItemId()->getUId());
457         int id = -1;
458         ss>>id;
459         eventWrapper->loadEvent(id);
460
461         event->setItem(eventWrapper->getAbstractEvent());
462         event->setResult(true);
463     }
464     Catch (NotFoundException)
465     {
466         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
467         event->setResult(false);
468         event->setExceptionCode(ExceptionCodes::NotFoundException);
469     }
470     Catch (Exception)
471     {
472         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
473         event->setResult(false);
474         event->setExceptionCode(ExceptionCodes::UnknownException);
475     }
476 }
477
478 void Calendar::OnRequestReceived(const IEventDeleteEventsPtr &events)
479 {
480     LogDebug("entered");
481     Try
482     {
483         if (events->getEventIds()->empty()) {
484             ThrowMsg(NullPointerException, "Item id array is empty.");
485         }
486
487         int returnValue = calendar_svc_begin_trans();
488         if(CAL_SUCCESS!=returnValue) {
489             ThrowMsg(PlatformException, "Begin transaction failed with error code: "<<returnValue);
490         } else {
491             LogInfo("Begin transaction succeeded.");
492         }
493
494         bool failedDeleting = false;
495         for(unsigned int i=0; i<events->getEventIds()->size(); i++)
496         {
497             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
498             events->getEventIds()->at(i)->setCalendarType(getType());
499             std::istringstream stream(events->getEventIds()->at(i)->getUId());
500             int id = -1;
501             stream>>id;
502             eventWrapper->getAbstractEvent()->setId(id);
503
504             std::stringstream ss(events->getEventIds()->at(i)->getRecurrenceId());
505             long long int rid;
506             ss>>rid;
507             eventWrapper->getAbstractEvent()->setRecurrenceId(rid);
508             eventWrapper->convertAbstractEventToPlatformEvent();
509
510             Try {
511                 eventWrapper->setCalendarId(getId());
512                 eventWrapper->setCalendarAccountId(getAccountId());
513                 eventWrapper->deleteEvent();
514             } Catch (NotFoundException) {
515                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
516                 events->setExceptionCode(ExceptionCodes::NotFoundException);
517                 failedDeleting = true;
518             } Catch (Exception) {
519                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
520                 events->setExceptionCode(ExceptionCodes::PlatformException);
521                 failedDeleting = true;
522             }
523         }
524
525         if( false==failedDeleting ) {
526             events->setResult(true);
527             returnValue = calendar_svc_end_trans(true);
528             LogInfo("End transaction return value with true flag: "<<returnValue);
529         } else {
530             events->setResult(false);
531
532             returnValue = calendar_svc_end_trans(false);
533             LogInfo("End transaction return value with false flag: "<<returnValue);
534         }
535     }
536     Catch (NotFoundException)
537     {
538         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
539         events->setResult(false);
540         events->setExceptionCode(ExceptionCodes::NotFoundException);
541     }
542     Catch (Exception)
543     {
544         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
545         events->setResult(false);
546         events->setExceptionCode(ExceptionCodes::UnknownException);
547     }
548 }
549
550 void Calendar::OnRequestReceived(const IEventFindEventsPtr &event)
551 {
552     LogDebug("entered");
553     event->setResult(true);
554
555     Try
556     {
557         calendar_db_init();
558
559         CalendarFilterPtr calendarFilter( new CalendarFilter() );
560
561         std::string query (std::string("SELECT ") + CAL_VALUE_INT_INDEX + " FROM schedule_table");
562         LogInfo("Default query statement: "<<query);
563
564                 TizenApis::Api::Tizen::IFilterVisitorPtr filterTraversal = DPL::StaticPointerCast<TizenApis::Api::Tizen::IFilterVisitor>(calendarFilter);
565
566         std::stringstream ssType;
567         std::stringstream ssAccount;
568         ssAccount<<getAccountId();
569                 if (event->getGenericFilterIsSet()) {
570             TizenApis::Api::Tizen::FilterPtr genericFilter = event->getGenericFilter();
571
572             TizenApis::Api::Tizen::FilterValidatorPtr validator = CalendarFilterValidatorFactory::getCalendarFilterValidator();
573             bool success = genericFilter->validate(validator);
574             if(!success) {
575                 ThrowMsg(InvalidArgumentException, "Invalid filter arguments.");
576             } else {
577                 LogInfo("Filter validation has passed.");
578             }
579
580                         genericFilter->travel(filterTraversal, 0);
581                         LogDebug("Traverse string [" << calendarFilter->getResult() << "]");
582                         query.append(calendarFilter->getResult());
583             query.append(std::string(" AND ") + CAL_VALUE_INT_ACCOUNT_ID + " = " + ssAccount.str());
584             if (getType()==CalendarEvent::TASK_TYPE) {
585                 ssType<<CALS_CALENDAR_TYPE_TODO;
586                 query.append(std::string(" AND ") + CAL_VALUE_INT_TYPE + " = " + ssType.str());
587             } else {
588                 ssType<<CALS_CALENDAR_TYPE_EVENT;
589                 query.append(std::string(" AND ") + CAL_VALUE_INT_TYPE + " = " + ssType.str());
590             }
591                 } else {
592             query.append(std::string(" WHERE ") + CAL_VALUE_INT_ACCOUNT_ID + " = " + ssAccount.str());
593             if (getType()==CalendarEvent::TASK_TYPE) {
594                 ssType<<CALS_CALENDAR_TYPE_TODO;
595                 query.append(std::string(" AND ") + CAL_VALUE_INT_TYPE + " = " + ssType.str());
596             } else {
597                 ssType<<CALS_CALENDAR_TYPE_EVENT;
598                 query.append(std::string(" AND ") + CAL_VALUE_INT_TYPE + " = " + ssType.str());
599             }
600                 }
601
602                 if (event->getSortModesIsSet()) {
603                         query.append(calendarFilter->makeQuerySortMode(event->getSortModes()));
604                         query.append(std::string(";"));
605                 }
606
607                 LogDebug("Filter query [" << query << "]");
608
609                 calendarFilter->executeQuery(query, event->getEvents());
610
611         LogDebug("Result count [" << event->getEvents()->size() << "]");
612
613         calendar_db_finish();
614
615         // Now load the full calendar item using the retrieved id.
616         for( unsigned int i=0; i<event->getEvents()->size(); i++) {
617             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvents()->at(i), getType()));
618             eventWrapper->loadEvent(event->getEvents()->at(i)->getId());
619
620             // If it's a detached event, set the saved rid.
621             if (eventWrapper->getAbstractEvent()->getParentId()>0) {
622                 LogInfo("Set the saved rid: "<<calendar_svc_struct_get_lli(eventWrapper->getPlatformEvent(), CAL_VALUE_LLI_COMPLETED_TIME));
623                 event->getEvents()->at(i)->setRecurrenceId(calendar_svc_struct_get_lli(eventWrapper->getPlatformEvent(), CAL_VALUE_LLI_COMPLETED_TIME));
624             }
625         }
626     }
627     Catch (InvalidArgumentException)
628     {
629         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
630         event->setResult(false);
631         event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
632     }
633     Catch (NotFoundException)
634     {
635         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
636         event->setResult(false);
637         event->setExceptionCode(ExceptionCodes::NotFoundException);
638     }
639     Catch (Exception)
640     {
641         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
642         event->setResult(false);
643         event->setExceptionCode(ExceptionCodes::UnknownException);
644     }
645 }
646
647 void Calendar::OnRequestReceived(const IEventCreateEventFromStringPtr &event)
648 {
649     LogDebug("entered");
650     Try
651     {
652         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType()));
653         eventWrapper->createEventFromString(event->getEventString());
654         event->setEvent(eventWrapper->convertPlatformEventToAbstractEvent());
655         event->getEvent()->setCalendarType(getType());
656         event->setResult(true);
657     }
658     Catch(PlatformException)
659     {
660                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
661         LogInfo("eventString: " + event->getEventString());
662         event->setResult(false);
663         event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
664     }
665     Catch (Exception)
666     {
667         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
668         LogInfo("eventString: " + event->getEventString());
669         event->setResult(false);
670         event->setExceptionCode(ExceptionCodes::UnknownException);
671     }
672 }
673
674 void Calendar::OnRequestReceived(const IEventExportEventToStringPtr &event)
675 {
676     LogDebug("entered");
677     Try
678     {
679         if (!event->getEvent()) {
680             ThrowMsg(NullPointerException, "event parameter is NULL");
681         }
682
683         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType()));
684         event->getEvent()->setCalendarType(getType());
685         eventWrapper->convertAbstractEventToPlatformEvent();
686         event->setEventString(eventWrapper->exportEventToString());
687         event->setResult(true);
688     }
689     Catch (Exception)
690     {
691         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
692         event->setResult(false);
693         event->setExceptionCode(ExceptionCodes::UnknownException);
694     }
695 }
696
697 static void eventChangedCb(void *user_data)
698 {
699     LogDebug("entered");
700
701     OnEventsChangedPtr eventPtr(new OnEventsChanged());
702     Try
703     {
704         Calendar *thisCalendar = (Calendar*) user_data;
705
706         // Determine the status of event change.
707         cal_iter *iter = NULL;
708         cal_struct *platformEvent = NULL;
709         int id;
710         int type;
711         int version = 0;
712         int errorCode;
713
714         int calendarId;
715         std::stringstream ss(thisCalendar->getId());
716         ss>>calendarId;
717
718         LogDebug("Getting items with calendar id: "<<calendarId<<", version: "<<thisCalendar->getLastChangedVersion()<<", type: "<<thisCalendar->getType());
719         if (CalendarEvent::TASK_TYPE==thisCalendar->getType()) {
720             errorCode = calendar_svc_todo_get_changes(calendarId,
721                     thisCalendar->getLastChangedVersion(),
722                     &iter);
723         } else {
724             errorCode = calendar_svc_event_get_changes(calendarId,
725                     thisCalendar->getLastChangedVersion(),
726                     &iter);
727         }
728         if( CAL_SUCCESS!=errorCode ) {
729             ThrowMsg(PlatformException, "Can't get the updated event list. Error code: "<<errorCode);
730         }
731
732         while( CAL_SUCCESS == calendar_svc_iter_next(iter) )
733         {
734             if ( CAL_SUCCESS != calendar_svc_iter_get_info(iter, &platformEvent) ) {
735                 ThrowMsg(PlatformException, "Can't get the calendar info.");
736             }
737
738             id = calendar_svc_struct_get_int(platformEvent, CALS_STRUCT_UPDATED_INT_ID);
739             type = calendar_svc_struct_get_int(platformEvent, CALS_STRUCT_UPDATED_INT_TYPE);
740             version = calendar_svc_struct_get_int(platformEvent, CALS_STRUCT_UPDATED_INT_VERSION);
741             LogDebug("id "<<id<<", type "<<type<<", version "<<version);
742             if ( CALS_UPDATED_TYPE_INSERTED==type ) {
743                 eventPtr->setStatus(OnEventsChanged::ON_ADD);
744             } else if ( CALS_UPDATED_TYPE_MODIFIED==type ) {
745                 eventPtr->setStatus(OnEventsChanged::ON_UPDATE);
746             } else if ( CALS_UPDATED_TYPE_DELETED==type ) {
747                 eventPtr->setStatus(OnEventsChanged::ON_DELETE);
748             } else {
749                 if( platformEvent ) {
750                     calendar_svc_struct_free(&platformEvent);
751                 }
752                 calendar_svc_iter_remove(&iter);
753                 ThrowMsg(PlatformException, "Wrong syncStatus.");
754             }
755
756             DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(thisCalendar->getType()));
757             Try {
758                 eventWrapper->loadEvent(id);
759             } Catch (NotFoundException){
760                 LogDebug("Handling deleted event with index: "<<id);
761             }
762             eventPtr->addEvent(eventWrapper->getAbstractEvent());
763
764             if ( CAL_SUCCESS != calendar_svc_struct_free(&platformEvent) ) {
765                 ThrowMsg(PlatformException, "Can't free the platform event struct.");
766             }
767         }
768
769         if ( CAL_SUCCESS != calendar_svc_iter_remove(&iter) ) {
770             ThrowMsg(PlatformException, "Can't remove the iter.");
771         }
772
773         thisCalendar->setLastChangedVersion(version);
774         LogInfo("Last change fetch version: "<<thisCalendar->getLastChangedVersion());
775
776         eventPtr->setResult(true);
777         eventPtr->setCalendarType(thisCalendar->getType());
778
779         if( eventPtr->getEventList()->size() > 0 ) {
780             thisCalendar->m_changeEmitters.emit(eventPtr);
781         } else {
782             LogInfo("No actual changes. Skip signal emission.");
783         }
784     }
785     Catch (Exception)
786     {
787         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
788     }
789 }
790
791 void Calendar::OnRequestReceived(const IEventWatchChangesPtr &event)
792 {
793     LogDebug("entered");
794     Try
795     {
796         // Subscribe the watch to the platform just once.
797         if( m_changeEmitters.size()==0 )
798         {
799             if (CAL_SUCCESS!=calendar_svc_begin_trans() ) {
800                 ThrowMsg(PlatformException, "Transaction failed.");
801             } else {
802                 if( CAL_SUCCESS!=calendar_svc_subscribe_change(eventChangedCb, this) ) {
803                     calendar_svc_end_trans(true);
804                     ThrowMsg(PlatformException, "Can't subscribe the db change noti.");
805                 } else {
806                     // Save the last change fetch version to start watching.
807                     int version = calendar_svc_end_trans(true);
808                     setLastChangedVersion(version);
809                     LogInfo("Last change fetch version: "<<getLastChangedVersion());
810                 }
811             }
812         }
813
814         m_changeEmitters.attach(event->getEmitter());
815         event->setWatchId(event->getEmitter()->getId());
816         event->setResult(true);
817     }
818     Catch (Exception)
819     {
820         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
821         event->setResult(false);
822         event->setExceptionCode(ExceptionCodes::UnknownException);
823     }
824 }
825
826 void Calendar::OnRequestReceived(const IEventClearWatchPtr &event)
827 {
828     LogDebug("entered");
829     Try
830     {
831         if( m_changeEmitters.detach(event->getWatchId()) ) {
832             if( m_changeEmitters.size()==0 ) {
833                 if( CAL_SUCCESS!=calendar_svc_unsubscribe_change(eventChangedCb) ) {
834                     ThrowMsg(PlatformException, "Can't unsubscribe the db change noti.");
835                 } else {
836                     LogDebug("Platform watch cleared successfully.");
837                 }
838             }
839             event->setResult(true);
840         } else {
841             LogInfo("Wrong watch Id.");
842             event->setResult(false);
843         }
844     }
845     Catch (Exception)
846     {
847         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
848         event->setResult(false);
849         event->setExceptionCode(ExceptionCodes::UnknownException);
850     }
851 }
852
853 void Calendar::OnRequestReceived(const IEventExpandEventRecurrencePtr &event)
854 {
855     LogDebug("entered");
856     const CalendarEventPtr calEvent = event->getEvent();
857     const long long int startDate = event->getStartDate();
858     const long long int endDate = event->getEndDate();
859     event->setResult(true);
860
861     Try {
862         if ( 0 >= calEvent->getRecurrenceRule()->getFrequency())
863         {
864             ThrowMsg(InvalidArgumentException, "This is not a recurring event.");
865         }
866
867         DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(CalendarEvent::EVENT_TYPE));
868         // We must load the event from the DB in order to get the auto-calculated repeat end time.
869         eventWrapper->loadEvent(calEvent->getId());
870
871         cal_iter *iter = NULL;
872         cal_struct *cs;
873         int candidateIndex;
874         long long int dtstart, dtend;
875         int calendarId;
876         std::stringstream ss(getId());
877         ss>>calendarId;
878
879         int returnVal = calendar_svc_event_get_normal_list_by_period(calendarId, CALS_LIST_PERIOD_NORMAL_BASIC, startDate, endDate, &iter);
880         if( CAL_SUCCESS!=returnVal ) {
881             ThrowMsg(PlatformException, "Getting event instances failed due to "<<returnVal);
882         }
883
884         while ( CAL_SUCCESS==calendar_svc_iter_next(iter) )
885         {
886             cs = NULL;
887             returnVal = calendar_svc_iter_get_info(iter, &cs);
888             if( CAL_SUCCESS!=returnVal ){
889                 LogDebug("Iterator get info failed due to "<<returnVal);
890                 continue;
891             }
892
893             candidateIndex = calendar_svc_struct_get_int(cs, CALS_LIST_PERIOD_NORMAL_BASIC_INT_EVENTID);
894             if(candidateIndex==calEvent->getId()) {
895                 DPL::ScopedPtr<EventWrapper> recurringEventWrapper(new EventWrapper(getType()));
896                 recurringEventWrapper->loadEvent(calEvent->getId());
897
898                 // Set distintive attributes of each instance.
899                 dtstart = calendar_svc_struct_get_lli(cs, CALS_LIST_PERIOD_NORMAL_BASIC_LLI_DTSTART_UTIME);
900                 dtend = calendar_svc_struct_get_lli(cs, CALS_LIST_PERIOD_NORMAL_BASIC_LLI_DTEND_UTIME);
901                 recurringEventWrapper->getAbstractEvent()->setRecurrenceId(dtstart);
902                 recurringEventWrapper->getAbstractEvent()->setStartTime(dtstart);
903                 recurringEventWrapper->getAbstractEvent()->setEndTime(dtend);
904                 LogInfo("Found a valid event instance with dtstart: "<<dtstart<<" and dtend: "<<dtend);
905
906                 event->addExpandedEvent(recurringEventWrapper->getAbstractEvent());
907             }
908         }
909         LogInfo("Length of expanded events from parent: "<<event->getExpandedEventList()->size());
910
911         // Consider the detached events also.
912         iter = NULL;
913         cal_struct *platformEvent = NULL;
914         int parentId = event->getEvent()->getId();
915         if(CAL_SUCCESS != calendar_svc_find_event_list(getAccountId(), CAL_VALUE_INT_ORIGINAL_EVENT_ID, (void*) parentId, &iter)) {
916             LogInfo("No detached instances found.");
917         }
918
919         while (CAL_SUCCESS == calendar_svc_iter_next(iter)) {
920             platformEvent = NULL;
921             if (CAL_SUCCESS != calendar_svc_iter_get_info(iter, &platformEvent)) {
922                 ThrowMsg(PlatformException, "Can't get event info.");
923             }
924
925             int detachedEventId = calendar_svc_struct_get_int(platformEvent, CAL_VALUE_INT_INDEX);
926             long long int detachedStartTime = calendar_svc_struct_get_lli(platformEvent, CALS_VALUE_LLI_DTSTART_UTIME);
927             long long int detachedEndTime = calendar_svc_struct_get_lli(platformEvent, CALS_VALUE_LLI_DTEND_UTIME);
928             if (detachedStartTime>=startDate && detachedStartTime<=endDate) {
929                 LogInfo("Found a valid detached event: "<<detachedStartTime);
930                 DPL::ScopedPtr<EventWrapper> detachedEventWrapper(new EventWrapper(getType()));
931                 detachedEventWrapper->loadEvent(detachedEventId);
932
933                 // Set the same parent uid to each instances
934                 detachedEventWrapper->getAbstractEvent()->setId(parentId);
935                 // Set distintive attributes of each instance.
936                 detachedEventWrapper->getAbstractEvent()->setRecurrenceId(detachedStartTime);
937                 detachedEventWrapper->getAbstractEvent()->setStartTime(detachedStartTime);
938                 detachedEventWrapper->getAbstractEvent()->setEndTime(detachedEndTime);
939
940                 event->addExpandedEvent(detachedEventWrapper->getAbstractEvent());
941             }
942         }
943
944         LogInfo("Length of total expanded events: "<<event->getExpandedEventList()->size());
945     }
946     Catch (InvalidArgumentException)
947     {
948         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
949         event->setResult(false);
950         event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
951     }
952     Catch (Exception)
953     {
954         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
955         event->setResult(false);
956         event->setExceptionCode(ExceptionCodes::UnknownException);
957     }
958 }
959
960 }
961 }
962 }