diff options
Diffstat (limited to 'mobile_src/Calendar/Calendar.cpp')
-rwxr-xr-x | mobile_src/Calendar/Calendar.cpp | 1410 |
1 files changed, 1410 insertions, 0 deletions
diff --git a/mobile_src/Calendar/Calendar.cpp b/mobile_src/Calendar/Calendar.cpp new file mode 100755 index 0000000..7986362 --- /dev/null +++ b/mobile_src/Calendar/Calendar.cpp @@ -0,0 +1,1410 @@ +// +// Tizen Web Device API +// Copyright (c) 2012 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include <calendar2.h> +#include <dpl/scoped_ptr.h> +#include "Calendar.h" +#include "CalendarManager.h" +#include "CalendarFilter.h" +#include "CalendarFilterValidator.h" +#include "CalendarUtility.h" +#include "OnEventsChanged.h" +#include "IEventWatchChanges.h" +#include "IEventClearWatch.h" +#include "EventId.h" +#include <IFilter.h> +#include <IFilterVisitor.h> +#include <sstream> +#include <algorithm> +#include <Logger.h> + +using namespace WrtDeviceApis::Commons; + +namespace DeviceAPI { +namespace Calendar { + +Calendar::Calendar() +{ +} + +Calendar::~Calendar() +{ +} + +void Calendar::OnRequestReceived(const IEventAddEventPtr &event) +{ + Try + { + if (!event->getEvent()) { + ThrowMsg(NullPointerException, "Item parameter is NULL."); + } + if (event->getEvent()->getIdIsSet()) { + LoggerW("Non-null item id."); + event->getEvent()->resetId(); + } + + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType())); + + if(getIsUnified()) { + LoggerD("Set the default calendar id for a unified calendar item."); + event->getEvent()->setCalendarId(DEFAULT_EVENT_CALENDAR_BOOK_ID); + } else { + std::stringstream ss(getId()); + int calendarId; + ss>>calendarId; + event->getEvent()->setCalendarId(calendarId); + } + + eventWrapper->convertAbstractEventToPlatformEvent(); + + eventWrapper->saveEvent(); + + event->setResult(true); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } +} + +void Calendar::OnRequestReceived(const IEventAddEventsPtr &event) +{ + calendar_list_h listForAdd = NULL; + + Try + { + if (event->getEvents()->empty()) { + ThrowMsg(NullPointerException, "Item array is empty."); + } + + int ret, count = 0; + calendar_record_h record = NULL; + int* ids = NULL; + + ret = calendar_list_create(&listForAdd); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't create a list: "<<ret); + } + + for(unsigned int i=0; i<event->getEvents()->size(); i++) { + CalendarEventPtr theItem = event->getEvents()->at(i); + if (theItem->getIdIsSet()) { + LoggerW("Item has index: " << i << ". Resetting it."); + theItem->resetId(); + } + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(theItem, getType())); + + if(getIsUnified()) { + LoggerD("Set the default calendar id for a unified calendar item."); + theItem->setCalendarId(DEFAULT_EVENT_CALENDAR_BOOK_ID); + } else { + std::stringstream ss(getId()); + int calendarId; + ss>>calendarId; + theItem->setCalendarId(calendarId); + } + + eventWrapper->convertAbstractEventToPlatformEvent(); + + // Clone the record because the platform event will be freed by destructor. + record = NULL; + ret = calendar_record_clone(eventWrapper->getPlatformEvent(), &record); + if(CALENDAR_ERROR_NONE!=ret) { + ThrowMsg(PlatformException, "Clonning failed: "<<ret); + } + + ret = calendar_list_add(listForAdd, record); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't add the item to the list: "<<ret); + } + } + + ret = calendar_db_insert_records(listForAdd, &ids, &count); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't insert the item list: "<<ret); + } else { + LoggerD("Add records requst done with count: "<<count); + } + + for(int i=0; i<count; i++) { + event->getEvents()->at(i)->setId(ids[i]); + } + + if(ids) { + free(ids); + } + + event->setResult(true); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } + + if(listForAdd) { + calendar_list_destroy(listForAdd, true); + } +} + +void Calendar::OnRequestReceived(const IEventUpdateEventPtr &event) +{ + calendar_query_h query = NULL; + calendar_filter_h filter = NULL; + + Try + { + if (!event->getEvent()) { + ThrowMsg(NullPointerException, "Item object is NULL."); + } + + CalendarEventPtr theItem = event->getEvent(); + if (!theItem->getIdIsSet()) { + ThrowMsg(InvalidArgumentException, "Item id is not set."); + } + + int ret; + + const char *dataType; + if(getType() == CalendarEvent::TASK_TYPE) { + dataType = _calendar_todo._uri; + } else { + dataType = _calendar_event._uri; + } + + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(theItem, getType())); + eventWrapper->convertAbstractEventToPlatformEvent(true); + + if ( event->getUpdateAllInstances() || 0>=theItem->getRecurrenceRule()->getFrequency() || UNDEFINED_TIME==theItem->getRecurrenceId()) { + // Platform detects the detached events and uptates all instances. + eventWrapper->saveEvent(); + } else { + LoggerD("Update the exdate for a recurring parent event and add a new child event."); + + // First update the parent event. + EventRecurrenceRulePtr rrule = theItem->getRecurrenceRule(); + (*rrule->getExceptions()).push_back(theItem->getRecurrenceId()); + + std::string exdate = ""; + for( unsigned int i=0; i<rrule->getExceptions()->size(); i++ ) { + std::stringstream ss; + ss<<rrule->getExceptions()->at(i); + exdate.append(ss.str()); + if(i!=rrule->getExceptions()->size()-1) { + exdate.append(","); + } + } + ret = calendar_record_set_str(eventWrapper->getPlatformEvent(), _calendar_event.exdate, exdate.c_str()); + if(ret!=CALENDAR_ERROR_NONE) { + ThrowMsg(PlatformException, "Can't update the exdate: "<<ret); + } else { + LoggerD("Set the exdate for the parent event: "<<exdate); + } + + // Don't set the recurrence id for the parent event. + ret = calendar_record_set_str(eventWrapper->getPlatformEvent(), _calendar_event.recurrence_id, NULL); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't set recurrence id."); + } + + eventWrapper->saveEvent(); + + // Now add the detached child event. + EventRecurrenceRulePtr emptyRRule( new EventRecurrenceRule() ); + // Detached event should not have rrule set. + theItem->setRecurrenceRule(emptyRRule); + + theItem->setParentId(theItem->getId()); + + // Convert the modified child event. + eventWrapper->convertAbstractEventToPlatformEvent(); + + // Reset id for record insertion. + theItem->resetId(); + eventWrapper->saveEvent(); + + theItem->setIsDetached(true); + } + + event->setResult(true); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } + + if(query) { + calendar_query_destroy(query); + } + if(filter) { + calendar_filter_destroy(filter); + } +} + +void Calendar::OnRequestReceived(const IEventUpdateEventsPtr &event) +{ + calendar_list_h listForUpdate = NULL; + calendar_list_h listForAdd = NULL; + calendar_query_h query = NULL; + calendar_filter_h filter = NULL; + + Try + { + if (event->getEvents()->empty()) { + ThrowMsg(NullPointerException, "Item array is empty."); + } + + int ret, count = -1; + calendar_record_h record = NULL; + + const char *dataType; + if(getType() == CalendarEvent::TASK_TYPE) { + dataType = _calendar_todo._uri; + } else { + dataType = _calendar_event._uri; + } + + ret = calendar_list_create(&listForUpdate); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't create a list for update: "<<ret); + } + ret = calendar_list_create(&listForAdd); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't create a list for add: "<<ret); + } + + for(unsigned int i=0; i<event->getEvents()->size(); i++) { + CalendarEventPtr thisEvent = event->getEvents()->at(i); + if (!thisEvent->getIdIsSet()) { + ThrowMsg(InvalidArgumentException, "Item id is not set."); + } + + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(thisEvent, getType())); + eventWrapper->convertAbstractEventToPlatformEvent(true); + + if( true==thisEvent->getIsDetached() ) { + // Treat the detached event same as the parent event. + record = NULL; + ret = calendar_record_clone(eventWrapper->getPlatformEvent(), &record); + if(CALENDAR_ERROR_NONE!=ret) { + ThrowMsg(PlatformException, "Clonning failed: "<<ret); + } + + ret = calendar_list_add(listForUpdate, record); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't add the detached item to the list: "<<ret); + } else { + LoggerD("Added the detached event to the update list: "<<thisEvent->getId()); + } + } else if (event->getUpdateAllInstances() || 0>=thisEvent->getRecurrenceRule()->getFrequency() || UNDEFINED_TIME==thisEvent->getRecurrenceId()) { + // Platform detects the detached events and uptates all instances. + record = NULL; + ret = calendar_record_clone(eventWrapper->getPlatformEvent(), &record); + if(CALENDAR_ERROR_NONE!=ret) { + ThrowMsg(PlatformException, "Clonning failed: "<<ret); + } + + ret = calendar_list_add(listForUpdate, record); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't add the item to the list: "<<ret); + } + } else { + LoggerD("Update the exdate for a recurring parent event and add a new child event."); + DPL::ScopedPtr<EventWrapper> eventWrapperChild(new EventWrapper(thisEvent, getType())); + eventWrapperChild->convertAbstractEventToPlatformEvent(true); + + std::stringstream ss; + ss<<thisEvent->getRecurrenceId(); + ret = calendar_record_set_str(eventWrapperChild->getPlatformEvent(), _calendar_event.recurrence_id, ss.str().c_str()); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Cannot set event recurrence id: "<<ret); + } else { + LoggerD("Saved the rid for the child: "<<thisEvent->getRecurrenceId()); + } + + ret = calendar_record_set_int(eventWrapperChild->getPlatformEvent(), _calendar_event.original_event_id, thisEvent->getId()); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Cannot set the parent id: "<<ret); + } + + ret = calendar_record_set_int(eventWrapperChild->getPlatformEvent(), _calendar_event.freq, CALENDAR_RECURRENCE_NONE); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Cannot set the frequency: "<<ret); + } + + record = NULL; + ret = calendar_record_clone(eventWrapperChild->getPlatformEvent(), &record); + if(CALENDAR_ERROR_NONE!=ret) { + ThrowMsg(PlatformException, "Clonning the child event failed: "<<ret); + } + + ret = calendar_list_add(listForAdd, record); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't add the item to the add list: "<<ret); + } + + thisEvent->setIsDetached(true); + + // Now update the parent event. + EventRecurrenceRulePtr rrule = thisEvent->getRecurrenceRule(); + (*rrule->getExceptions()).push_back(thisEvent->getRecurrenceId()); + + std::string exdate = ""; + for( unsigned int j=0; j<rrule->getExceptions()->size(); j++ ) { + std::stringstream ss; + ss<<rrule->getExceptions()->at(j); + exdate.append(ss.str()); + if(j!=rrule->getExceptions()->size()-1) { + exdate.append(","); + } + } + ret = calendar_record_set_str(eventWrapper->getPlatformEvent(), _calendar_event.exdate, exdate.c_str()); + if(ret!=CALENDAR_ERROR_NONE) { + ThrowMsg(PlatformException, "Can't update the exdate: "<<ret); + } else { + LoggerD("Set the exdate for the parent event: "<<exdate); + } + + record = NULL; + ret = calendar_record_clone(eventWrapper->getPlatformEvent(), &record); + if(CALENDAR_ERROR_NONE!=ret) { + ThrowMsg(PlatformException, "Clonning the child event failed: "<<ret); + } + + ret = calendar_list_add(listForUpdate, record); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't add the item to the update list: "<<ret); + } + } + } + + // Perform the platform operations. + count = -1; + ret = calendar_list_get_count(listForAdd, &count); + if(CALENDAR_ERROR_NONE!=ret){ + ThrowMsg(PlatformException, "Getting list count failed: "<<ret); + } else { + LoggerD("Final list count for add: "<<count); + } + if(count>0) { + ret = calendar_db_insert_records(listForAdd, NULL, NULL); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't insert the item list: "<<ret); + } else { + LoggerD("Add records requst done for update batch operation."); + } + } + + count = -1; + ret = calendar_list_get_count(listForUpdate, &count); + if(CALENDAR_ERROR_NONE!=ret){ + ThrowMsg(PlatformException, "Getting list count failed: "<<ret); + } else { + LoggerD("Final list count for update: "<<count); + } + if(count>0) { + ret = calendar_db_update_records(listForUpdate); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't update the item list: "<<ret); + } else { + LoggerD("Update records requst done for update batch operation."); + } + } + + event->setResult(true); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } + + if(listForAdd) { + calendar_list_destroy(listForAdd, true); + } + if(listForUpdate) { + calendar_list_destroy(listForUpdate, true); + } + if(query) { + calendar_query_destroy(query); + } + if(filter) { + calendar_filter_destroy(filter); + } +} + +void Calendar::OnRequestReceived(const IEventDeleteEventPtr &event) +{ + Try + { + if (!event->getEventId()) { + ThrowMsg(NullPointerException, "Item id is not set."); + } + + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType())); + event->getEventId()->setCalendarType(getType()); + std::istringstream stream(event->getEventId()->getUId()); + int id = -1; + stream>>id; + eventWrapper->getAbstractEvent()->setId(id); + + std::stringstream ss(event->getEventId()->getRecurrenceId()); + long long int rid; + ss>>rid; + + LoggerD("id: " << id << ", rid: " << rid); + + eventWrapper->loadEvent(id); + + // recurrence id is reset while loading the platform event. + eventWrapper->getAbstractEvent()->setRecurrenceId(rid); + + eventWrapper->deleteEvent(); + event->setResult(true); + } + Catch (NotFoundException) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::NotFoundException); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } +} + +void Calendar::OnRequestReceived(const IEventGetPtr &event) +{ + Try + { + if (!event->getItemId()) { + ThrowMsg(NullPointerException, "Id parameter is NULL"); + } + + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType())); + std::stringstream ss(event->getItemId()->getUId()); + int id = -1; + ss>>id; + + eventWrapper->loadEvent(id); + + event->setItem(eventWrapper->getAbstractEvent()); + event->setResult(true); + } + Catch (NotFoundException) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::NotFoundException); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } +} + +void Calendar::OnRequestReceived(const IEventDeleteEventsPtr &event) +{ + calendar_list_h listForUpdate = NULL; + calendar_query_h query = NULL; + calendar_filter_h filter = NULL; + + Try + { + if (event->getEventIds()->empty()) { + ThrowMsg(NullPointerException, "Item id array is empty."); + } + + std::vector<int> listForDelete; + std::vector<int> listForDetached; + std::vector<int> listForDetachedParent; + + int ret, id, count; + long long int rid; + calendar_record_h item, record; + const char *dataType = NULL; + + ret = calendar_list_create(&listForUpdate); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't create a list for update: "<<ret); + } + + for(unsigned int i=0; i<event->getEventIds()->size(); i++) { + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType())); + event->getEventIds()->at(i)->setCalendarType(getType()); + + std::istringstream stream(event->getEventIds()->at(i)->getUId()); + stream>>id; + eventWrapper->getAbstractEvent()->setId(id); + + eventWrapper->loadEvent(id); + item = eventWrapper->getPlatformEvent(); + + std::stringstream ss(event->getEventIds()->at(i)->getRecurrenceId()); + ss>>rid; + eventWrapper->getAbstractEvent()->setRecurrenceId(rid); + + // If the recurrenceId is set, delete the instance of recurring event only. + LoggerD("id to delete: " << id << ", rid: " << rid << ", type: " << getType()); + + dataType = NULL; + if(getType() == CalendarEvent::TASK_TYPE) { + dataType = _calendar_todo._uri; + } else { + dataType = _calendar_event._uri; + } + + /* Platform detects the detached events and deletes them automatically. + But if both parent and detached ids are added to the list, platform error is returned. */ + if ( 0>=rid ) { + listForDelete.push_back(id); + } else if (true==eventWrapper->getAbstractEvent()->getIsDetached() ) { + listForDetached.push_back(id); + + int parentId; + ret = calendar_record_get_int(eventWrapper->getPlatformEvent(), _calendar_event.original_event_id, &parentId); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't get the parent id: "<<ret); + } + listForDetachedParent.push_back(parentId); + LoggerD("Added the detached event id: "<<id<<", parent id: "<<parentId); + } else { + EventRecurrenceRulePtr rrule = eventWrapper->getAbstractEvent()->getRecurrenceRule(); + (*rrule->getExceptions()).push_back(rid); + + std::string exdate = ""; + for( unsigned int i=0; i<rrule->getExceptions()->size(); i++ ) { + std::stringstream ss; + ss<<rrule->getExceptions()->at(i); + exdate.append(ss.str()); + if(i!=rrule->getExceptions()->size()-1) { + exdate.append(","); + } + } + ret = calendar_record_set_str(item, _calendar_event.exdate, exdate.c_str()); + if(ret!=CALENDAR_ERROR_NONE) { + ThrowMsg(PlatformException, "Can't delete the instance: "<<ret); + } else { + LoggerD("Set the exdate: "<<exdate); + } + + record = NULL; + ret = calendar_record_clone(item, &record); + if(CALENDAR_ERROR_NONE!=ret) { + ThrowMsg(PlatformException, "Clonning failed: "<<ret); + } + + ret = calendar_list_add(listForUpdate, record); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't add the item to the list: "<<ret); + } + LoggerD("Calendar item instance added for update."); + } + } + + // Perform the platform operations. + // Uptate operatoin should be done first not to update records after deletion. + count = -1; + ret = calendar_list_get_count(listForUpdate, &count); + if(CALENDAR_ERROR_NONE!=ret){ + LoggerW("Getting list count for update failed: "<<ret); + } else { + LoggerD("Final list count for update: "<<count); + } + if(count>0) { + ret = calendar_db_update_records(listForUpdate); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't update the item list: "<<ret); + } else { + LoggerD("Update records requst done for update batch operation."); + } + } + + // Merge the detached event id list if the parent is not included in the delete list. + count = listForDetached.size(); + LoggerD("Number of detached events: "<<count); + while(count--) { + std::vector<int>::iterator it; + it = std::find(listForDelete.begin(), listForDelete.end(), listForDetachedParent.at(count)); + if(listForDelete.end()==it) { + listForDelete.push_back(listForDetached.at(count)); + LoggerD("Add the detached event id to the delete list: "<<listForDetached.at(count)); + } else { + LoggerD("The parent id is already included to the delete list: "<<listForDetachedParent.at(count)); + } + } + count = listForDelete.size(); + + LoggerD("Final list count for deletion: "<<count); + if(count>0) { + ret = calendar_db_delete_records(dataType, &listForDelete[0], count); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't delete the records: "<<ret); + } else { + LoggerD("Delete records requst done for delete batch operation."); + } + } + + event->setResult(true); + } + Catch (NotFoundException) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::NotFoundException); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } + + if(query) { + calendar_query_destroy(query); + } + if(filter) { + calendar_filter_destroy(filter); + } + if(listForUpdate) { + calendar_list_destroy(listForUpdate, true); + } +} + +void Calendar::OnRequestReceived(const IEventFindEventsPtr &event) +{ + Try + { + CalendarFilterPtr calendarFilter( new CalendarFilter() ); + + calendarFilter->setType(getType()); + LoggerD("Default filter created with type "<<getType()); + + DeviceAPI::Tizen::IFilterVisitorPtr filterTraversal = DPL::StaticPointerCast<DeviceAPI::Tizen::IFilterVisitor>(calendarFilter); + + int calendarId; + std::stringstream ss(getId()); + ss>>calendarId; + if (event->getGenericFilterIsSet()) { + DeviceAPI::Tizen::FilterPtr genericFilter = event->getGenericFilter(); + + DeviceAPI::Tizen::FilterValidatorPtr validator = CalendarFilterValidatorFactory::getCalendarFilterValidator(); + bool success = genericFilter->validate(validator); + if(!success) { + ThrowMsg(InvalidArgumentException, "Invalid filter arguments."); + } else { + LoggerD("Filter validation has passed."); + } + + genericFilter->travel(filterTraversal, 0); + + if(getIsUnified()) { + LoggerD("Set all calendars flag for a unified calendar."); + calendarFilter->setCalendarId(CALENDAR_BOOK_FILTER_ALL, true); + } else { + LoggerD("Set additional calendar id: "<<calendarId); + calendarFilter->setCalendarId(calendarId, true); + } + } else { + if(getIsUnified()) { + LoggerD("Set all calendars flag for a unified calendar."); + calendarFilter->setCalendarId(CALENDAR_BOOK_FILTER_ALL, false); + } else { + LoggerD("Set calendar id: "<<calendarId); + calendarFilter->setCalendarId(calendarId, false); + } + } + + if (event->getSortModesIsSet()) { + calendarFilter->setSortMode(event->getSortModes()); + } + + calendarFilter->executeQuery(); + + LoggerD("Return the query result after conversion."); + + calendar_list_h resultList = calendarFilter->getResultRecordList(); + int ret; + int count = calendarFilter->getResultRecordCount(); + calendar_record_h currentRecord = NULL; + + calendar_list_first(resultList); + + while(count--) { + currentRecord = NULL; + ret = calendar_list_get_current_record_p(resultList, ¤tRecord); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record: "<<ret); + } + + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(currentRecord, getType())); + event->addEvent(eventWrapper->convertPlatformEventToAbstractEvent()); + + calendar_list_next(resultList); + } + LoggerD("Length of found items: "<<event->getEvents()->size()); + + // Handle the recurring event range filter corner case. + int id = -1, parentCount = -1; + bool found = false; + resultList = calendarFilter->getNormalInstanceResultRecordList(); + count = calendarFilter->getNormalInstanceResultRecordCount(); + LoggerD("Number of found normal instances: "<<count); + + currentRecord = NULL; + calendar_list_first(resultList); + while(count--) { + currentRecord = NULL; + ret = calendar_list_get_current_record_p(resultList, ¤tRecord); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get a current record: "<<ret); + } + + id = -1; + ret = calendar_record_get_int(currentRecord, _calendar_instance_normal_calendar_book.event_id, &id); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't get the normal instance parent id: "<<ret); + } + + // Skip if the parent event is already found. + parentCount = event->getEvents()->size(); + found = false; + while(parentCount--) { + if(id==event->getEvents()->at(parentCount)->getId()) { + LoggerD("Found the id: "<<id<<", thus skip this."); + found = true; + break; + } + } + + if(false==found) { + LoggerD("Add the normal instance parent: "<<id); + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType())); + eventWrapper->loadEvent(id); + event->addEvent(eventWrapper->convertPlatformEventToAbstractEvent()); + } + + calendar_list_next(resultList); + } + LoggerD("Length of found items including normal instances: "<<event->getEvents()->size()); + + resultList = calendarFilter->getAlldayInstanceResultRecordList(); + count = calendarFilter->getAlldayInstanceResultRecordCount(); + LoggerD("Number of found allday instances: "<<count); + + currentRecord = NULL; + calendar_list_first(resultList); + while(count--) { + currentRecord = NULL; + ret = calendar_list_get_current_record_p(resultList, ¤tRecord); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get a current record: "<<ret); + } + + id = -1; + ret = calendar_record_get_int(currentRecord, _calendar_instance_allday_calendar_book.event_id, &id); + if (CALENDAR_ERROR_NONE != ret) { + ThrowMsg(PlatformException, "Can't get the allday instance parent id: "<<ret); + } + + // Skip if the parent event is already found. + parentCount = event->getEvents()->size(); + found = false; + while(parentCount--) { + if(id==event->getEvents()->at(parentCount)->getId()) { + LoggerD("Found the id: "<<id<<", thus skip this."); + found = true; + break; + } + } + + if(false==found) { + LoggerD("Add the allday instance parent: "<<id); + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType())); + eventWrapper->loadEvent(id); + event->addEvent(eventWrapper->convertPlatformEventToAbstractEvent()); + } + + calendar_list_next(resultList); + } + LoggerD("Length of found items including allday instances: "<<event->getEvents()->size()); + + event->setResult(true); + } + Catch (InvalidArgumentException) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::InvalidArgumentException); + } + Catch (NotFoundException) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::NotFoundException); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } +} + +void Calendar::OnRequestReceived(const IEventCreateEventFromStringPtr &event) +{ + Try + { + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(getType())); + eventWrapper->createEventFromString(event->getEventString()); + event->setEvent(eventWrapper->convertPlatformEventToAbstractEvent()); + event->getEvent()->setCalendarType(getType()); + event->setResult(true); + } + Catch(PlatformException) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + LoggerD("eventString: " + event->getEventString()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::InvalidArgumentException); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + LoggerD("eventString: " + event->getEventString()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } +} + +void Calendar::OnRequestReceived(const IEventExportEventToStringPtr &event) +{ + Try + { + if (!event->getEvent()) { + ThrowMsg(NullPointerException, "event parameter is NULL"); + } + + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(event->getEvent(), getType())); + event->getEvent()->setCalendarType(getType()); + eventWrapper->convertAbstractEventToPlatformEvent(); + event->setEventString(eventWrapper->exportEventToString(event->getFormat())); + event->setResult(true); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } +} + +static void eventChangedCb(const char *view_uri, void *user_data) +{ + LoggerD("Items change cb with view_uri: "<<view_uri); + + OnEventsChangedPtr eventPtr(new OnEventsChanged()); + calendar_list_h list = NULL; + + Try + { + if (user_data == NULL) { + LoggerD("user_data is NULL."); + return; + } + + Calendar *thisCalendar = (Calendar*) user_data; + + int ret, id, type, updatedVersion, calendarId, count = 0; + + + if(thisCalendar->getIsUnified()) { + LoggerD("Set the all calendar id for a unified calendar."); + calendarId = CALENDAR_BOOK_FILTER_ALL; + } else { + std::stringstream ss(thisCalendar->getId()); + ss>>calendarId; + } + + LoggerD("Getting items with calendar id: "<<calendarId<<", version: "<<thisCalendar->getLastChangedVersion()<<", type: "<<thisCalendar->getType()); + if (CalendarEvent::TASK_TYPE==thisCalendar->getType()) { + ret = calendar_db_get_changes_by_version(_calendar_todo._uri, calendarId, thisCalendar->getLastChangedVersion(), &list, &updatedVersion); + } else { + ret = calendar_db_get_changes_by_version(_calendar_event._uri, calendarId, thisCalendar->getLastChangedVersion(), &list, &updatedVersion); + } + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Can't get the updated item list: "<<ret); + } + + ret = calendar_list_get_count(list, &count); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Can't get the item count: "<<ret); + } else { + LoggerD("Item count: "<<count); + } + + calendar_list_first(list); + + calendar_record_h currentRecord = NULL; + while(count--) + { + currentRecord = NULL; + ret = calendar_list_get_current_record_p(list, ¤tRecord); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record: "<<ret); + } + + ret = calendar_record_get_int(currentRecord, _calendar_updated_info.id ,&id); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get updated info id: "<<ret); + } + + ret = calendar_record_get_int(currentRecord, _calendar_updated_info.modified_status ,&type); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get updated info modified status: "<<ret); + } + + LoggerD("id "<<id<<", type "<<type); + if ( CALENDAR_EVENT_MODIFIED_STATUS_INSERTED==type ) { + eventPtr->setStatus(OnEventsChanged::ON_ADD); + } else if ( CALENDAR_EVENT_MODIFIED_STATUS_UPDATED==type ) { + eventPtr->setStatus(OnEventsChanged::ON_UPDATE); + } else if ( CALENDAR_EVENT_MODIFIED_STATUS_DELETED==type ) { + eventPtr->setStatus(OnEventsChanged::ON_DELETE); + } else { + LoggerW("Wrong change type."); + calendar_list_next(list); + continue; + } + + DPL::ScopedPtr<EventWrapper> eventWrapper(new EventWrapper(thisCalendar->getType())); + Try { + eventWrapper->loadEvent(id); + } Catch (NotFoundException){ + LoggerD("Handling deleted event with index: "<<id); + } + eventPtr->addEvent(eventWrapper->getAbstractEvent()); + + calendar_list_next(list); + } + + ret = calendar_db_get_current_version(&updatedVersion); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Can't get new version: "<<ret); + } + + thisCalendar->setLastChangedVersion(updatedVersion); + LoggerD("Last change fetch version: "<<thisCalendar->getLastChangedVersion()); + + eventPtr->setResult(true); + eventPtr->setCalendarType(thisCalendar->getType()); + + if( eventPtr->getEventList()->size() > 0 ) { + thisCalendar->m_changeEmitters.emit(eventPtr); + } else { + LoggerD("No actual changes. Skip signal emission."); + } + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + } + + if( list ) { + calendar_list_destroy(list, true); + } +} + +void Calendar::OnRequestReceived(const IEventWatchChangesPtr &event) +{ + Try + { + // Subscribe the watch to the platform just once. + int ret; + if( m_changeEmitters.size()==0 ) + { + const char *dataType; + if(getType() == CalendarEvent::TASK_TYPE) { + dataType = _calendar_todo._uri; + } else { + dataType = _calendar_event._uri; + } + + ret = calendar_db_add_changed_cb(dataType, eventChangedCb, this); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Can't add db changed cb: "<<ret); + } else { + // Save the last change fetch version to start watching. + int version; + ret = calendar_db_get_current_version(&version); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Can't get version: "<<ret); + } else { + setLastChangedVersion(version); + LoggerD("Last change fetch version: "<<getLastChangedVersion()); + } + } + } + + m_changeEmitters.attach(event->getEmitter()); + event->setWatchId(event->getEmitter()->getId()); + event->setResult(true); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } +} + +void Calendar::OnRequestReceived(const IEventClearWatchPtr &event) +{ + Try + { + if( m_changeEmitters.detach(event->getWatchId()) ) { + if( m_changeEmitters.size()==0 ) { + const char *dataType; + if(getType() == CalendarEvent::TASK_TYPE) { + dataType = _calendar_todo._uri; + } else { + dataType = _calendar_event._uri; + } + + if( CALENDAR_ERROR_NONE!=calendar_db_remove_changed_cb(dataType, eventChangedCb, this) ) { + ThrowMsg(PlatformException, "Can't remove change cb."); + } else { + LoggerD("Platform watch cleared successfully."); + } + } + event->setResult(true); + } else { + LoggerD("Wrong watch Id."); + event->setResult(false); + } + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } +} + +void Calendar::OnRequestReceived(const IEventExpandEventRecurrencePtr &event) +{ + const CalendarEventPtr calEvent = event->getEvent(); + const long long int startDate = event->getStartDate(); + const long long int endDate = event->getEndDate(); + bool isAllDay = calEvent->getIsAllDay(); + + calendar_query_h query = NULL; + calendar_filter_h filter = NULL; + calendar_list_h list = NULL; + + Try { + if ( 0 >= calEvent->getRecurrenceRule()->getFrequency()) { + ThrowMsg(InvalidArgumentException, "This is not a recurring event."); + } + + calendar_record_h currentRecord = NULL; + int ret, currentRecordIndex, count=0; + + calendar_time_s st, et; + if( true==isAllDay ) { + st.type = CALENDAR_TIME_LOCALTIME; + st.time.date = CalendarUtility::LLIToCalTime(calEvent->getTimeZone().c_str(), startDate).time.date; + + et.type = CALENDAR_TIME_LOCALTIME; + et.time.date = CalendarUtility::LLIToCalTime(calEvent->getTimeZone().c_str(), endDate).time.date; + } else { + st.type = CALENDAR_TIME_UTIME; + st.time.utime = startDate; + + et.type = CALENDAR_TIME_UTIME; + et.time.utime = endDate; + } + + if( true==isAllDay ) { + ret = calendar_query_create(_calendar_instance_allday_calendar_book._uri, &query); + } else { + ret = calendar_query_create(_calendar_instance_normal_calendar_book._uri, &query); + } + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Creating a query failed: "<<ret); + } + + if( true==isAllDay ) { + ret = calendar_filter_create(_calendar_instance_allday_calendar_book._uri, &filter); + } else { + ret = calendar_filter_create(_calendar_instance_normal_calendar_book._uri, &filter); + } + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Creating a filter failed: "<<ret); + } + + if( true==isAllDay ) { + ret = calendar_filter_add_caltime(filter, _calendar_instance_allday_calendar_book.start_time, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL, st); + } else { + ret = calendar_filter_add_caltime(filter, _calendar_instance_normal_calendar_book.start_time, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL, st); + } + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Adding a caltime filter failed: "<<ret); + } + + ret = calendar_filter_add_operator(filter, CALENDAR_FILTER_OPERATOR_AND); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Adding a filter operator failed: "<<ret); + } + + if( true==isAllDay ) { + ret = calendar_filter_add_caltime(filter, _calendar_instance_allday_calendar_book.end_time, CALENDAR_MATCH_LESS_THAN_OR_EQUAL, et); + } else { + ret = calendar_filter_add_caltime(filter, _calendar_instance_normal_calendar_book.end_time, CALENDAR_MATCH_LESS_THAN_OR_EQUAL, et); + } + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Adding a caltime filter failed: "<<ret); + } + + ret = calendar_query_set_filter(query, filter); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Setting a filter: "<<ret); + } + + ret = calendar_db_get_records_with_query(query, 0, 0, &list); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Getting event instances failed: "<<ret); + } + + ret = calendar_list_get_count(list, &count); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Can't get the item count: "<<ret); + } else { + LoggerD("Item count: "<<count<<", isAllDay: "<<isAllDay); + } + + calendar_list_first(list); + + while(count--) + { + currentRecord = NULL; + ret = calendar_list_get_current_record_p(list, ¤tRecord); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record: "<<ret); + } + + if( true==isAllDay ) { + ret = calendar_record_get_int(currentRecord, _calendar_instance_allday_calendar_book.event_id, ¤tRecordIndex); + } else { + ret = calendar_record_get_int(currentRecord, _calendar_instance_normal_calendar_book.event_id, ¤tRecordIndex); + } + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record id: "<<ret); + } + + if(currentRecordIndex==calEvent->getId()) { + DPL::ScopedPtr<EventWrapper> recurringEventWrapper(new EventWrapper(getType())); + recurringEventWrapper->loadEvent(calEvent->getId()); + + // Set distintive attributes of each instance. + if( true==isAllDay ) { + ret = calendar_record_get_caltime(currentRecord, _calendar_instance_allday_calendar_book.start_time, &st); + + recurringEventWrapper->getAbstractEvent()->setRecurrenceId(CalendarUtility::calTimeToLLI(calEvent->getTimeZone().c_str(), st)); + recurringEventWrapper->getAbstractEvent()->setStartTime(CalendarUtility::calTimeToLLI(calEvent->getTimeZone().c_str(), st)); + } else { + ret = calendar_record_get_caltime(currentRecord, _calendar_instance_normal_calendar_book.start_time, &st); + + recurringEventWrapper->getAbstractEvent()->setRecurrenceId(st.time.utime); + recurringEventWrapper->getAbstractEvent()->setStartTime(st.time.utime); + } + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record start time: "<<ret); + } + + if( true==isAllDay ) { + ret = calendar_record_get_caltime(currentRecord, _calendar_instance_allday_calendar_book.end_time, &et); + + recurringEventWrapper->getAbstractEvent()->setEndTime(CalendarUtility::calTimeToLLI(calEvent->getTimeZone().c_str(), et)); + } else { + ret = calendar_record_get_caltime(currentRecord, _calendar_instance_normal_calendar_book.end_time, &et); + + recurringEventWrapper->getAbstractEvent()->setEndTime(et.time.utime); + } + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record end time: "<<ret); + } + + LoggerD("Found a valid event instance with rid: "<<recurringEventWrapper->getAbstractEvent()->getRecurrenceId()); + + event->addExpandedEvent(recurringEventWrapper->getAbstractEvent()); + } else { + LoggerD("Skip unmatched instance with event_id: "<<currentRecordIndex<<" and parent id: "<<calEvent->getId()); + } + + calendar_list_next(list); + } + LoggerD("Length of expanded events from parent: "<<event->getExpandedEventList()->size()); + + if(query) { + calendar_query_destroy(query); + query = NULL; + } + if(filter) { + calendar_filter_destroy(filter); + filter = NULL; + } + if( list ) { + calendar_list_destroy(list, true); + list = NULL; + } + + // Consider the detached events also. + currentRecord = NULL; + int parentId = event->getEvent()->getId(); + + ret = calendar_query_create(_calendar_event._uri, &query); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Creating a query failed: "<<ret); + } + + ret = calendar_filter_create(_calendar_event._uri, &filter); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Creating a filter failed: "<<ret); + } + + ret = calendar_filter_add_int(filter, _calendar_event.original_event_id, CALENDAR_MATCH_EQUAL, parentId); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Adding an int filter failed: "<<ret); + } + + ret = calendar_query_set_filter(query, filter); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Setting a filter: "<<ret); + } + + ret = calendar_db_get_records_with_query(query, 0, 0, &list); + if(CALENDAR_ERROR_NONE!=ret) { + ThrowMsg(PlatformException, "Finding detached instances failed: "<<ret); + } + + ret = calendar_list_get_count(list, &count); + if( CALENDAR_ERROR_NONE!=ret ) { + ThrowMsg(PlatformException, "Can't get the item count: "<<ret); + } else { + LoggerD("Item count: "<<count); + } + + calendar_list_first(list); + + while(count--) + { + currentRecord = NULL; + ret = calendar_list_get_current_record_p(list, ¤tRecord); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record: "<<ret); + } + + ret = calendar_record_get_int(currentRecord, _calendar_event.id, ¤tRecordIndex); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record id: "<<ret); + } + + st = {CALENDAR_TIME_UTIME, {0}}; + ret = calendar_record_get_caltime(currentRecord, _calendar_event.start_time, &st); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record start time: "<<ret); + } + + et = {CALENDAR_TIME_UTIME, {0}}; + ret = calendar_record_get_caltime(currentRecord, _calendar_event.end_time, &et); + if ( CALENDAR_ERROR_NONE != ret ) { + ThrowMsg(PlatformException, "Can't get current record end time: "<<ret); + } + + if (st.time.utime>=startDate && et.time.utime<=endDate) { + LoggerD("Found a valid detached event: "<<st.time.utime); + DPL::ScopedPtr<EventWrapper> detachedEventWrapper(new EventWrapper(getType())); + detachedEventWrapper->loadEvent(currentRecordIndex); + + // Set the same parent uid to each instances + detachedEventWrapper->getAbstractEvent()->setId(parentId); + // Set distintive attributes of each instance. + detachedEventWrapper->getAbstractEvent()->setRecurrenceId(st.time.utime); + detachedEventWrapper->getAbstractEvent()->setStartTime(st.time.utime); + detachedEventWrapper->getAbstractEvent()->setEndTime(et.time.utime); + + event->addExpandedEvent(detachedEventWrapper->getAbstractEvent()); + } + + calendar_list_next(list); + } + + LoggerD("Length of total expanded events: "<<event->getExpandedEventList()->size()); + + event->setResult(true); + + if(query) { + calendar_query_destroy(query); + query = NULL; + } + if(filter) { + calendar_filter_destroy(filter); + filter = NULL; + } + if( list ) { + calendar_list_destroy(list, true); + list = NULL; + } + } + Catch (InvalidArgumentException) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::InvalidArgumentException); + } + Catch (Exception) + { + LoggerW("Exception: "<<_rethrown_exception.GetMessage()); + event->setResult(false); + event->setExceptionCode(ExceptionCodes::UnknownException); + } + + if(query) { + calendar_query_destroy(query); + } + if(filter) { + calendar_filter_destroy(filter); + } + if( list ) { + calendar_list_destroy(list, true); + } +} + +} +} |