2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @file JSGeocoder.cpp
19 * @author Sangtai Kim (sangtai.kim@samsung.com)
21 * @brief Implementation of the JSGeocoder class
24 #include "JSGeocoder.h"
25 #include "GeocoderController.h"
27 #include <API/Geocoder/GeocoderFactory.h>
28 #include <API/Geocoder/EventGeocoder.h>
29 #include <CommonsJavaScript/Converter.h>
30 #include <CommonsJavaScript/Validator.h>
31 #include <CommonsJavaScript/JSUtils.h>
32 #include <CommonsJavaScript/JSCallbackManager.h>
34 #include <CommonsJavaScript/Utils.h>
36 #include <Tizen/Common/JSTizenExceptionFactory.h>
37 #include <Tizen/Common/JSTizenException.h>
38 #include <Tizen/Common/SecurityExceptions.h>
40 #include "plugin_config.h"
44 //using namespace TizenApis::Tizen1_0::Platform;
45 using namespace WrtDeviceApis;
46 using namespace WrtDeviceApis::Commons;
47 using namespace WrtDeviceApis::CommonsJavaScript;
48 using namespace TizenApis::Tizen1_0::Api::Geocoder;
49 using namespace TizenApis::Commons;
54 //#define GET_ADDRESS_ARGUMENT_COUNT 4
55 //#define GET_POSITION_ARGUMENT_COUNT 3
57 const std::string JSGeocoder::JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT = "Invalid argument";
59 const std::string JSGeocoder::GEOCODER_ADDRESS_COUNTRY = "country";
60 const std::string JSGeocoder::GEOCODER_ADDRESS_REGION = "region";
61 const std::string JSGeocoder::GEOCODER_ADDRESS_COUNTY = "county";
62 const std::string JSGeocoder::GEOCODER_ADDRESS_CITY = "city";
63 const std::string JSGeocoder::GEOCODER_ADDRESS_STREET = "street";
64 const std::string JSGeocoder::GEOCODER_ADDRESS_STREET_NUMBER = "streetNumber";
65 const std::string JSGeocoder::GEOCODER_ADDRESS_PREMISES = "premises";
66 const std::string JSGeocoder::GEOCODER_ADDRESS_ADDTIONAL_INFORMATION = "additionalInformation";
67 const std::string JSGeocoder::GEOCODER_ADDRESS_POSTAL_CODE = "postalCode";
69 const std::string JSGeocoder::GEOCODER_COORDINATES_LATITUDE = "latitude";
70 const std::string JSGeocoder::GEOCODER_COORDINATES_LONGITUDE = "longitude";
72 const std::string JSGeocoder::gGeocoderAddressArray[] = {
73 GEOCODER_ADDRESS_COUNTRY,
74 GEOCODER_ADDRESS_REGION,
75 GEOCODER_ADDRESS_COUNTY,
76 GEOCODER_ADDRESS_CITY,
77 GEOCODER_ADDRESS_STREET,
78 GEOCODER_ADDRESS_STREET_NUMBER,
79 GEOCODER_ADDRESS_PREMISES,
80 GEOCODER_ADDRESS_ADDTIONAL_INFORMATION,
81 GEOCODER_ADDRESS_POSTAL_CODE
84 JSClassRef JSGeocoder::m_jsClassRef = NULL;
86 JSClassDefinition JSGeocoder::m_classInfo = {
88 kJSClassAttributeNone,
98 NULL, //deleteProperty,Geolocation
99 NULL, //getPropertyNames,
106 JSStaticFunction JSGeocoder::m_function[] = {
107 { "geocode", JSGeocoder::geocode, kJSPropertyAttributeNone },
108 { "reverseGeocode", JSGeocoder::reverseGeocode, kJSPropertyAttributeNone },
112 const JSClassRef JSGeocoder::getClassRef() {
114 m_jsClassRef = JSClassCreate(&m_classInfo);
119 const JSClassDefinition* JSGeocoder::getClassInfo() {
123 void JSGeocoder::initialize(JSContextRef context, JSObjectRef object) {
124 JSGeocoderPriv* priv = static_cast<JSGeocoderPriv*> (JSObjectGetPrivate(object));
125 assert(!priv && "Invalid object creation.");
126 IGeocoderPtr geocoder(GeocoderFactory::getInstance().getGeocoder());
127 priv = new JSGeocoderPriv(context, geocoder);
128 if (!JSObjectSetPrivate(object, static_cast<void*> (priv))) {
129 LogError("Object can't store private data.");
134 void JSGeocoder::finalize(JSObjectRef object) {
135 JSGeocoderPriv* priv = static_cast<JSGeocoderPriv*> (JSObjectGetPrivate(object));
136 JSObjectSetPrivate(object, NULL);
137 LogDebug("Deleting gallery");
141 GeocoderProperties JSGeocoder::toGeocoderProperties(JSContextRef context, const JSValueRef& arg){
142 GeocoderProperties properties;
144 CommonsJavaScript::Converter converter(context);
146 JSValueRef valueRefLatitude = JSUtils::getJSProperty(context, arg, GEOCODER_COORDINATES_LATITUDE);
147 if(valueRefLatitude!=NULL && JSValueIsNumber(context, valueRefLatitude)){
148 properties.latitude = converter.toDouble(valueRefLatitude);
150 Throw(WrtDeviceApis::Commons::InvalidArgumentException);
153 JSValueRef valueRefLongitude = JSUtils::getJSProperty(context, arg, GEOCODER_COORDINATES_LONGITUDE);
154 if(valueRefLongitude!=NULL && JSValueIsNumber(context, valueRefLongitude)){
155 properties.longitude = converter.toDouble(valueRefLongitude);
157 Throw(WrtDeviceApis::Commons::InvalidArgumentException);
163 bool JSGeocoder::hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception) {
164 return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
167 JSValueRef JSGeocoder::getAddressByCoordinates(JSContextRef context, JSObjectRef thisObject, size_t argumentCount,
168 const JSValueRef arguments[], JSValueRef* exception) {
170 JSGeocoderPriv *priv = static_cast<JSGeocoderPriv*> (JSObjectGetPrivate(thisObject));
172 assert(priv && "Invalid private pointer.");
173 CommonsJavaScript::Converter converter(context);
174 Validator check(context, exception);
176 JSValueRef onSuccess = NULL;
177 JSValueRef onError = NULL;
179 GeocoderProperties properties;
181 properties = toGeocoderProperties(context, arguments[0]);
182 }Catch(WrtDeviceApis::Commons::InvalidArgumentException){
183 return JSTizenExceptionFactory::postException(context, exception,
184 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
187 double latitude = properties.latitude;
188 double longitude = properties.longitude;
190 if(argumentCount==2){
191 onSuccess = arguments[1];
193 if(check.isCallback(onSuccess) != true){
194 LogError("Wrong callbacks parameters");
195 return JSTizenExceptionFactory::postException(context, exception,
196 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
198 }else if(argumentCount==3){
199 onSuccess = arguments[1];
200 onError = arguments[2];
201 if(check.isCallback(onSuccess)!=true || check.isCallback(onError)!=true){
202 LogError("Wrong callbacks parameters");
203 return JSTizenExceptionFactory::postException(context, exception,
204 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
207 LogError("Wrong callbacks parameters");
208 return JSTizenExceptionFactory::postException(context, exception,
209 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
212 return getAddressInternal(context, latitude, longitude, thisObject, onSuccess, onError);
216 JSValueRef JSGeocoder::getAddressInternal(JSContextRef context, double latitude, double longitude, JSObjectRef thisObject, JSValueRef onSuccess, JSValueRef onError){
217 LogDebug(" <<< latitude:" << latitude << ", longitude:" << longitude);
219 JSGeocoderPriv *priv = static_cast<JSGeocoderPriv*> (JSObjectGetPrivate(thisObject));
220 JSContextRef gContext = priv->getContext();
221 assert(priv && "Invalid private pointer.");
223 JSCallbackManagerPtr cbm(JSCallbackManager::createObject(priv->getContext(), onSuccess, onError));
225 EventGeocoderPtr event(new EventGeocoder());
226 SharedPtr < IEventController > eventContr = StaticPointerCast<IEventController> (event);
227 JSObjectRef pendingOperation = CommonsJavaScript::makePendingOperation(gContext, event);
230 IGeocoderPtr geocoder(priv->getObject());
232 event->setPrivateData(StaticPointerCast<IEventPrivateData> (cbm));
233 event->setForAsynchronousCall(new GeocoderController(cbm));
234 event->setLatitude(latitude);
235 event->setLongitude(longitude);
236 event->setEventType(EventGeocoder::GEOCODER_EVENT_GET_ADDRESS);
238 geocoder->getAddressFromPosition(event);
239 }Catch (WrtDeviceApis::Commons::PendingOperationException){
240 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,
241 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT));
242 }Catch (WrtDeviceApis::Commons::ConversionException){
243 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,
244 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT));
245 }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
246 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,
247 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT));
248 }Catch(WrtDeviceApis::Commons::Exception){
249 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
250 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,
251 JSTizenException::UNKNOWN_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT ));
255 return pendingOperation;
260 JSValueRef JSGeocoder::getAddressByPosition(JSContextRef context, JSObjectRef thisObject, size_t argumentCount,
261 const JSValueRef arguments[], JSValueRef* exception) {
263 JSValueRef onSuccess = NULL;
264 JSValueRef onError = NULL;
266 JSGeocoderPriv *priv = static_cast<JSGeocoderPriv*> (JSObjectGetPrivate(thisObject));
268 assert(priv && "Invalid private pointer.");
269 CommonsJavaScript::Converter converter(context);
270 Validator check(context, exception);
272 if(argumentCount==3){
273 onSuccess = arguments[2];
275 if(check.isCallback(onSuccess) != true){
276 LogError("Wrong callbacks parameters");
277 return JSTizenExceptionFactory::postException(context, exception,
278 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
280 }else if(argumentCount==4){
281 onSuccess = arguments[2];
282 onError = arguments[3];
283 if(check.isCallback(onSuccess)!=true || check.isCallback(onError)!=true){
284 LogError("Wrong callbacks parameters");
285 return JSTizenExceptionFactory::postException(context, exception,
286 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
289 LogError("Wrong callbacks parameters");
290 return JSTizenExceptionFactory::postException(context, exception,
291 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
294 //check is valid ratitude and longitude
295 if(JSValueIsNull(context, arguments[0]) || JSValueIsUndefined(context, arguments[0])){
296 LogError("[ERROR]Wrong latitude");
297 return JSTizenExceptionFactory::postException(context, exception,
298 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
301 if(JSValueIsNull(context, arguments[1]) || JSValueIsUndefined(context, arguments[1])){
302 LogError("[ERROR]Wrong longitude");
303 return JSTizenExceptionFactory::postException(context, exception,
304 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
307 double l_latitude = 0.0;
308 double l_longitude = 0.0;
311 l_latitude = static_cast<double>(converter.toDouble(arguments[0]));
312 l_longitude = static_cast<double>(converter.toDouble(arguments[1]));
313 }Catch(WrtDeviceApis::Commons::ConversionException){
314 LogError("[ERROR]Conversion Exception");
315 return JSTizenExceptionFactory::postException(context, exception,
316 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
319 return getAddressInternal(context, l_latitude, l_longitude, thisObject, onSuccess, onError);
322 JSValueRef JSGeocoder::geocode(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
323 const JSValueRef arguments[], JSValueRef* exception) {
325 LogDebug("arumentConunt:" << argumentCount);
327 JSGeocoderPriv *priv = static_cast<JSGeocoderPriv*> (JSObjectGetPrivate(thisObject));
328 assert(priv && "Invalid private pointer.");
330 AceSecurityStatus status = GEOCODER_CHECK_ACCESS(priv->getContext(), GEOCODER_FUNCTION_API_REVERSE_GEOCODE);
331 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
333 CommonsJavaScript::Converter converter(context);
334 Validator check(context, exception);
336 //argument[0] : Address
337 //argument[1] : success callback
338 //argument[2] : error callback //Optional
340 //argument[0] : AddressString
341 //argument[1] : success callback
342 //argument[2] : error callback //Optional
344 if(argumentCount<GET_POSITION_ARGUMENT_COUNT || !check.isCallback(arguments[1])){
345 LogError("Wrong callbacks parameters");
346 return JSTizenExceptionFactory::postException(context, exception,
347 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
350 JSValueRef onSuccess = NULL;
351 JSValueRef onError = NULL;
353 if(argumentCount==2){
354 onSuccess = arguments[1];
356 if(check.isCallback(onSuccess) != true){
357 LogError("Wrong callbacks parameters");
358 return JSTizenExceptionFactory::postException(context, exception,
359 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
361 }else if(argumentCount==3){
362 onSuccess = arguments[1];
363 onError = arguments[2];
364 if(check.isCallback(onSuccess)!=true || check.isCallback(onError)!=true){
365 LogError("Wrong callbacks parameters");
366 return JSTizenExceptionFactory::postException(context, exception,
367 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
370 LogError("Wrong callbacks parameters");
371 return JSTizenExceptionFactory::postException(context, exception,
372 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
375 std::string strAddress;
376 EventGeocoderPtr event(new EventGeocoder());
378 if(JSValueIsString(context, arguments[0])==true){ //TYPE is B
379 strAddress = converter.toString(arguments[0]);
380 event->setAddressString(strAddress);
382 JSValueRef addressUnit = NULL;
383 int sizeOfGeocoderAddressUnit = sizeof(gGeocoderAddressArray) / sizeof(std::string);
384 LogDebug("sizeOfGeocoderAddressUnit : " << sizeOfGeocoderAddressUnit);
386 std::map<std::string, std::string> addressMap;
388 //check is valid ratitude and address
389 if ((!JSValueIsNull(context, arguments[0]) && !JSValueIsUndefined(context, arguments[0]))){
390 for(int i=0; i<sizeOfGeocoderAddressUnit; i++){
391 addressUnit = JSUtils::getJSProperty(context, arguments[0], gGeocoderAddressArray[i], exception);
392 if(addressUnit!=NULL && JSValueIsString(context, addressUnit)){
393 strAddress = converter.toString(addressUnit);
395 LogDebug("strAddress : " << strAddress);
397 addressMap.insert(pair<std::string, std::string>(gGeocoderAddressArray[i], strAddress));
404 LogError("[ERROR]Wrong Address");
405 return JSTizenExceptionFactory::postException(context, exception,
406 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT);
409 setAddressData(event, addressMap);
412 JSCallbackManagerPtr cbm(JSCallbackManager::createObject(priv->getContext(), onSuccess, onError));
414 SharedPtr < IEventController > eventContr = StaticPointerCast<IEventController> (event);
415 JSObjectRef pendingOperation = CommonsJavaScript::makePendingOperation(context, event);
418 IGeocoderPtr geocoder(priv->getObject());
420 event->setPrivateData(StaticPointerCast<IEventPrivateData> (cbm));
421 event->setForAsynchronousCall(new GeocoderController(cbm));
422 event->setEventType(EventGeocoder::GEOCODER_EVENT_GET_POSITION);
424 geocoder->getPositionFromAddress(event);
425 }Catch (WrtDeviceApis::Commons::PendingOperationException){
426 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,
427 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT ));
428 }Catch (WrtDeviceApis::Commons::ConversionException){
429 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,
430 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT ));
431 }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
432 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,
433 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT ));
434 }Catch(WrtDeviceApis::Commons::Exception){
435 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
436 cbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,
437 JSTizenException::INVALID_VALUES_ERROR, JSGEOCODER_EXCEPTION_STRING_INVALID_ARGUMENT ));
441 return pendingOperation;
444 JSValueRef JSGeocoder::reverseGeocode (JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
445 const JSValueRef arguments[], JSValueRef* exception) {
447 LogDebug("arumentConunt:" << argumentCount);
449 JSGeocoderPriv *priv = static_cast<JSGeocoderPriv*> (JSObjectGetPrivate(thisObject));
450 AceSecurityStatus status = GEOCODER_CHECK_ACCESS(priv->getContext(), GEOCODER_FUNCTION_API_GEOCODE);
451 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
453 //argument[0] : latitude
454 //argument[1] : longitude
455 //argument[2] : success callback
456 //argument[3] : error callback //optional
458 //argument[0] : Coordinates
459 //argument[1] : success callback
460 //argument[2] : error callback //optional
461 if(JSValueIsObject(context, arguments[0]) == true){ //argument[0] is Coordinates
462 return getAddressByCoordinates(context, thisObject, argumentCount, arguments, exception);
464 return getAddressByPosition(context, thisObject, argumentCount, arguments, exception);
468 int JSGeocoder::setAddressData(const Api::Geocoder::EventGeocoderPtr& event, std::map<std::string, std::string>& addressMap)
470 std::map<std::string, std::string>::iterator it;
472 it = addressMap.find(GEOCODER_ADDRESS_COUNTRY);
473 if(it != addressMap.end()){
474 event->setCountry(it->second);
477 it = addressMap.find(GEOCODER_ADDRESS_REGION);
478 if(it != addressMap.end()){
479 event->setRegion(it->second);
482 it = addressMap.find(GEOCODER_ADDRESS_COUNTY);
483 if(it != addressMap.end()){
484 event->setCounty(it->second);
487 it = addressMap.find(GEOCODER_ADDRESS_CITY);
488 if(it != addressMap.end()){
489 event->setCity(it->second);
492 it = addressMap.find(GEOCODER_ADDRESS_STREET);
493 if(it != addressMap.end()){
494 event->setStreet(it->second);
497 it = addressMap.find(GEOCODER_ADDRESS_STREET_NUMBER);
498 if(it != addressMap.end()){
499 event->setStreetNumber(it->second);
502 it = addressMap.find(GEOCODER_ADDRESS_PREMISES);
503 if(it != addressMap.end()){
504 event->setPremises(it->second);
507 it = addressMap.find(GEOCODER_ADDRESS_ADDTIONAL_INFORMATION);
508 if(it != addressMap.end()){
509 event->setAdditionalInformation(it->second);
512 it = addressMap.find(GEOCODER_ADDRESS_POSTAL_CODE);
513 if(it != addressMap.end()){
514 event->setPostalCode(it->second);