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



commit e6b882c3d4b7251154a2f11125279fdc4cda64ca
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 |  115 +++++++++++++++++++++++++++++++++++----
 geocode-glib/geocode-ipclient.h |   11 ++--
 geocode-glib/test-geoip.c       |   22 ++++----
 3 files changed, 121 insertions(+), 27 deletions(-)
---
diff --git a/geocode-glib/geocode-ipclient.c b/geocode-glib/geocode-ipclient.c
index b52ef88..c74b045 100644
--- a/geocode-glib/geocode-ipclient.c
+++ b/geocode-glib/geocode-ipclient.c
@@ -23,7 +23,9 @@
 #include <stdlib.h>
 #include <glib.h>
 #include <libsoup/soup.h>
+#include <json-glib/json-glib.h>
 #include "geocode-ipclient.h"
+#include "geocode-error.h"
 
 /**
  * SECTION:geocode-ipclient
@@ -39,6 +41,12 @@ enum {
         N_PROPERTIES
 };
 
+typedef enum {
+        SERVER_ERROR_INVALID_IP_ADDRESS = 0,
+        SERVER_INVALID_ENTRY,
+        SERVER_DATABASE
+} ServerError;
+
 struct _GeocodeIpclientPrivate {
         char *ip;
         char *server;
@@ -280,6 +288,87 @@ geocode_ipclient_search_async (GeocodeIpclient           *ipclient,
         g_object_unref (query);
 }
 
+static gboolean
+parse_server_error (JsonObject *object, GError **error) {
+        ServerError 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 SERVER_ERROR_INVALID_IP_ADDRESS:
+                        error_code = GEOCODE_ERROR_INVALID_ARGUMENTS;
+                        break;
+                case SERVER_INVALID_ENTRY:
+                        error_code = GEOCODE_ERROR_NO_MATCHES;
+                        break;
+                case SERVER_DATABASE:
+                        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;
+        GString *string;
+
+        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");
+
+        string = g_string_new ("");
+        if (json_object_has_member (object, "city")) {
+                g_string_append (string,
+                                 json_object_get_string_member (object, "city"));
+        }
+
+        if (json_object_has_member (object, "region")) {
+                if (string->len > 0)
+                        g_string_append_c (string, ',');
+                g_string_append (string,
+                                 json_object_get_string_member (object, "region"));
+        }
+
+        if (json_object_has_member (object, "country_name")) {
+                if (string->len > 0)
+                        g_string_append_c (string, ',');
+                g_string_append (string,
+                                 json_object_get_string_member (object, "country_name"));
+        }
+
+        location->description = g_string_free (string, FALSE);
+        g_object_unref (parser);
+
+        return location;
+}
+
 /**
  * geocode_ipclient_search_finish:
  * @ipclient: a #GeocodeIpclient representing a query
@@ -288,17 +377,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: 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 +397,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 +410,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: 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 +439,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..19ca905 100644
--- a/geocode-glib/test-geoip.c
+++ b/geocode-glib/test-geoip.c
@@ -14,7 +14,7 @@ test_search (gconstpointer data)
 {
         GeocodeIpclient *ipclient;
         GError *error = NULL;
-        char *contents;
+        GeocodeLocation *location;
         const char *ip;
 
         ip = (const char *) data;
@@ -23,16 +23,14 @@ test_search (gconstpointer data)
         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_object_unref (location);
         g_object_unref (ipclient);
-        g_print ("%s\n", contents);
-        g_free (contents);
 }
 
 static void
@@ -42,17 +40,17 @@ 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);
 
+        g_object_unref (location);
         g_object_unref (object);
         exit (0);
 }


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