[geocode-glib/wip/place-details: 2/2] lib: geocode_forward_search*() returns places
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geocode-glib/wip/place-details: 2/2] lib: geocode_forward_search*() returns places
- Date: Fri, 26 Apr 2013 00:03:23 +0000 (UTC)
commit 5bbaefcef3a3c0b9cec0adf431faf5b8477557fa
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date: Thu Apr 25 04:45:10 2013 +0300
lib: geocode_forward_search*() returns places
geocode_forward_search*() now return list of GeocodePlace objects rather
than simple GeocodeLocation objects.
geocode-glib/geocode-forward.c | 234 ++++++++++++++++++----------------------
geocode-glib/test-gcglib.c | 112 ++++++++++++++++----
2 files changed, 196 insertions(+), 150 deletions(-)
---
diff --git a/geocode-glib/geocode-forward.c b/geocode-glib/geocode-forward.c
index 8be2dd5..aa01697 100644
--- a/geocode-glib/geocode-forward.c
+++ b/geocode-glib/geocode-forward.c
@@ -98,6 +98,8 @@ _geocode_parse_single_result_json (const char *contents,
GError **error)
{
GHashTable *ht;
+ GeocodePlace *place = NULL;
+ char *name;
GeocodeLocation *loc;
gdouble longitude;
gdouble latitude;
@@ -108,13 +110,17 @@ _geocode_parse_single_result_json (const char *contents,
longitude = g_ascii_strtod (g_hash_table_lookup (ht, "longitude"), NULL);
latitude = g_ascii_strtod (g_hash_table_lookup (ht, "latitude"), NULL);
+ name = g_hash_table_lookup (ht, "line2");
loc = geocode_location_new_with_description (longitude,
latitude,
GEOCODE_LOCATION_ACCURACY_UNKNOWN,
- g_hash_table_lookup (ht, "line2"));
+ name);
+ place = geocode_place_new_with_location (name, GEOCODE_PLACE_TYPE_UNKNOWN, loc);
+
+ g_object_unref (loc);
g_hash_table_destroy (ht);
- return g_list_append (NULL, loc);
+ return g_list_append (NULL, place);
}
static struct {
@@ -472,8 +478,8 @@ geocode_forward_search_async (GeocodeForward *forward,
*
* Finishes a forward geocoding operation. See geocode_forward_search_async().
*
- * Returns: (element-type GeocodeLocation) (transfer container): A list of
- * locations or %NULL in case of errors. Free the returned list with
+ * Returns: (element-type GeocodePlace) (transfer container): A list of
+ * places or %NULL in case of errors. Free the returned list with
* g_list_free() when done.
**/
GList *
@@ -533,11 +539,27 @@ insert_place_attr (GHashTable *ht,
json_reader_end_member (reader);
goto end;
} else if (g_str_has_suffix (element_name, " attrs")) {
- g_debug ("Ignoring attributes element '%s'", element_name);
- value = g_strdup (""); /* So that they're ignored */
+ if (IS_EL("placeTypeName attrs")) {
+ char *code;
+
+ json_reader_read_member (reader, "code");
+ code = g_strdup_printf ("%" G_GINT64_FORMAT, json_reader_get_int_value (reader));
+ g_hash_table_insert (ht, g_strdup ("placeType"), code);
+ json_reader_end_member (reader);
+ goto end;
+ } else {
+ g_debug ("Ignoring attributes element '%s'", element_name);
+ value = g_strdup (""); /* So that they're ignored */
+ }
} else if (IS_EL("boundingBox")) {
g_debug ("Ignoring element '%s'", element_name);
value = g_strdup (""); /* So that they're ignored */
+ } else if (IS_EL("placeTypeName")) {
+ /* This string is also localized so we want the code rather
+ * than name, which we extract above.
+ */
+ g_debug ("Ignoring element '%s'", element_name);
+ value = g_strdup (""); /* So that they're ignored */
} else {
value = g_strdup (json_reader_get_string_value (reader));
}
@@ -556,131 +578,100 @@ end:
json_reader_end_member (reader);
}
-static gboolean
-node_free_func (GNode *node,
- gpointer user_data)
-{
- /* Leaf nodes are GeocodeLocation objects
- * which we reuse for the results */
- if (G_NODE_IS_LEAF (node) == FALSE)
- g_free (node->data);
-
- return FALSE;
-}
-
-#define N_ATTRS 7
-static const char const *attributes[7] = {
- "country",
- "admin1",
- "admin2",
- "admin3",
- "postal",
- "placeTypeName",
- "locality1"
+static struct {
+ const char *yahoo_attr;
+ const char *place_prop; /* NULL to ignore */
+} yahoo_to_place_map[] = {
+ { "postal", "postal-code" },
+ { "locality1", "town" },
+ { "admin1", "state" },
+ { "admin2", "county" },
+ { "admin3", "administrative-area" },
+ { "country", "country" },
};
static void
-insert_place_into_tree (GNode *location_tree, GHashTable *ht)
+fill_place_from_entry (const char *key,
+ const char *value,
+ GeocodePlace *place)
{
- GNode *start = location_tree, *child = NULL;
- GeocodeLocation *loc = NULL;
- char *attr_val = NULL;
- char *name;
- gdouble longitude, latitude;
guint i;
- for (i = 0; i < G_N_ELEMENTS(attributes); i++) {
- attr_val = g_hash_table_lookup (ht, attributes[i]);
- if (!attr_val) {
- /* Add a dummy node if the attribute value is not
- * available for the place */
- child = g_node_insert_data (start, -1, NULL);
- } else {
- /* If the attr value (eg for country United States)
- * already exists, then keep on adding other attributes under that node. */
- child = g_node_first_child (start);
- while (child &&
- child->data &&
- g_ascii_strcasecmp (child->data, attr_val) != 0) {
- child = g_node_next_sibling (child);
- }
- if (!child) {
- /* create a new node */
- child = g_node_insert_data (start, -1, g_strdup (attr_val));
- }
+
+ for (i = 0; i < G_N_ELEMENTS (yahoo_to_place_map); i++) {
+ if (g_str_equal (key, yahoo_to_place_map[i].yahoo_attr)){
+ g_object_set (G_OBJECT (place),
+ yahoo_to_place_map[i].place_prop,
+ value,
+ NULL);
+ break;
}
- start = child;
}
+}
- /* Get latitude and longitude and create GeocodeLocation object.
- * The leaf node of the tree is the GeocodeLocation object */
- longitude = g_ascii_strtod (g_hash_table_lookup (ht, "longitude"), NULL);
- latitude = g_ascii_strtod (g_hash_table_lookup (ht, "latitude"), NULL);
- name = g_hash_table_lookup (ht, "name");
+static char *
+create_description_from_place (GeocodePlace *place)
+{
+ GString *description;
+ const char *state, *admin_area, *country;
+
+ description = g_string_new (geocode_place_get_name (place));
+ state = geocode_place_get_state (place);
+ admin_area = geocode_place_get_administrative_area (place);
+ if (state != NULL || admin_area != NULL) {
+ g_string_append (description, ", ");
+ if (state != NULL)
+ g_string_append (description, state);
+ else if (admin_area != NULL)
+ g_string_append (description, admin_area);
+ }
- loc = geocode_location_new_with_description (latitude,
- longitude,
- GEOCODE_LOCATION_ACCURACY_UNKNOWN,
- name);
+ country = geocode_place_get_country (place);
+ if (country != NULL) {
+ g_string_append (description, ", ");
+ g_string_append (description, country);
+ }
- g_node_insert_data (start, -1, loc);
+ return g_string_free (description, FALSE);
}
static void
-make_location_list_from_tree (GNode *node,
- char **s_array,
- GList **location_list,
- int i)
+insert_place_into_list (GList **place_list, GHashTable *ht)
{
- GNode *child;
- gboolean add_attribute = FALSE;
-
- if (node == NULL)
- return;
-
- if (G_NODE_IS_LEAF (node)) {
- GPtrArray *rev_s_array;
- GeocodeLocation *loc;
- const char *name;
- char *description;
- int counter = 0;
-
- rev_s_array = g_ptr_array_new ();
+ GeocodePlaceType place_type;
+ GeocodePlace *place = NULL;
+ GeocodeLocation *loc = NULL;
+ char *name, *description;
+ gdouble longitude, latitude;
- /* If leaf node, then add all the attributes in the s_array
- * and set it to the description of the loc object */
- loc = (GeocodeLocation *) node->data;
+ name = g_hash_table_lookup (ht, "name");
+ place_type = atoi (g_hash_table_lookup (ht, "placeType"));
+ place = geocode_place_new (name, place_type);
- name = geocode_location_get_description (loc);
+ g_hash_table_foreach (ht, (GHFunc) fill_place_from_entry, place);
- /* To print the attributes in a meaningful manner
- * reverse the s_array */
- g_ptr_array_add (rev_s_array, (gpointer) name);
- for (counter = 1; counter <= i; counter++)
- g_ptr_array_add (rev_s_array, s_array[i - counter]);
- g_ptr_array_add (rev_s_array, NULL);
- description = g_strjoinv (", ", (char **) rev_s_array->pdata);
- g_ptr_array_unref (rev_s_array);
+ /* Yahoo API doesn't give us street addresses so we'll just have to
+ * live with only street name for now. */
+ if (place_type == GEOCODE_PLACE_TYPE_SUBURB) {
+ const char *street = g_hash_table_lookup (ht, "locality2");
+ if (street != NULL)
+ geocode_place_set_street_address (place, street);
+ }
- geocode_location_set_description (loc, description);
- g_free (description);
+ /* Get latitude and longitude and create GeocodeLocation object. */
+ longitude = g_ascii_strtod (g_hash_table_lookup (ht, "longitude"), NULL);
+ latitude = g_ascii_strtod (g_hash_table_lookup (ht, "latitude"), NULL);
+ description = create_description_from_place (place);
- *location_list = g_list_prepend (*location_list, loc);
- } else {
- /* If there are other attributes with a different value,
- * add those attributes to the string to differentiate them */
- if (g_node_prev_sibling (node) ||
- g_node_next_sibling (node))
- add_attribute = TRUE;
-
- if (add_attribute) {
- s_array[i] = node->data;
- i++;
- }
- }
+ loc = geocode_location_new_with_description (latitude,
+ longitude,
+ GEOCODE_LOCATION_ACCURACY_UNKNOWN,
+ description);
+ g_free (description);
+ geocode_place_set_location (place, loc);
+ g_object_unref (loc);
- for (child = node->children; child != NULL; child = child->next)
- make_location_list_from_tree (child, s_array, location_list, i);
+ *place_list = g_list_prepend (*place_list, place);
}
GList *
@@ -693,8 +684,6 @@ _geocode_parse_search_json (const char *contents,
JsonReader *reader;
const GError *err = NULL;
int num_places, i;
- GNode *location_tree;
- char *s_array[N_ATTRS];
ret = NULL;
@@ -716,8 +705,6 @@ _geocode_parse_search_json (const char *contents,
if (num_places < 0)
goto parse;
- location_tree = g_node_new (NULL);
-
for (i = 0; i < num_places; i++) {
GHashTable *ht;
char **members;
@@ -732,8 +719,8 @@ _geocode_parse_search_json (const char *contents,
for (j = 0; members != NULL && members[j] != NULL; j++)
insert_place_attr (ht, reader, members[j]);
- /* Populate the tree with place details */
- insert_place_into_tree (location_tree, ht);
+ /* Populate the list with place details */
+ insert_place_into_list (&ret, ht);
g_hash_table_destroy (ht);
g_strfreev (members);
@@ -741,17 +728,6 @@ _geocode_parse_search_json (const char *contents,
json_reader_end_element (reader);
}
- make_location_list_from_tree (location_tree, s_array, &ret, 0);
-
- g_node_traverse (location_tree,
- G_IN_ORDER,
- G_TRAVERSE_ALL,
- -1,
- (GNodeTraverseFunc) node_free_func,
- NULL);
-
- g_node_destroy (location_tree);
-
g_object_unref (parser);
g_object_unref (reader);
ret = g_list_reverse (ret);
@@ -773,8 +749,8 @@ parse:
* Gets the result of a forward geocoding
* query using a web service.
*
- * Returns: (element-type GeocodeLocation) (transfer container): A list of
- * locations or %NULL in case of errors. Free the returned list with
+ * Returns: (element-type GeocodePlace) (transfer container): A list of
+ * places or %NULL in case of errors. Free the returned list with
* g_list_free() when done.
**/
GList *
diff --git a/geocode-glib/test-gcglib.c b/geocode-glib/test-gcglib.c
index e90a1f7..72d78f9 100644
--- a/geocode-glib/test-gcglib.c
+++ b/geocode-glib/test-gcglib.c
@@ -22,6 +22,15 @@ print_loc (GeocodeLocation *loc)
}
static void
+print_place (GeocodePlace *place)
+{
+ /* For now just print the underlying location */
+ GeocodeLocation *loc = geocode_place_get_location (place);
+
+ print_loc (loc);
+}
+
+static void
print_res (const char *key,
const char *value,
gpointer data)
@@ -71,11 +80,11 @@ got_geocode_search_cb (GObject *source_object,
}
for (l = results; l != NULL; l = l->next) {
- GeocodeLocation *loc = l->data;
+ GeocodePlace *place = l->data;
g_print ("Got geocode search answer:\n");
- print_loc (loc);
- g_object_unref (loc);
+ print_place (place);
+ g_object_unref (place);
}
g_list_free (results);
@@ -129,6 +138,7 @@ test_xep (void)
GHashTable *tp;
GeocodeForward *object;
GList *res;
+ GeocodePlace *place;
GeocodeLocation *loc;
GError *error = NULL;
@@ -155,11 +165,13 @@ test_xep (void)
g_object_unref (object);
- loc = res->data;
+ place = res->data;
+ loc = geocode_place_get_location (place);
+ g_assert (loc != NULL);
g_assert_cmpfloat (geocode_location_get_latitude (loc), ==, -0.589669);
g_assert_cmpfloat (geocode_location_get_longitude (loc), ==, 51.237070);
- g_object_unref (loc);
+ g_object_unref (place);
g_list_free (res);
}
@@ -169,6 +181,7 @@ test_pub (void)
GeocodeForward *object;
GError *error = NULL;
GList *res;
+ GeocodePlace *place;
GeocodeLocation *loc;
object = geocode_forward_new_for_string ("9, old palace road, guildford, surrey");
@@ -183,12 +196,14 @@ test_pub (void)
g_object_unref (object);
g_assert_cmpint (g_list_length (res), ==, 1);
- loc = res->data;
+ place = res->data;
+ loc = geocode_place_get_location (place);
+ g_assert (loc != NULL);
g_assert_cmpfloat (geocode_location_get_latitude (loc), ==, -0.589669);
g_assert_cmpfloat (geocode_location_get_longitude (loc), ==, 51.237070);
- g_object_unref (loc);
+ g_object_unref (place);
g_list_free (res);
}
@@ -221,14 +236,27 @@ test_search (void)
got_france = FALSE;
got_texas = FALSE;
for (l = results; l != NULL; l = l->next) {
- GeocodeLocation *loc = l->data;
+ GeocodeLocation *loc;
+ GeocodePlace *place = l->data;
+ g_assert (g_strcmp0 (geocode_place_get_name (place), "Paris") == 0);
- if (g_strcmp0 (geocode_location_get_description (loc), "Paris, France") == 0)
+ loc = geocode_place_get_location (place);
+ g_assert (loc != NULL);
+ g_print ("location desc: %s\n", geocode_location_get_description (loc));
+
+ if (g_strcmp0 (geocode_place_get_state (place), "Ile-de-France") == 0 &&
+ g_strcmp0 (geocode_place_get_country (place), "France") == 0 &&
+ g_strcmp0 (geocode_location_get_description (loc),
+ "Paris, Ile-de-France, France") == 0)
got_france = TRUE;
- else if (g_strcmp0 (geocode_location_get_description (loc), "Paris, Texas, United States") ==
0)
+ else if (g_strcmp0 (geocode_place_get_state (place), "Texas") == 0 &&
+ g_strcmp0 (geocode_place_get_country (place),
+ "United States") == 0 &&
+ g_strcmp0 (geocode_location_get_description (loc),
+ "Paris, Texas, United States") == 0)
got_texas = TRUE;
- g_object_unref (loc);
+ g_object_unref (place);
if (got_france && got_texas)
break;
@@ -248,6 +276,7 @@ test_search_lat_long (void)
GeocodeForward *object;
GError *error = NULL;
GList *res;
+ GeocodePlace *place;
GeocodeLocation *loc;
object = geocode_forward_new_for_string ("Santa María del Río");
@@ -259,9 +288,20 @@ test_search_lat_long (void)
g_assert (res != NULL);
g_object_unref (object);
- loc = res->data;
+ place = res->data;
+ loc = geocode_place_get_location (place);
+ g_assert (loc != NULL);
+
g_assert_cmpfloat (geocode_location_get_latitude (loc) - 21.800699, <, 0.000001);
g_assert_cmpfloat (geocode_location_get_longitude (loc) - -100.735626, <, 0.000001);
+ g_assert_cmpstr (geocode_place_get_name (place), ==, "Santa Maria Del Rio");
+ g_assert_cmpstr (geocode_place_get_town (place), ==, "Santa Maria Del Rio");
+ g_assert_cmpstr (geocode_place_get_state (place), ==, "San Luis Potosi");
+ g_assert_cmpstr (geocode_place_get_county (place), ==, "Santa Maria del Rio");
+ g_assert_cmpstr (geocode_place_get_country (place), ==, "Mexico");
+ g_assert_cmpstr (geocode_location_get_description (loc),
+ ==,
+ "Santa Maria Del Rio, San Luis Potosi, Mexico");
g_list_free_full (res, (GDestroyNotify) g_object_unref);
}
@@ -287,6 +327,7 @@ test_locale (void)
GeocodeForward *object;
GError *error = NULL;
GList *res;
+ GeocodePlace *place;
GeocodeLocation *loc;
char *old_locale;
@@ -303,11 +344,18 @@ test_locale (void)
g_assert (res != NULL);
g_object_unref (object);
- loc = res->data;
- g_assert_cmpstr (geocode_location_get_description (loc), ==, "Moskva, Rusko");
+ place = res->data;
+ g_assert_cmpstr (geocode_place_get_name (place), ==, "Moskva");
+ /* For some reason, Yahoo doesn't localise the state's name in this case */
+ g_assert_cmpstr (geocode_place_get_state (place), ==, "Moscow Federal City");
+ g_assert_cmpstr (geocode_place_get_country (place), ==, "Rusko");
+
+ loc = geocode_place_get_location (place);
+ g_assert (loc != NULL);
+ g_assert_cmpstr (geocode_location_get_description (loc), ==, "Moskva, Moscow Federal City, Rusko");
g_assert_cmpfloat (geocode_location_get_latitude (loc) - 55.756950, <, 0.000001);
g_assert_cmpfloat (geocode_location_get_longitude (loc) - 37.614971, <, 0.000001);
- print_loc (loc);
+ print_place (place);
g_list_free_full (res, (GDestroyNotify) g_object_unref);
@@ -322,9 +370,20 @@ test_locale (void)
g_assert (res != NULL);
g_object_unref (object);
- loc = res->data;
- g_assert_cmpstr (geocode_location_get_description (loc), ==, "Bonneville, Rhône-Alpes, France");
- print_loc (loc);
+ place = res->data;
+ loc = geocode_place_get_location (place);
+ g_assert (loc != NULL);
+
+ g_assert_cmpstr (geocode_place_get_name (place), ==, "Bonneville");
+ g_assert_cmpstr (geocode_place_get_town (place), ==, "Bonneville");
+ g_assert_cmpstr (geocode_place_get_state (place), ==, "Rhône-Alpes");
+ g_assert_cmpstr (geocode_place_get_county (place), ==, "Haute-Savoie");
+ g_assert_cmpstr (geocode_place_get_administrative_area (place), ==, "Bonneville");
+ g_assert_cmpstr (geocode_place_get_country (place), ==, "France");
+ g_assert_cmpstr (geocode_location_get_description (loc),
+ ==,
+ "Bonneville, Rhône-Alpes, France");
+ print_place (place);
g_list_free_full (res, (GDestroyNotify) g_object_unref);
@@ -388,6 +447,7 @@ test_search_json (void)
GError *error = NULL;
GList *list;
char *contents;
+ GeocodePlace *place;
GeocodeLocation *loc;
if (g_file_get_contents (TEST_SRCDIR "/geoplanet-rio.json",
@@ -400,8 +460,18 @@ test_search_json (void)
g_assert (list != NULL);
g_assert_cmpint (g_list_length (list), ==, 10);
- loc = list->data;
- g_assert_cmpstr (geocode_location_get_description (loc), ==, "Rio de Janeiro, Brazil");
+ place = list->data;
+ loc = geocode_place_get_location (place);
+ g_assert (loc != NULL);
+
+ g_assert_cmpstr (geocode_place_get_name (place), ==, "Rio de Janeiro");
+ g_assert_cmpstr (geocode_place_get_town (place), ==, "Rio de Janeiro");
+ g_assert_cmpstr (geocode_place_get_state (place), ==, "Rio de Janeiro");
+ g_assert_cmpstr (geocode_place_get_county (place), ==, "Rio de Janeiro");
+ g_assert_cmpstr (geocode_place_get_country (place), ==, "Brazil");
+ g_assert_cmpstr (geocode_location_get_description (loc),
+ ==,
+ "Rio de Janeiro, Rio de Janeiro, Brazil");
g_list_free_full (list, (GDestroyNotify) g_object_unref);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]