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