Update change log and spec for wrt-plugins-tizen_0.4.52
[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                         std::string strUnit = convert.toDurationUnitString(convert.getDurationUnit(object));
118                         if (strUnit == "")
119                                 ThrowMsg(InvalidArgumentException, "unit string is invald.");
120                         return convert.toJSValueRef(strUnit);
121                 }
122         } Catch (ConversionException) {
123                 LoggerE("ConversionException: " << _rethrown_exception.GetMessage());
124         } Catch (InvalidArgumentException) {
125                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
126         } Catch (WrtDeviceApis::Commons::Exception) {
127                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
128         }
129         return JSValueMakeUndefined(context);
130 }
131
132 bool JSTimeDuration::setProperty(JSContextRef context, JSObjectRef object,
133         JSStringRef propertyName, JSValueRef value,  JSValueRef* exception)
134 {
135         LoggerD("Enter");
136
137         Try     {
138                 TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
139                 if (!privateObject) {
140                         LoggerE("Private object is not set.");
141                         ThrowMsg(NullPointerException, "Private object not initialized");
142                 }
143
144                 DurationPropertiesPtr duration = privateObject->getObject();
145                 TimeUtilConverter convert(context);
146
147                 if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_TIMEDURATION_LENGTH)) {
148                         duration->length = convert.toLongLong(value);
149                 } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_TIMEDURATION_UNIT)) {
150                         short unit = convert.toDurationUnit(convert.toString(value));
151                         if (unit == 0xff)
152                                 ThrowMsg(ConversionException, "property doesn't exist.");
153                         duration->unit = unit;
154                 } else
155                         return false;
156
157                 return true;
158         } Catch (NullPointerException) {
159                 LoggerE("NullPointerException: " << _rethrown_exception.GetMessage());
160                 *exception = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
161         } Catch (ConversionException) {
162                 LoggerE("ConversionException: " << _rethrown_exception.GetMessage());
163                 *exception = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
164         } Catch (InvalidArgumentException) {
165                 LoggerE("InvalidArgumentException: " << _rethrown_exception.GetMessage());
166                 *exception = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
167         } Catch (WrtDeviceApis::Commons::Exception) {
168                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
169                 *exception = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
170         }
171         return false;
172 }
173
174 JSObjectRef JSTimeDuration::createJSObject(JSContextRef context,
175         const DurationProperties &durations)
176 {
177     DurationPropertiesPtr durationProps(new DurationProperties(durations));
178     TimeDurationPrivObject *priv = new TimeDurationPrivObject(context, durationProps);
179
180     if (!priv) {
181         ThrowMsg(NullPointerException, "Can not new an object");
182     }
183     return JSObjectMake(context, getClassRef(), priv);
184 }
185
186 JSObjectRef JSTimeDuration::createJSObject(JSContextRef context,
187         const DurationPropertiesPtr duration)
188 {
189     TimeDurationPrivObject *priv = new TimeDurationPrivObject(context, duration);
190     if (!priv) {
191         ThrowMsg(NullPointerException, "Private object is null.");
192     }
193     return JSObjectMake(context, getClassRef(), priv);
194 }
195
196 JSObjectRef JSTimeDuration::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
197         LoggerD("entered");
198         TimeUtilConverter convert(ctx);
199         Try {
200                 DurationProperties duration;
201                 if (argumentCount == 0)
202                         duration.length = convert.toLongLong(JSValueMakeUndefined(ctx));
203                 else
204                         duration.length = convert.toLongLong(arguments[0]);
205
206                 if (argumentCount > 1) {
207                         if (!JSValueIsUndefined(ctx, arguments[1]) && !JSValueIsNull(ctx, arguments[1])) {
208                                 std::string unit = convert.toString(arguments[1]);
209                                 duration.unit = convert.toDurationUnit(unit);
210                                 if (duration.unit == 0xff)
211                                         ThrowMsg(ConversionException, "Argument(unit) is invalid(wrong type unit)");
212                         }
213                 }
214                 JSObjectRef timeDuration = createJSObject(ctx, duration);
215                 if (timeDuration) {
216                         JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
217                     JSObjectSetProperty(ctx, timeDuration, ctorName, constructor,
218                         kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
219                 JSStringRelease(ctorName);
220                         return timeDuration;
221                 }
222         } Catch(NullPointerException) {
223                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
224                 return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
225         } Catch(WrtDeviceApis::Commons::UnknownException) {
226                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
227                 return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
228         } Catch(ConversionException) {
229                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
230                 return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
231         } Catch (InvalidArgumentException) {
232                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
233                 return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
234         } Catch (WrtDeviceApis::Commons::Exception) {
235             LoggerW("Trying to get incorrect value");
236         }
237         return JSWebAPIErrorFactory::postException(ctx, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
238 }
239
240 JSValueRef JSTimeDuration::diffTimeDuration(JSContextRef context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception, CompareType type) {
241         LoggerD("entered");
242
243         TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(thisObject));
244         if (!privateObject) {
245                 LoggerE("Private object is not set.");
246                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
247         }
248
249         TimeUtilConverter converter(context);
250
251         DurationProperties first = converter.getDurationProperties(thisObject);
252         DurationProperties second;
253         if (argumentCount == 0)
254                 second= converter.getDurationProperties(JSValueMakeUndefined(context));
255         else
256                 second= converter.getDurationProperties(arguments[0]);
257
258         DurationProperties diff;
259         if (first.unit > second.unit) {
260                 long long firstLength = converter.convertDurationLength(first, second.unit);
261                 diff.unit = second.unit;
262                 diff.length = firstLength - second.length;
263         } else {
264                 long long secondLength = converter.convertDurationLength(second, first.unit);
265                 diff.unit = first.unit;
266                 diff.length = first.length - secondLength;
267         }
268
269         switch (type) {
270                 case EQUALSTO:
271                 {
272                         if (diff.length == 0)
273                                 return converter.toJSValueRef(true);
274                         else
275                                 return converter.toJSValueRef(false);
276                 }
277                 case LESSTHAN:
278                 {
279                         if (diff.length < 0)
280                                 return converter.toJSValueRef(true);
281                         else
282                                 return converter.toJSValueRef(false);
283                 }
284                 case GREATERTHAN:
285                 {
286                         if (diff.length > 0)
287                                 return converter.toJSValueRef(true);
288                         else
289                                 return converter.toJSValueRef(false);
290                 }
291                 case DIFFERENCE:
292                 default:
293                         return converter.makeDurationObject(converter.optimizedTimeDuration(diff));
294         }
295 }
296
297 JSValueRef JSTimeDuration::difference(JSContextRef context, JSObjectRef function, 
298         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
299         LoggerD("Entered");
300         Try {
301                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, DIFFERENCE);
302         } Catch(ConversionException) {
303                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
304                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
305         } Catch (InvalidArgumentException) {
306                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
307                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
308         } Catch (UnsupportedException) {
309                 LoggerE("JSTimeUtil::hasInstance NotSupportedException");
310                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR , "Not Support");
311         } Catch (PlatformException) {
312                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
313         } Catch (WrtDeviceApis::Commons::Exception) {
314                 LoggerE("Exception: " << _rethrown_exception.GetMessage());             
315         }
316         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
317 }
318
319 JSValueRef JSTimeDuration::equalsTo(JSContextRef context, JSObjectRef function, 
320         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
321         LoggerD("Entered");
322         Try {
323                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, EQUALSTO);
324         } Catch(ConversionException) {
325                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
326                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
327         } Catch (InvalidArgumentException) {
328                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
329                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
330         } Catch (UnsupportedException) {
331                 LoggerE("JSTimeUtil::hasInstance NotSupportedException");
332                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR , "Not Support");
333         } Catch (PlatformException) {
334                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
335         } Catch (WrtDeviceApis::Commons::Exception) {
336                 LoggerE("Exception: " << _rethrown_exception.GetMessage());                     
337         }
338         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
339 }
340
341 JSValueRef JSTimeDuration::lessThan(JSContextRef context, JSObjectRef function, 
342         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
343         LoggerD("Entered");
344         Try {
345                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, LESSTHAN);
346         } Catch(ConversionException) {
347                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
348                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
349         } Catch (InvalidArgumentException) {
350                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
351                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
352         } Catch (UnsupportedException) {
353                 LoggerE("JSTimeUtil::hasInstance NotSupportedException");
354                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR , "Not Support");
355         } Catch (PlatformException) {
356                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
357         } Catch (WrtDeviceApis::Commons::Exception) {
358                 LoggerE("Exception: " << _rethrown_exception.GetMessage());             
359         }
360         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
361 }
362
363 JSValueRef JSTimeDuration::greaterThan(JSContextRef context, JSObjectRef function, 
364         JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception) {
365         LoggerD("Entered");
366         Try {
367                 return diffTimeDuration(context, thisObject, argumentCount, arguments, exception, GREATERTHAN);
368         } Catch(ConversionException) {
369                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
370                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type Mismatch");
371         } Catch (InvalidArgumentException) {
372                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
373                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid Values");
374         } Catch (UnsupportedException) {
375                 LoggerE("JSTimeUtil::hasInstance NotSupportedException");
376                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR , "Not Support");
377         } Catch (PlatformException) {
378                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
379         } Catch (WrtDeviceApis::Commons::Exception) {
380                 LoggerE("Exception: " << _rethrown_exception.GetMessage());
381         }
382         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
383 }
384
385 } //Time
386 } //DeviceAPI