bc624483f3590fe37581c6843467e055e90de520
[profile/ivi/wrt-plugins-tizen.git] / src / standards / Tizen / TimeUtil / JSTimeDuration.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 <string>
19 #include <memory>
20 #include <dpl/log/log.h>
21 #include <cmath>
22 #include <Commons/Exception.h>
23 #include <CommonsJavaScript/Utils.h>
24 #include <CommonsJavaScript/JSCallbackManager.h>
25 #include <Tizen/Common/JSTizenExceptionFactory.h>
26 #include <Tizen/Common/JSTizenException.h>
27
28 #include <API/TimeUtil/TimeUtilFactory.h>
29
30 #include "JSTimeDuration.h"
31 #include "TimeUtilConverter.h"
32 #include "plugin_config.h"
33
34 namespace TizenApis {
35 namespace Tizen1_0 {
36
37 using namespace DPL;
38 using namespace TizenApis::Commons;
39 using namespace TizenApis::Api::TimeUtil;
40 using namespace WrtDeviceApis::Commons;
41 using namespace WrtDeviceApis::CommonsJavaScript;
42
43 #define TIZEN10_TIMEDURATION_LENGTH "length"
44 #define TIZEN10_TIMEDURATION_UNIT "unit"
45
46 JSClassDefinition JSTimeDuration::m_classInfo = {
47     0,
48     kJSClassAttributeNone,
49     "TimeDuration",
50     0,
51     m_property,
52     m_function,
53     initialize,
54     finalize,
55     NULL, //HasProperty,
56     NULL, //GetProperty,
57     setProperty, //SetProperty,
58     NULL, //DeleteProperty,
59     NULL, //GetPropertyNames,
60     NULL, //CallAsFunction,
61     constructor, //CallAsConstructor,
62     hasInstance,
63     NULL, //ConvertToType
64 };
65
66
67 JSStaticFunction JSTimeDuration::m_function[] = {
68     {"difference",           JSTimeDuration::difference,            kJSPropertyAttributeNone},
69     {"equalsTo",           JSTimeDuration::equalsTo,            kJSPropertyAttributeNone},
70     {"lessThan",           JSTimeDuration::lessThan,            kJSPropertyAttributeNone},
71     {"greaterThan",           JSTimeDuration::greaterThan,            kJSPropertyAttributeNone},
72 };
73
74 JSStaticValue JSTimeDuration::m_property[] =
75 {
76     //TimdDurationProperties
77         {TIZEN10_TIMEDURATION_LENGTH,  getProperty, setProperty, kJSPropertyAttributeNone},
78         {TIZEN10_TIMEDURATION_UNIT,  getProperty, setProperty, kJSPropertyAttributeNone},
79         { 0, 0, 0, 0 }
80 };
81
82 const JSClassRef JSTimeDuration::getClassRef()
83 {
84     if (!m_jsClassRef) {
85         m_jsClassRef = JSClassCreate(&m_classInfo);
86     }
87     return m_jsClassRef;
88 }
89
90 const JSClassDefinition* JSTimeDuration::getClassInfo()
91 {
92     return &m_classInfo;
93 }
94
95 JSClassRef JSTimeDuration::m_jsClassRef = JSClassCreate(JSTimeDuration::getClassInfo());
96
97 void JSTimeDuration::initialize(JSContextRef context, JSObjectRef object)
98 {
99         LogDebug("entered Nothing to do.");
100
101         if (!JSObjectGetPrivate(object)) {
102                 LogDebug("Private object not set... setting it.");
103                 DurationProperties durations;
104                 DurationPropertiesPtr durationProps(new DurationProperties(durations));
105                 TimeDurationPrivObject *priv = new TimeDurationPrivObject(context, durationProps);
106
107                 if (!JSObjectSetPrivate(object, priv)) {
108                         delete priv;
109                 }
110         }
111 }
112
113 void JSTimeDuration::finalize(JSObjectRef object)
114 {
115         TimeDurationPrivObject* priv = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
116         JSObjectSetPrivate(object, NULL);
117         LogDebug("Deleting TimeDuration");
118         delete priv;
119 }
120
121 JSValueRef JSTimeDuration::getProperty(JSContextRef context, JSObjectRef object,
122         JSStringRef propertyName, JSValueRef* exception)
123 {
124         LogDebug("Enter");
125
126         Try     {
127                 TimeUtilConverter convert(context);
128
129                 LogDebug("propertyName : " << convert.toString(propertyName));
130                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN10_TIMEDURATION_LENGTH)) {
131                         return convert.toJSValueRef(static_cast<double>(convert.getDurationLength(object)));
132                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN10_TIMEDURATION_UNIT)) {
133                         std::string strUnit = convert.toDurationUnitString(convert.getDurationUnit(object));
134                         if (strUnit == "")
135                                 ThrowMsg(InvalidArgumentException, "unit string is invald.");
136                         return convert.toJSValueRef(strUnit);
137                 }
138         } Catch (ConversionException) {
139                 LogError("ConversionException: " << _rethrown_exception.GetMessage());
140         } Catch (InvalidArgumentException) {
141                 LogError("Exception: " << _rethrown_exception.GetMessage());
142         } Catch (WrtDeviceApis::Commons::Exception) {
143                 LogError("Exception: " << _rethrown_exception.GetMessage());
144         }
145         return JSValueMakeUndefined(context);
146 }
147
148 bool JSTimeDuration::setProperty(JSContextRef context, JSObjectRef object,
149         JSStringRef propertyName, JSValueRef value,  JSValueRef* exception)
150 {
151         LogDebug("Enter");
152
153         Try     {
154                 TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
155                 if (!privateObject) {
156                         LogError("Private object is not set.");
157                         ThrowMsg(NullPointerException, "Private object not initialized");
158                 }
159
160                 DurationPropertiesPtr duration = privateObject->getObject();
161                 TimeUtilConverter convert(context);
162
163                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN10_TIMEDURATION_LENGTH)) {
164                         duration->length = static_cast<long long>(convert.toDouble(value));
165                         if (std::isnan(duration->length)  || std::isinf(duration->length))
166                                 duration->length = 0;
167                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN10_TIMEDURATION_UNIT)) {
168                         short unit = convert.toDurationUnit(convert.toString(value));
169                         if (unit == 0xff)
170                                 ThrowMsg(ConversionException, "property doesn't exist.");
171                         duration->unit = unit;
172                 } else
173                         return false;
174
175                 return true;
176         } Catch (NullPointerException) {
177                 LogError("NullPointerException: " << _rethrown_exception.GetMessage());
178                 *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
179         } Catch (ConversionException) {
180                 LogError("ConversionException: " << _rethrown_exception.GetMessage());
181                 *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
182         } Catch (InvalidArgumentException) {
183                 LogError("InvalidArgumentException: " << _rethrown_exception.GetMessage());
184                 *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::INVALID_VALUES_ERROR, "Invalid Values");
185         } Catch (WrtDeviceApis::Commons::Exception) {
186                 LogError("Exception: " << _rethrown_exception.GetMessage());
187                 *exception = JSTizenExceptionFactory::makeErrorObject(context, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
188         }
189         return false;
190 }
191
192 JSObjectRef JSTimeDuration::createJSObject(JSContextRef context,
193         const DurationProperties &durations)
194 {
195     DurationPropertiesPtr durationProps(new DurationProperties(durations));
196     TimeDurationPrivObject *priv = new TimeDurationPrivObject(context, durationProps);
197
198     if (!priv) {
199         ThrowMsg(NullPointerException, "Can not new an object");
200     }
201     return JSObjectMake(context, getClassRef(), priv);
202 }
203
204 JSObjectRef JSTimeDuration::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
205         LogDebug("entered");
206         TimeUtilConverter convert(ctx);
207         Try {
208                 TimeDurationPrivObject* mainPriv = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(constructor));
209                 JSContextRef global_context = mainPriv ? mainPriv->getContext() : ctx;
210
211                 DurationProperties duration;
212                 if (argumentCount == 0)
213                         duration.length = convert.toDouble(JSValueMakeUndefined(ctx));
214                 else
215                         duration.length = convert.toDouble(arguments[0]);
216
217                 if (std::isnan(duration.length) || std::isinf(duration.length))
218                         duration.length = 0;
219
220                 if (argumentCount > 1) {
221                         if (!JSValueIsUndefined(ctx, arguments[1]) && !JSValueIsNull(ctx, arguments[1])) {
222                                 std::string unit = convert.toString(arguments[1]);
223                                 duration.unit = convert.toDurationUnit(unit);
224                                 if (duration.unit == 0xff)
225                                         ThrowMsg(ConversionException, "Argument(unit) is invalid(wrong type unit)");
226                         }
227                 }
228                 return createJSObject(ctx, duration);
229         } Catch(NullPointerException) {
230                 LogError("Exception: " << _rethrown_exception.GetMessage());
231                 *exception = JSTizenExceptionFactory::makeErrorObject(ctx, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
232                 return NULL;
233         } Catch(UnknownException) {
234                 LogError("Exception: " << _rethrown_exception.GetMessage());
235                 *exception = JSTizenExceptionFactory::makeErrorObject(ctx, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
236                 return NULL;
237         } Catch(ConversionException) {
238                 LogError("Exception: " << _rethrown_exception.GetMessage());
239                 *exception = JSTizenExceptionFactory::makeErrorObject(ctx, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
240                 return NULL;
241         } Catch (InvalidArgumentException) {
242                 LogError("Exception: " << _rethrown_exception.GetMessage());
243                 *exception = JSTizenExceptionFactory::makeErrorObject(ctx, JSTizenException::INVALID_VALUES_ERROR, "Invalid Values");
244                 return NULL;
245         } Catch (WrtDeviceApis::Commons::Exception) {
246             LogWarning("Trying to get incorrect value");
247         }
248         *exception = JSTizenExceptionFactory::makeErrorObject(ctx, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
249         return NULL;
250 }
251
252 bool JSTimeDuration::hasInstance(JSContextRef context,
253         JSObjectRef constructor,
254         JSValueRef possibleInstance,
255         JSValueRef* exception)
256 {
257     return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
258 }
259
260 JSValueRef JSTimeDuration::diffTimeDuration(JSContextRef context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception, CompareType type) {
261         LogDebug("entered");
262
263         AceSecurityStatus status = TIMEUTIL_CHECK_ACCESS(
264                 TIMEUTIL_FUNCTION_API_READ_FUNCS);
265         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
266
267         TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(thisObject));
268         if (!privateObject) {
269                 LogError("Private object is not set.");
270                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
271         }
272
273         TimeUtilConverter converter(context);
274
275         DurationProperties first = converter.getDurationPropertis(thisObject);
276         DurationProperties second;
277         if (argumentCount == 0)
278                 second= converter.getDurationPropertis(JSValueMakeUndefined(context));
279         else
280                 second= converter.getDurationPropertis(arguments[0]);
281
282         DurationProperties diff;
283         if (first.unit > second.unit) {
284                 long long firstLength = converter.convertDurationLength(first, second.unit);
285                 diff.unit = second.unit;
286                 diff.length = firstLength - second.length;
287         } else {
288                 long long secondLength = converter.convertDurationLength(second, first.unit);
289                 diff.unit = first.unit;
290                 diff.length = first.length - secondLength;
291         }
292
293         switch (type) {
294                 case EQUALSTO:
295                 {
296                         if (diff.length == 0)
297                                 return converter.toJSValueRef(TRUE);
298                         else
299                                 return converter.toJSValueRef(FALSE);
300                 }
301                 case LESSTHAN:
302                 {
303                         if (diff.length < 0)
304                                 return converter.toJSValueRef(TRUE);
305                         else
306                                 return converter.toJSValueRef(FALSE);
307                 }
308                 case GREATERTHAN:
309                 {
310                         if (diff.length > 0)
311                                 return converter.toJSValueRef(TRUE);
312                         else
313                                 return converter.toJSValueRef(FALSE);
314                 }
315                 case DIFFERENCE:
316                 default:
317                         return converter.makeDurationObject(diff);
318         }
319 }
320
321 JSValueRef JSTimeDuration::difference(JSContextRef context, JSObjectRef function, 
322         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
323         LogDebug("Entered");
324         Try {
325                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, DIFFERENCE);
326         } Catch(ConversionException) {
327                 LogError("Exception: " << _rethrown_exception.GetMessage());
328                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
329         } Catch (InvalidArgumentException) {
330                 LogError("Exception: " << _rethrown_exception.GetMessage());
331                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Invalid Values");
332         } Catch (UnsupportedException) {
333                 LogError("JSTimeUtil::hasInstance NotSupportedException");
334                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR , "Not Support");
335         } Catch (PlatformException) {
336                 LogError("Exception: " << _rethrown_exception.GetMessage());
337                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
338         } Catch (WrtDeviceApis::Commons::Exception) {
339                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");                    
340         }
341         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
342 }
343
344 JSValueRef JSTimeDuration::equalsTo(JSContextRef context, JSObjectRef function, 
345         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
346         LogDebug("Entered");
347         Try {
348                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, EQUALSTO);
349         } Catch(ConversionException) {
350                 LogError("Exception: " << _rethrown_exception.GetMessage());
351                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
352         } Catch (InvalidArgumentException) {
353                 LogError("Exception: " << _rethrown_exception.GetMessage());
354                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Invalid Values");
355         } Catch (UnsupportedException) {
356                 LogError("JSTimeUtil::hasInstance NotSupportedException");
357                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR , "Not Support");
358         } Catch (PlatformException) {
359                 LogError("Exception: " << _rethrown_exception.GetMessage());
360                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
361         } Catch (WrtDeviceApis::Commons::Exception) {
362                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");                    
363         }
364         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
365 }
366
367 JSValueRef JSTimeDuration::lessThan(JSContextRef context, JSObjectRef function, 
368         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
369         LogDebug("Entered");
370         Try {
371                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, LESSTHAN);
372         } Catch(ConversionException) {
373                 LogError("Exception: " << _rethrown_exception.GetMessage());
374                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
375         } Catch (InvalidArgumentException) {
376                 LogError("Exception: " << _rethrown_exception.GetMessage());
377                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Invalid Values");
378         } Catch (UnsupportedException) {
379                 LogError("JSTimeUtil::hasInstance NotSupportedException");
380                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR , "Not Support");
381         } Catch (PlatformException) {
382                 LogError("Exception: " << _rethrown_exception.GetMessage());
383                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
384         } Catch (WrtDeviceApis::Commons::Exception) {
385                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");                    
386         }
387         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
388 }
389
390 JSValueRef JSTimeDuration::greaterThan(JSContextRef context, JSObjectRef function, 
391         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
392         LogDebug("Entered");
393         Try {
394                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, GREATERTHAN);
395         } Catch(ConversionException) {
396                 LogError("Exception: " << _rethrown_exception.GetMessage());
397                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type Mismatch");
398         } Catch (InvalidArgumentException) {
399                 LogError("Exception: " << _rethrown_exception.GetMessage());
400                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::INVALID_VALUES_ERROR, "Invalid Values");
401         } Catch (UnsupportedException) {
402                 LogError("JSTimeUtil::hasInstance NotSupportedException");
403                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::NOT_SUPPORTED_ERROR , "Not Support");
404         } Catch (PlatformException) {
405                 LogError("Exception: " << _rethrown_exception.GetMessage());
406                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
407         } Catch (WrtDeviceApis::Commons::Exception) {
408                 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");                    
409         }
410         return JSTizenExceptionFactory::postException(context, exception, JSTizenException::UNKNOWN_ERROR, "Unknown Error");
411 }
412
413 } //Tizen1_0
414 } //TizenApis