upload tizen1.0 source
[profile/ivi/wrt-plugins-tizen.git] / src / standards / Tizen / Calendar / JSCalendarEvent.cpp
index e8610ec..eac5832 100755 (executable)
 
 
 #include <ctime>
-#include <dpl/log.h>
+#include <dpl/log/log.h>
 #include <CommonsJavaScript/PrivateObject.h>
 #include <CommonsJavaScript/Converter.h>
 #include <CommonsJavaScript/JSUtils.h>
-#include <Tizen/Common/JSTizenExceptionFactory.h>
+#include <CommonsJavaScript/Utils.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
 #include <API/Calendar/EventId.h>
 #include "JSCalendarEvent.h"
 #include "JSCalendarItemProperties.h"
 #include "CalendarConverter.h"
-#include "JSEventId.h"
+#include "JSCalendarEventId.h"
+#include "plugin_config.h"
+#include "CalendarResponseDispatcher.h"
 #include <Tizen/TimeUtil/TimeUtilConverter.h>
 #include <Tizen/TimeUtil/JSTZDate.h>
+#include <Tizen/Common/JSTizenException.h>
+#include <Tizen/Common/JSTizenExceptionFactory.h>
+#include <Tizen/Common/SecurityExceptions.h>
 
 using namespace TizenApis::Api::Calendar;
 using namespace WrtDeviceApis::Commons;
 using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace TizenApis::Commons;
 
 namespace TizenApis {
 namespace Tizen1_0 {
 namespace Calendar {
 
-#define TIZEN_CALENDAR_EVENT_ATTRIBUTENAME "CalendarEvent"
-
-#define TIZEN_CALENDAR_EVENT_ID "id"
-#define TIZEN_CALENDAR_EVENT_LASTMODIFIEDDATE "lastModificationDate"
-#define TIZEN_CALENDAR_EVENT_IS_DETACHED "isDetached"
-
 JSClassDefinition JSCalendarEvent::m_classInfo = {
     0,
     kJSClassAttributeNone,
-    TIZEN_CALENDAR_EVENT_ATTRIBUTENAME,
+    TIZEN_INTERFACE_CALENDAR_EVENT,
     JSCalendarItemProperties::getClassRef(),
     m_property,
-    NULL, //    m_function,
+    m_function,
     initialize,
     finalize,
     NULL, //hasProperty,
@@ -58,7 +60,7 @@ JSClassDefinition JSCalendarEvent::m_classInfo = {
     NULL, //DeleteProperty,
     NULL, //GetPropertyNames,
     NULL, //CallAsFunction,
-    NULL, //CallAsConstructor,
+    constructor,
     NULL, //HasInstance,
     NULL  //ConvertToType
 };
@@ -66,7 +68,7 @@ JSClassDefinition JSCalendarEvent::m_classInfo = {
 JSStaticValue JSCalendarEvent::m_property[] = {
     { TIZEN_CALENDAR_EVENT_ID, getPropertyId,
       NULL, kJSPropertyAttributeReadOnly },
-    { TIZEN_CALENDAR_EVENT_LASTMODIFIEDDATE, getPropertyLastModifiedDate,
+    { TIZEN_CALENDAR_EVENT_LAST_MODIFICATION_DATE, getPropertyLastModificationDate,
       NULL, kJSPropertyAttributeReadOnly },
     { TIZEN_CALENDAR_EVENT_IS_DETACHED, getPropertyIsDetached,
       NULL, kJSPropertyAttributeReadOnly },
@@ -74,27 +76,134 @@ JSStaticValue JSCalendarEvent::m_property[] = {
     { 0, 0, 0, 0 }
 };
 
+JSStaticFunction JSCalendarEvent::m_function[] = {
+    { CALENDAR_FUNCTION_API_EXPAND_RECURRENCE, expandRecurrence, kJSPropertyAttributeNone },
+
+    { 0, 0, 0 }
+};
+
 JSClassRef JSCalendarEvent::m_jsClassRef = JSClassCreate(JSCalendarEvent::getClassInfo());
 
+ICalendarPtr JSCalendarEvent::m_calendar = CalendarFactory::getInstance().createCalendarObject();
+
 void JSCalendarEvent::initialize(JSContextRef context,
         JSObjectRef object)
 {
-    LogDebug("entered");
-    CalendarEventPrivObject *priv =
-        static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
-    if (!priv) {
-        CalendarEventPtr privateData(new CalendarEvent());
-        priv = new CalendarEventPrivObject(context, privateData);
-        JSObjectSetPrivate(object, static_cast<void*>(priv));
-        LogDebug("new event is created");
+    if (!JSObjectGetPrivate(object)) {
+        LogDebug("Create calendar event private object.");
+        CalendarEventPtr event( new CalendarEvent() );
+        CalendarEventPrivObject *priv = new CalendarEventPrivObject(context, event);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
     } else {
-        LogDebug("private object already exists");
+        LogDebug("Private object alrerady set.");
+    }
+
+    if (m_calendar) {
+        m_calendar->setType(CalendarEvent::EVENT_TYPE);
+        LogDebug("Calendar object type is set to event.");
     }
 }
 
 void JSCalendarEvent::finalize(JSObjectRef object)
 {
-    LogDebug("entered");
+    LogDebug("enter");
+    CalendarEventPrivObject* priv = static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
+    if (priv) {
+        delete priv;
+        JSObjectSetPrivate(object, NULL);
+    }
+}
+
+JSObjectRef JSCalendarEvent::constructor(JSContextRef context,
+    JSObjectRef constructor,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+       LogDebug("entered");
+
+    Try
+    {
+               CalendarEventPrivObject* privateObject = static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(constructor));
+               JSContextRef globalContext = privateObject->getContext();
+
+        CalendarConverter converter(globalContext);
+        CalendarEventPtr event;
+
+        if (argumentCount==0) {
+            CalendarEventPtr result(new CalendarEvent());
+            event = result;
+        } else if (argumentCount==1) {
+            LogInfo("eventInitDict case");
+            if (JSValueIsUndefined(context, arguments[0]) || JSValueIsNull(context, arguments[0])) {
+                CalendarEventPtr result(new CalendarEvent());
+                event = result;
+            } else if (JSValueIsObject(context, arguments[0])) {
+                event = converter.toEvent(arguments[0]);
+                if (!event) {
+                    ThrowMsg(ConversionException, "Parameter conversion failed.");
+                }
+            } else {
+                ThrowMsg(ConversionException, "Parameter conversion failed.");
+            }
+        } else if (argumentCount>=2) {
+            LogInfo("event stringRepresentation case");
+            std::string eventStr;
+            CalendarEvent::VObjectFormat format = CalendarEvent::UNDEFINED_FORMAT;
+            eventStr = converter.toString(arguments[0]);
+            format = converter.toVObjectFormat(converter.toString(arguments[1]));
+
+            IEventCreateEventFromStringPtr dplEvent(new IEventCreateEventFromString());
+            dplEvent->setEventString(eventStr);
+            dplEvent->setFormat(format);
+            dplEvent->setForSynchronousCall();
+            m_calendar->createEventFromString(dplEvent);
+
+            // Process the returned object.
+            if (dplEvent->getResult()) {
+                LogInfo("Successfully created an event.");
+                event = dplEvent->getEvent();
+            } else {
+                if (dplEvent->getExceptionCode()==ExceptionCodes::InvalidArgumentException) {
+                    ThrowMsg(InvalidArgumentException, "Wrong string to convert.");
+                } else {
+                    ThrowMsg(UnknownException, "Converting string failed.");
+                }
+            }
+        }
+
+        return createJSCalendarEvent(globalContext, event);
+    }
+    Catch(UnsupportedException)
+    {
+        LogWarning("Exception: "<<_rethrown_exception.GetMessage());
+        *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LogWarning("Exception: "<<_rethrown_exception.GetMessage());
+        *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LogWarning("Exception: "<<_rethrown_exception.GetMessage());
+        *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LogWarning("Exception: "<<_rethrown_exception.GetMessage());
+        *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+
+    return NULL;
+}
+
+JSObjectRef JSCalendarEvent::createJSCalendarEvent(JSContextRef context, CalendarEventPtr event)
+{
+    CalendarEventPrivObject *priv = new CalendarEventPrivObject(context, event);
+    return JSObjectMake(context, getClassRef(), priv);
 }
 
 const JSClassRef JSCalendarEvent::getClassRef()
@@ -146,6 +255,111 @@ void JSCalendarEvent::setPrivateObject(const CalendarEventPtr &event,
     }
 }
 
+JSValueRef JSCalendarEvent::expandRecurrence(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LogDebug("entered");
+
+    CalendarEventPrivObject *privateObject =
+        static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = CALENDAR_CHECK_ACCESS(CALENDAR_FUNCTION_API_EXPAND_RECURRENCE);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        CalendarEventPtr event = privateObject->getObject();
+        if (!event) {
+            ThrowMsg(ConversionException, "Parameter conversion failed.");
+        }
+
+        JSContextRef globalContext = privateObject->getContext();
+        CalendarConverter converter(context);
+
+        std::time_t startDate = 0;
+        std::time_t endDate = INT_MAX; // about 60 years in 4 bytes system.
+        TimeUtilConverter timeConverter(context);
+        if (argumentCount>=1) {
+            if (JSValueIsObjectOfClass(context, arguments[0], JSTZDate::getClassRef())) {
+                startDate = timeConverter.toTZDateTimeT(arguments[0]);
+                LogInfo("startDate: "<<startDate);
+            } else {
+                ThrowMsg(ConversionException, "Wrong first parameter type.");
+            }
+        }
+        if (argumentCount>=2) {
+            if (JSValueIsObjectOfClass(context, arguments[1], JSTZDate::getClassRef())) {
+                endDate = timeConverter.toTZDateTimeT(arguments[1]);
+                LogInfo("endDate: "<<endDate);
+            } else {
+                ThrowMsg(ConversionException, "Wrong second parameter type.");
+            }
+        }
+
+        JSValueRef onError = argumentCount > 1 ? converter.toFunctionOrNull(arguments[3]) : NULL;
+
+        JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext, NULL, onError);
+
+        Validator validator(context);
+        if (validator.isCallback(arguments[2])) {
+            cbm->setOnSuccess(arguments[2]);
+        } else {
+            ThrowMsg(ConversionException, "Wrong third parameter type.");
+        }
+
+               // Protect the super object until the callback operation is finished.
+               JSValueProtect(globalContext, thisObject);
+
+        LogDebug("Proceed the expand event to the platform.");
+
+        IEventExpandEventRecurrencePtr dplEvent(new IEventExpandEventRecurrence());
+        dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(cbm));
+        dplEvent->setForAsynchronousCall(&CalendarResponseDispatcher::getInstance());
+        dplEvent->setEvent(event);
+        dplEvent->setStartDate(startDate);
+        dplEvent->setEndDate(endDate);
+        m_calendar->expandEventRecurrence(dplEvent);
+
+        return JSValueMakeUndefined(context);
+    }
+    Catch(UnsupportedException)
+    {
+               LogWarning("Exception: "<<_rethrown_exception.GetMessage());
+        return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+               LogWarning("Exception: "<<_rethrown_exception.GetMessage());
+        return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+               LogWarning("Exception: "<<_rethrown_exception.GetMessage());
+        return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch (NotFoundException)
+    {
+               LogWarning("Exception: "<<_rethrown_exception.GetMessage());
+        return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_FOUND_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+               LogWarning("Exception: "<<_rethrown_exception.GetMessage());
+        return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
 JSValueRef JSCalendarEvent::getPropertyId(JSContextRef context,
         JSObjectRef object,
         JSStringRef propertyName,
@@ -154,15 +368,23 @@ JSValueRef JSCalendarEvent::getPropertyId(JSContextRef context,
     LogDebug("entered");
     Try
     {
-        CalendarConverterFactory::ConverterType converter =
-            CalendarConverterFactory::getConverter(context);
-        CalendarEventPtr event = getPrivateObject(object);
+        CalendarEventPrivObject *privateObject =
+            static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
+        CalendarEventPtr event = privateObject->getObject();
 
         EventIdPtr eventId( new EventId() );
-        eventId->setUId(event->getUId());
-        eventId->setRecurrenceId(event->getRecurrenceId());
-        eventId->setTimeZone(event->getTimeZone());
-        return converter->toJSValueRef(eventId);
+               if (0<event->getParentId()) {
+                       std::stringstream ss;
+                       ss<<event->getParentId();
+                       eventId->setUId(ss.str());
+               } else {
+               eventId->setUId(event->getUId());
+               }
+        std::stringstream ss;
+        std::time_t rid = event->getRecurrenceId();
+        ss<<rid;
+        eventId->setRecurrenceId(ss.str());
+        return JSCalendarEventId::createJSCalendarEventId(context, eventId);
     }
     Catch(Exception)
     {
@@ -171,7 +393,7 @@ JSValueRef JSCalendarEvent::getPropertyId(JSContextRef context,
     return JSValueMakeUndefined(context);
 }
 
-JSValueRef JSCalendarEvent::getPropertyLastModifiedDate(JSContextRef context,
+JSValueRef JSCalendarEvent::getPropertyLastModificationDate(JSContextRef context,
         JSObjectRef object,
         JSStringRef propertyName,
         JSValueRef* exception)
@@ -182,15 +404,14 @@ JSValueRef JSCalendarEvent::getPropertyLastModifiedDate(JSContextRef context,
         CalendarEventPrivObject *privateObject =
             static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
         CalendarEventPtr event = privateObject->getObject();
-
         if (!event) {
             Throw(NullPointerException);
         }
-        if (event->getLastModifiedDate() != 0) {
-            // Use the global context saved in the event struct.
-            return JSTZDate::createJSObject(privateObject->getContext(), event->getLastModifiedDate(), event->getTimeZone());
+
+        if (UNDEFINED_TIME==event->getLastModifiedDate()) {
+            return JSValueMakeNull(context);
         } else {
-            return JSValueMakeUndefined(context);
+            return JSTZDate::createJSObject(context, event->getLastModifiedDate(), event->getTimeZone());
         }
     }
     Catch(Exception)
@@ -208,8 +429,12 @@ JSValueRef JSCalendarEvent::getPropertyIsDetached(JSContextRef context,
     LogDebug("entered");
     Try
     {
-        Converter converter(context);
         CalendarEventPtr event = getPrivateObject(object);
+        if(CalendarEvent::EVENT_TYPE != event->getCalendarType()) {
+            return JSValueMakeUndefined(context);
+        }
+
+        Converter converter(context);
         return converter.toJSValueRef(event->getIsDetached());
     }
     Catch(Exception)