Update change log and spec for wrt-plugins-tizen_0.2.84
[framework/web/wrt-plugins-tizen.git] / src / standards / Tizen / Calendar / JSCalendarEvent.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 <ctime>
19 #include <dpl/log/log.h>
20 #include <CommonsJavaScript/PrivateObject.h>
21 #include <CommonsJavaScript/Converter.h>
22 #include <CommonsJavaScript/JSUtils.h>
23 #include <CommonsJavaScript/Utils.h>
24 #include <CommonsJavaScript/Validator.h>
25 #include <CommonsJavaScript/JSCallbackManager.h>
26 #include <API/Calendar/EventId.h>
27 #include "JSCalendarEvent.h"
28 #include "JSCalendarItemProperties.h"
29 #include "CalendarConverter.h"
30 #include "JSCalendarEventId.h"
31 #include "plugin_config.h"
32 #include "CalendarResponseDispatcher.h"
33 #include <Tizen/TimeUtil/TimeUtilConverter.h>
34 #include <Tizen/TimeUtil/JSTZDate.h>
35 #include <Tizen/Common/JSTizenException.h>
36 #include <Tizen/Common/JSTizenExceptionFactory.h>
37 #include <Tizen/Common/SecurityExceptions.h>
38
39 #include "CalendarAsyncCallbackManager.h"
40
41 using namespace TizenApis::Api::Calendar;
42 using namespace WrtDeviceApis::Commons;
43 using namespace WrtDeviceApis::CommonsJavaScript;
44 using namespace TizenApis::Commons;
45
46 namespace TizenApis {
47 namespace Tizen1_0 {
48 namespace Calendar {
49
50 JSClassDefinition JSCalendarEvent::m_classInfo = {
51     0,
52     kJSClassAttributeNone,
53     TIZEN_INTERFACE_CALENDAR_EVENT,
54     JSCalendarItemProperties::getClassRef(),
55     m_property,
56     m_function,
57     initialize,
58     finalize,
59     NULL, //hasProperty,
60     NULL, //getProperty,
61     NULL, //setProperty,
62     NULL, //DeleteProperty,
63     NULL, //GetPropertyNames,
64     NULL, //CallAsFunction,
65     constructor,
66     NULL, //HasInstance,
67     NULL  //ConvertToType
68 };
69
70 JSStaticValue JSCalendarEvent::m_property[] = {
71     { TIZEN_CALENDAR_EVENT_ID, getPropertyId,
72       NULL, kJSPropertyAttributeReadOnly },
73     { TIZEN_CALENDAR_EVENT_LAST_MODIFICATION_DATE, getPropertyLastModificationDate,
74       NULL, kJSPropertyAttributeReadOnly },
75     { TIZEN_CALENDAR_EVENT_IS_DETACHED, getPropertyIsDetached,
76       NULL, kJSPropertyAttributeReadOnly },
77
78     { 0, 0, 0, 0 }
79 };
80
81 JSStaticFunction JSCalendarEvent::m_function[] = {
82     { CALENDAR_FUNCTION_API_EXPAND_RECURRENCE, expandRecurrence, kJSPropertyAttributeNone },
83
84     { 0, 0, 0 }
85 };
86
87 JSClassRef JSCalendarEvent::m_jsClassRef = JSClassCreate(JSCalendarEvent::getClassInfo());
88
89 ICalendarPtr JSCalendarEvent::m_calendar = CalendarFactory::getInstance().createCalendarObject();
90
91 void JSCalendarEvent::initialize(JSContextRef context,
92         JSObjectRef object)
93 {
94     if (!JSObjectGetPrivate(object)) {
95         LogDebug("Create calendar event private object.");
96         CalendarEventPtr event( new CalendarEvent() );
97         CalendarEventPrivObject *priv = new CalendarEventPrivObject(context, event);
98         if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
99             delete priv;
100         }
101     } else {
102         LogDebug("Private object alrerady set.");
103     }
104
105     if (m_calendar) {
106         m_calendar->setType(CalendarEvent::EVENT_TYPE);
107         LogDebug("Calendar object type is set to event.");
108     }
109 }
110
111 void JSCalendarEvent::finalize(JSObjectRef object)
112 {
113     LogDebug("enter");
114     CalendarEventPrivObject* priv = static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
115     if (priv) {
116         delete priv;
117         JSObjectSetPrivate(object, NULL);
118     }
119 }
120
121 JSObjectRef JSCalendarEvent::constructor(JSContextRef context,
122     JSObjectRef constructor,
123     size_t argumentCount,
124     const JSValueRef arguments[],
125     JSValueRef* exception)
126 {
127         LogDebug("entered");
128
129     Try
130     {
131                 CalendarEventPrivObject* privateObject = static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(constructor));
132                 JSContextRef globalContext = privateObject->getContext();
133
134         CalendarConverter converter(globalContext);
135         CalendarEventPtr event;
136
137         if (argumentCount==0) {
138             CalendarEventPtr result(new CalendarEvent());
139             event = result;
140         } else if (argumentCount==1) {
141             LogInfo("eventInitDict case");
142             if (JSValueIsUndefined(context, arguments[0]) || JSValueIsNull(context, arguments[0])) {
143                 CalendarEventPtr result(new CalendarEvent());
144                 event = result;
145             } else if (JSValueIsObject(context, arguments[0])) {
146                 event = converter.toEvent(arguments[0]);
147                 if (!event) {
148                     ThrowMsg(ConversionException, "Parameter conversion failed.");
149                 }
150             } else {
151                 ThrowMsg(ConversionException, "Parameter conversion failed.");
152             }
153         } else if (argumentCount>=2) {
154             LogInfo("event stringRepresentation case");
155             std::string eventStr;
156             CalendarEvent::VObjectFormat format = CalendarEvent::UNDEFINED_FORMAT;
157             eventStr = converter.toString(arguments[0]);
158             format = converter.toVObjectFormat(converter.toString(arguments[1]));
159
160             IEventCreateEventFromStringPtr dplEvent(new IEventCreateEventFromString());
161             dplEvent->setEventString(eventStr);
162             dplEvent->setFormat(format);
163             dplEvent->setForSynchronousCall();
164             m_calendar->createEventFromString(dplEvent);
165
166             // Process the returned object.
167             if (dplEvent->getResult()) {
168                 LogInfo("Successfully created an event.");
169                 event = dplEvent->getEvent();
170             } else {
171                 if (dplEvent->getExceptionCode()==ExceptionCodes::InvalidArgumentException) {
172                     ThrowMsg(InvalidArgumentException, "Wrong string to convert.");
173                 } else {
174                     ThrowMsg(UnknownException, "Converting string failed.");
175                 }
176             }
177         }
178
179         return createJSCalendarEvent(globalContext, event);
180     }
181     Catch(UnsupportedException)
182     {
183         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
184         *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
185     }
186     Catch(InvalidArgumentException)
187     {
188         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
189         *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
190     }
191     Catch(ConversionException)
192     {
193         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
194         *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
195     }
196     Catch(Exception)
197     {
198         LogWarning("Exception: "<<_rethrown_exception.GetMessage());
199         *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
200     }
201
202     return NULL;
203 }
204
205 JSObjectRef JSCalendarEvent::createJSCalendarEvent(JSContextRef context, CalendarEventPtr event)
206 {
207     CalendarEventPrivObject *priv = new CalendarEventPrivObject(context, event);
208     return JSObjectMake(context, getClassRef(), priv);
209 }
210
211 const JSClassRef JSCalendarEvent::getClassRef()
212 {
213     if (!m_jsClassRef) {
214         m_jsClassRef = JSClassCreate(&m_classInfo);
215     }
216     return m_jsClassRef;
217 }
218
219 const JSClassDefinition* JSCalendarEvent::getClassInfo()
220 {
221     return &m_classInfo;
222 }
223
224 CalendarEventPtr JSCalendarEvent::getPrivateObject(JSObjectRef object)
225 {
226     LogDebug("entered");
227     CalendarEventPrivObject *priv =
228         static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
229     if (!priv) {
230         ThrowMsg(NullPointerException, "Private object is null");
231     }
232     CalendarEventPtr result = priv->getObject();
233     if (!result) {
234         ThrowMsg(NullPointerException, "Private object is null");
235     }
236     return result;
237 }
238
239 void JSCalendarEvent::setPrivateObject(const CalendarEventPtr &event,
240         JSContextRef ctx,
241         const JSObjectRef object)
242 {
243     LogDebug("entered");
244     Try
245     {
246         CalendarEventPrivObject *priv =
247             static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
248         delete priv;
249         priv = new CalendarEventPrivObject(ctx, event);
250         if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
251             delete priv;
252         }
253     }
254     Catch(Exception)
255     {
256         LogError("Error during replacing event object");
257     }
258 }
259
260 JSValueRef JSCalendarEvent::expandRecurrence(JSContextRef context,
261         JSObjectRef object,
262         JSObjectRef thisObject,
263         size_t argumentCount,
264         const JSValueRef arguments[],
265         JSValueRef* exception)
266 {
267     LogDebug("entered");
268
269     CalendarEventPrivObject *privateObject =
270         static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(thisObject));
271
272     AceSecurityStatus status = CALENDAR_CHECK_ACCESS(CALENDAR_FUNCTION_API_EXPAND_RECURRENCE);
273
274     TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
275
276     Try
277     {
278         if (!privateObject) {
279             ThrowMsg(ConversionException, "Object is null.");
280         }
281
282         CalendarEventPtr event = privateObject->getObject();
283         if (!event) {
284             ThrowMsg(ConversionException, "Parameter conversion failed.");
285         }
286
287         JSContextRef globalContext = privateObject->getContext();
288         CalendarConverter converter(context);
289
290         std::time_t startDate = 0;
291         std::time_t endDate = INT_MAX; // about 60 years in 4 bytes system.
292         TimeUtilConverter timeConverter(context);
293         if (argumentCount>=1) {
294             if (JSValueIsObjectOfClass(context, arguments[0], JSTZDate::getClassRef())) {
295                 startDate = (long long int) (timeConverter.getTimeInMilliseconds(arguments[0])/1000);
296                 LogInfo("startDate: "<<startDate);
297             } else {
298                 ThrowMsg(ConversionException, "Wrong first parameter type.");
299             }
300         }
301         if (argumentCount>=2) {
302             if (JSValueIsObjectOfClass(context, arguments[1], JSTZDate::getClassRef())) {
303                 endDate = (long long int) (timeConverter.getTimeInMilliseconds(arguments[1])/1000);
304                 LogInfo("endDate: "<<endDate);
305             } else {
306                 ThrowMsg(ConversionException, "Wrong second parameter type.");
307             }
308         }
309
310         JSValueRef onError = argumentCount > 3 ? converter.toFunctionOrNull(arguments[3]) : NULL;
311
312         JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext, NULL, onError);
313
314         Validator validator(context);
315         if (validator.isCallback(arguments[2])) {
316             cbm->setOnSuccess(arguments[2]);
317         } else {
318             ThrowMsg(ConversionException, "Wrong third parameter type.");
319         }
320
321                 cbm->setObject(thisObject);
322
323         LogDebug("Proceed the expand event to the platform.");
324
325         IEventExpandEventRecurrencePtr dplEvent(new IEventExpandEventRecurrence());
326         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(cbm));
327         dplEvent->setForAsynchronousCall(&CalendarResponseDispatcher::getInstance());
328         dplEvent->setEvent(event);
329         dplEvent->setStartDate(startDate);
330         dplEvent->setEndDate(endDate);
331         m_calendar->expandEventRecurrence(dplEvent);
332
333                 CalendarAsyncCallbackManagerSingleton::Instance().registerCallbackManager(cbm, globalContext);
334
335         return JSValueMakeUndefined(context);
336     }
337     Catch(UnsupportedException)
338     {
339                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
340         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
341     }
342     Catch(InvalidArgumentException)
343     {
344                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
345         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
346     }
347     Catch(ConversionException)
348     {
349                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
350         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
351     }
352     Catch (NotFoundException)
353     {
354                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
355         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_FOUND_ERROR, _rethrown_exception.GetMessage());
356     }
357     Catch(Exception)
358     {
359                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
360         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
361     }
362
363     return JSValueMakeUndefined(context);
364 }
365
366 JSValueRef JSCalendarEvent::getPropertyId(JSContextRef context,
367         JSObjectRef object,
368         JSStringRef propertyName,
369         JSValueRef* exception)
370 {
371     LogDebug("entered");
372     Try
373     {
374         CalendarEventPrivObject *privateObject =
375             static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
376         CalendarEventPtr event = privateObject->getObject();
377
378         EventIdPtr eventId( new EventId() );
379                 if (0<event->getParentId()) {
380                         std::stringstream ss;
381                         ss<<event->getParentId();
382                         eventId->setUId(ss.str());
383                 } else {
384                     if (UNDEFINED_ITEM_ID==event->getId()) {
385                 return JSValueMakeNull(context);
386                     } else {
387                 eventId->setUId(event->getUId());
388                     }
389                 }
390         std::stringstream ss;
391         std::time_t rid = event->getRecurrenceId();
392         ss<<rid;
393         eventId->setRecurrenceId(ss.str());
394         return JSCalendarEventId::createJSCalendarEventId(context, eventId);
395     }
396     Catch(Exception)
397     {
398                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
399     }
400     return JSValueMakeUndefined(context);
401 }
402
403 JSValueRef JSCalendarEvent::getPropertyLastModificationDate(JSContextRef context,
404         JSObjectRef object,
405         JSStringRef propertyName,
406         JSValueRef* exception)
407 {
408     LogDebug("entered");
409     Try
410     {
411         CalendarEventPrivObject *privateObject =
412             static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
413         CalendarEventPtr event = privateObject->getObject();
414         if (!event) {
415             ThrowMsg(NullPointerException, "Event object is NULL.");
416         }
417
418         if (UNDEFINED_TIME==event->getLastModifiedDate()) {
419             return JSValueMakeNull(context);
420         } else {
421             TimeUtilConverter timeConverter(context);
422             return timeConverter.toJSValueRefTZDate((double)(event->getLastModifiedDate()*1000.0), event->getTimeZone());
423         }
424     }
425     Catch(Exception)
426     {
427                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
428     }
429     return JSValueMakeUndefined(context);
430 }
431
432 JSValueRef JSCalendarEvent::getPropertyIsDetached(JSContextRef context,
433         JSObjectRef object,
434         JSStringRef propertyName,
435         JSValueRef* exception)
436 {
437     LogDebug("entered");
438     Try
439     {
440         CalendarEventPtr event = getPrivateObject(object);
441         if(CalendarEvent::EVENT_TYPE != event->getCalendarType()) {
442             return JSValueMakeUndefined(context);
443         }
444
445         Converter converter(context);
446         return converter.toJSValueRef(event->getIsDetached());
447     }
448     Catch(Exception)
449     {
450                 LogWarning("Exception: "<<_rethrown_exception.GetMessage());
451     }
452     return JSValueMakeUndefined(context);
453 }
454
455 bool JSCalendarEvent::validate(JSContextRef ctx,
456         const JSObjectRef object,
457         JSValueRef* exception)
458 {
459     LogDebug("entered");
460     CalendarEventPrivObject *priv =
461         static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
462     if (priv == NULL) {
463         return false;
464     }
465     CalendarEventPtr event = priv->getObject();
466     if (!event) {
467         return false;
468     }
469     return event->validate();
470 }
471
472 }
473 }
474 }