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