[geocode-glib/gnome-maps: 6/9] lib: geocode_ipclient_search* should return location



commit 97720de85ee752460b077b89a0059b54482ffc21
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Fri Mar 22 02:28:18 2013 +0200

    lib: geocode_ipclient_search* should return location
    
    This API will be a lot more useful if we provide a parsed GeocodeLocation
    object to the caller rather than just the raw JSON string we get as
    response from server.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=696526

 geocode-glib/geocode-ipclient.c |  107 +++++++++++++++++++++++++++++++++++----
 geocode-glib/geocode-ipclient.h |   11 ++--
 geocode-glib/test-geoip.c       |   60 +++++++++++++--------
 3 files changed, 140 insertions(+), 38 deletions(-)
---
diff --git a/geocode-glib/geocode-ipclient.c b/geocode-glib/geocode-ipclient.c
index b52ef88..d2704dc 100644
--- a/geocode-glib/geocode-ipclient.c
+++ b/geocode-glib/geocode-ipclient.c
@@ -23,7 +23,10 @@
 #include <stdlib.h>
 #include <glib.h>
 #include <libsoup/soup.h>
+#include <json-glib/json-glib.h>
 #include "geocode-ipclient.h"
+#include "geocode-error.h"
+#include "geocode-ip-server/geoip-server.h"
 
 /**
  * SECTION:geocode-ipclient
@@ -280,6 +283,84 @@ geocode_ipclient_search_async (GeocodeIpclient           *ipclient,
         g_object_unref (query);
 }
 
+static gboolean
+parse_server_error (JsonObject *object, GError **error) {
+        GeoipServerError server_error_code;
+        int error_code;
+        const char *error_message;
+
+        if (!json_object_has_member (object, "error_code"))
+            return FALSE;
+
+        server_error_code = json_object_get_int_member (object, "error_code");
+        switch (server_error_code) {
+                case INVALID_IP_ADDRESS_ERR:
+                        error_code = GEOCODE_ERROR_INVALID_ARGUMENTS;
+                        break;
+                case INVALID_ENTRY_ERR:
+                        error_code = GEOCODE_ERROR_NO_MATCHES;
+                        break;
+                case DATABASE_ERR:
+                        error_code = GEOCODE_ERROR_INTERNAL_SERVER;
+                        break;
+        }
+
+        error_message = json_object_get_string_member (object, "error_message");
+
+        g_set_error_literal (error,
+                             GEOCODE_ERROR,
+                             error_code,
+                             error_message);
+
+        return TRUE;
+}
+
+static GeocodeLocation *
+json_to_location (const char *json, GError **error) {
+        JsonParser *parser;
+        JsonNode *node;
+        JsonObject *object;
+        GeocodeLocation *location;
+        char *desc = NULL;
+
+        parser = json_parser_new ();
+
+        if (!json_parser_load_from_data (parser, json, -1, error))
+                return NULL;
+
+        node = json_parser_get_root (parser);
+        object = json_node_get_object (node);
+
+        if (parse_server_error (object, error))
+                return NULL;
+
+        location = geocode_location_new (0, 0);
+        location->latitude = json_object_get_double_member (object, "latitude");
+        location->longitude = json_object_get_double_member (object, "longitude");
+
+        if (json_object_has_member (object, "city"))
+                desc = g_strdup_printf ("%s, %s, %s",
+                                        json_object_get_string_member (object, "city"),
+                                        json_object_get_string_member (object, "region_name"),
+                                        json_object_get_string_member (object, "country_name"));
+        else if (json_object_has_member (object, "region_name"))
+                desc = g_strdup_printf ("%s, %s",
+                                        json_object_get_string_member (object, "region_name"),
+                                        json_object_get_string_member (object, "country_name"));
+        else if (json_object_has_member (object, "country_name"))
+                desc = g_strdup_printf ("%s",
+                                        json_object_get_string_member (object, "country_name"));
+
+        if (desc != NULL) {
+            geocode_location_set_description (location, desc);
+            g_free (desc);
+        }
+
+        g_object_unref (parser);
+
+        return location;
+}
+
 /**
  * geocode_ipclient_search_finish:
  * @ipclient: a #GeocodeIpclient representing a query
@@ -288,17 +369,17 @@ geocode_ipclient_search_async (GeocodeIpclient           *ipclient,
  *
  * Finishes a geolocation search operation. See geocode_ipclient_search_async().
  *
- * Returns: a string containing the result of the query in JSON format
- * or %NULL in case of errors.
- * Free the returned string with g_free() when done.
+ * Returns: (transfer full): A #GeocodeLocation object or %NULL in case of
+ * errors. Free the returned object with g_object_unref() when done.
  **/
-char *
+GeocodeLocation *
 geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
                                 GAsyncResult    *res,
                                 GError          **error)
 {
         GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
         char *contents = NULL;
+        GeocodeLocation *location;
 
         g_return_val_if_fail (GEOCODE_IS_IPCLIENT (ipclient), NULL);
 
@@ -308,7 +389,10 @@ geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
                 return NULL;
 
         contents = g_simple_async_result_get_op_res_gpointer (simple);
-        return contents;
+        location = json_to_location (contents, error);
+        g_free (contents);
+
+        return location;
 }
 
 /**
@@ -318,16 +402,16 @@ geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
  *
  * Gets the geolocation data for an IP address from the server.
  *
- * Returns: a string containing the result of the query in JSON format
- * or %NULL in case of errors.
- * Free the returned string with g_free() when done.
+ * Returns: (transfer full): A #GeocodeLocation object or %NULL in case of
+ * errors. Free the returned object with g_object_unref() when done.
  **/
-char *
+GeocodeLocation *
 geocode_ipclient_search (GeocodeIpclient        *ipclient,
                          GError                 **error)
 {
         char *contents;
         GFile *query;
+        GeocodeLocation *location;
 
         g_return_val_if_fail (GEOCODE_IS_IPCLIENT (ipclient), NULL);
         g_return_val_if_fail (ipclient->priv->server != NULL, NULL);
@@ -347,5 +431,8 @@ geocode_ipclient_search (GeocodeIpclient        *ipclient,
         }
         g_object_unref (query);
 
-        return contents;
+        location = json_to_location (contents, error);
+        g_free (contents);
+
+        return location;
 }
diff --git a/geocode-glib/geocode-ipclient.h b/geocode-glib/geocode-ipclient.h
index ab9e7d9..7bd26da 100644
--- a/geocode-glib/geocode-ipclient.h
+++ b/geocode-glib/geocode-ipclient.h
@@ -25,6 +25,7 @@
 
 #include <glib.h>
 #include <gio/gio.h>
+#include "geocode-location.h"
 
 G_BEGIN_DECLS
 
@@ -71,12 +72,12 @@ void geocode_ipclient_search_async  (GeocodeIpclient       *ipclient,
                                      GAsyncReadyCallback    callback,
                                      gpointer               user_data);
 
-char *geocode_ipclient_search_finish (GeocodeIpclient   *ipclient,
-                                      GAsyncResult      *res,
-                                      GError            **error);
+GeocodeLocation *geocode_ipclient_search_finish (GeocodeIpclient   *ipclient,
+                                                 GAsyncResult      *res,
+                                                 GError            **error);
 
-char *geocode_ipclient_search (GeocodeIpclient *ipclient,
-                               GError          **error);
+GeocodeLocation *geocode_ipclient_search (GeocodeIpclient *ipclient,
+                                          GError          **error);
 
 G_END_DECLS
 
diff --git a/geocode-glib/test-geoip.c b/geocode-glib/test-geoip.c
index b119ee1..895e643 100644
--- a/geocode-glib/test-geoip.c
+++ b/geocode-glib/test-geoip.c
@@ -9,30 +9,39 @@
 
 static GMainLoop *loop = NULL;
 
+typedef struct {
+        const char *ip;
+
+        double expected_latitude;
+        double expected_longitude;
+        const char *expected_description;
+} TestData;
+
 static void
 test_search (gconstpointer data)
 {
         GeocodeIpclient *ipclient;
         GError *error = NULL;
-        char *contents;
-        const char *ip;
+        GeocodeLocation *location;
+        TestData *test_data = (TestData *) data;
 
-        ip = (const char *) data;
-        if (ip)
-                ipclient = geocode_ipclient_new_for_ip ("24.34.34.24");
+        if (test_data->ip)
+                ipclient = geocode_ipclient_new_for_ip (test_data->ip);
         else {
                 ipclient = geocode_ipclient_new ();
         }
-        contents = geocode_ipclient_search (ipclient, &error);
-        if (!contents) {
+        location = geocode_ipclient_search (ipclient, &error);
+        if (!location) {
                 g_warning ("Failed at getting the geolocation information: %s", error->message);
                 g_error_free (error);
         }
-        g_assert (contents != NULL);
-        g_assert (strstr (contents, "\"ERROR\"") == NULL);
+        g_assert (location != NULL);
+        g_assert (location->latitude == test_data->expected_latitude);
+        g_assert (location->longitude == test_data->expected_longitude);
+        g_assert (location->description != NULL &&
+                  strcmp(location->description, test_data->expected_description) == 0);
+        geocode_location_free (location);
         g_object_unref (ipclient);
-        g_print ("%s\n", contents);
-        g_free (contents);
 }
 
 static void
@@ -42,31 +51,30 @@ print_geolocation_info_cb (GObject          *source_object,
 {
         GeocodeIpclient *object = (GeocodeIpclient *) source_object;
         GError *error = NULL;
-        char *results;
+        GeocodeLocation *location;
 
-        results = geocode_ipclient_search_finish (object, res, &error);
-        if (results == NULL) {
+        location = geocode_ipclient_search_finish (object, res, &error);
+        if (location == NULL) {
                 g_message ("Failed to search the geolocation info: %s", error->message);
                 g_error_free (error);
                 exit (1);
         }
-        g_print ("%s\n", results);
-        g_free (results);
+        g_print ("Location: %s (%f,%f)\n", location->description, location->latitude,  location->longitude);
 
+        geocode_location_free (location);
         g_object_unref (object);
         exit (0);
 }
 
-
 int main (int argc, char **argv)
 {
         GError *error = NULL;
         GOptionContext *context;
         GeocodeIpclient *ipclient;
-        char *ip = NULL;
+        TestData data = { NULL, 0.0f, 0.0f, NULL };
         gboolean regr = FALSE;
         const GOptionEntry entries[] = {
-                { "ip", 0, 0, G_OPTION_ARG_STRING, &ip, "The ip address for which to search the geolocation 
data", NULL },
+                { "ip", 0, 0, G_OPTION_ARG_STRING, &data.ip, "The ip address for which to search the 
geolocation data", NULL },
                 { "regr", 0, 0, G_OPTION_ARG_NONE, &regr, "Run the default testcases", NULL },
                 { NULL }
         };
@@ -86,13 +94,19 @@ int main (int argc, char **argv)
         }
 
         if (regr == TRUE) {
-                g_test_add_data_func ("/geoip/search_with_ip", "24.24.24.24", test_search);
-                g_test_add_data_func ("/geocode/search", NULL, test_search);
+                data.expected_latitude = 43.089199f;
+                data.expected_longitude = -76.025002f;
+                data.expected_description = "East Syracuse, New York, United States";
+
+                g_test_add_data_func ("/geocode/search", &data, test_search);
+
+                data.ip = "24.24.24.24";
+                g_test_add_data_func ("/geoip/search_with_ip", &data, test_search);
                 return g_test_run ();
         }
 
-        if (ip)
-                ipclient = geocode_ipclient_new_for_ip (ip);
+        if (data.ip)
+                ipclient = geocode_ipclient_new_for_ip (data.ip);
         else
                 ipclient = geocode_ipclient_new ();
         geocode_ipclient_search_async (ipclient, NULL, print_geolocation_info_cb, NULL);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]