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