Added maps_plugin_geocode_by_structured_address and all Place Maps Service calls. 54/79554/1
authorgknisely <greg@mapzen.com>
Tue, 5 Jul 2016 15:17:53 +0000 (11:17 -0400)
committerBaldur Gudbjornsson <baldur@mapzen.com>
Mon, 11 Jul 2016 16:36:30 +0000 (12:36 -0400)
Change-Id: I6b41a633e38f98ab73dfa9e8be7e6ec6efd23d13

13 files changed:
include/mapzen_plugin.h
src/mapzen/mapzen_api.c
src/mapzen/mapzen_api.h
src/mapzen/mapzen_geocode.c
src/mapzen/mapzen_jsonparser.cpp
src/mapzen/mapzen_place.c
src/mapzen/mapzen_place.h
src/mapzen/mapzen_queue.c
src/mapzen/mapzen_queue.h
src/mapzen/mapzen_restcurl.c
src/mapzen/mapzen_server_private.h
src/mapzen/mapzen_types.h
src/mapzen_plugin.c

index df24cfd..c2d33c8 100644 (file)
@@ -48,6 +48,17 @@ typedef struct callback_place {
        int reqID;
 } callback_info_place;
 
+typedef struct callback_place_list {
+       maps_service_search_place_list_cb callback;
+       void *data;
+       int reqID;
+} callback_info_place_list;
+
+typedef struct callback_place_details {
+       maps_service_get_place_details_cb callback;
+       void *data;
+       int reqID;
+} callback_info_place_details;
 
 /* TODO: IMPLEMENT THESE FOR REAL */
 
@@ -55,12 +66,6 @@ int maps_plugin_multi_reverse_geocode(const maps_coordinates_list_h geocode_list
        const maps_preference_h preference, maps_service_multi_reverse_geocode_cb callback,
        void *user_data, int *request_id);
 
-int maps_plugin_search_place_list(const maps_area_h boundary, const maps_place_filter_h filter,
-       maps_preference_h preference, maps_service_search_place_list_cb callback, void* user_data, int* request_id);
-
-int maps_plugin_get_place_details(const char* url,
-       maps_service_get_place_details_cb callback, void* user_data, int* request_id);
-
 int maps_plugin_create_map_view(maps_view_h hView, maps_plugin_map_view_ready_cb pCbFunc);
 
 int maps_plugin_destroy_map_view(maps_view_h hView);
@@ -135,6 +140,12 @@ int maps_plugin_search_place(const maps_coordinates_h position, int distance, co
 /* Place search by area */
 int maps_plugin_search_place_by_area(const maps_area_h boundary, const maps_place_filter_h filter, maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id);
 
+/* Place search by area, return list*/
+int maps_plugin_search_place_list(const maps_area_h boundary, const maps_place_filter_h filter, maps_preference_h preference, maps_service_search_place_list_cb callback, void *user_data, int *request_id);
+
+/* Get a Place via a uri */
+int maps_plugin_get_place_details(const char* uri, maps_service_get_place_details_cb callback, void* user_data, int* request_id);
+
 /* Place search by address */
 int maps_plugin_search_place_by_address(const char *address, const maps_area_h boundary, const maps_place_filter_h filter, maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id);
 
index 26e709f..111ba88 100644 (file)
@@ -61,7 +61,23 @@ int mapzen_reverse_geocode(mapzen_revgeocode_req_s *req_details, mapzen_reverse_
 int mapzen_search_place(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data)
 {
        int ret = MAPZEN_ERROR_NONE;
-       ret = start_places_service(req_details, callback, request_id, user_data);
+       ret = start_place_service(req_details, callback, request_id, user_data);
+
+       return ret;
+}
+
+int mapzen_get_place_details(mapzen_get_details_req_s *req_details, mapzen_get_place_details_cb callback, int request_id, void *user_data)
+{
+       int ret = MAPZEN_ERROR_NONE;
+       ret = start_place_details_service(req_details, callback, request_id, user_data);
+
+       return ret;
+}
+
+int mapzen_search_place_list(mapzen_search_req_s *req_details, mapzen_place_list_search_cb callback, int request_id, void *user_data)
+{
+       int ret = MAPZEN_ERROR_NONE;
+       ret = start_places_list_service(req_details, callback, request_id, user_data);
 
        return ret;
 }
index ceddc3a..74765e5 100644 (file)
@@ -43,6 +43,10 @@ typedef void (*mapzen_reverse_geocode_cb) (mapzen_error_e result, int request_id
 
 typedef void (*mapzen_place_search_cb) (mapzen_error_e result, int request_id, GList *places, void *user_data);
 
+typedef void (*mapzen_get_place_details_cb) (mapzen_error_e result, int request_id, GList *places, void *user_data);
+
+typedef void (*mapzen_place_list_search_cb) (mapzen_error_e result, int request_id, GList *places, void *user_data);
+
 typedef void (*mapzen_route_cb) (mapzen_error_e result, int request_id, mapzen_route_resp_s *route_info, void *user_data);
 
 typedef void (*mapzen_maptile_cb) (mapzen_error_e result, int request_id, char *buffer, void *user_data);
@@ -59,6 +63,10 @@ int mapzen_reverse_geocode(mapzen_revgeocode_req_s *req_details, mapzen_reverse_
 
 int mapzen_search_place(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data);
 
+int mapzen_get_place_details(mapzen_get_details_req_s *req_details, mapzen_get_place_details_cb callback, int request_id, void *user_data);
+
+int mapzen_search_place_list(mapzen_search_req_s *req_details, mapzen_place_list_search_cb callback, int request_id, void *user_data);
+
 int mapzen_start_route(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data);
 
 #ifdef __cplusplus
index 66fa098..0c12fa7 100644 (file)
@@ -17,6 +17,8 @@
 #include <stdio.h>
 #include <glib.h>
 #include <pthread.h>
+#include <curl/curl.h>
+
 #include "mapzen_geocode.h"
 #include "mapzen_types.h"
 #include "mapzen_server_private.h"
@@ -45,8 +47,10 @@ int query_geocode_within_bounding_box(gchar *maps_key, char *address, coords_s t
        snprintf(tmpStr, sizeof(tmpStr), "&size=%d", num_results);
        STRCAT(url, tmpStr);
 
-       snprintf(tmpStr, sizeof(tmpStr), "&text=%s", address);
+       char* encoded = curl_escape(address, 0);
+       snprintf(tmpStr, sizeof(tmpStr), "&text=%s", encoded);
        STRCAT(url, tmpStr);
+       curl_free(encoded);
 
        add_handle(url, REQ_TYPE_GEOCODE, user_data);
 
@@ -72,8 +76,10 @@ int query_geocode_within_circle(gchar *maps_key, char *address, coords_s center,
        snprintf(tmpStr, sizeof(tmpStr), "&size=%d", num_results);
        STRCAT(url, tmpStr);
 
-       snprintf(tmpStr, sizeof(tmpStr), "&text=%s", address);
+       char* encoded = curl_escape(address, 0);
+       snprintf(tmpStr, sizeof(tmpStr), "&text=%s", encoded);
        STRCAT(url, tmpStr);
+       curl_free(encoded);
 
        add_handle(url, REQ_TYPE_GEOCODE, user_data);
 
@@ -96,8 +102,10 @@ int query_geocode(gchar *maps_key, char *address, int num_results, gpointer user
        snprintf(tmpStr, sizeof(tmpStr), "&size=%d", num_results);
        STRCAT(url, tmpStr);
 
-       snprintf(tmpStr, sizeof(tmpStr), "&text=%s", address);
+       char* encoded = curl_escape(address, 0);
+       snprintf(tmpStr, sizeof(tmpStr), "&text=%s", encoded);
        STRCAT(url, tmpStr);
+       curl_free(encoded);
 
        add_handle(url, REQ_TYPE_GEOCODE, user_data);
 
index 02581d9..16988ec 100644 (file)
@@ -186,10 +186,10 @@ static void __parse_geocode_response(char *response, int size, int *status, GLis
                                        *coordsList = g_list_append(*coordsList, coord);
                                else
                                        *coordsList = g_list_insert_before(*coordsList, NULL, coord);
-                               *status = 0;
                        }
                }
        }
+       *status = 0;
 }
 
 /****************** REVERSE GEOCODE *********************/
@@ -220,9 +220,7 @@ static void __parse_revgeocode_response(char *response, int size, int *status, m
                                rapidjson::Value::ConstMemberIterator coords = geom->value.FindMember("coordinates");
                                if(coords == geom->value.MemberEnd() || !coords->value.IsArray() || coords->value.Size() != 2)
                                        continue;
-                               maps_coordinates_s coord;
-                               coord.longitude = coords->value[0].GetDouble();
-                               coord.latitude = coords->value[1].GetDouble();
+
                                //NOTE: it seems as though the tizen maps plugin api assumes that reverse geocode results will
                                //actually be at the coordinates where you requested the reverse geocode. the mapzen api can return
                                //POIS which are some distance away from the location and currently this is not accounted for :o(
@@ -249,25 +247,102 @@ static void __parse_revgeocode_response(char *response, int size, int *status, m
                                                (*respAddr) = NULL;
                                        }//forget the rest, we have one with something in it
                                        else {
-                                               *status = 0;
                                                break;
                                        }
                                }
                        }
                }
-
        }
+       *status = 0;
 }
 
 /****************  PLACE SEARCH ********************/
 
 static void __parse_place_response(char *response, int size, GList **placeList)
 {
+
+       MAP_DEBUG("Inside __parse_place_response.");
+
        if (!response || !placeList) return;
 
        *placeList = NULL;
 
-       //TODO
+       //crack open that json
+       rapidjson::Document document;
+       document.Parse(std::string(response, size).c_str());
+       rapidjson::Value::ConstMemberIterator features = document.FindMember("features");
+       if(features != document.MemberEnd() && features->value.IsArray()) {
+               //for each feature
+               for (rapidjson::Value::ConstValueIterator f = features->value.Begin(); f != features->value.End(); ++f) {
+                       //it has to have geometry
+                       rapidjson::Value::ConstMemberIterator geom = f->FindMember("geometry");
+                       if(geom != f->MemberEnd()) {
+                               //skip non-points
+                               rapidjson::Value::ConstMemberIterator type = geom->value.FindMember("type");
+                               if(type == geom->value.MemberEnd() || strcmp(type->value.GetString(), "Point"))
+                                       continue;
+                               //get actual points
+                               rapidjson::Value::ConstMemberIterator coords = geom->value.FindMember("coordinates");
+                               if(coords == geom->value.MemberEnd() || !coords->value.IsArray() || coords->value.Size() != 2)
+                                       continue;
+
+                               coords_s coordinate;
+                               coordinate.longitude = coords->value[0].GetDouble();
+                               coordinate.latitude = coords->value[1].GetDouble();
+
+                               //get out the address information
+                               rapidjson::Value::ConstMemberIterator properties = f->FindMember("properties");
+                               if(properties != f->MemberEnd()) {
+                                       //fill this out as we go
+                                       mapzen_place_resp_s *respPlaces = (mapzen_place_resp_s *)g_malloc0(sizeof(mapzen_place_resp_s));
+
+                                       respPlaces->place_id = NULL;
+                                       respPlaces->categories = NULL;
+                                       respPlaces->display_name = NULL;
+                                       respPlaces->address = NULL;
+
+                                       bool something = false;
+                                       something = __get_string(properties->value, "gid", &respPlaces->place_id) || something;
+                                       something = __get_string(properties->value, "name", &respPlaces->display_name) || something;
+
+                                       respPlaces->address = (mapzen_address_resp_s *)g_malloc(sizeof(mapzen_address_resp_s));
+
+                                       something = __get_string(properties->value, "housenumber", &respPlaces->address->housenumber) || something;
+                                       something = __get_string(properties->value, "street", &respPlaces->address->street) || something;
+                                       something = __get_string(properties->value, "neighbourhood", &respPlaces->address->neighbourhood) || something;
+                                       something = __get_string(properties->value, "county", &respPlaces->address->county) || something;
+                                       something = __get_string(properties->value, "region", &respPlaces->address->region) || something;
+                                       something = __get_string(properties->value, "country", &respPlaces->address->country) || something;
+                                       something = __get_string(properties->value, "country_a", &respPlaces->address->country_a) || something;
+                                       something = __get_string(properties->value, "locality", &respPlaces->address->localadmin) || something;
+                                       something = __get_string(properties->value, "postalcode", &respPlaces->address->postalcode) || something;
+
+                                       respPlaces->coordinates = coordinate;
+
+                                       respPlaces->categories = NULL;
+                                       rapidjson::Value::ConstMemberIterator categories = properties->value.FindMember("category");
+                                       if (categories != geom->value.MemberEnd() && categories->value.IsArray()) {
+                                               for (rapidjson::SizeType i = 0; i < categories->value.Size(); i++) {
+                                                       if (respPlaces->categories == NULL)
+                                                               respPlaces->categories = g_list_append(respPlaces->categories, g_strdup(categories->value[i].GetString()));
+                                                       else
+                                                               respPlaces->categories = g_list_insert_before(respPlaces->categories, NULL, g_strdup(categories->value[i].GetString()));
+                                               }
+                                       }
+
+                                       if(!something) {
+                                               g_free(respPlaces);
+                                               respPlaces = NULL;
+                                       } else {
+                                               if (*placeList == NULL)
+                                                       *placeList = g_list_append(*placeList, respPlaces);
+                                               else
+                                                       *placeList = g_list_insert_before(*placeList, NULL, respPlaces);
+                                       }
+                               }
+                       }
+               }
+       }
 }
 
 /********************* ROUTE RESPONSE ***********************/
@@ -416,6 +491,92 @@ void post_curl_response(char *response, int size, mapzen_resp_type type, void *u
 
                        break;
                }
+       case RESP_TYPE_PLACES_DETAILS:
+               {
+                       MAP_DEBUG("Inside Places Details JSON Parsing..");
+                       MapzenPlaceDetailsQueryData *queryData = (MapzenPlaceDetailsQueryData *)user_data;
+                       MapzenPlaceDetailsResponseData *responseData = (MapzenPlaceDetailsResponseData *)g_malloc(sizeof(MapzenPlaceDetailsResponseData));
+
+                       if (responseData) {
+                               responseData->requestId = queryData->requestId;
+                               responseData->get_place_details_cb = queryData->get_place_details_cb;
+                               responseData->user_data = queryData->user_data;
+
+                               if (response && (size > 0)) {
+                                       /* Coords Result GList */
+                                       GList *placeList = NULL;
+
+                                       MAP_DEBUG("Search Places Details :- Parsing Json Response");
+                                       __parse_place_response(response, size, &placeList);
+
+                                       if (placeList != NULL) {
+                                               /* Put the response in queue */
+                                               responseData->error = MAPZEN_ERROR_NONE;
+                                               responseData->places = placeList;
+                                       } else {
+                                               /* REPSONSE PARSING FAILURE */
+                                               MAP_DEBUG("addr Response is NULL");
+                                               responseData->error = MAPZEN_ERROR_UNKNOWN;
+                                               responseData->places = NULL;
+                                       }
+                               } else {
+                                       responseData->error = MAPZEN_ERROR_UNKNOWN;
+                                       responseData->places = NULL;
+                               }
+
+                               mapzen_push_to_queue(type, (gpointer)responseData);
+                       }
+
+                       if (queryData) {
+                               g_free(queryData);
+                               queryData = NULL;
+                       }
+
+                       break;
+               }
+       case RESP_TYPE_PLACES_LIST:
+               {
+                       MAP_DEBUG("Inside Places List JSON Parsing..");
+                       MapzenPlaceListQueryData *queryData = (MapzenPlaceListQueryData *)user_data;
+                       MapzenPlaceListResponseData *responseData = (MapzenPlaceListResponseData *)g_malloc(sizeof(MapzenPlaceListResponseData));
+
+                       if (responseData) {
+                               responseData->requestId = queryData->requestId;
+                               responseData->place_list_search_cb = queryData->place_list_search_cb;
+                               responseData->user_data = queryData->user_data;
+
+                               if (response && (size > 0)) {
+                                       /* Coords Result GList */
+                                       GList *placeList = NULL;
+
+                                       MAP_DEBUG("Search Places :- Parsing Json Response");
+                                       __parse_place_response(response, size, &placeList);
+
+                                       if (placeList != NULL) {
+                                               /* Put the response in queue */
+                                               responseData->error = MAPZEN_ERROR_NONE;
+                                               responseData->places = placeList;
+                                       } else {
+                                               /* REPSONSE PARSING FAILURE */
+                                               MAP_DEBUG("addr Response is NULL");
+                                               responseData->error = MAPZEN_ERROR_UNKNOWN;
+                                               responseData->places = NULL;
+                                       }
+                               } else {
+                                       responseData->error = MAPZEN_ERROR_UNKNOWN;
+                                       responseData->places = NULL;
+                               }
+
+                               mapzen_push_to_queue(type, (gpointer)responseData);
+                       }
+
+                       if (queryData) {
+                               g_free(queryData);
+                               queryData = NULL;
+                       }
+
+                       break;
+               }
        case RESP_TYPE_ROUTE:
                {
                        MAP_DEBUG("Inside Route JSON Parsing..");
index 8df590a..111657a 100644 (file)
 #include <stdlib.h>
 #include <glib.h>
 #include <pthread.h>
+#include <curl/curl.h>
+
 #include "mapzen_place.h"
 #include "mapzen_types.h"
-#include "mapzen_server_private.h"
 #include "mapzen_debug.h"
 #include "mapzen_queue.h"
 #include "mapzen_restcurl.h"
 #include "mapzen_util.h"
 
-#define PLACES_URL     "https://open.mapzenapi.com/nominatim/v1/search.php?format=json"
+#define CATEGORIES_URL "http://pelias.dev.mapzen.com/v1/nearby?api_key=%s"
+#define KEYWORD_CATEGORIES_URL "https://search.mapzen.com/v1/search?api_key=%s"
+#define PLACE_DETAILS_URL      "https://search.mapzen.com/v1/place?api_key=%s"
 
-int query_places(gchar *maps_key, gchar *search_str, mapzen_boundary_s *boundary, int num_res, gpointer user_data)
+int query_places(gchar *maps_key, gchar *search_str, gchar *categories, mapzen_boundary_s *boundary, int num_res, gpointer user_data, mapzen_req_type type)
 {
        char url[1024];
        char tmpStr[512];
 
-       STRCPY(url, PLACES_URL);
+       if (search_str != NULL || boundary->type == MAPZEN_BOUNDARY_RECT) {
+               if (maps_key != NULL)
+                       snprintf(tmpStr, sizeof(tmpStr), KEYWORD_CATEGORIES_URL, maps_key);
+               else snprintf(tmpStr, sizeof(tmpStr), KEYWORD_CATEGORIES_URL, "null");
+               STRCPY(url, tmpStr);
+
+               if (search_str != NULL) {
+                       char* encoded = curl_escape(search_str, 0);
+                       snprintf(tmpStr, sizeof(tmpStr), "&text=%s", encoded);
+                       STRCAT(url, tmpStr);
+                       curl_free(encoded);
+               }
 
-       if (search_str != NULL) {
-               snprintf(tmpStr, sizeof(tmpStr), "&q=%s", search_str);
-               strncat(url, tmpStr, sizeof(url)-strlen(url)-1);
+               if (categories != NULL) {
+                       char* encoded = curl_escape(categories, 0);
+                       snprintf(tmpStr, sizeof(tmpStr), "&categories=%s", encoded);
+                       STRCAT(url, tmpStr);
+                       curl_free(encoded);
+               }
+       } else {
+               if (maps_key != NULL)
+                       snprintf(tmpStr, sizeof(tmpStr), CATEGORIES_URL, maps_key);
+               else snprintf(tmpStr, sizeof(tmpStr), CATEGORIES_URL, "null");
+               STRCPY(url, tmpStr);
+
+               if (categories != NULL) {
+                       char* encoded = curl_escape(categories, 0);
+                       snprintf(tmpStr, sizeof(tmpStr), "&categories=%s", encoded);
+                       STRCAT(url, tmpStr);
+                       curl_free(encoded);
+               }
        }
 
        if (boundary != NULL) {
                if (boundary->type == MAPZEN_BOUNDARY_RECT) {
-                       snprintf(tmpStr, sizeof(tmpStr), "&viewbox=%f,%f,%f,%f", boundary->rect.top_left.longitude, boundary->rect.top_left.latitude, boundary->rect.bottom_right.longitude, boundary->rect.bottom_right.latitude);
-
-                       strncat(url, tmpStr, sizeof(url)-strlen(url)-1);
+                       snprintf(tmpStr, sizeof(tmpStr), "&boundary.rect.min_lat=%f&boundary.rect.min_lon=%f&boundary.rect.max_lat=%f&boundary.rect.max_lon=%f",
+                                       boundary->rect.bottom_right.latitude, boundary->rect.top_left.longitude,
+                                       boundary->rect.top_left.latitude, boundary->rect.bottom_right.longitude);
+                       STRCAT(url, tmpStr);
                } else if (boundary->type == MAPZEN_BOUNDARY_CIRCLE) {
-                       coords_s *top_left = NULL, *bottom_right = NULL;
-                       coords_s circle = boundary->circle.center;
-                       gdouble radius = (boundary->circle.radius) * 0.001;
 
-                       /* Calculate the top left coordinate of bounding box. */
-                       calculate_point(circle.latitude, circle.longitude, 315, radius, &top_left);
+                       if (search_str == NULL) {
+                               snprintf(tmpStr, sizeof(tmpStr), "&point.lon=%f&point.lat=%f&boundary.circle.radius=%f",
+                                               boundary->circle.center.longitude, boundary->circle.center.latitude, boundary->circle.radius);
+                               STRCAT(url, tmpStr);
+                       } else {
+                               snprintf(tmpStr, sizeof(tmpStr), "&boundary.circle.lon=%f&boundary.circle.lat=%f&boundary.circle.radius=%f",
+                                               boundary->circle.center.longitude, boundary->circle.center.latitude, boundary->circle.radius);
+                               STRCAT(url, tmpStr);
+                       }
+               }
+       }
 
-                       /* Calculate the bottom right coordinate of bounding box. */
-                       calculate_point(circle.latitude, circle.longitude, 135, radius, &bottom_right);
+       snprintf(tmpStr, sizeof(tmpStr), "&size=%d", num_res);
+       STRCAT(url, tmpStr);
 
-                       if (top_left && bottom_right) {
-                               snprintf(tmpStr, sizeof(tmpStr), "&viewbox=%f,%f,%f,%f", top_left->longitude, top_left->latitude, bottom_right->longitude, bottom_right->latitude);
-                               strncat(url, tmpStr, sizeof(url)-strlen(url)-1);
-                       }
+       add_handle(url, type, user_data);
 
-                       if (top_left) {
-                               g_free(top_left);
-                               top_left = NULL;
-                       }
-                       if (bottom_right) {
-                               g_free(bottom_right);
-                               bottom_right = NULL;
-                       }
-               }
+       return 0;
+}
 
-               STRCAT(url, "&bounded=1");
-       }
+int query_place_details(gchar *maps_key, gchar *ids, gpointer user_data)
+{
+       char url[1024];
+       char tmpStr[512];
 
-       STRCAT(url, "&addressdetails=1");
+       if (maps_key != NULL)
+               snprintf(tmpStr, sizeof(tmpStr), PLACE_DETAILS_URL, maps_key);
+       else snprintf(tmpStr, sizeof(tmpStr), PLACE_DETAILS_URL, "null");
+               STRCPY(url, tmpStr);
 
-       if (num_res > 0) {
-               snprintf(tmpStr, sizeof(tmpStr), "&limit=%d", num_res);
+       if (ids != NULL) {
+               char* encoded = curl_escape(ids, 0);
+               snprintf(tmpStr, sizeof(tmpStr), "&ids=%s", encoded);
                STRCAT(url, tmpStr);
+               curl_free(encoded);
        }
 
-       add_handle(url, REQ_TYPE_PLACES, user_data);
+       add_handle(url, REQ_TYPE_PLACES_DETAILS, user_data);
 
        return 0;
 }
index ed122a1..84026a1 100644 (file)
 
 #include "mapzen_api.h"
 #include "mapzen_types.h"
+#include "mapzen_server_private.h"
 
-int query_places(gchar *maps_key, gchar *search_str, mapzen_boundary_s *boundary, int num_res, gpointer user_data);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int query_places(gchar *maps_key, gchar *search_str, gchar *categories, mapzen_boundary_s *boundary, int num_res, gpointer user_data,  mapzen_req_type type);
+int query_place_details(gchar *maps_key, gchar *ids, gpointer user_data);
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* _MAPZEN_PLACES_H_ */
index db1a3d7..46a78d0 100644 (file)
@@ -39,6 +39,8 @@ GList *reqCancelList = NULL;
 static void __free_geocode_response(void *ptr);
 static void __free_revgeocode_response(void *ptr);
 static void __free_place_response(void *ptr);
+static void __free_place_details_response(void *ptr);
+static void __free_place_list_response(void *ptr);
 static void __free_route_response(void *ptr);
 
 int add_to_geocode_list(mapzen_geocode_req_s *req_details, mapzen_geocode_cb callback, int request_id, void *user_data)
@@ -105,7 +107,7 @@ int add_to_revgeocode_list(mapzen_revgeocode_req_s *req_details, mapzen_reverse_
        return MAPZEN_ERROR_NONE;
 }
 
-int add_to_places_list(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data)
+int add_to_place_list(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data)
 {
        mapzen_request_s *req = (mapzen_request_s *)g_malloc0(sizeof(mapzen_request_s));
 
@@ -137,8 +139,80 @@ int add_to_places_list(mapzen_search_req_s *req_details, mapzen_place_search_cb
        return MAPZEN_ERROR_NONE;
 }
 
+int add_to_place_details_list(mapzen_get_details_req_s *req_details, mapzen_get_place_details_cb callback, int request_id, void *user_data)
+{
+       mapzen_request_s *req = (mapzen_request_s *)g_malloc0(sizeof(mapzen_request_s));
+
+       if (req != NULL) {
+
+               req->type = REQ_TYPE_PLACES_DETAILS;
+
+               mapzen_get_place_details_req *data = (mapzen_get_place_details_req *)g_malloc0(sizeof(mapzen_get_place_details_req));
+
+               if (data != NULL) {
+                       data->req_details = req_details;
+                       data->requestId = request_id;
+                       data->get_place_details_cb = callback;
+                       data->user_data = user_data;
+
+                       req->request = data;
+
+                       MAP_DEBUG("Added PLACE Details request to places List");
+
+                       pthread_mutex_lock(&__requestLock);
+                       if (requestList == NULL)
+                               requestList = g_list_append(requestList, (gpointer)req);
+                       else
+                               requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+                       pthread_mutex_unlock(&__requestLock);
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int add_to_places_list(mapzen_search_req_s *req_details, mapzen_place_list_search_cb callback, int request_id, void *user_data)
+{
+
+       MAP_DEBUG("add_to_place_list");
+
+
+       mapzen_request_s *req = (mapzen_request_s *)g_malloc0(sizeof(mapzen_request_s));
+
+       if (req != NULL) {
+
+               req->type = REQ_TYPE_PLACES_LIST;
+
+               mapzen_search_place_list_req *data = (mapzen_search_place_list_req *)g_malloc0(sizeof(mapzen_search_place_list_req));
+
+               if (data != NULL) {
+                       data->req_details = req_details;
+                       data->requestId = request_id;
+                       data->search_place_list_cb = callback;
+                       data->user_data = user_data;
+
+                       req->request = data;
+
+                       MAP_DEBUG("Added PLACE request to places List");
+
+                       pthread_mutex_lock(&__requestLock);
+                       if (requestList == NULL)
+                               requestList = g_list_append(requestList, (gpointer)req);
+                       else
+                               requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+                       pthread_mutex_unlock(&__requestLock);
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
 int add_to_route_list(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data)
 {
+
+       MAP_DEBUG("add_to_place_list");
+
+
        mapzen_request_s *req = (mapzen_request_s *)g_malloc0(sizeof(mapzen_request_s));
 
        if (req != NULL) {
@@ -305,6 +379,58 @@ int remove_from_request_list(int request_id)
                                        is_request_cancelled = true;
                                        break;
                                }
+                       } else if (req->type == REQ_TYPE_PLACES_DETAILS) {
+                               mapzen_get_place_details_req *places_req = (mapzen_get_place_details_req *) req->request;
+
+                               if (places_req->requestId == request_id) {
+                                       /* Means the request is pending in queue. Not started yet */
+                                       /* Deleting the request from the request queue */
+                                       pthread_mutex_lock(&__requestLock);
+                                       requestList = g_list_remove(requestList, (gpointer)req);
+                                       pthread_mutex_unlock(&__requestLock);
+                                       mapzen_get_details_req_s *place_req_details = (mapzen_get_details_req_s *)places_req->req_details;
+
+                                       if (place_req_details)
+                                               g_free(place_req_details);
+                                       place_req_details = NULL;
+
+                                       g_free(places_req);
+                                       places_req = NULL;
+
+                                       g_free(req);
+                                       req = NULL;
+
+                                       __remove_from_cancel_list(request_id);
+
+                                       is_request_cancelled = true;
+                                       break;
+                               }
+                       } else if (req->type == REQ_TYPE_PLACES_LIST) {
+                               mapzen_search_place_list_req *places_req = (mapzen_search_place_list_req *) req->request;
+
+                               if (places_req->requestId == request_id) {
+                                       /* Means the request is pending in queue. Not started yet */
+                                       /* Deleting the request from the request queue */
+                                       pthread_mutex_lock(&__requestLock);
+                                       requestList = g_list_remove(requestList, (gpointer)req);
+                                       pthread_mutex_unlock(&__requestLock);
+                                       mapzen_search_req_s *place_req_details = (mapzen_search_req_s *)places_req->req_details;
+
+                                       if (place_req_details)
+                                               g_free(place_req_details);
+                                       place_req_details = NULL;
+
+                                       g_free(places_req);
+                                       places_req = NULL;
+
+                                       g_free(req);
+                                       req = NULL;
+
+                                       __remove_from_cancel_list(request_id);
+
+                                       is_request_cancelled = true;
+                                       break;
+                               }
                        }
                }
 
@@ -425,7 +551,23 @@ static gboolean __timeout_cb(gpointer data)
                                                } else if (req->type == REQ_TYPE_PLACES) {
                                                        mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
                                                        if (places_req) {
-                                                               start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+                                                               start_place_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_DETAILS) {
+                                                       mapzen_get_place_details_req *places_req = (mapzen_get_place_details_req *) req->request;
+                                                       if (places_req) {
+                                                               start_place_details_service(places_req->req_details, places_req->get_place_details_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_LIST) {
+                                                       mapzen_search_place_list_req *places_req = (mapzen_search_place_list_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_list_service(places_req->req_details, places_req->search_place_list_cb, places_req->requestId, places_req->user_data);
 
                                                                g_free(places_req);
                                                                places_req = NULL;
@@ -498,7 +640,23 @@ static gboolean __timeout_cb(gpointer data)
                                                } else if (req->type == REQ_TYPE_PLACES) {
                                                        mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
                                                        if (places_req) {
-                                                               start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+                                                               start_place_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_DETAILS) {
+                                                       mapzen_get_place_details_req *places_req = (mapzen_get_place_details_req *) req->request;
+                                                       if (places_req) {
+                                                               start_place_details_service(places_req->req_details, places_req->get_place_details_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_LIST) {
+                                                       mapzen_search_place_list_req *places_req = (mapzen_search_place_list_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_list_service(places_req->req_details, places_req->search_place_list_cb, places_req->requestId, places_req->user_data);
 
                                                                g_free(places_req);
                                                                places_req = NULL;
@@ -570,7 +728,23 @@ static gboolean __timeout_cb(gpointer data)
                                                } else if (req->type == REQ_TYPE_PLACES) {
                                                        mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
                                                        if (places_req) {
-                                                               start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+                                                               start_place_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_DETAILS) {
+                                                       mapzen_get_place_details_req *places_req = (mapzen_get_place_details_req *) req->request;
+                                                       if (places_req) {
+                                                               start_place_details_service(places_req->req_details, places_req->get_place_details_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_LIST) {
+                                                       mapzen_search_place_list_req *places_req = (mapzen_search_place_list_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_list_service(places_req->req_details, places_req->search_place_list_cb, places_req->requestId, places_req->user_data);
 
                                                                g_free(places_req);
                                                                places_req = NULL;
@@ -598,18 +772,194 @@ static gboolean __timeout_cb(gpointer data)
 
                case RESP_TYPE_PLACES:
                        {
-                               MapzenPlaceResponseData *placesData = (MapzenPlaceResponseData *) (response->data);
+                               MapzenPlaceResponseData *placesData = (MapzenPlaceResponseData *) (response->data);
+                               if (placesData != NULL) {
+                                       MAP_DEBUG("Sending places result.");
+                                       if (__is_request_in_cancel_list(placesData->requestId) == false) {
+                                               /* Deliver results to consumer */
+                                               placesData->place_search_cb(placesData->error, placesData->requestId, placesData->places, placesData->user_data);
+                                       } else {
+                                               /* If present in cancel list, dont trigger the response. */
+                                               /* Remove the requestId from cancel list. */
+                                               __remove_from_cancel_list(placesData->requestId);
+                                       }
+                                       __free_place_response(placesData);
+
+                                       g_free(placesData);
+                                       placesData = NULL;
+                               }
+
+                               /* Start the Next valid request */
+                               if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+                                       MAP_DEBUG("Fetching the next request from the request list....");
+                                       mapzen_request_s *req = get_next_request();
+                                       if (req) {
+                                               pthread_mutex_lock(&__requestLock);
+                                               requestList = g_list_remove(requestList, (gpointer)req);
+                                               pthread_mutex_unlock(&__requestLock);
+
+                                               if (req->type == REQ_TYPE_GEOCODE) {
+                                                       mapzen_geocode_req *geocode_req = (mapzen_geocode_req *) req->request;
+                                                       if (geocode_req != NULL) {
+                                                               start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+                                                               g_free(geocode_req);
+                                                               geocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_REVGEOCODE) {
+                                                       mapzen_revgeocode_req *revgeocode_req = (mapzen_revgeocode_req *) req->request;
+                                                       if (revgeocode_req != NULL) {
+                                                               start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+                                                               g_free(revgeocode_req);
+                                                               revgeocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES) {
+                                                       mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
+                                                       if (places_req) {
+                                                               start_place_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_DETAILS) {
+                                                       mapzen_get_place_details_req *places_req = (mapzen_get_place_details_req *) req->request;
+                                                       if (places_req) {
+                                                               start_place_details_service(places_req->req_details, places_req->get_place_details_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_LIST) {
+                                                       mapzen_search_place_list_req *places_req = (mapzen_search_place_list_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_list_service(places_req->req_details, places_req->search_place_list_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_ROUTE) {
+                                                       mapzen_route_req *route_req = (mapzen_route_req *) req->request;
+                                                       if (route_req) {
+                                                               start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+                                                               g_free(route_req);
+                                                               route_req = NULL;
+                                                       }
+                                               }
+
+                                               g_free(req);
+                                               req = NULL;
+                                       } else {
+                                               MAP_DEBUG("No request in queue or request type is wrong");
+                                       }
+                               } else {
+                                       MAP_DEBUG("Libcurl request queue is FULL..");
+                               }
+                       }
+                       break;
+               case RESP_TYPE_PLACES_DETAILS:
+                       {
+                               MapzenPlaceDetailsResponseData *placesData = (MapzenPlaceDetailsResponseData *) (response->data);
+                               if (placesData != NULL) {
+                                       MAP_DEBUG("Sending places details result.");
+                                       if (__is_request_in_cancel_list(placesData->requestId) == false) {
+                                               /* Deliver results to consumer */
+                                               placesData->get_place_details_cb(placesData->error, placesData->requestId, placesData->places, placesData->user_data);
+                                       } else {
+                                               /* If present in cancel list, dont trigger the response. */
+                                               /* Remove the requestId from cancel list. */
+                                               __remove_from_cancel_list(placesData->requestId);
+                                       }
+                                       __free_place_details_response(placesData);
+
+                                       g_free(placesData);
+                                       placesData = NULL;
+                               }
+
+                               /* Start the Next valid request */
+                               if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+                                       MAP_DEBUG("Fetching the next request from the request list....");
+                                       mapzen_request_s *req = get_next_request();
+                                       if (req) {
+                                               pthread_mutex_lock(&__requestLock);
+                                               requestList = g_list_remove(requestList, (gpointer)req);
+                                               pthread_mutex_unlock(&__requestLock);
+
+                                               if (req->type == REQ_TYPE_GEOCODE) {
+                                                       mapzen_geocode_req *geocode_req = (mapzen_geocode_req *) req->request;
+                                                       if (geocode_req != NULL) {
+                                                               start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+                                                               g_free(geocode_req);
+                                                               geocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_REVGEOCODE) {
+                                                       mapzen_revgeocode_req *revgeocode_req = (mapzen_revgeocode_req *) req->request;
+                                                       if (revgeocode_req != NULL) {
+                                                               start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+                                                               g_free(revgeocode_req);
+                                                               revgeocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES) {
+                                                       mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
+                                                       if (places_req) {
+                                                               start_place_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_DETAILS) {
+                                                       mapzen_get_place_details_req *places_req = (mapzen_get_place_details_req *) req->request;
+                                                       if (places_req) {
+                                                               start_place_details_service(places_req->req_details, places_req->get_place_details_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_LIST) {
+                                                       mapzen_search_place_list_req *places_req = (mapzen_search_place_list_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_list_service(places_req->req_details, places_req->search_place_list_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_ROUTE) {
+                                                       mapzen_route_req *route_req = (mapzen_route_req *) req->request;
+                                                       if (route_req) {
+                                                               start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+                                                               g_free(route_req);
+                                                               route_req = NULL;
+                                                       }
+                                               }
+
+                                               g_free(req);
+                                               req = NULL;
+                                       } else {
+                                               MAP_DEBUG("No request in queue or request type is wrong");
+                                       }
+                               } else {
+                                       MAP_DEBUG("Libcurl request queue is FULL..");
+                               }
+                       }
+                       break;
+               case RESP_TYPE_PLACES_LIST:
+                       {
+                               MapzenPlaceListResponseData *placesData = (MapzenPlaceListResponseData *) (response->data);
                                if (placesData != NULL) {
-                                       MAP_DEBUG("Sending places result..");
+                                       MAP_DEBUG("Sending places list result.");
                                        if (__is_request_in_cancel_list(placesData->requestId) == false) {
                                                /* Deliver results to consumer */
-                                               placesData->place_search_cb(placesData->error, placesData->requestId, placesData->places, placesData->user_data);
+                                               placesData->place_list_search_cb(placesData->error, placesData->requestId, placesData->places, placesData->user_data);
                                        } else {
                                                /* If present in cancel list, dont trigger the response. */
                                                /* Remove the requestId from cancel list. */
                                                __remove_from_cancel_list(placesData->requestId);
                                        }
-                                       __free_place_response(placesData);
+                                       __free_place_list_response(placesData);
 
                                        g_free(placesData);
                                        placesData = NULL;
@@ -643,7 +993,23 @@ static gboolean __timeout_cb(gpointer data)
                                                } else if (req->type == REQ_TYPE_PLACES) {
                                                        mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
                                                        if (places_req) {
-                                                               start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+                                                               start_place_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_DETAILS) {
+                                                       mapzen_get_place_details_req *places_req = (mapzen_get_place_details_req *) req->request;
+                                                       if (places_req) {
+                                                               start_place_details_service(places_req->req_details, places_req->get_place_details_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES_LIST) {
+                                                       mapzen_search_place_list_req *places_req = (mapzen_search_place_list_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_list_service(places_req->req_details, places_req->search_place_list_cb, places_req->requestId, places_req->user_data);
 
                                                                g_free(places_req);
                                                                places_req = NULL;
@@ -668,7 +1034,6 @@ static gboolean __timeout_cb(gpointer data)
                                }
                        }
                        break;
-
                default:
                        MAP_DEBUG("UNKNOWN RESPONSE TYPE");
                        break;
@@ -819,14 +1184,194 @@ static void __free_place_response(void *ptr)
                                mapzen_place->address = NULL;
                        }
 
-                       if (mapzen_place->category) {
-                               g_free(mapzen_place->category);
-                               mapzen_place->category = NULL;
+                       if (mapzen_place->categories) {
+                               if (g_list_length(mapzen_place->categories) > 0) {
+
+                                       g_list_foreach(mapzen_place->categories, (GFunc)g_free, NULL);
+                                       g_list_free(mapzen_place->categories);
+                                       mapzen_place->categories = NULL;
+                               }
+                       }
+
+                       if (mapzen_place->place_id) {
+                               g_free(mapzen_place->place_id);
+                               mapzen_place->place_id = NULL;
+                       }
+
+                       if (mapzen_place->display_name) {
+                               g_free(mapzen_place->display_name);
+                               mapzen_place->display_name = NULL;
+                       }
+
+                       placeData->places = g_list_remove(placeData->places, (gpointer)mapzen_place);
+
+                       g_free(mapzen_place);
+                       mapzen_place = NULL;
+
+                       place = g_list_first(placeData->places);
+               }
+               g_list_free(placeData->places);
+               placeData->places = NULL;
+
+               if (placeData->user_data) {
+                       g_free(placeData->user_data);
+                       placeData->user_data = NULL;
+               }
+       }
+}
+
+static void __free_place_details_response(void *ptr)
+{
+       MapzenPlaceDetailsResponseData *placeData = (MapzenPlaceDetailsResponseData *) (ptr);
+       if (placeData) {
+               GList *place = NULL;
+               place = g_list_first(placeData->places);
+
+               while (place) {
+                       mapzen_place_resp_s *mapzen_place = (mapzen_place_resp_s *) place->data;
+
+                       if (mapzen_place->address) {
+                                       if (mapzen_place->address->street) {
+                                               g_free(mapzen_place->address->street);
+                                               mapzen_place->address->street = NULL;
+                                       }
+                                       if (mapzen_place->address->neighbourhood) {
+                                               g_free(mapzen_place->address->neighbourhood);
+                                               mapzen_place->address->neighbourhood = NULL;
+                                       }
+                                       if (mapzen_place->address->housenumber) {
+                                               g_free(mapzen_place->address->housenumber);
+                                               mapzen_place->address->housenumber = NULL;
+                                       }
+                                       if (mapzen_place->address->localadmin) {
+                                               g_free(mapzen_place->address->localadmin);
+                                               mapzen_place->address->localadmin = NULL;
+                                       }
+                                       if (mapzen_place->address->county) {
+                                               g_free(mapzen_place->address->county);
+                                               mapzen_place->address->county = NULL;
+                                       }
+                                       if (mapzen_place->address->region) {
+                                               g_free(mapzen_place->address->region);
+                                               mapzen_place->address->region = NULL;
+                                       }
+                                       if (mapzen_place->address->country) {
+                                               g_free(mapzen_place->address->country);
+                                               mapzen_place->address->country = NULL;
+                                       }
+                                       if (mapzen_place->address->country_a) {
+                                               g_free(mapzen_place->address->country_a);
+                                               mapzen_place->address->country_a = NULL;
+                                       }
+                                       if (mapzen_place->address->postalcode) {
+                                               g_free(mapzen_place->address->postalcode);
+                                               mapzen_place->address->postalcode = NULL;
+                                       }
+                               g_free(mapzen_place->address);
+                               mapzen_place->address = NULL;
+                       }
+
+                       if (mapzen_place->categories) {
+                               if (g_list_length(mapzen_place->categories) > 0) {
+
+                                       g_list_foreach(mapzen_place->categories, (GFunc)g_free, NULL);
+                                       g_list_free(mapzen_place->categories);
+                                       mapzen_place->categories = NULL;
+                               }
+                       }
+
+                       if (mapzen_place->place_id) {
+                               g_free(mapzen_place->place_id);
+                               mapzen_place->place_id = NULL;
+                       }
+
+                       if (mapzen_place->display_name) {
+                               g_free(mapzen_place->display_name);
+                               mapzen_place->display_name = NULL;
+                       }
+
+                       placeData->places = g_list_remove(placeData->places, (gpointer)mapzen_place);
+
+                       g_free(mapzen_place);
+                       mapzen_place = NULL;
+
+                       place = g_list_first(placeData->places);
+               }
+               g_list_free(placeData->places);
+               placeData->places = NULL;
+
+               if (placeData->user_data) {
+                       g_free(placeData->user_data);
+                       placeData->user_data = NULL;
+               }
+       }
+}
+
+static void __free_place_list_response(void *ptr)
+{
+       MapzenPlaceListResponseData *placeData = (MapzenPlaceListResponseData *) (ptr);
+       if (placeData) {
+               GList *place = NULL;
+               place = g_list_first(placeData->places);
+
+               while (place) {
+                       mapzen_place_resp_s *mapzen_place = (mapzen_place_resp_s *) place->data;
+
+                       if (mapzen_place->address) {
+                                       if (mapzen_place->address->street) {
+                                               g_free(mapzen_place->address->street);
+                                               mapzen_place->address->street = NULL;
+                                       }
+                                       if (mapzen_place->address->neighbourhood) {
+                                               g_free(mapzen_place->address->neighbourhood);
+                                               mapzen_place->address->neighbourhood = NULL;
+                                       }
+                                       if (mapzen_place->address->housenumber) {
+                                               g_free(mapzen_place->address->housenumber);
+                                               mapzen_place->address->housenumber = NULL;
+                                       }
+                                       if (mapzen_place->address->localadmin) {
+                                               g_free(mapzen_place->address->localadmin);
+                                               mapzen_place->address->localadmin = NULL;
+                                       }
+                                       if (mapzen_place->address->county) {
+                                               g_free(mapzen_place->address->county);
+                                               mapzen_place->address->county = NULL;
+                                       }
+                                       if (mapzen_place->address->region) {
+                                               g_free(mapzen_place->address->region);
+                                               mapzen_place->address->region = NULL;
+                                       }
+                                       if (mapzen_place->address->country) {
+                                               g_free(mapzen_place->address->country);
+                                               mapzen_place->address->country = NULL;
+                                       }
+                                       if (mapzen_place->address->country_a) {
+                                               g_free(mapzen_place->address->country_a);
+                                               mapzen_place->address->country_a = NULL;
+                                       }
+                                       if (mapzen_place->address->postalcode) {
+                                               g_free(mapzen_place->address->postalcode);
+                                               mapzen_place->address->postalcode = NULL;
+                                       }
+                               g_free(mapzen_place->address);
+                               mapzen_place->address = NULL;
+                       }
+
+                       if (mapzen_place->categories) {
+                               if (g_list_length(mapzen_place->categories) > 0) {
+
+                                       g_list_foreach(mapzen_place->categories, (GFunc)g_free, NULL);
+                                       g_list_free(mapzen_place->categories);
+                                       mapzen_place->categories = NULL;
+                               }
                        }
-                       if (mapzen_place->subcategory) {
-                               g_free(mapzen_place->subcategory);
-                               mapzen_place->subcategory = NULL;
+
+                       if (mapzen_place->place_id) {
+                               g_free(mapzen_place->place_id);
+                               mapzen_place->place_id = NULL;
                        }
+
                        if (mapzen_place->display_name) {
                                g_free(mapzen_place->display_name);
                                mapzen_place->display_name = NULL;
@@ -998,6 +1543,28 @@ int mapzen_deinit_queue()
                                        }
                                }
                                break;
+                       case RESP_TYPE_PLACES_DETAILS:
+                               {
+                                       MapzenPlaceDetailsResponseData *placeData = (MapzenPlaceDetailsResponseData *) (response->data);
+                                       if (placeData != NULL) {
+                                               __free_place_details_response(placeData);
+
+                                               g_free(placeData);
+                                               placeData = NULL;
+                                       }
+                               }
+                               break;
+                       case RESP_TYPE_PLACES_LIST:
+                               {
+                                       MapzenPlaceListResponseData *placeData = (MapzenPlaceListResponseData *) (response->data);
+                                       if (placeData != NULL) {
+                                               __free_place_list_response(placeData);
+
+                                               g_free(placeData);
+                                               placeData = NULL;
+                                       }
+                               }
+                               break;
                        case RESP_TYPE_ROUTE:
                                {
                                        MapzenRouteResponseData *routeData = (MapzenRouteResponseData *) (response->data);
@@ -1197,13 +1764,15 @@ int start_route_service(mapzen_route_req_s *req_details, mapzen_route_cb callbac
        return MAPZEN_ERROR_NONE;
 }
 
-int start_places_service(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data)
+int start_place_service(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data)
 {
+       MAP_DEBUG("Inside start_place_service.");
+
        int num_running_req = get_num_running_requests();
 
        if (num_running_req >= CURL_MAX_CONNECTS) {
                /* Add the request to queue */
-               add_to_places_list(req_details, callback, request_id, user_data);
+               add_to_place_list(req_details, callback, request_id, user_data);
        } else {
                MapzenPlaceQueryData *queryData = (MapzenPlaceQueryData *)g_malloc0(sizeof(MapzenPlaceQueryData));
 
@@ -1212,7 +1781,89 @@ int start_places_service(mapzen_search_req_s *req_details, mapzen_place_search_c
                        queryData->place_search_cb = callback;
                        queryData->user_data = user_data;
 
-                       query_places(req_details->maps_key, req_details->search_string, req_details->boundary, req_details->num_res, queryData);
+                       query_places(req_details->maps_key, req_details->search_string, req_details->categories, req_details->boundary, req_details->num_res, queryData, REQ_TYPE_PLACES);
+               }
+
+               if (req_details) {
+                       if (req_details->maps_key) {
+                               g_free(req_details->maps_key);
+                               req_details->maps_key = NULL;
+                       }
+                       if (req_details->boundary) {
+                               g_free(req_details->boundary);
+                               req_details->boundary = NULL;
+                       }
+                       if (req_details->search_string) {
+                               g_free(req_details->search_string);
+                               req_details->search_string = NULL;
+                       }
+                       if (req_details->categories) {
+                               g_free(req_details->categories);
+                               req_details->categories = NULL;
+                       }
+                       g_free(req_details);
+                       req_details = NULL;
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int start_place_details_service(mapzen_get_details_req_s *req_details, mapzen_get_place_details_cb callback, int request_id, void *user_data)
+{
+       MAP_DEBUG("Inside start_place_service.");
+
+       int num_running_req = get_num_running_requests();
+
+       if (num_running_req >= CURL_MAX_CONNECTS) {
+               /* Add the request to queue */
+               add_to_place_details_list(req_details, callback, request_id, user_data);
+       } else {
+               MapzenPlaceDetailsQueryData *queryData = (MapzenPlaceDetailsQueryData *)g_malloc0(sizeof(MapzenPlaceDetailsQueryData));
+
+               if (queryData != NULL) {
+                       queryData->requestId = request_id;
+                       queryData->get_place_details_cb = callback;
+                       queryData->user_data = user_data;
+
+                       query_place_details(req_details->maps_key, req_details->uri, queryData);
+               }
+
+               if (req_details) {
+                       if (req_details->maps_key) {
+                               g_free(req_details->maps_key);
+                               req_details->maps_key = NULL;
+                       }
+                       if (req_details->uri) {
+                               g_free(req_details->uri);
+                               req_details->uri = NULL;
+                       }
+                       g_free(req_details);
+                       req_details = NULL;
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int start_places_list_service(mapzen_search_req_s *req_details, mapzen_place_list_search_cb callback, int request_id, void *user_data)
+{
+       MAP_DEBUG("Inside start_places_list_service.");
+
+       int num_running_req = get_num_running_requests();
+
+       if (num_running_req >= CURL_MAX_CONNECTS) {
+               /* Add the request to queue */
+               add_to_places_list(req_details, callback, request_id, user_data);
+       } else {
+               MapzenPlaceListQueryData *queryData = (MapzenPlaceListQueryData *)g_malloc0(sizeof(MapzenPlaceListQueryData));
+
+               if (queryData != NULL) {
+                       queryData->requestId = request_id;
+                       queryData->place_list_search_cb = callback;
+                       queryData->user_data = user_data;
+
+                       query_places(req_details->maps_key, req_details->search_string, req_details->categories, req_details->boundary, req_details->num_res, queryData, REQ_TYPE_PLACES_LIST);
                }
 
                if (req_details) {
@@ -1228,6 +1879,10 @@ int start_places_service(mapzen_search_req_s *req_details, mapzen_place_search_c
                                g_free(req_details->search_string);
                                req_details->search_string = NULL;
                        }
+                       if (req_details->categories) {
+                               g_free(req_details->categories);
+                               req_details->categories = NULL;
+                       }
                        g_free(req_details);
                        req_details = NULL;
                }
index 3d0d73c..a06a6be 100644 (file)
@@ -53,17 +53,35 @@ typedef struct {
        void *user_data;
 } mapzen_search_place_req;
 
+typedef struct {
+       mapzen_get_details_req_s *req_details;
+       mapzen_get_place_details_cb get_place_details_cb;
+       int requestId;
+       void *user_data;
+} mapzen_get_place_details_req;
+
+typedef struct {
+       mapzen_search_req_s *req_details;
+       mapzen_place_list_search_cb search_place_list_cb;
+       int requestId;
+       void *user_data;
+} mapzen_search_place_list_req;
+
 int add_to_geocode_list(mapzen_geocode_req_s *req_details, mapzen_geocode_cb callback, int request_id, void *user_data);
 int add_to_revgeocode_list(mapzen_revgeocode_req_s *req_details, mapzen_reverse_geocode_cb callback, int request_id, void *user_data);
 int add_to_route_list(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data);
-int add_to_places_list(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data);
+int add_to_place_list(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data);
+int add_to_place_details_list(mapzen_get_details_req_s *req_details, mapzen_get_place_details_cb callback, int request_id, void *user_data);
+int add_to_places_list(mapzen_search_req_s *req_details, mapzen_place_list_search_cb callback, int request_id, void *user_data);
 
 int remove_from_request_list(int request_id);
 
 int start_geocode_service(mapzen_geocode_req_s *req_details, mapzen_geocode_cb callback, int request_id, void *user_data);
 int start_reversegeocode_service(mapzen_revgeocode_req_s *req_details, mapzen_reverse_geocode_cb callback, int request_id, void *user_data);
 int start_route_service(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data);
-int start_places_service(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data);
+int start_place_service(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data);
+int start_place_details_service(mapzen_get_details_req_s *req_details, mapzen_get_place_details_cb callback, int request_id, void *user_data);
+int start_places_list_service(mapzen_search_req_s *req_details, mapzen_place_list_search_cb callback, int request_id, void *user_data);
 
 int mapzen_init_queue();
 int mapzen_deinit_queue();
index a8d8928..f69b708 100644 (file)
@@ -325,6 +325,7 @@ static int __progress_info(void *p, double dltotal, double dlnow, double ultotal
 
 int add_handle(const char *url, mapzen_req_type type, void *user_data)
 {
+
        if (!url || !user_data) return -1;
 
        int req_id = -1;
@@ -339,6 +340,12 @@ int add_handle(const char *url, mapzen_req_type type, void *user_data)
        case REQ_TYPE_PLACES:
                req_id = ((MapzenPlaceQueryData *) user_data)->requestId;
                break;
+       case REQ_TYPE_PLACES_LIST:
+               req_id = ((MapzenPlaceListQueryData *) user_data)->requestId;
+               break;
+       case REQ_TYPE_PLACES_DETAILS:
+               req_id = ((MapzenPlaceDetailsQueryData *) user_data)->requestId;
+               break;
        case REQ_TYPE_ROUTE:
                req_id = ((MapzenRouteQueryData *) user_data)->requestId;
                break;
@@ -421,6 +428,12 @@ static void __post_curl(mapzen_req_type type, MemoryStruct_s *m_chunk, void *use
        case REQ_TYPE_PLACES:
                resp_type = RESP_TYPE_PLACES;
                break;
+       case REQ_TYPE_PLACES_LIST:
+               resp_type = RESP_TYPE_PLACES_LIST;
+               break;
+       case REQ_TYPE_PLACES_DETAILS:
+               resp_type = RESP_TYPE_PLACES_DETAILS;
+               break;
        case REQ_TYPE_ROUTE:
                resp_type = RESP_TYPE_ROUTE;
                break;
@@ -635,6 +648,32 @@ int deinit_curl()
                                        }
                                }
                                        break;
+                               case REQ_TYPE_PLACES_DETAILS:
+                               {
+                                       MapzenPlaceDetailsQueryData *queryData = (MapzenPlaceDetailsQueryData *)curlArg->user_data;
+                                       if (queryData) {
+                                               if (queryData->user_data) {
+                                                       g_free(queryData->user_data);
+                                                       queryData->user_data = NULL;
+                                               }
+                                               g_free(queryData);
+                                               queryData = NULL;
+                                       }
+                               }
+                                       break;
+                               case REQ_TYPE_PLACES_LIST:
+                               {
+                                       MapzenPlaceListQueryData *queryData = (MapzenPlaceListQueryData *)curlArg->user_data;
+                                       if (queryData) {
+                                               if (queryData->user_data) {
+                                                       g_free(queryData->user_data);
+                                                       queryData->user_data = NULL;
+                                               }
+                                               g_free(queryData);
+                                               queryData = NULL;
+                                       }
+                               }
+                                       break;
                                case REQ_TYPE_ROUTE:
                                {
                                        MapzenRouteQueryData *queryData = (MapzenRouteQueryData *)curlArg->user_data;
index c688b8e..f587cd9 100644 (file)
@@ -23,6 +23,8 @@ typedef enum {
        REQ_TYPE_GEOCODE = 0,
        REQ_TYPE_REVGEOCODE,
        REQ_TYPE_PLACES,
+       REQ_TYPE_PLACES_LIST,
+       REQ_TYPE_PLACES_DETAILS,
        REQ_TYPE_ROUTE,
        REQ_TYPE_NONE
 } mapzen_req_type;
@@ -31,6 +33,8 @@ typedef enum {
        RESP_TYPE_GEOCODE = 0,
        RESP_TYPE_REVGEOCODE,
        RESP_TYPE_PLACES,
+       RESP_TYPE_PLACES_LIST,
+       RESP_TYPE_PLACES_DETAILS,
        RESP_TYPE_ROUTE,
        RESP_TYPE_NONE
 } mapzen_resp_type;
@@ -63,6 +67,18 @@ typedef struct {
 } MapzenPlaceQueryData;
 
 typedef struct {
+       int requestId;
+       mapzen_place_list_search_cb place_list_search_cb;
+       void *user_data;
+} MapzenPlaceListQueryData;
+
+typedef struct {
+       int requestId;
+       mapzen_get_place_details_cb get_place_details_cb;
+       void *user_data;
+} MapzenPlaceDetailsQueryData;
+
+typedef struct {
        mapzen_error_e error;
        int requestId;
        mapzen_geocode_cb geocode_cb;
@@ -95,6 +111,22 @@ typedef struct {
 } MapzenPlaceResponseData;
 
 typedef struct {
+       mapzen_error_e error;
+       int requestId;
+       mapzen_get_place_details_cb get_place_details_cb;
+       GList *places;
+       void *user_data;
+} MapzenPlaceDetailsResponseData;
+
+typedef struct {
+       mapzen_error_e error;
+       int requestId;
+       mapzen_place_list_search_cb place_list_search_cb;
+       GList *places;
+       void *user_data;
+} MapzenPlaceListResponseData;
+
+typedef struct {
        mapzen_resp_type type;
        void *data;
 } MapzenQueueData;
index ddf1264..2c41b02 100644 (file)
@@ -111,14 +111,18 @@ typedef struct {
 typedef struct {
        gchar *maps_key;
        gchar *search_string;
+       gchar *categories;
        gint num_res;
-       gchar *country_code;
        mapzen_boundary_s *boundary;
-       GList *excludes;
 } mapzen_search_req_s;
 
 typedef struct {
        gchar *maps_key;
+       gchar *uri;
+} mapzen_get_details_req_s;
+
+typedef struct {
+       gchar *maps_key;
        coords_s from;
        coords_s to;
        route_unit unit;
@@ -149,11 +153,8 @@ typedef struct {
        gchar *place_id;
        gchar *display_name;
        mapzen_address_resp_s *address;
-       rectangle_s bounding_box;
        coords_s coordinates;
-       gchar *category;
-       gchar *subcategory;
-       gchar *icon_url;
+       GList *categories;
 } mapzen_place_resp_s;
 
 typedef struct {
index 069b525..0d2a9e2 100644 (file)
@@ -113,41 +113,6 @@ static maps_route_turn_type_e __convert_route_turn_type(int index)
        return type;
 }*/
 
-static bool __replace_space(char *place_name, char **modified_place_name)
-{
-       if (!place_name) return false;
-
-       int new_str_len = 0;
-       char *ch;
-       for (ch = place_name; *ch != '\0'; ch++) {
-               if (*ch == ' ')
-                       new_str_len += 2;
-               new_str_len++;
-       }
-
-       if (strlen(place_name) < new_str_len) {
-               *modified_place_name = (char *)g_malloc((new_str_len + 1) * sizeof(char));
-               if (*modified_place_name) {
-                       char *ch1, *ch2;
-                       for (ch1 = place_name, ch2 = *modified_place_name; *ch1 != '\0'; ch1++) {
-                               if (*ch1 == ' ') {
-                                       ch2[0] = '%';
-                                       ch2[1] = '2';
-                                       ch2[2] = '0';
-                                       ch2 += 3;
-                               } else {
-                                       *ch2 = *ch1;
-                                       ch2++;
-                               }
-                       }
-                       *ch2 = '\0';
-
-                       return true;
-               }
-       }
-       return false;
-}
-
 
 /*MASSIVE TODO:
  *
@@ -159,10 +124,6 @@ static bool __replace_space(char *place_name, char **modified_place_name)
 EXPORT_API int maps_plugin_multi_reverse_geocode(const maps_coordinates_list_h geocode_list,
        const maps_preference_h preference, maps_service_multi_reverse_geocode_cb callback,
        void *user_data, int *request_id){return  MAPS_ERROR_NOT_SUPPORTED ;}
-EXPORT_API int maps_plugin_search_place_list(const maps_area_h boundary, const maps_place_filter_h filter,
-       maps_preference_h preference, maps_service_search_place_list_cb callback, void* user_data, int* request_id){return  MAPS_ERROR_NOT_SUPPORTED ;}
-EXPORT_API int maps_plugin_get_place_details(const char* url,
-       maps_service_get_place_details_cb callback, void* user_data, int* request_id){return  MAPS_ERROR_NOT_SUPPORTED ;}
 EXPORT_API int maps_plugin_create_map_view(maps_view_h hView, maps_plugin_map_view_ready_cb pCbFunc){return  MAPS_ERROR_NOT_SUPPORTED ;}
 EXPORT_API int maps_plugin_destroy_map_view(maps_view_h hView){return  MAPS_ERROR_NOT_SUPPORTED ;}
 EXPORT_API int maps_plugin_render_map(maps_view_h hView,
@@ -223,6 +184,7 @@ EXPORT_API int maps_plugin_shutdown(maps_plugin_h plugin)
 
 EXPORT_API int maps_plugin_is_service_supported(maps_service_e service, bool *supported)
 {
+
        if (!supported)
                return MAPS_ERROR_INVALID_PARAMETER;
 
@@ -232,8 +194,10 @@ EXPORT_API int maps_plugin_is_service_supported(maps_service_e service, bool *su
        case MAPS_SERVICE_GEOCODE_BY_STRUCTURED_ADDRESS:
        case MAPS_SERVICE_REVERSE_GEOCODE:
        case MAPS_SERVICE_SEARCH_PLACE:
+       case MAPS_SERVICE_SEARCH_PLACE_LIST:
        case MAPS_SERVICE_SEARCH_PLACE_BY_AREA:
        case MAPS_SERVICE_SEARCH_PLACE_BY_ADDRESS:
+       case MAPS_SERVICE_SEARCH_GET_PLACE_DETAILS:
        case MAPS_SERVICE_SEARCH_ROUTE:
        case MAPS_SERVICE_SEARCH_ROUTE_WAYPOINTS:
        case MAPS_SERVICE_CANCEL_REQUEST:
@@ -243,6 +207,8 @@ EXPORT_API int maps_plugin_is_service_supported(maps_service_e service, bool *su
                *supported = false;
                return MAPS_ERROR_NOT_SUPPORTED;
        }
+
+
 }
 
 EXPORT_API int maps_plugin_is_data_supported(maps_service_data_e data, bool *supported)
@@ -375,20 +341,7 @@ EXPORT_API int maps_plugin_geocode(const char *address, const maps_preference_h
                MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
        }
 
-       char *modified_address = NULL;
-       bool b_isAddress_modified = false;
-       b_isAddress_modified = __replace_space((char *)address, &modified_address);
-
-       if (b_isAddress_modified)
-               geocode_req->address = g_strdup((gchar *) modified_address);
-       else
-               geocode_req->address = g_strdup((gchar *) address);
-
-       if (modified_address) {
-               g_free(modified_address);
-               modified_address = NULL;
-       }
-
+       geocode_req->address = g_strdup((gchar *) address);
        geocode_req->maps_key = g_strdup((gchar *) __provider_key);
        geocode_req->boundary = NULL;
 
@@ -426,20 +379,7 @@ EXPORT_API int maps_plugin_geocode_inside_area(const char *address, const maps_a
                MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
        }
 
-       char *modified_address = NULL;
-       bool b_isAddress_modified = false;
-       b_isAddress_modified = __replace_space((char *)address, &modified_address);
-
-       if (b_isAddress_modified)
-               geocode_req->address = g_strdup((gchar *) modified_address);
-       else
-               geocode_req->address = g_strdup((gchar *) address);
-
-       if (modified_address) {
-               g_free(modified_address);
-               modified_address = NULL;
-       }
-
+       geocode_req->address = g_strdup((gchar *) address);
        geocode_req->maps_key = g_strdup((gchar *) __provider_key);
 
        int max_result = 0;
@@ -498,35 +438,53 @@ EXPORT_API int maps_plugin_geocode_by_structured_address(const maps_address_h ad
 
        char resultAddressQuery[1024] = "";
 
+       char *house_number = NULL;
+       maps_address_get_building_number(address, &house_number);
+
        char *street = NULL;
        maps_address_get_street(address, &street);
-       if (street != NULL)
+       if (street != NULL) {
+               if (house_number != NULL) {
+                       STRCAT(resultAddressQuery, house_number);
+                       STRCAT(resultAddressQuery, " ");
+               }
                STRCAT(resultAddressQuery, street);
+       }
 
        char *city = NULL;
        maps_address_get_city(address, &city);
        if ((strlen(resultAddressQuery) > 0) && (city != NULL)) {
-               STRCAT(resultAddressQuery, ",");
+               STRCAT(resultAddressQuery, ", ");
                STRCAT(resultAddressQuery, city);
        } else if (city != NULL) {
                STRCAT(resultAddressQuery, city);
        }
 
+       char *county = NULL;
+       maps_address_get_county(address, &county);
+       if ((strlen(resultAddressQuery) > 0) && (county != NULL)) {
+               STRCAT(resultAddressQuery, ", ");
+               STRCAT(resultAddressQuery, county);
+       }  else if (county != NULL) {
+               STRCAT(resultAddressQuery, county);
+       }
+
        char *state = NULL;
        maps_address_get_state(address, &state);
        if ((strlen(resultAddressQuery) > 0) && (state != NULL)) {
-               STRCAT(resultAddressQuery, ",");
+               STRCAT(resultAddressQuery, ", ");
                STRCAT(resultAddressQuery, state);
        } else if (state != NULL) {
                STRCAT(resultAddressQuery, state);
        }
 
-#if 0
-       char *district = NULL;
-       maps_address_get_district(address, &district);
-       if ((strlen(resultAddressQuery) > 0) && (district != NULL)) {
+       char *postal_code = NULL;
+       maps_address_get_postal_code(address, &postal_code);
+       if ((strlen(resultAddressQuery) > 0) && (postal_code != NULL)) {
                STRCAT(resultAddressQuery, ", ");
-               STRCAT(resultAddressQuery, district);
+               STRCAT(resultAddressQuery, postal_code);
+       } else if (postal_code != NULL) {
+               STRCAT(resultAddressQuery, postal_code);
        }
 
        char *country = NULL;
@@ -534,48 +492,22 @@ EXPORT_API int maps_plugin_geocode_by_structured_address(const maps_address_h ad
        if ((strlen(resultAddressQuery) > 0) && (country != NULL)) {
                STRCAT(resultAddressQuery, ", ");
                STRCAT(resultAddressQuery, country);
+       } else if (country != NULL) {
+               STRCAT(resultAddressQuery, country);
        }
 
-       char *country_code = NULL;
-       maps_address_get_country_code(address, &country_code);
-       if ((strlen(resultAddressQuery) > 0) && (country_code != NULL)) {
-               STRCAT(resultAddressQuery, ", ");
-               STRCAT(resultAddressQuery, country_code);
-       } else if (country_code != NULL) {
-               STRCAT(resultAddressQuery, country_code);
-       }
-
-       char *county = NULL;
-       maps_address_get_county(address, &county);
-       if ((strlen(resultAddressQuery) > 0) && (county != NULL)) {
-               STRCAT(resultAddressQuery, ", ");
-               STRCAT(resultAddressQuery, county);
-       }
-#endif
-
-       char *postal_code = NULL;
-       maps_address_get_postal_code(address, &postal_code);
-       if ((strlen(resultAddressQuery) > 0) && (postal_code != NULL)) {
-               STRCAT(resultAddressQuery, ",");
-               STRCAT(resultAddressQuery, postal_code);
-       } else if (postal_code != NULL) {
-               STRCAT(resultAddressQuery, postal_code);
-       }
-
-       char *modified_address = NULL;
-       bool b_isAddress_modified = false;
-       b_isAddress_modified = __replace_space(resultAddressQuery, &modified_address);
-
-       if (b_isAddress_modified)
-               geocode_req->address = g_strdup((gchar *) modified_address);
-       else
-               geocode_req->address = g_strdup((gchar *) resultAddressQuery);
-
-       if (modified_address) {
-               g_free(modified_address);
-               modified_address = NULL;
+       if (country == NULL) {
+               char *country_code = NULL;
+               maps_address_get_country_code(address, &country_code);
+               if ((strlen(resultAddressQuery) > 0) && (country_code != NULL)) {
+                       STRCAT(resultAddressQuery, ", ");
+                       STRCAT(resultAddressQuery, country_code);
+               } else if (country_code != NULL) {
+                       STRCAT(resultAddressQuery, country_code);
+               }
        }
 
+       geocode_req->address = g_strdup((gchar *) resultAddressQuery);
        geocode_req->maps_key = g_strdup((gchar *) __provider_key);
        geocode_req->boundary = NULL;
 
@@ -1062,7 +994,6 @@ static void __mapzen_place_search_cb(mapzen_error_e result, int request_id, GLis
                                maps_place_set_id(place, mapzen_place->place_id);
                                maps_place_set_name(place, mapzen_place->display_name);
 
-                               MAPS_LOGD("Before address..");
                                /* Address */
                                if (mapzen_place->address) {
                                        maps_address_h addr = NULL;
@@ -1090,28 +1021,42 @@ static void __mapzen_place_search_cb(mapzen_error_e result, int request_id, GLis
                                maps_place_set_location(place, coord);
                                maps_coordinates_destroy(coord);
 
-                               maps_place_category_h place_cat;
-                               maps_place_category_create(&place_cat);
-                               maps_place_category_set_name(place_cat, mapzen_place->category);
+                               GList *cats = NULL;
+                               cats = g_list_first(mapzen_place->categories);
 
                                maps_item_list_h cat_list;
                                maps_item_list_create(&cat_list);
-                               maps_item_list_append(cat_list, (void *) place_cat, maps_place_category_clone);
-                               maps_place_set_categories(place, cat_list);
 
-                               maps_place_category_destroy(place_cat);
+                               while (cats != NULL) {
+                                       if (cats->data != NULL) {
+                                               maps_place_category_h place_cat;
+                                               maps_place_category_create(&place_cat);
+                                               maps_place_category_set_name(place_cat, cats->data);
+                                               maps_item_list_append(cat_list, (void *) place_cat, maps_place_category_clone);
+                                               maps_place_category_destroy(place_cat);
+                                       }
+                                       cats = g_list_next(cats);
+                               }
+
+                               if (g_list_length(cat_list) > 0) {
+                                       maps_place_set_categories(place, cat_list);
+                                       maps_item_list_remove_all(cat_list, maps_place_category_destroy);
+                               }
                                maps_item_list_destroy(cat_list);
 
-                               maps_place_image_h place_image;
-                               maps_place_image_create(&place_image);
-                               maps_place_image_set_url(place_image, mapzen_place->icon_url);
-                               maps_item_list_h image_list;
-                               maps_item_list_create(&image_list);
-                               maps_item_list_append(image_list, (void *) place_image, maps_place_image_clone);
-                               maps_place_set_images(place, image_list);
+                               // Don't have URLs yet....
+                               //maps_place_image_h place_image = NULL;
+                               //maps_place_image_create(&place_image);
+                               //no url at this time.
+                               //maps_place_image_set_url(place_image, mapzen_place->icon_url);
+                               //maps_item_list_h image_list;
+                               //maps_item_list_create(&image_list);
+                               //maps_item_list_append(image_list, (void *) place_image, maps_place_image_clone);
+                               //maps_place_set_images(place, image_list);
 
-                               maps_place_image_destroy(place_image);
-                               maps_item_list_destroy(image_list);
+                               //maps_place_image_destroy(place_image);
+                               //maps_item_list_remove_all(image_list, maps_place_image_destroy);
+                               //maps_item_list_destroy(image_list);
 
                                bool b = calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, index, total_count, place, calldata_place->data);
                                if (!b)
@@ -1127,6 +1072,209 @@ static void __mapzen_place_search_cb(mapzen_error_e result, int request_id, GLis
        }
 }
 
+static void __mapzen_place_get_details_cb(mapzen_error_e result, int request_id, GList *places, void *user_data)
+{
+       MAPS_LOGD("Got places details result from ENGINE...");
+
+       callback_info_place_details *calldata_place = (callback_info_place_details *) user_data;
+
+       if (result != MAPZEN_ERROR_NONE || places == NULL) {
+               MAPS_LOGD("Got places result from ENGINE...result is NULL");
+               calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, NULL, calldata_place->data);
+       } else {
+               guint total_count = 0;
+               total_count = g_list_length(places);
+               // Should only have one result
+               if (total_count == 1) {
+                       maps_place_h place = NULL;
+                       MAPS_LOGD("Got places details result from ENGINE... count -> %d", total_count);
+
+                       GList *temp_place = NULL;
+                       temp_place = g_list_first(places);
+
+                       if (temp_place) {
+                               maps_place_create(&place);
+                               mapzen_place_resp_s *mapzen_place = (mapzen_place_resp_s *) temp_place->data;
+                               maps_place_set_id(place, mapzen_place->place_id);
+                               maps_place_set_name(place, mapzen_place->display_name);
+
+                               /* Address */
+                               if (mapzen_place->address) {
+                                       maps_address_h addr = NULL;
+                                       maps_address_create(&addr);
+
+                                       maps_address_set_street(addr, mapzen_place->address->street);
+                                       maps_address_set_building_number(addr, mapzen_place->address->housenumber);
+                                       maps_address_set_city(addr, mapzen_place->address->localadmin);
+                                       maps_address_set_county(addr, mapzen_place->address->county);
+                                       maps_address_set_state(addr, mapzen_place->address->region);
+                                       maps_address_set_country(addr, mapzen_place->address->country);
+                                       maps_address_set_country_code(addr, mapzen_place->address->country_a);
+                                       maps_address_set_postal_code(addr, mapzen_place->address->postalcode);
+                                       maps_address_set_freetext(addr, mapzen_place->display_name);
+
+                                       maps_place_set_address(place, addr);
+                                       maps_address_destroy(addr);
+                               } else {
+                                       maps_place_set_address(place, NULL);
+                               }
+
+                               maps_coordinates_h coord;
+                               maps_coordinates_create(mapzen_place->coordinates.latitude, mapzen_place->coordinates.longitude, &coord);
+
+                               maps_place_set_location(place, coord);
+                               maps_coordinates_destroy(coord);
+
+                               GList *cats = NULL;
+                               cats = g_list_first(mapzen_place->categories);
+
+                               maps_item_list_h cat_list;
+                               maps_item_list_create(&cat_list);
+
+                               while (cats != NULL) {
+                                       if (cats->data != NULL) {
+                                               maps_place_category_h place_cat;
+                                               maps_place_category_create(&place_cat);
+                                               maps_place_category_set_name(place_cat, cats->data);
+                                               maps_item_list_append(cat_list, (void *) place_cat, maps_place_category_clone);
+                                               maps_place_category_destroy(place_cat);
+                                       }
+                                       cats = g_list_next(cats);
+                               }
+
+                               if (g_list_length(cat_list) > 0) {
+                                       maps_place_set_categories(place, cat_list);
+                                       maps_item_list_remove_all(cat_list, maps_place_category_destroy);
+                               }
+                               maps_item_list_destroy(cat_list);
+
+                               // Don't have URLs yet....
+                               //maps_place_image_h place_image = NULL;
+                               //maps_place_image_create(&place_image);
+                               //no url at this time.
+                               //maps_place_image_set_url(place_image, mapzen_place->icon_url);
+                               //maps_item_list_h image_list;
+                               //maps_item_list_create(&image_list);
+                               //maps_item_list_append(image_list, (void *) place_image, maps_place_image_clone);
+                               //maps_place_set_images(place, image_list);
+
+                               //maps_place_image_destroy(place_image);
+                               //maps_item_list_remove_all(image_list, maps_place_image_destroy);
+                               //maps_item_list_destroy(image_list);
+
+                               calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, place, calldata_place->data);
+                               return;
+                       }
+               }
+       }
+       calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, NULL, calldata_place->data);
+}
+
+static void __maps_service_search_place_list_cb(mapzen_error_e result, int request_id, GList *places, void *user_data)
+{
+       MAPS_LOGD("Got places result from ENGINE...");
+
+       callback_info_place_list *calldata_place = (callback_info_place_list *) user_data;
+
+       if (result != MAPZEN_ERROR_NONE || places == NULL) {
+               MAPS_LOGD("Got places result from ENGINE...result is NULL");
+               calldata_place->callback((maps_error_e) __convert_to_maps_error(result), calldata_place->reqID, 0, NULL, calldata_place->data);
+       } else {
+               guint total_count = 0;
+               total_count = g_list_length(places);
+               if (total_count > 0) {
+                       maps_place_h place = NULL;
+                       MAPS_LOGD("Got places result from ENGINE... count -> %d", total_count);
+
+                       maps_place_list_h place_list = NULL;
+                       maps_place_list_create(&place_list);
+
+                       GList *temp_place = NULL;
+                       temp_place = g_list_first(places);
+
+                       while (temp_place) {
+                               maps_place_create(&place);
+                               mapzen_place_resp_s *mapzen_place = (mapzen_place_resp_s *) temp_place->data;
+                               maps_place_set_id(place, mapzen_place->place_id);
+                               maps_place_set_name(place, mapzen_place->display_name);
+
+                               /* Address */
+                               if (mapzen_place->address) {
+                                       maps_address_h addr = NULL;
+                                       maps_address_create(&addr);
+
+                                       maps_address_set_street(addr, mapzen_place->address->street);
+                                       maps_address_set_building_number(addr, mapzen_place->address->housenumber);
+                                       maps_address_set_city(addr, mapzen_place->address->localadmin);
+                                       maps_address_set_county(addr, mapzen_place->address->county);
+                                       maps_address_set_state(addr, mapzen_place->address->region);
+                                       maps_address_set_country(addr, mapzen_place->address->country);
+                                       maps_address_set_country_code(addr, mapzen_place->address->country_a);
+                                       maps_address_set_postal_code(addr, mapzen_place->address->postalcode);
+                                       maps_address_set_freetext(addr, mapzen_place->display_name);
+
+                                       maps_place_set_address(place, addr);
+                                       maps_address_destroy(addr);
+                               } else {
+                                       maps_place_set_address(place, NULL);
+                               }
+
+                               maps_coordinates_h coord;
+                               maps_coordinates_create(mapzen_place->coordinates.latitude, mapzen_place->coordinates.longitude, &coord);
+
+                               maps_place_set_location(place, coord);
+                               maps_coordinates_destroy(coord);
+
+                               GList *cats = NULL;
+                               cats = g_list_first(mapzen_place->categories);
+
+                               maps_item_list_h cat_list;
+                               maps_item_list_create(&cat_list);
+
+                               while (cats != NULL) {
+                                       if (cats->data != NULL) {
+                                               maps_place_category_h place_cat;
+                                               maps_place_category_create(&place_cat);
+                                               maps_place_category_set_name(place_cat, cats->data);
+                                               maps_item_list_append(cat_list, (void *) place_cat, maps_place_category_clone);
+                                               maps_place_category_destroy(place_cat);
+                                       }
+                                       cats = g_list_next(cats);
+                               }
+
+                               if (g_list_length(cat_list) > 0) {
+                                       maps_place_set_categories(place, cat_list);
+                                       maps_item_list_remove_all(cat_list, maps_place_category_destroy);
+                               }
+                               maps_item_list_destroy(cat_list);
+
+                               // Don't have URLs yet....
+                               //maps_place_image_h place_image = NULL;
+                               //maps_place_image_create(&place_image);
+                               //no url at this time.
+                               //maps_place_image_set_url(place_image, mapzen_place->icon_url);
+                               //maps_item_list_h image_list;
+                               //maps_item_list_create(&image_list);
+                               //maps_item_list_append(image_list, (void *) place_image, maps_place_image_clone);
+                               //maps_place_set_images(place, image_list);
+
+                               //maps_place_image_destroy(place_image);
+                               //maps_item_list_remove_all(image_list, maps_place_image_destroy);
+                               //maps_item_list_destroy(image_list);
+
+                               maps_item_list_append(place_list, place, maps_place_clone);
+                               maps_place_image_destroy(place);
+                               place = NULL;
+                               temp_place = temp_place->next;
+                       }
+                       calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, total_count, place_list, calldata_place->data);
+
+               } else {
+                       calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, total_count, NULL, calldata_place->data);
+               }
+       }
+}
+
 EXPORT_API int maps_plugin_search_place(const maps_coordinates_h position, int distance, const maps_place_filter_h filter, const maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id)
 {
        if (!position || !filter || !callback || !request_id)
@@ -1161,37 +1309,24 @@ EXPORT_API int maps_plugin_search_place(const maps_coordinates_h position, int d
        MAPS_LOGD("Place Result limit :: %d", place_req->num_res);
 
        char *categoryName = NULL;
-       char *place_name = NULL;
+       char *searchKeyword = NULL;
 
        maps_place_category_h category = NULL;
        maps_place_filter_get_category(filter, &category);
+       maps_place_filter_get_keyword(filter, &searchKeyword);
 
-       if (category)
+       if (category) {
                maps_place_category_get_name(category, &categoryName);
+               maps_place_category_destroy(category);
+       }
 
-       maps_place_filter_get_place_name(filter, &place_name);
-
-       char *modified_place_name = NULL;
-       bool b_isPlaceName_modified = false;
-       if (place_name)
-               b_isPlaceName_modified = __replace_space(place_name, &modified_place_name);
+       if (categoryName)
+               place_req->categories = g_strdup_printf("%s", categoryName);
 
-       MAPS_LOGD("Modified Place String.. ");
-       MAPS_LOGD(" >>>> %s", modified_place_name);
+       if (searchKeyword)
+               place_req->search_string = g_strdup_printf("%s", searchKeyword);
 
-       if (categoryName && place_name) {
-               if (b_isPlaceName_modified)
-                       place_req->search_string = g_strdup_printf("%s[%s]", modified_place_name, categoryName);
-               else
-                       place_req->search_string = g_strdup_printf("%s[%s]", place_name, categoryName);
-       } else if (categoryName) {
-               place_req->search_string = g_strdup_printf("[%s]", categoryName);
-       } else if (place_name) {
-               if (b_isPlaceName_modified)
-                       place_req->search_string = g_strdup_printf("%s", modified_place_name);
-               else
-                       place_req->search_string = g_strdup_printf("%s", place_name);
-       } else {
+       if (!searchKeyword && !categoryName) {
                g_free(calldata_place);
                calldata_place = NULL;
                g_free(place_req);
@@ -1199,12 +1334,17 @@ EXPORT_API int maps_plugin_search_place(const maps_coordinates_h position, int d
                return MAPS_ERROR_INVALID_PARAMETER;
        }
 
-       if (modified_place_name) {
-               g_free(modified_place_name);
-               modified_place_name = NULL;
+       if (searchKeyword) {
+               g_free(searchKeyword);
+               searchKeyword = NULL;
+       }
+
+       if (categoryName) {
+               g_free(categoryName);
+               categoryName = NULL;
        }
 
-       MAPS_LOGD(">>>>>>>> Place search string :: %s <<<<<<<<<", place_req->search_string);
+       MAPS_LOGD(">>>>>>>> Place search categories :: %s <<<<<<<<<", place_req->categories);
 
        place_req->boundary = NULL;
        place_req->boundary = (mapzen_boundary_s *)g_malloc0(sizeof(mapzen_boundary_s));
@@ -1259,34 +1399,24 @@ EXPORT_API int maps_plugin_search_place_by_area(const maps_area_h boundary, cons
        MAPS_LOGD("Place Result limit :: %d", place_req->num_res);
 
        char *categoryName = NULL;
-       char *place_name = NULL;
+       char *searchKeyword = NULL;
 
        maps_place_category_h category = NULL;
        maps_place_filter_get_category(filter, &category);
+       maps_place_filter_get_keyword(filter, &searchKeyword);
 
-       if (category)
+       if (category) {
                maps_place_category_get_name(category, &categoryName);
+               maps_place_category_destroy(category);
+       }
 
-       maps_place_filter_get_place_name(filter, &place_name);
+       if (categoryName)
+               place_req->categories = g_strdup_printf("%s", categoryName);
 
-       char *modified_place_name = NULL;
-       bool b_isPlaceName_modified = false;
-       if (place_name)
-               b_isPlaceName_modified = __replace_space(place_name, &modified_place_name);
+       if (searchKeyword)
+               place_req->search_string = g_strdup_printf("%s", searchKeyword);
 
-       if (categoryName && place_name) {
-               if (b_isPlaceName_modified)
-                       place_req->search_string = g_strdup_printf("%s[%s]", modified_place_name, categoryName);
-               else
-                       place_req->search_string = g_strdup_printf("%s[%s]", place_name, categoryName);
-       } else if (categoryName) {
-               place_req->search_string = g_strdup_printf("[%s]", categoryName);
-       } else if (place_name) {
-               if (b_isPlaceName_modified)
-                       place_req->search_string = g_strdup_printf("%s", modified_place_name);
-               else
-                       place_req->search_string = g_strdup_printf("%s", place_name);
-       } else {
+       if (!searchKeyword && !categoryName) {
                g_free(calldata_place);
                calldata_place = NULL;
                g_free(place_req);
@@ -1294,12 +1424,18 @@ EXPORT_API int maps_plugin_search_place_by_area(const maps_area_h boundary, cons
                return MAPS_ERROR_INVALID_PARAMETER;
        }
 
-       if (modified_place_name) {
-               g_free(modified_place_name);
-               modified_place_name = NULL;
+       if (searchKeyword) {
+               g_free(searchKeyword);
+               searchKeyword = NULL;
        }
 
-       MAPS_LOGD(">>>>>>>> Place search string :: %s <<<<<<<<<", place_req->search_string);
+       if (categoryName) {
+               g_free(categoryName);
+               categoryName = NULL;
+       }
+
+       MAPS_LOGD(">>>>>>>> Place search categories :: %s <<<<<<<<<", place_req->categories);
+
        place_req->boundary = NULL;
        maps_area_s *bound = (maps_area_s *) boundary;
 
@@ -1330,6 +1466,136 @@ EXPORT_API int maps_plugin_search_place_by_area(const maps_area_h boundary, cons
        return __convert_to_maps_error(ret);
 }
 
+EXPORT_API int maps_plugin_search_place_list(const maps_area_h boundary, const maps_place_filter_h filter, const maps_preference_h preference, maps_service_search_place_list_cb callback, void *user_data, int *request_id)
+{
+
+       if (!boundary || !filter || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_place_list *calldata_place = (callback_info_place_list *)g_malloc0(sizeof(callback_info_place_list));
+       if (calldata_place == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_place->callback = callback;
+       calldata_place->data = user_data;
+
+       mapzen_search_req_s *place_req = (mapzen_search_req_s *)g_malloc0(sizeof(mapzen_search_req_s));
+       if (place_req == NULL) {
+               g_free(calldata_place);
+               calldata_place = NULL;
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       place_req->maps_key = g_strdup((gchar *) __provider_key);
+
+       int max_result;
+       maps_preference_get_max_results(preference, &max_result);
+
+       if (max_result == 0)
+               place_req->num_res = DEFAULT_NUM_RESULTS;
+       else
+               place_req->num_res = max_result;
+
+       MAPS_LOGD("Place Result limit :: %d", place_req->num_res);
+
+       char *categoryName = NULL;
+       char *searchKeyword = NULL;
+
+       maps_place_category_h category = NULL;
+       maps_place_filter_get_category(filter, &category);
+       maps_place_filter_get_keyword(filter, &searchKeyword);
+
+       if (category) {
+               maps_place_category_get_name(category, &categoryName);
+               maps_place_category_destroy(category);
+       }
+
+       if (categoryName)
+               place_req->categories = g_strdup_printf("%s", categoryName);
+
+       if (searchKeyword)
+               place_req->search_string = g_strdup_printf("%s", searchKeyword);
+
+       if (!searchKeyword && !categoryName) {
+               g_free(calldata_place);
+               calldata_place = NULL;
+               g_free(place_req);
+               place_req = NULL;
+               return MAPS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (searchKeyword) {
+               g_free(searchKeyword);
+               searchKeyword = NULL;
+       }
+
+       if (categoryName) {
+               g_free(categoryName);
+               categoryName = NULL;
+       }
+
+       MAPS_LOGD(">>>>>>>> Place search categories :: %s <<<<<<<<<", place_req->categories);
+
+       place_req->boundary = NULL;
+       maps_area_s *bound = (maps_area_s *) boundary;
+
+       if (bound->type != MAPS_AREA_NONE) {
+               place_req->boundary = (mapzen_boundary_s *)g_malloc0(sizeof(mapzen_boundary_s));
+
+               if (place_req->boundary != NULL) {
+                       if (bound->type == MAPS_AREA_CIRCLE) {
+                               place_req->boundary->type = MAPZEN_BOUNDARY_CIRCLE;
+                               place_req->boundary->circle.center.latitude = bound->circle.center.latitude;
+                               place_req->boundary->circle.center.longitude = bound->circle.center.longitude;
+                               place_req->boundary->circle.radius = bound->circle.radius;
+                       } else if (bound->type == MAPS_AREA_RECTANGLE) {
+                               place_req->boundary->type = MAPZEN_BOUNDARY_RECT;
+                               place_req->boundary->rect.top_left.latitude = bound->rect.top_left.latitude;
+                               place_req->boundary->rect.top_left.longitude = bound->rect.top_left.longitude;
+                               place_req->boundary->rect.bottom_right.latitude = bound->rect.bottom_right.latitude;
+                               place_req->boundary->rect.bottom_right.longitude = bound->rect.bottom_right.longitude;
+                       }
+               }
+       }
+
+       *request_id = ++__request_id;
+       calldata_place->reqID = __request_id;
+
+       int ret = mapzen_search_place_list(place_req, __maps_service_search_place_list_cb, __request_id, (void *) calldata_place);
+
+       return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_get_place_details(const char* uri, maps_service_get_place_details_cb callback, void* user_data, int* request_id)
+{
+       if (!uri || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_place_details *calldata_place = (callback_info_place_details *)g_malloc0(sizeof(callback_info_place_details));
+       if (calldata_place == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_place->callback = callback;
+       calldata_place->data = user_data;
+
+       mapzen_get_details_req_s *place_req = (mapzen_get_details_req_s *)g_malloc0(sizeof(mapzen_get_details_req_s));
+       if (place_req == NULL) {
+               g_free(calldata_place);
+               calldata_place = NULL;
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       place_req->maps_key = g_strdup((gchar *) __provider_key);
+       place_req->uri = g_strdup_printf("%s", uri);
+
+       *request_id = ++__request_id;
+       calldata_place->reqID = __request_id;
+
+       int ret = mapzen_get_place_details(place_req, __mapzen_place_get_details_cb, __request_id, (void *) calldata_place);
+
+       return __convert_to_maps_error(ret);
+}
+
 EXPORT_API int maps_plugin_search_place_by_address(const char *address, const maps_area_h boundary, const maps_place_filter_h filter, const maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id)
 {
        if (!address || !boundary || !filter || !callback || !request_id)
@@ -1366,31 +1632,32 @@ EXPORT_API int maps_plugin_search_place_by_address(const char *address, const ma
        maps_place_category_h category = NULL;
        maps_place_filter_get_category(filter, &category);
 
-       if (category)
+       if (category) {
                maps_place_category_get_name(category, &categoryName);
+               maps_place_category_destroy(category);
+       }
+
+       if (categoryName)
+               place_req->categories = g_strdup_printf("%s", categoryName);
 
-       char *modified_address = NULL;
-       bool b_isAddress_modified = false;
        if (address)
-               b_isAddress_modified = __replace_space((char *) address, &modified_address);
+               place_req->search_string = g_strdup_printf("%s", address);
 
-       if (categoryName) {
-               if (b_isAddress_modified)
-                       place_req->search_string = g_strdup_printf("%s[%s]", modified_address, categoryName);
-               else
-                       place_req->search_string = g_strdup_printf("%s[%s]", address, categoryName);
-       } else {
-               if (b_isAddress_modified)
-                       place_req->search_string = g_strdup_printf("%s", modified_address);
-               else
-                       place_req->search_string = g_strdup_printf("%s", address);
+       if (!address && !categoryName) {
+               g_free(calldata_place);
+               calldata_place = NULL;
+               g_free(place_req);
+               place_req = NULL;
+               return MAPS_ERROR_INVALID_PARAMETER;
        }
 
-       if (modified_address) {
-               g_free(modified_address);
-               modified_address = NULL;
+       if (categoryName) {
+               g_free(categoryName);
+               categoryName = NULL;
        }
 
+       MAPS_LOGD(">>>>>>>> Place search categories :: %s <<<<<<<<<", place_req->categories);
+
        place_req->boundary = NULL;
        maps_area_s *bound = (maps_area_s *) boundary;