9e4a19de4397a3b1cf2209ffdf2e1b9a34149f2f
[framework/web/wrt-plugins-tizen.git] / src / Tizen / AnyFactory.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  * @file        AnyType.cpp
20  * @author      Kisub Song (kisubs.song@samsung.com)
21  * @version     0.1
22  * @brief       Declaration of the JSFilter class
23  */
24
25 #include "AnyFactory.h"
26 #include <string.h>
27 #include <locale.h>
28 #include <Commons/Exception.h>
29 #include <PlatformException.h>
30 #include <JSUtil.h>
31 #include <sstream>
32 #include <Logger.h>
33
34 namespace DeviceAPI {
35 namespace Tizen {
36
37 using namespace DeviceAPI::Common;
38
39 class PrivateAny : public Any
40 {
41 public:
42         PrivateAny();
43         PrivateAny(JSContextRef context, const JSValueRef value, PrimitiveType type);
44         virtual ~PrivateAny();
45
46 private:
47         bool isDate(JSContextRef jsContext, JSValueRef jsValue) const;
48         std::tm *toDateTm(time_t time) const;
49         std::string toJSON(JSContextRef jsContext, JSValueRef jsValue) const;
50         std::string toString(JSContextRef jsContext, JSValueRef jsValue) const;
51 };
52
53 PrivateAny::PrivateAny() : Any()
54 {
55         m_isNullOrUndefined = true;
56         m_type = PrimitiveType_Null;
57         m_json = "null";
58         m_str = "null";
59 }
60
61 PrivateAny::PrivateAny(JSContextRef context, const JSValueRef value, PrimitiveType type) : Any()
62 {
63         m_type = type;
64
65         if(type == PrimitiveType_NoType)
66                 throw UnknownException("Cannot create any with NoType");
67
68         if(JSValueIsUndefined(context, value) || JSValueIsNull(context, value))
69                 m_isNullOrUndefined = true;
70
71         try
72         {
73                 if(type == PrimitiveType_Boolean)
74                         m_value.b = JSUtil::JSValueToBoolean(context, value);
75                 else if(type == PrimitiveType_Long)
76                         m_value.l = JSUtil::JSValueToLong(context, value);
77                 else if(type == PrimitiveType_ULong)
78                         m_value.ul = JSUtil::JSValueToULong(context, value);
79                 else if(type == PrimitiveType_LongLong)
80                         m_value.ll = JSUtil::JSValueToLongLong(context, value);
81                 else if(type == PrimitiveType_ULongLong)
82                         m_value.ull = JSUtil::JSValueToULongLong(context, value);
83                 else if(type == PrimitiveType_Double)
84                         m_value.d = JSUtil::JSValueToDouble(context, value);
85                 else if(type == PrimitiveType_String)
86                 {
87                         m_value.str = new std::string();
88                         *m_value.str = JSUtil::JSValueToString(context, value);
89                 }
90                 else if(type == PrimitiveType_Time)
91                         m_value.t = toDateTm(JSUtil::JSValueToTimeT(context, value));
92         }
93         catch(BasePlatformException &e)
94         {
95                 if(!m_isNullOrUndefined)
96                 {
97                         throw e;
98                 }
99
100                 m_type = PrimitiveType_Null;
101                 m_json = "null";
102         }
103
104         if(m_json.empty())
105                 m_json = toJSON(context, value);
106
107         m_str = toString(context, value);
108 }
109
110 PrivateAny::~PrivateAny()
111 {
112         if(m_type == PrimitiveType_String)
113         {
114                 if(m_value.str != NULL)
115                         delete m_value.str;
116         }
117         else if(m_type == PrimitiveType_Time)
118         {
119                 if(m_value.t != NULL)
120                         delete m_value.t;
121         }
122 }
123
124 bool PrivateAny::isDate(JSContextRef jsContext, JSValueRef jsValue) const
125 {
126         JSObjectRef jsObjectGlobal = JSContextGetGlobalObject(jsContext);
127         JSStringRef jsStringDate = JSStringCreateWithUTF8CString("Date");
128         JSValueRef jsValueDate = JSObjectGetProperty(jsContext, jsObjectGlobal, jsStringDate, NULL);
129         JSStringRelease(jsStringDate);
130
131         JSObjectRef jsObjectDate = JSValueToObject(jsContext, jsValueDate, NULL);
132
133         return JSValueIsInstanceOfConstructor(jsContext, jsValue, jsObjectDate, NULL);
134 }
135
136 std::tm * PrivateAny::toDateTm(time_t time) const
137 {
138         char* currentLocale = setlocale(LC_TIME, NULL);
139         if (currentLocale == NULL)
140                 throw UnknownException("Fail to get current locale");
141         char* currentLocaleDup = strdup(currentLocale);
142         if (currentLocaleDup == NULL)
143                 throw UnknownException("Fail to dup current locale");
144         if (setlocale(LC_TIME, "C") == NULL)
145                 throw UnknownException("Fail to set locale");
146
147         std::tm *timeTm = new std::tm;
148         memcpy(timeTm, localtime(&time), sizeof(std::tm));
149
150         if (setlocale(LC_TIME, currentLocaleDup) == NULL)
151                 throw UnknownException("Fail to set locale");
152
153         free(currentLocaleDup);
154
155         return timeTm;
156 }
157
158 std::string PrivateAny::toJSON(JSContextRef context, JSValueRef value) const
159 {
160         JSValueRef jsError = NULL;
161         JSStringRef jsStrJson = JSValueCreateJSONString(context, value, 0, &jsError);
162         if(jsError != NULL || jsStrJson == NULL)
163         {
164                 LoggerE("Fail to create JSON string");
165                 return std::string("");
166         }
167
168         std::string result = JSUtil::JSStringToString(context, jsStrJson);
169         JSStringRelease(jsStrJson);
170
171         return result;
172 }
173
174 std::string PrivateAny::toString(JSContextRef context, JSValueRef value) const
175 {
176         std::string result;
177
178         if(m_type == PrimitiveType_String)
179         {
180                 result = *m_value.str;
181         }
182         else if(m_type == PrimitiveType_Long ||
183                         m_type == PrimitiveType_ULong ||
184                         m_type == PrimitiveType_LongLong ||
185                         m_type == PrimitiveType_ULongLong)
186         {
187                 std::stringstream ss;
188
189                 if(m_type == PrimitiveType_Long)
190                         ss << m_value.l;
191                 else if(m_type == PrimitiveType_ULong)
192                         ss << m_value.ul;
193                 else if(m_type == PrimitiveType_LongLong)
194                         ss << m_value.ll;
195                 else if(m_type == PrimitiveType_ULongLong)
196                         ss << m_value.ull;
197
198                 result = ss.str();
199         }
200         else
201         {
202                 JSValueRef jsError = NULL;
203                 JSStringRef jsStrJson = JSValueToStringCopy(context, value, &jsError);
204                 if(jsError == NULL && jsStrJson != NULL)
205                 {
206                         result = JSUtil::JSStringToString(context, jsStrJson);
207                         JSStringRelease(jsStrJson);
208                 }
209         }
210
211         return result;
212 }
213
214 AnyPtr AnyFactory::createAny(JSContextRef context, JSValueRef value, PrimitiveType type)
215 {
216         AnyPtr any(NULL);
217
218         try
219         {
220                 any = AnyPtr(new PrivateAny(context, value, type));
221         }
222         catch(TypeMismatchException &e)
223         {
224                 ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Type error occured while converting JSValueRef");
225         }
226         catch(BasePlatformException &e)
227         {
228                 ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Unknown error occured while converting JSValueRef");
229         }
230
231         return any;
232 }
233
234 AnyPtr AnyFactory::createAnyNoException(JSContextRef context, JSValueRef value, PrimitiveType type)
235 {
236         try
237         {
238                 return AnyPtr(new PrivateAny(context, value, type));
239         }
240         catch(BasePlatformException &e)
241         {
242                 LoggerE("Error while converting (" << e.getName() << ") : " << e.getMessage());
243         }
244
245         return AnyPtr(new PrivateAny());
246 }
247
248 AnyPtr AnyFactory::createAnyEmpty(JSContextRef context)
249 {
250         return AnyPtr(new PrivateAny());
251 }
252
253 } // Tizen
254 } // DeviceAPI