Update change log and spec for wrt-plugins-tizen_0.4.38
[framework/web/wrt-plugins-tizen.git] / src / TimeUtil / JSTimeDuration.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include <string>
19 #include <memory>
20 #include <cmath>
21 #include <Commons/Exception.h>
22 #include <CommonsJavaScript/Utils.h>
23 #include <CommonsJavaScript/JSCallbackManager.h>
24 #include <JSWebAPIErrorFactory.h>
25 #include "JSTimeDuration.h"
26 #include "TimeUtilConverter.h"
27 #include <Logger.h>
28
29 namespace DeviceAPI {
30 namespace Time {
31
32 using namespace DPL;
33 using namespace DeviceAPI::Common;
34 using namespace WrtDeviceApis::Commons;
35 using namespace WrtDeviceApis::CommonsJavaScript;
36
37 #define TIZEN_TIMEDURATION_LENGTH "length"
38 #define TIZEN_TIMEDURATION_UNIT "unit"
39
40 JSClassDefinition JSTimeDuration::m_classInfo = {
41     0,
42     kJSClassAttributeNone,
43     "TimeDuration",
44     0,
45     m_property,
46     m_function,
47     initialize,
48     finalize,
49     NULL, //HasProperty,
50     NULL, //GetProperty,
51     setProperty, //SetProperty,
52     NULL, //DeleteProperty,
53     NULL, //GetPropertyNames,
54     NULL, //CallAsFunction,
55     NULL, //CallAsConstructor,
56     NULL,
57     NULL, //ConvertToType
58 };
59
60
61 JSStaticFunction JSTimeDuration::m_function[] = {
62     {"difference",           JSTimeDuration::difference,            kJSPropertyAttributeNone},
63     {"equalsTo",           JSTimeDuration::equalsTo,            kJSPropertyAttributeNone},
64     {"lessThan",           JSTimeDuration::lessThan,            kJSPropertyAttributeNone},
65     {"greaterThan",           JSTimeDuration::greaterThan,            kJSPropertyAttributeNone},
66 };
67
68 JSStaticValue JSTimeDuration::m_property[] =
69 {
70     //TimdDurationProperties
71         {TIZEN_TIMEDURATION_LENGTH,  getProperty, setProperty, kJSPropertyAttributeNone},
72         {TIZEN_TIMEDURATION_UNIT,  getProperty, setProperty, kJSPropertyAttributeNone},
73         { 0, 0, 0, 0 }
74 };
75
76 const JSClassRef JSTimeDuration::getClassRef()
77 {
78     if (!m_jsClassRef) {
79         m_jsClassRef = JSClassCreate(&m_classInfo);
80     }
81     return m_jsClassRef;
82 }
83
84 const JSClassDefinition* JSTimeDuration::getClassInfo()
85 {
86     return &m_classInfo;
87 }
88
89 JSClassRef JSTimeDuration::m_jsClassRef = JSClassCreate(JSTimeDuration::getClassInfo());
90
91 void JSTimeDuration::initialize(JSContextRef context, JSObjectRef object)
92 {
93         LoggerD("entered Nothing to do.");
94 }
95
96 void JSTimeDuration::finalize(JSObjectRef object)
97 {
98         TimeDurationPrivObject* priv = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
99         JSObjectSetPrivate(object, NULL);
100         LoggerD("Deleting TimeDuration");
101         delete priv;
102 }
103
104 JSValueRef JSTimeDuration::getProperty(JSContextRef context, JSObjectRef object,
105         JSStringRef propertyName, JSValueRef* exception)
106 {
107         LoggerD("Enter");
108
109         Try     {
110                 TimeUtilConverter convert(context);
111
112                 LoggerD("propertyName : " << convert.toString(propertyName));
113                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_TIMEDURATION_LENGTH)) {
114                         return convert.toJSValueRef(static_cast<double>(convert.getDurationLength(object)));
115                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_TIMEDURATION_UNIT)) {
116                         std::string strUnit = convert.toDurationUnitString(convert.getDurationUnit(object));
117                         if (strUnit == "")
118                                 ThrowMsg(InvalidArgumentException, "unit string is invald.");
119                         return convert.toJSValueRef(strUnit);
120                 }
121         } Catch (ConversionException) {
122                 LoggerE("ConversionException: " << _rethrown_exception.GetMessage());
123         } Catch (InvalidArgumentException) {
124                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
125         } Catch (WrtDeviceApis::Commons::Exception) {
126                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
127         }
128         return JSValueMakeUndefined(context);
129 }
130
131 bool JSTimeDuration::setProperty(JSContextRef context, JSObjectRef object,
132         JSStringRef propertyName, JSValueRef value,  JSValueRef* exception)
133 {
134         LoggerD("Enter");
135
136         Try     {
137                 TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
138                 if (!privateObject) {
139                         LoggerE("Private object is not set.");
140                         ThrowMsg(NullPointerException, "Private object not initialized");
141                 }
142
143                 DurationPropertiesPtr duration = privateObject->getObject();
144                 TimeUtilConverter convert(context);
145
146                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_TIMEDURATION_LENGTH)) {
147                         duration->length = convert.toLongLong(value);
148                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_TIMEDURATION_UNIT)) {
149                         short unit = convert.toDurationUnit(convert.toString(value));
150                         if (unit == 0xff)
151                                 ThrowMsg(ConversionException, "property doesn't exist.");
152                         duration->unit = unit;
153                 } else
154                         return false;
155
156                 return true;
157         } Catch (NullPointerException) {
158                 LoggerE("NullPointerException: " << _rethrown_exception.GetMessage());
159                 *exception = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
160         } Catch (ConversionException) {
161                 LoggerE("ConversionException: " << _rethrown_exception.GetMessage());
162                 *exception = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
163         } Catch (InvalidArgumentException) {
164                 LoggerE("InvalidArgumentException: " << _rethrown_exception.GetMessage());
165                 *exception = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
166         } Catch (WrtDeviceApis::Commons::Exception) {
167                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
168                 *exception = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
169         }
170         return false;
171 }
172
173 JSObjectRef JSTimeDuration::createJSObject(JSContextRef context,
174         const DurationProperties &durations)
175 {
176     DurationPropertiesPtr durationProps(new DurationProperties(durations));
177     TimeDurationPrivObject *priv = new TimeDurationPrivObject(context, durationProps);
178
179     if (!priv) {
180         ThrowMsg(NullPointerException, "Can not new an object");
181     }
182     return JSObjectMake(context, getClassRef(), priv);
183 }
184
185 JSObjectRef JSTimeDuration::createJSObject(JSContextRef context,
186         const DurationPropertiesPtr duration)
187 {
188     TimeDurationPrivObject *priv = new TimeDurationPrivObject(context, duration);
189     if (!priv) {
190         ThrowMsg(NullPointerException, "Private object is null.");
191     }
192     return JSObjectMake(context, getClassRef(), priv);
193 }
194
195 JSObjectRef JSTimeDuration::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
196         LoggerD("entered");
197         TimeUtilConverter convert(ctx);
198         Try {
199                 DurationProperties duration;
200                 if (argumentCount == 0)
201                         duration.length = convert.toLongLong(JSValueMakeUndefined(ctx));
202                 else
203                         duration.length = convert.toLongLong(arguments[0]);
204
205                 if (argumentCount > 1) {
206                         if (!JSValueIsUndefined(ctx, arguments[1]) && !JSValueIsNull(ctx, arguments[1])) {
207                                 std::string unit = convert.toString(arguments[1]);
208                                 duration.unit = convert.toDurationUnit(unit);
209                                 if (duration.unit == 0xff)
210                                         ThrowMsg(ConversionException, "Argument(unit) is invalid(wrong type unit)");
211                         }
212                 }
213                 JSObjectRef timeDuration = createJSObject(ctx, duration);
214                 if (timeDuration) {
215                         JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
216                     JSObjectSetProperty(ctx, timeDuration, ctorName, constructor,
217                         kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
218                 JSStringRelease(ctorName);
219                         return timeDuration;
220                 }
221         } Catch(NullPointerException) {
222                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
223                 return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
224         } Catch(WrtDeviceApis::Commons::UnknownException) {
225                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
226                 return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
227         } Catch(ConversionException) {
228                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
229                 return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
230         } Catch (InvalidArgumentException) {
231                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
232                 return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
233         } Catch (WrtDeviceApis::Commons::Exception) {
234             LoggerW("Trying to get incorrect value");
235         }
236         return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
237 }
238
239 JSValueRef JSTimeDuration::diffTimeDuration(JSContextRef context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception, CompareType type) {
240         LoggerD("entered");
241
242         TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(thisObject));
243         if (!privateObject) {
244                 LoggerE("Private object is not set.");
245                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
246         }
247
248         TimeUtilConverter converter(context);
249
250         DurationProperties first = converter.getDurationProperties(thisObject);
251         DurationProperties second;
252         if (argumentCount == 0)
253                 second= converter.getDurationProperties(JSValueMakeUndefined(context));
254         else
255                 second= converter.getDurationProperties(arguments[0]);
256
257         DurationProperties diff;
258         if (first.unit > second.unit) {
259                 long long firstLength = converter.convertDurationLength(first, second.unit);
260                 diff.unit = second.unit;
261                 diff.length = firstLength - second.length;
262         } else {
263                 long long secondLength = converter.convertDurationLength(second, first.unit);
264                 diff.unit = first.unit;
265                 diff.length = first.length - secondLength;
266         }
267
268         switch (type) {
269                 case EQUALSTO:
270                 {
271                         if (diff.length == 0)
272                                 return converter.toJSValueRef(true);
273                         else
274                                 return converter.toJSValueRef(false);
275                 }
276                 case LESSTHAN:
277                 {
278                         if (diff.length < 0)
279                                 return converter.toJSValueRef(true);
280                         else
281                                 return converter.toJSValueRef(false);
282                 }
283                 case GREATERTHAN:
284                 {
285                         if (diff.length > 0)
286                                 return converter.toJSValueRef(true);
287                         else
288                                 return converter.toJSValueRef(false);
289                 }
290                 case DIFFERENCE:
291                 default:
292                         return converter.makeDurationObject(diff);
293         }
294 }
295
296 JSValueRef JSTimeDuration::difference(JSContextRef context, JSObjectRef function, 
297         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
298         LoggerD("Entered");
299         Try {
300                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, DIFFERENCE);
301         } Catch(ConversionException) {
302                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
303                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
304         } Catch (InvalidArgumentException) {
305                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
306                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
307         } Catch (UnsupportedException) {
308                 LoggerE("JSTimeUtil::hasInstance NotSupportedException");
309                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR , "Not Support");
310         } Catch (PlatformException) {
311                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
312         } Catch (WrtDeviceApis::Commons::Exception) {
313                 LoggerE("Exception: " << _rethrown_exception.GetMessage());             
314         }
315         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
316 }
317
318 JSValueRef JSTimeDuration::equalsTo(JSContextRef context, JSObjectRef function, 
319         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
320         LoggerD("Entered");
321         Try {
322                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, EQUALSTO);
323         } Catch(ConversionException) {
324                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
325                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
326         } Catch (InvalidArgumentException) {
327                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
328                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
329         } Catch (UnsupportedException) {
330                 LoggerE("JSTimeUtil::hasInstance NotSupportedException");
331                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR , "Not Support");
332         } Catch (PlatformException) {
333                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
334         } Catch (WrtDeviceApis::Commons::Exception) {
335                 LoggerE("Exception: " << _rethrown_exception.GetMessage());                     
336         }
337         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
338 }
339
340 JSValueRef JSTimeDuration::lessThan(JSContextRef context, JSObjectRef function, 
341         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
342         LoggerD("Entered");
343         Try {
344                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, LESSTHAN);
345         } Catch(ConversionException) {
346                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
347                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
348         } Catch (InvalidArgumentException) {
349                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
350                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
351         } Catch (UnsupportedException) {
352                 LoggerE("JSTimeUtil::hasInstance NotSupportedException");
353                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR , "Not Support");
354         } Catch (PlatformException) {
355                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
356         } Catch (WrtDeviceApis::Commons::Exception) {
357                 LoggerE("Exception: " << _rethrown_exception.GetMessage());             
358         }
359         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
360 }
361
362 JSValueRef JSTimeDuration::greaterThan(JSContextRef context, JSObjectRef function, 
363         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
364         LoggerD("Entered");
365         Try {
366                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, GREATERTHAN);
367         } Catch(ConversionException) {
368                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
369                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
370         } Catch (InvalidArgumentException) {
371                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
372                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
373         } Catch (UnsupportedException) {
374                 LoggerE("JSTimeUtil::hasInstance NotSupportedException");
375                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR , "Not Support");
376         } Catch (PlatformException) {
377                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
378         } Catch (WrtDeviceApis::Commons::Exception) {
379                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
380         }
381         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
382 }
383
384 } //Time
385 } //DeviceAPI