[gnome-maps/wip/osm-edit: 47/47] osmShim: Add OSM XML to Json shim library using libxml2.
- From: Marcus Lundblad <mlundblad src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-maps/wip/osm-edit: 47/47] osmShim: Add OSM XML to Json shim library using libxml2.
- Date: Thu, 30 Apr 2015 13:01:20 +0000 (UTC)
commit 369dba795e02553968ba752007ed8f534157116d
Author: Marcus Lundblad <ml update uu se>
Date: Sun Mar 22 20:17:42 2015 +0100
osmShim: Add OSM XML to Json shim library using libxml2.
Shim library routines used to parse OSM XML objects into GObject representations
of OSM objects.
lib/Makefile.am | 16 +-
lib/maps-osm-changeset.c | 56 +++++++
lib/maps-osm-changeset.h | 50 ++++++
lib/maps-osm-node.c | 203 +++++++++++++++++++++++++
lib/maps-osm-node.h | 53 +++++++
lib/maps-osm-object.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++
lib/maps-osm-object.h | 63 ++++++++
lib/maps-osm-relation.c | 157 +++++++++++++++++++
lib/maps-osm-relation.h | 58 +++++++
lib/maps-osm-way.c | 77 ++++++++++
lib/maps-osm-way.h | 49 ++++++
lib/maps-osm.c | 374 ++++++++++++++++++++++++----------------------
lib/maps-osm.h | 18 ++-
src/mapBubble.js | 14 +-
src/osmConnection.js | 65 +++------
src/osmEdit.js | 13 +-
src/placeBubble.js | 2 +-
17 files changed, 1391 insertions(+), 251 deletions(-)
---
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ddbd06d..1f3fcc0 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,8 +4,12 @@ BUILT_SOURCES = \
maps-enum-types.c \
maps-enum-types.h
-libgnome_maps_headers_private = maps-contact-store.h maps-contact.h maps.h maps-osm.h
-libgnome_maps_sources = maps-contact-store.c maps-contact.c maps-osm.c
+libgnome_maps_headers_private = maps-contact-store.h maps-contact.h \
+ maps.h maps-osm.h maps-osm-changeset.h maps-osm-node.h \
+ maps-osm-object.h maps-osm-relation.h maps-osm-way.h
+libgnome_maps_sources = maps-contact-store.c maps-contact.c maps-osm.c \
+ maps-osm-changeset.c maps-osm-node.c maps-osm-object.c \
+ maps-osm-way.c maps-osm-relation.c
libgnome_maps_la_SOURCES = \
$(libgnome_maps_sources) \
$(libgnome_maps_headers_private) \
@@ -32,14 +36,10 @@ if HAVE_INTROSPECTION
INTROSPECTION_SCANNER_ARGS = --warn-all
GnomeMaps-1.0.gir: libgnome-maps.la
-GnomeMaps_1_0_gir_INCLUDES = \
- GLib-2.0 \
- GObject-2.0 \
- GeocodeGlib-1.0 \
- Champlain-0.12
+GnomeMaps_1_0_gir_INCLUDES = GLib-2.0 GObject-2.0 GeocodeGlib-1.0 Champlain-0.12
GnomeMaps_1_0_gir_PACKAGES = gobject-2.0 geocode-glib-1.0
GnomeMaps_1_0_gir_FILES = $(libgnome_maps_la_SOURCES)
-GnomeMaps_1_0_gir_CFLAGS = $(MAPS_CFLAGS) -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)
+GnomeMaps_1_0_gir_CFLAGS = $(MAPS_CFLAGS) -I$(top_srcdir) -I$(top_builddir)
GnomeMaps_1_0_gir_LIBS = libgnome-maps.la
GnomeMaps_1_0_gir_EXPORT_PACKAGES = gnome-maps-1.0
GnomeMaps_1_0_gir_SCANNERFLAGS = \
diff --git a/lib/maps-osm-changeset.c b/lib/maps-osm-changeset.c
new file mode 100644
index 0000000..f292e2e
--- /dev/null
+++ b/lib/maps-osm-changeset.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#include "maps-osm-changeset.h"
+
+G_DEFINE_TYPE (MapsOSMChangeset, maps_osm_changeset,
+ MAPS_TYPE_OSMOBJECT)
+
+static const char *
+maps_osm_changeset_get_xml_tag_name (void)
+{
+ return "changeset";
+}
+
+static void
+maps_osm_changeset_class_init (MapsOSMChangesetClass *klass)
+{
+ MapsOSMObjectClass *object_class = MAPS_OSMOBJECT_CLASS (klass);
+
+ object_class->get_xml_tag_name = maps_osm_changeset_get_xml_tag_name;
+}
+
+static void
+maps_osm_changeset_init (MapsOSMChangeset *changeset)
+{
+}
+
+MapsOSMChangeset *
+maps_osm_changeset_new (const char *comment, const char *source)
+{
+ MapsOSMChangeset *changeset = g_object_new (MAPS_TYPE_OSMCHANGESET, NULL);
+
+ if (comment)
+ maps_osm_object_set_tag (MAPS_OSMOBJECT (changeset), "comment", comment);
+
+ if (source)
+ maps_osm_object_set_tag (MAPS_OSMOBJECT (changeset), "source", source);
+
+ return changeset;
+}
diff --git a/lib/maps-osm-changeset.h b/lib/maps-osm-changeset.h
new file mode 100644
index 0000000..9572ed9
--- /dev/null
+++ b/lib/maps-osm-changeset.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#ifndef __MAPS_OSM_CHANGESET_H__
+#define __MAPS_OSM_CHANGESET_H__
+
+#include "maps-osm-object.h"
+
+#include <glib-object.h>
+
+#define MAPS_TYPE_OSMCHANGESET maps_osm_changeset_get_type ()
+G_DECLARE_FINAL_TYPE(MapsOSMChangeset, maps_osm_changeset, MAPS, OSMCHANGESET,
+ MapsOSMObject)
+
+struct _MapsOSMChangeset
+{
+ MapsOSMObject parent_instance;
+};
+
+struct _MapsOSMChangesetClass
+{
+ MapsOSMObjectClass parent_class;
+};
+
+/**
+ * maps_osm_changeset_new:
+ * @comment: (nullable): A comment about the OSM change, optional
+ * @source: (nullable): The source of the OSM change, optional
+ */
+MapsOSMChangeset *maps_osm_changeset_new (const char *comment,
+ const char *source);
+
+#endif /* __MAPS_OSM_CHANGESET_H__ */
+
diff --git a/lib/maps-osm-node.c b/lib/maps-osm-node.c
new file mode 100644
index 0000000..564acd3
--- /dev/null
+++ b/lib/maps-osm-node.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#include "maps-osm-node.h"
+
+struct _MapsOSMNodePrivate
+{
+ double lon;
+ double lat;
+};
+
+enum {
+ PROP_0,
+
+ PROP_LON,
+ PROP_LAT
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (MapsOSMNode, maps_osm_node,
+ MAPS_TYPE_OSMOBJECT)
+
+
+static void
+maps_osm_node_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MapsOSMNode *node = MAPS_OSMNODE (object);
+
+ switch (property_id)
+ {
+ case PROP_LON:
+ node->priv->lon = g_value_get_double (value);
+ break;
+
+ case PROP_LAT:
+ node->priv->lat = g_value_get_double (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+maps_osm_node_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MapsOSMNode *node = MAPS_OSMNODE (object);
+
+ switch (property_id)
+ {
+ case PROP_LON:
+ g_value_set_double (value,
+ node->priv->lon);
+ break;
+
+ case PROP_LAT:
+ g_value_set_double (value,
+ node->priv->lat);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static const char *
+maps_osm_node_get_xml_tag_name (void)
+{
+ return "node";
+}
+
+static GHashTable *
+maps_osm_node_get_xml_attributes (const MapsOSMObject *object)
+{
+ const MapsOSMNode *node = MAPS_OSMNODE (object);
+ GHashTable *attributes;
+ char buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+ attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, g_free);
+
+ g_ascii_dtostr (buf, sizeof (buf), node->priv->lon);
+ g_hash_table_insert (attributes, "lon", g_strdup (buf));
+ g_ascii_dtostr (buf, sizeof (buf), node->priv->lat);
+ g_hash_table_insert (attributes, "lat", g_strdup (buf));
+
+ return attributes;
+}
+
+static void
+maps_osm_node_class_init (MapsOSMNodeClass *klass)
+{
+ GObjectClass *node_class = G_OBJECT_CLASS (klass);
+ MapsOSMObjectClass *object_class = MAPS_OSMOBJECT_CLASS (klass);
+ GParamSpec *pspec;
+
+ node_class->get_property = maps_osm_node_get_property;
+ node_class->set_property = maps_osm_node_set_property;
+ object_class->get_xml_tag_name = maps_osm_node_get_xml_tag_name;
+ object_class->get_xml_attributes = maps_osm_node_get_xml_attributes;
+
+ /**
+ * MapsOSMNode:lon:
+ *
+ * The longitude of the node.
+ */
+ pspec = g_param_spec_double ("lon",
+ "Longitude",
+ "Longitude",
+ -180.0,
+ 180.0,
+ 0.0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (node_class, PROP_LON, pspec);
+
+ /**
+ * MapsOSMNode:lat:
+ *
+ * The latitude of the node.
+ */
+ pspec = g_param_spec_double ("lat",
+ "Latitude",
+ "Latitude",
+ -90.0,
+ 90.0,
+ 0.0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (node_class, PROP_LAT, pspec);
+}
+
+static void
+maps_osm_node_init (MapsOSMNode *node)
+{
+ node->priv = maps_osm_node_get_instance_private (node);
+
+ node->priv->lon = 0.0;
+ node->priv->lat = 0.0;
+}
+
+MapsOSMNode *
+maps_osm_node_new (guint64 id, guint version, guint64 changeset,
+ double lon, double lat)
+{
+ return g_object_new (MAPS_TYPE_OSMNODE,
+ "id", id,
+ "version", version,
+ "changeset", changeset,
+ "lon", lon,
+ "lat", lat, NULL);
+}
+
+double
+maps_osm_node_get_lon (MapsOSMNode *node)
+{
+ double lon;
+
+ g_object_get (node, "lon", &lon);
+ return lon;
+}
+
+void
+maps_osm_node_set_lon (MapsOSMNode *node, double lon)
+{
+ g_object_set (node, "lon", lon);
+}
+
+double
+maps_osm_node_get_lat (MapsOSMNode *node)
+{
+ double lat;
+
+ g_object_get (node, "lat", &lat);
+ return lat;
+}
+
+void
+maps_osm_node_set_lat (MapsOSMNode *node, double lat)
+{
+ g_object_set (node, "lat", lat);
+}
diff --git a/lib/maps-osm-node.h b/lib/maps-osm-node.h
new file mode 100644
index 0000000..638a45a
--- /dev/null
+++ b/lib/maps-osm-node.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#ifndef __MAPS_OSM_NODE_H__
+#define __MAPS_OSM_NODE_H__
+
+#include "maps-osm-object.h"
+
+#include <glib-object.h>
+
+#define MAPS_TYPE_OSMNODE maps_osm_node_get_type ()
+G_DECLARE_FINAL_TYPE(MapsOSMNode, maps_osm_node, MAPS, OSMNODE,
+ MapsOSMObject)
+
+typedef struct _MapsOSMNodePrivate MapsOSMNodePrivate;
+
+struct _MapsOSMNode
+{
+ MapsOSMObject parent_instance;
+ MapsOSMNodePrivate *priv;
+};
+
+struct _MapsOSMNodeClass
+{
+ MapsOSMObjectClass parent_class;
+};
+
+MapsOSMNode *maps_osm_node_new (guint64 id, guint version, guint64 changeset,
+ double lon, double lat);
+
+double maps_osm_node_get_lon (MapsOSMNode *node);
+void maps_osm_node_set_lon (MapsOSMNode *node, double lon);
+double maps_osm_node_get_lat (MapsOSMNode *node);
+void maps_osm_node_set_lat (MapsOSMNode *node, double lon);
+
+
+#endif //__MAPS_OSM_NODE_H__
diff --git a/lib/maps-osm-object.c b/lib/maps-osm-object.c
new file mode 100644
index 0000000..95a2167
--- /dev/null
+++ b/lib/maps-osm-object.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#include "maps-osm-object.h"
+
+struct _MapsOSMObjectPrivate
+{
+ guint64 id;
+ guint version;
+ guint64 changeset;
+
+ GHashTable *tags;
+};
+
+enum {
+ PROP_0,
+
+ PROP_ID,
+ PROP_VERSION,
+ PROP_CHANGESET
+};
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MapsOSMObject, maps_osm_object,
+ G_TYPE_OBJECT)
+
+static void
+maps_osm_object_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MapsOSMObject *osm_object = MAPS_OSMOBJECT (object);
+ MapsOSMObjectPrivate *priv =
+ maps_osm_object_get_instance_private (osm_object);
+
+ switch (property_id)
+ {
+ case PROP_ID:
+ priv->id = g_value_get_uint64 (value);
+ break;
+
+ case PROP_VERSION:
+ g_debug ("setting version: %d\n", g_value_get_uint (value));
+ priv->version = g_value_get_uint (value);
+ break;
+
+ case PROP_CHANGESET:
+ priv->changeset = g_value_get_uint64 (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+maps_osm_object_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MapsOSMObject *osm_object = MAPS_OSMOBJECT (object);
+ MapsOSMObjectPrivate *priv =
+ maps_osm_object_get_instance_private (osm_object);
+
+ switch (property_id)
+ {
+ case PROP_ID:
+ g_value_set_uint64 (value,
+ priv->id);
+ break;
+
+ case PROP_VERSION:
+ g_value_set_uint (value,
+ priv->version);
+ g_debug ("getting version: %d\n", g_value_get_uint (value));
+ break;
+
+ case PROP_CHANGESET:
+ g_value_set_uint64 (value,
+ priv->changeset);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+maps_osm_object_dispose (GObject *object)
+{
+ MapsOSMObject *osm_object = MAPS_OSMOBJECT (object);
+ MapsOSMObjectPrivate *priv =
+ maps_osm_object_get_instance_private (osm_object);
+
+ g_hash_table_destroy (priv->tags);
+ priv->tags = NULL;
+
+ G_OBJECT_CLASS (maps_osm_object_parent_class)->dispose (object);
+}
+
+/* base implementation returning no object-specific XML attributes */
+static GHashTable *
+maps_osm_object_get_xml_attributes (const MapsOSMObject *object)
+{
+ return g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+/* base implementation return no object-specific child XML nodes */
+static xmlNodePtr
+maps_osm_object_get_xml_child_nodes (const MapsOSMObject *object)
+{
+ return NULL;
+}
+
+static void
+maps_osm_object_class_init (MapsOSMObjectClass *klass)
+{
+ GObjectClass *maps_class = G_OBJECT_CLASS (klass);
+ MapsOSMObjectClass *object_class = MAPS_OSMOBJECT_CLASS (klass);
+ GParamSpec *pspec;
+
+ maps_class->dispose = maps_osm_object_dispose;
+ maps_class->get_property = maps_osm_object_get_property;
+ maps_class->set_property = maps_osm_object_set_property;
+ object_class->get_xml_attributes = maps_osm_object_get_xml_attributes;
+ object_class->get_xml_child_nodes = maps_osm_object_get_xml_child_nodes;
+
+ /**
+ * MapsOSMObject:id:
+ *
+ * The OSM id of the object.
+ */
+ pspec = g_param_spec_uint64 ("id",
+ "ID",
+ "ID",
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (maps_class, PROP_ID, pspec);
+
+ /**
+ * MapsOSMObject:version:
+ *
+ * The latest OSM version of the object.
+ */
+ pspec = g_param_spec_uint("version",
+ "Version",
+ "Version",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (maps_class, PROP_VERSION, pspec);
+
+ /**
+ * MapsOSMObject:changeset:
+ *
+ * The OSM changeset for the current upload of the object.
+ */
+ pspec = g_param_spec_uint64 ("changeset",
+ "Changeset",
+ "Changeset",
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (maps_class, PROP_CHANGESET, pspec);
+}
+
+static void
+maps_osm_object_init (MapsOSMObject *object)
+{
+ MapsOSMObjectPrivate *priv = maps_osm_object_get_instance_private (object);
+
+ priv->tags = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_free);
+}
+
+guint64
+maps_osm_object_get_id (MapsOSMObject *object)
+{
+ guint64 id;
+
+ g_object_get (G_OBJECT (object), "id", &id);
+ return id;
+}
+
+void
+maps_osm_object_set_id (MapsOSMObject *object, guint64 id)
+{
+ g_object_set (G_OBJECT (object), "id", id);
+}
+
+guint
+maps_osm_object_get_version (MapsOSMObject *object)
+{
+ guint version;
+
+ g_object_get (G_OBJECT (object), "version", &version);
+ return version;
+}
+
+void
+maps_osm_object_set_version (MapsOSMObject *object, guint version)
+{
+ g_object_set (G_OBJECT (object), "version", version);
+}
+
+guint64
+maps_osm_object_get_changeset (MapsOSMObject *object)
+{
+ guint64 changeset;
+
+ g_object_get (G_OBJECT (object), "changeset", &changeset);
+ return changeset;
+}
+
+void
+maps_osm_object_set_changset (MapsOSMObject *object, guint64 changeset)
+{
+ g_object_set (G_OBJECT (object), "changeset", changeset);
+}
+
+const char *
+maps_osm_object_get_tag (const MapsOSMObject *object, const char *key)
+{
+ MapsOSMObjectPrivate *priv = maps_osm_object_get_instance_private (object);
+
+ return g_hash_table_lookup (priv->tags, key);
+}
+
+void
+maps_osm_object_set_tag (MapsOSMObject *object,
+ const char *key, const char *value)
+{
+ MapsOSMObjectPrivate *priv = maps_osm_object_get_instance_private (object);
+
+ g_hash_table_insert (priv->tags, g_strdup (key), g_strdup (value));
+}
+
+void
+maps_osm_object_delete_tag (MapsOSMObject *object, const char *key)
+{
+ MapsOSMObjectPrivate *priv = maps_osm_object_get_instance_private (object);
+
+ g_hash_table_remove (priv->tags, key);
+}
+
+void
+maps_osm_object_foreach_tag (gpointer key, gpointer value, gpointer user_data)
+{
+ const char *name = (const char *) key;
+ const char *val = (const char *) value;
+ xmlNodePtr object_node = (xmlNodePtr) user_data;
+ xmlNodePtr tag_node;
+
+ tag_node = xmlNewNode (NULL, "tag");
+ xmlNewProp (tag_node, "k", key);
+ xmlNewProp (tag_node, "v", val);
+ xmlAddChild (object_node, tag_node);
+}
+
+void
+maps_osm_object_foreach_type_attr (gpointer key, gpointer value,
+ gpointer user_data)
+{
+ const char *name = (const char *) key;
+ const char *val = (const char *) value;
+ xmlNodePtr object_node = (xmlNodePtr) user_data;
+
+ xmlNewProp (object_node, name, val);
+}
+
+xmlDocPtr
+maps_osm_object_to_xml (const MapsOSMObject *object)
+{
+ MapsOSMObjectPrivate *priv;
+ xmlDocPtr doc;
+ xmlNodePtr osm_node;
+ xmlNodePtr object_node;
+ const char *type;
+ guint64 id;
+ guint version;
+ guint64 changeset;
+ GHashTable *type_attrs;
+ xmlNodePtr type_sub_nodes;
+
+ doc = xmlNewDoc ("1.0");
+ osm_node = xmlNewNode (NULL, "osm");
+ priv = (MapsOSMObjectPrivate *) maps_osm_object_get_instance_private (object);
+ type = MAPS_OSMOBJECT_GET_CLASS (object)->get_xml_tag_name ();
+ object_node = xmlNewNode (NULL, type);
+
+ /* add common OSM attributes */
+ id = priv->id;
+ version = priv->version;
+ changeset = priv->changeset;
+
+ if (id != 0) {
+ char buf[16];
+ g_snprintf (buf, 16, "%" G_GUINT64_FORMAT, id);
+ xmlNewProp (object_node, "id", buf);
+ }
+
+ if (version != 0) {
+ char buf[16];
+ g_snprintf (buf, 16, "%d", version);
+ xmlNewProp (object_node, "version", buf);
+ }
+
+ if (changeset != 0) {
+ char buf[16];
+ g_snprintf (buf, 16, "%" G_GUINT64_FORMAT, changeset);
+ xmlNewProp (object_node, "changeset", buf);
+ }
+
+ /* add OSM tags */
+ g_hash_table_foreach (priv->tags, maps_osm_object_foreach_tag, object_node);
+
+ /* add type-specific attributes */
+ type_attrs = MAPS_OSMOBJECT_GET_CLASS (object)->get_xml_attributes (object);
+ g_hash_table_foreach (type_attrs, maps_osm_object_foreach_type_attr,
+ object_node);
+ g_hash_table_destroy (type_attrs);
+
+ /* add type-specific sub-nodes */
+ type_sub_nodes =
+ MAPS_OSMOBJECT_GET_CLASS (object)->get_xml_child_nodes (object);
+ if (type_sub_nodes)
+ xmlAddChildList (object_node, type_sub_nodes);
+
+ /* add type node to top node */
+ xmlAddChild (osm_node, object_node);
+ xmlDocSetRootElement (doc, osm_node);
+
+ return doc;
+}
+
+
+char *
+maps_osm_object_serialize (const MapsOSMObject *object)
+{
+ xmlDocPtr doc;
+ xmlChar *result;
+ int size;
+
+ doc = maps_osm_object_to_xml (object);
+ xmlDocDumpMemory (doc, &result, &size);
+ xmlFreeDoc (doc);
+
+ return result;
+}
diff --git a/lib/maps-osm-object.h b/lib/maps-osm-object.h
new file mode 100644
index 0000000..b2f3180
--- /dev/null
+++ b/lib/maps-osm-object.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#ifndef __MAPS_OSM_OBJECT_H__
+#define __MAPS_OSM_OBJECT_H__
+
+#include <glib-object.h>
+#include <libxml/xpath.h>
+
+#define MAPS_TYPE_OSMOBJECT maps_osm_object_get_type ()
+G_DECLARE_DERIVABLE_TYPE(MapsOSMObject, maps_osm_object, MAPS, OSMOBJECT,
+ GObject)
+
+typedef struct _MapsOSMObjectPrivate MapsOSMObjectPrivate;
+
+struct _MapsOSMObjectClass
+{
+ GObjectClass parent_class;
+
+ /* return the name of the distinguishing OSM XML tag (beneeth <osm/>) */
+ const char * (* get_xml_tag_name) (void);
+
+ /* return hash table with XML attributes (key/values) specific for
+ the object (on the XML tag beneeth <osm/>) */
+ GHashTable * (* get_xml_attributes) (const MapsOSMObject *object);
+
+ /* return a list of custom object-specific XML tags to attach,
+ can return NULL if there's no object-specific nodes */
+ xmlNodePtr (* get_xml_child_nodes) (const MapsOSMObject *object);
+};
+
+guint64 maps_osm_object_get_id (MapsOSMObject *object);
+void maps_osm_object_set_id (MapsOSMObject *object, guint64 id);
+guint maps_osm_object_get_version (MapsOSMObject *object);
+void maps_osm_object_set_version (MapsOSMObject *object, guint version);
+guint64 maps_osm_object_get_changeset (MapsOSMObject *object);
+void maps_osm_object_set_changeset (MapsOSMObject *object, guint64 changeset);
+
+const char *maps_osm_object_get_tag (const MapsOSMObject *object,
+ const char *key);
+void maps_osm_object_set_tag (MapsOSMObject *object, const char *key,
+ const char *value);
+void maps_osm_object_delete_tag (MapsOSMObject *object, const char *key);
+
+char *maps_osm_object_serialize (const MapsOSMObject *object);
+
+#endif //__MAPS_OSM_OBJECT_H__
diff --git a/lib/maps-osm-relation.c b/lib/maps-osm-relation.c
new file mode 100644
index 0000000..8ce261d
--- /dev/null
+++ b/lib/maps-osm-relation.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#include "maps-osm-relation.h"
+
+struct _MapsOSMRelationPrivate
+{
+ GList *members;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (MapsOSMRelation, maps_osm_relation,
+ MAPS_TYPE_OSMOBJECT);
+
+typedef struct
+{
+ char *role;
+ guint type;
+ guint64 ref;
+} MapsOSMRelationMember;
+
+static void
+maps_osm_relation_member_free (gpointer data)
+{
+ MapsOSMRelationMember *member = (MapsOSMRelationMember *) data;
+
+ g_free (member->role);
+}
+
+static void
+maps_osm_relation_dispose (GObject *object)
+{
+ MapsOSMRelation *relation = MAPS_OSMRELATION (object);
+
+ g_list_free_full (relation->priv->members, maps_osm_relation_member_free);
+ relation->priv->members = NULL;
+
+ G_OBJECT_CLASS (maps_osm_relation_parent_class)->dispose (object);
+}
+
+static const char *
+maps_osm_relation_get_xml_tag_name (void)
+{
+ return "relation";
+}
+
+static const char *
+maps_osm_relation_member_type_to_string (guint type)
+{
+ switch (type) {
+ case MEMBER_TYPE_NODE:
+ return "node";
+ case MEMBER_TYPE_WAY:
+ return "way";
+ case MEMBER_TYPE_RELATION:
+ return "relation";
+ default:
+ g_warning ("Unknown relation member type: %d\n", type);
+ return NULL;
+ }
+}
+
+static xmlNodePtr
+maps_osm_relation_get_member_node (const MapsOSMRelationMember *member)
+{
+ xmlNodePtr node = xmlNewNode (NULL, "member");
+ char buf[16];
+
+ if (member->role)
+ xmlNewProp (node, "role", g_strdup (member->role));
+
+ xmlNewProp (node, "type",
+ maps_osm_relation_member_type_to_string (member->type));
+ g_snprintf (buf, 16, "%" G_GUINT64_FORMAT, member->ref);
+ xmlNewProp (node, "ref", buf);
+
+ return node;
+}
+
+static xmlNodePtr
+maps_osm_relation_get_xml_child_nodes (const MapsOSMObject *object)
+{
+ MapsOSMRelation *relation = MAPS_OSMRELATION (object);
+ xmlNodePtr nodes = NULL;
+ const GList *members = relation->priv->members;
+
+ if (members) {
+ const GList *iter;
+ nodes = maps_osm_relation_get_member_node ((MapsOSMRelationMember *)
+ members->data);
+
+ for (iter = members->next; iter; iter = iter->next) {
+ xmlAddSibling (nodes,
+ maps_osm_relation_get_member_node (
+ (MapsOSMRelationMember *) iter->data));
+ }
+ }
+
+ return nodes;
+}
+
+static void
+maps_osm_relation_class_init (MapsOSMRelationClass *klass)
+{
+ GObjectClass *relation_class = G_OBJECT_CLASS (klass);
+ MapsOSMObjectClass *object_class = MAPS_OSMOBJECT_CLASS (klass);
+
+ relation_class->dispose = maps_osm_relation_dispose;
+ object_class->get_xml_tag_name = maps_osm_relation_get_xml_tag_name;
+ object_class->get_xml_child_nodes = maps_osm_relation_get_xml_child_nodes;
+}
+
+static void
+maps_osm_relation_init (MapsOSMRelation *relation)
+{
+ relation->priv = maps_osm_relation_get_instance_private (relation);
+}
+
+MapsOSMRelation *
+maps_osm_relation_new (guint64 id, guint version, guint64 changeset)
+{
+ return g_object_new (MAPS_TYPE_OSMRELATION,
+ "id", id,
+ "version", version,
+ "changeset", changeset);
+}
+
+void
+maps_osm_relation_add_member (MapsOSMRelation *relation,
+ const gchar *role, guint type, guint64 ref)
+{
+ MapsOSMRelationMember *member = g_new (MapsOSMRelationMember, 1);
+
+ member->role = g_strdup (role);
+ member->type = type;
+ member->ref = ref;
+
+ relation->priv->members = g_list_append (relation->priv->members,
+ member);
+}
+
+
diff --git a/lib/maps-osm-relation.h b/lib/maps-osm-relation.h
new file mode 100644
index 0000000..9e0119d
--- /dev/null
+++ b/lib/maps-osm-relation.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#ifndef __MAPS_OSM_RELATION_H__
+#define __MAPS_OSM_RELATION_H__
+
+#include "maps-osm-object.h"
+
+#include <glib-object.h>
+
+#define MAPS_TYPE_OSMRELATION maps_osm_relation_get_type ()
+G_DECLARE_FINAL_TYPE(MapsOSMRelation, maps_osm_relation, MAPS, OSMRELATION,
+ MapsOSMObject)
+
+typedef struct _MapsOSMRelationPrivate MapsOSMRelationPrivate;
+
+struct _MapsOSMRelation
+{
+ MapsOSMObject parent_instance;
+ MapsOSMRelationPrivate *priv;
+};
+
+struct _MapsOSMRelationClass
+{
+ MapsOSMObjectClass parent_class;
+};
+
+enum {
+ MEMBER_TYPE_NODE,
+ MEMBER_TYPE_WAY,
+ MEMBER_TYPE_RELATION
+};
+
+MapsOSMRelation *maps_osm_relation_new (guint64 id, guint version,
+ guint64 changeset);
+
+void maps_osm_relation_add_member (MapsOSMRelation *relation,
+ const char *role, guint type,
+ guint64 ref);
+
+#endif /* __MAPS_OSM_RELATION_H__ */
+
diff --git a/lib/maps-osm-way.c b/lib/maps-osm-way.c
new file mode 100644
index 0000000..31bb720
--- /dev/null
+++ b/lib/maps-osm-way.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#include "maps-osm-way.h"
+
+struct _MapsOSMWayPrivate
+{
+ GArray *node_ids;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (MapsOSMWay, maps_osm_way,
+ MAPS_TYPE_OSMOBJECT);
+
+static void
+maps_osm_way_dispose (GObject *object)
+{
+ MapsOSMWay *way = MAPS_OSMWAY (object);
+
+ g_array_free (way->priv->node_ids, TRUE);
+ way->priv->node_ids = NULL;
+
+ G_OBJECT_CLASS (maps_osm_way_parent_class)->dispose (object);
+}
+
+static const char *
+maps_osm_way_get_xml_tag_name (void)
+{
+ return "way";
+}
+
+static void
+maps_osm_way_class_init (MapsOSMWayClass *klass)
+{
+ GObjectClass *way_class = G_OBJECT_CLASS (klass);
+ MapsOSMObjectClass *object_class = MAPS_OSMOBJECT_CLASS (klass);
+
+ way_class->dispose = maps_osm_way_dispose;
+ object_class->get_xml_tag_name = maps_osm_way_get_xml_tag_name;
+}
+
+static void
+maps_osm_way_init (MapsOSMWay *way)
+{
+ way->priv = maps_osm_way_get_instance_private (way);
+ way->priv->node_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
+}
+
+MapsOSMWay *
+maps_osm_way_new (guint64 id, guint version, guint64 changeset)
+{
+ return g_object_new (MAPS_TYPE_OSMWAY,
+ "id", id,
+ "version", version,
+ "changeset", changeset);
+}
+
+void
+maps_osm_way_add_node_id (MapsOSMWay *way, guint64 id)
+{
+ g_array_append_val (way->priv->node_ids, id);
+}
diff --git a/lib/maps-osm-way.h b/lib/maps-osm-way.h
new file mode 100644
index 0000000..2817d3e
--- /dev/null
+++ b/lib/maps-osm-way.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+#ifndef __MAPS_OSM_WAY_H__
+#define __MAPS_OSM_WAY_H__
+
+#include "maps-osm-object.h"
+
+#include <glib-object.h>
+
+#define MAPS_TYPE_OSMWAY maps_osm_way_get_type ()
+G_DECLARE_FINAL_TYPE(MapsOSMWay, maps_osm_way, MAPS, OSMWAY,
+ MapsOSMObject)
+
+typedef struct _MapsOSMWayPrivate MapsOSMWayPrivate;
+
+struct _MapsOSMWay
+{
+ MapsOSMObject parent_instance;
+ MapsOSMWayPrivate *priv;
+};
+
+struct _MapsOSMWayClass
+{
+ MapsOSMObjectClass parent_class;
+};
+
+MapsOSMWay *maps_osm_way_new (guint64 id, guint version, guint64 changeset);
+
+void maps_osm_way_add_node_id (MapsOSMWay *way, guint64 id);
+
+#endif /* __MAPS_OSM_WAY_H__ */
+
diff --git a/lib/maps-osm.c b/lib/maps-osm.c
index 88dba0d..902a0d7 100644
--- a/lib/maps-osm.c
+++ b/lib/maps-osm.c
@@ -12,8 +12,7 @@
* for more details.
*
* You should have received a copy of the GNU General Public License along
- * with GNOME Maps; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
*
* Author: Marcus Lundblad <ml update uu se>
*/
@@ -23,17 +22,20 @@
#include <libxml/parser.h>
#include <libxml/xpath.h>
-void maps_osm_init (void)
+void
+maps_osm_init (void)
{
LIBXML_TEST_VERSION;
}
-void maps_osm_finalize (void)
+void
+maps_osm_finalize (void)
{
xmlCleanupParser ();
}
-static xmlDocPtr _read_xml_doc (const gchar *content, guint length)
+static xmlDocPtr
+read_xml_doc (const char *content, guint length)
{
xmlDoc *doc;
@@ -47,38 +49,32 @@ static xmlDocPtr _read_xml_doc (const gchar *content, guint length)
return doc;
}
-static gchar *_parse_tag (const xmlAttr *attrs)
+static void
+parse_tag (const xmlAttr *attrs, GHashTable *tags)
{
const xmlAttr *cur_attr;
- gchar *key;
- gchar *value;
- gchar *result;
+ char *key;
+ char *value;
+ char *result;
key = NULL;
value = NULL;
for (cur_attr = attrs; cur_attr; cur_attr = cur_attr->next) {
if (g_str_equal (cur_attr->name, "k")) {
- key = g_strescape (cur_attr->children->content, "");
+ key = cur_attr->children->content, "";
} else if (g_str_equal (cur_attr->name, "v")) {
- value = g_strescape (cur_attr->children->content, "");
+ value = cur_attr->children->content, "";
} else {
g_warning ("Unexpected tag property: %s\n", cur_attr->name);
}
}
- result = g_strdup_printf ("\"%s\": \"%s\"", key, value);
-
- if (key)
- g_free (key);
-
- if (value)
- g_free (value);
-
- return result;
+ g_hash_table_insert (tags, key, value);
}
-static GHashTable *_parse_attributes (const xmlNode *node)
+static GHashTable *
+parse_attributes (const xmlNode *node)
{
GHashTable *attributes;
const xmlAttr *cur_attr;
@@ -94,12 +90,13 @@ static GHashTable *_parse_attributes (const xmlNode *node)
return attributes;
}
-static GList *_parse_tags (const xmlNode *tag_child)
+static GHashTable *
+parse_tags (const xmlNode *tag_child)
{
- GList *tags;
+ GHashTable *tags;
const xmlNode *cur_node;
- tags = NULL;
+ tags = g_hash_table_new (g_str_hash, g_str_equal);
for (cur_node = tag_child; cur_node; cur_node = cur_node->next) {
/* skip non-element nodes */
@@ -108,25 +105,22 @@ static GList *_parse_tags (const xmlNode *tag_child)
}
if (g_str_equal (cur_node->name, "tag")) {
- gchar *tag;
+ char *tag;
- tag = _parse_tag (cur_node->properties);
-
- if (tag) {
- tags = g_list_append (tags, tag);
- }
+ parse_tag (cur_node->properties, tags);
}
}
return tags;
}
-static GList *_parse_node_refs (const xmlNode *node_ref_child)
+static GArray *
+parse_node_refs (const xmlNode *node_ref_child)
{
- GList *node_refs;
+ GArray *node_refs;
const xmlNode *cur_node;
- node_refs = NULL;
+ node_refs = g_array_new (FALSE, FALSE, sizeof (guint64));
for (cur_node = node_ref_child; cur_node; cur_node = cur_node->next) {
/* skip non-element nodes */
@@ -135,14 +129,19 @@ static GList *_parse_node_refs (const xmlNode *node_ref_child)
}
if (g_str_equal (cur_node->name, "nd")) {
- gchar *ref;
+ char *ref;
GHashTable *attributes;
- attributes = _parse_attributes (cur_node);
+ attributes = parse_attributes (cur_node);
ref = g_hash_table_lookup (attributes, "ref");
if (ref) {
- node_refs = g_list_append (node_refs, ref);
+ guint64 id = g_strtoull (ref);
+
+ if (id == 0)
+ g_warning ("Invalid node ref: %s", ref);
+ else
+ g_array_append (node_refs, id);
}
g_hash_table_destroy (attributes);
@@ -152,12 +151,13 @@ static GList *_parse_node_refs (const xmlNode *node_ref_child)
return node_refs;
}
-static xmlNode *_get_sub_node (xmlDoc *doc, const gchar *name)
+static xmlNode *
+get_sub_node (xmlDoc *doc, const char *name)
{
xmlNode *node;
xmlXPathContext *xpath_ctx;
xmlXPathObject * xpath_obj;
- gchar *xpath;
+ char *xpath;
xpath = g_strdup_printf ("/osm/%s", name);
xpath_ctx = xmlXPathNewContext (doc);
@@ -177,187 +177,195 @@ static xmlNode *_get_sub_node (xmlDoc *doc, const gchar *name)
return node;
}
-static void _fill_tags (GString *buffer, const GList *tag_list)
+static void
+for_each_tag (gpointer key, gpointer value, gpointer user_data)
{
- const GList *cur_tag;
+ const char *k = (const char *) key;
+ const char *v = (const char *) value;
+ MapsOSMObject *object = MAPS_OSMOBJECT (user_data);
- g_string_append (buffer, "\t\"tags\": {\n");
-
- for (cur_tag = tag_list; cur_tag; cur_tag = g_list_next (cur_tag)) {
- g_string_append_printf (buffer, "\t\t%s", cur_tag->data);
-
- if (g_list_next (cur_tag))
- g_string_append (buffer, ",");
-
- g_string_append (buffer, "\n");
- }
-
- g_string_append (buffer, "\t}\n");
+ maps_osm_object_set_tag (object, k, v);
}
-static void _fill_node_ref_list (GString *buffer, const GList *node_list)
+static void
+fill_tags (MapsOSMObject *object, GHashTable *tags)
{
- const GList *cur_tag;
-
- g_string_append (buffer, "\t\"nodeRefs\": [\n");
-
- for (cur_tag = node_list; cur_tag; cur_tag = g_list_next (cur_tag)) {
- g_string_append_printf (buffer, "\t\t%s", cur_tag->data);
-
- if (g_list_next (cur_tag))
- g_string_append (buffer, ",");
+ g_hash_table_foreach (tags, for_each_tag, object);
+}
- g_string_append (buffer, "\n");
+static void
+fill_node_ref_list (MapsOSMWay *way, const GArray *node_refs)
+{
+ int i;
+
+ for (i = 0; i < g_array_size (node_refs); i++) {
+ maps_osm_way_add_node_id (way, g_array_index (node_refs, guint64, i));
}
-
- g_string_append (buffer, "\t]\n");
-
}
/**
* maps_osm_parse_node:
* @content: XML data
* @length: Length of data
+ * Returns: (transfer full): An OSMNode
*/
-gchar *maps_osm_parse_node (const gchar *content, guint length)
+MapsOSMNode *
+maps_osm_parse_node (const char *content, guint length)
{
xmlDoc *doc;
xmlNode *node;
- const gchar *id;
- const gchar *changeset;
- const gchar *version;
- const gchar *lat;
- const gchar *lon;
-
+ const char *id_string;
+ guint64 id;
+ const char *changeset_string;
+ guint64 changeset;
+ const char *version_string;
+ guint version;
+ const char *lat_string;
+ double lat;
+ const char *lon_string;
+ double lon;
+
const xmlAttr *cur_attr;
- GString *buffer;
-
- GList *tag_list;
+ GHashTable *tags;
GHashTable *attributes;
+
+ MapsOSMNode *result;
- doc = _read_xml_doc (content, length);
+ doc = read_xml_doc (content, length);
if (!doc) {
return NULL;
}
- node = _get_sub_node (doc, "node");
+ node = get_sub_node (doc, "node");
if (!node) {
+ g_error ("Missing <node/> element");
xmlFreeDoc (doc);
return NULL;
}
- attributes = _parse_attributes (node);
+ attributes = parse_attributes (node);
- id = g_hash_table_lookup (attributes, "id");
- changeset = g_hash_table_lookup (attributes, "changeset");
- version = g_hash_table_lookup (attributes, "version");
- lat = g_hash_table_lookup (attributes, "lat");
- lon = g_hash_table_lookup (attributes, "lon");
+ id_string = g_hash_table_lookup (attributes, "id");
+ changeset_string = g_hash_table_lookup (attributes, "changeset");
+ version_string = g_hash_table_lookup (attributes, "version");
+ lat_string = g_hash_table_lookup (attributes, "lat");
+ lon_string = g_hash_table_lookup (attributes, "lon");
- if (!id || !changeset || !version || !lat || !lon) {
- g_error ("Missing required attributes\n");
+ if (!id_string || !changeset_string || !version_string
+ || !lat_string || !lon_string) {
+ g_warning ("Missing required attributes\n");
xmlFreeDoc (doc);
xmlFreeNode (node);
g_hash_table_destroy (attributes);
return NULL;
}
- buffer = g_string_new (NULL);
-
- g_string_append (buffer, "{\n");
- g_string_append_printf (buffer, "\t\"id\": \"%s\",\n", id);
- g_string_append_printf (buffer, "\t\"changeset\": \"%s\",\n", changeset);
- g_string_append_printf (buffer, "\t\"version\": \"%s\",\n", version);
- g_string_append_printf (buffer, "\t\"lat\": \"%s\",\n", lat);
- g_string_append_printf (buffer, "\t\"lon\": \"%s\",\n", lon);
+ g_debug ("version parsed: %s\n", version_string);
+
+ id = g_ascii_strtoull (id_string, NULL, 10);
+ changeset = g_ascii_strtoull (changeset_string, NULL, 10);
+ version = g_ascii_strtoull (version_string, NULL, 10);
+ lon = g_ascii_strtod (lon_string, NULL);
+ lat = g_ascii_strtod (lat_string, NULL);
+
g_hash_table_destroy (attributes);
+
+ result = maps_osm_node_new (id, version, changeset, lon, lat);
+
+ g_debug ("version: %d\n",
+ maps_osm_object_get_version (MAPS_OSMOBJECT (result)));
- tag_list = _parse_tags (node->children);
- _fill_tags (buffer, tag_list);
+ tags = parse_tags (node->children);
+ fill_tags (MAPS_OSMOBJECT (result), tags);
- g_list_free_full (tag_list, g_free);
- g_string_append (buffer, "}\n");
+ g_hash_table_destroy (tags);
xmlFreeDoc (doc);
xmlFreeNode (node);
- return g_string_free (buffer, FALSE);
+ return result;
}
-gchar *maps_osm_parse_way (const gchar *content, guint length)
+/**
+ * maps_osm_parse_way:
+ * @content: XML data
+ * @length: Length of data
+ * Returns: (transfer full): An OSMWay
+ */
+MapsOSMWay *
+maps_osm_parse_way (const char *content, guint length)
{
xmlDoc *doc;
xmlNode *way;
GHashTable *attributes;
- GList *tag_list;
- GList *node_refs_list;
- GString *buffer;
+ GHashTable *tags;
+ GArray *node_refs;
+ MapsOSMWay *result;
- const gchar *id;
- const gchar *changeset;
- const gchar *version;
+ const char *id_string;
+ guint64 id;
+ const char *changeset_string;
+ guint64 changeset;
+ const char *version_string;
+ guint version;
- doc = _read_xml_doc (content, length);
+ doc = read_xml_doc (content, length);
if (!doc) {
return NULL;
}
- way = _get_sub_node (doc, "way");
+ way = get_sub_node (doc, "way");
if (!way) {
xmlFreeDoc (doc);
return NULL;
}
- attributes = _parse_attributes (way);
+ attributes = parse_attributes (way);
- id = g_hash_table_lookup (attributes, "id");
- changeset = g_hash_table_lookup (attributes, "changeset");
- version = g_hash_table_lookup (attributes, "version");
+ id_string = g_hash_table_lookup (attributes, "id");
+ changeset_string = g_hash_table_lookup (attributes, "changeset");
+ version_string = g_hash_table_lookup (attributes, "version");
if (!id || !changeset || !version) {
- g_error ("Missing required attributes\n");
+ g_warning ("Missing required attributes\n");
xmlFreeDoc (doc);
xmlFreeNode (way);
g_hash_table_destroy (attributes);
return NULL;
}
- buffer = g_string_new (NULL);
-
- g_string_append (buffer, "{\n");
- g_string_append_printf (buffer, "\t\"id\": \"%s\",\n", id);
- g_string_append_printf (buffer, "\t\"changeset\": \"%s\",\n", changeset);
- g_string_append_printf (buffer, "\t\"version\": \"%s\",\n", version);
-
g_hash_table_destroy (attributes);
- tag_list = _parse_tags (way->children);
- _fill_tags (buffer, tag_list);
- g_list_free_full (tag_list, g_free);
+ id = g_ascii_strtoull (id_string, NULL, 10);
+ changeset = g_ascii_strtoull (changeset_string, NULL, 10);
+ version = g_ascii_strtoull (version_string, NULL, 10);
- g_string_append (buffer, "\t,\n");
+ result = maps_osm_way_new (id, changeset, version);
- node_refs_list = _parse_node_refs (way->children);
- _fill_node_ref_list (buffer, node_refs_list);
- g_list_free (node_refs_list);
+ tags = parse_tags (way->children);
+ fill_tags (MAPS_OSMOBJECT (result), tags);
+ g_hash_table_destroy (tags);
- g_string_append (buffer, "}\n");
+ node_refs = parse_node_refs (way->children);
+ fill_node_ref_list (result, node_refs);
+ g_array_free (node_refs, TRUE);
xmlFreeDoc (doc);
xmlFreeNode (way);
- return g_string_free (buffer, FALSE);
+ return result;
}
-static GList *_parse_members (const xmlNode *member_child)
+static GList *
+parse_members (const xmlNode *member_child)
{
const xmlNode *cur_node;
GList *members;
@@ -373,7 +381,7 @@ static GList *_parse_members (const xmlNode *member_child)
if (g_str_equal (cur_node->name, "member")) {
GHashTable *attributes;
- attributes = _parse_attributes (cur_node);
+ attributes = parse_attributes (cur_node);
members = g_list_append (members, attributes);
}
}
@@ -381,68 +389,80 @@ static GList *_parse_members (const xmlNode *member_child)
return members;
}
-static void _fill_members (GString *buffer, const GList *members)
+static void
+fill_members (MapsOSMRelation *relation, const GList *members)
{
const GList *cur;
- g_string_append (buffer, "\t\"members\":[\n");
-
for (cur = members; cur; cur = g_list_next (cur)) {
GHashTable *attributes = (GHashTable *) cur->data;
- const gchar *type = g_hash_table_lookup (attributes, "type");
- const gchar *role = g_hash_table_lookup (attributes, "role");
- const gchar *ref = g_hash_table_lookup (attributes, "ref");
+ const char *type_string = g_hash_table_lookup (attributes, "type");
+ guint type;
+ const char *role = g_hash_table_lookup (attributes, "role");
+ const char *ref_string = g_hash_table_lookup (attributes, "ref");
+ guint64 ref;
- g_string_append (buffer, "\t\t{");
- if (type)
- g_string_append_printf (buffer, "\"type\": \"%s\", ", type);
- if (role)
- g_string_append_printf (buffer, "\"role\": \"%s\", ", role);
- if (ref)
- g_string_append_printf (buffer, "\"ref\": \"%s\"", ref);
-
- g_string_append (buffer, "}");
+ if (ref_string)
+ ref = g_ascii_strtoull (ref_string, NULL, 10);
+
+ if (g_strcmp0 (type_string, "node") == 0) {
+ type = MEMBER_TYPE_NODE;
+ } else if (g_strcmp0 (type_string, "way") == 0) {
+ type = MEMBER_TYPE_WAY;
+ } else if (g_strcmp0 (type_string, "relation") == 0) {
+ type = MEMBER_TYPE_RELATION;
+ } else {
+ g_warning ("Unknown relation type: %s\n", type_string);
+ continue;
+ }
- if (g_list_next (cur))
- g_string_append (buffer, ",");
- g_string_append (buffer, "\n");
+ maps_osm_relation_add_member (relation, role, type, ref);
}
-
- g_string_append (buffer, "\t]\n");
}
-gchar *maps_osm_parse_relation (const gchar *content, guint length)
+/**
+ * maps_osm_parse_relation:
+ * @content: XML data
+ * @length: Length of data
+ * Returns: (transfer full): An OSMRelation
+ */
+MapsOSMRelation *
+maps_osm_parse_relation (const char *content, guint length)
{
xmlDoc *doc;
xmlNode *relation;
GHashTable *attributes;
- GList *tag_list;
+ GHashTable *tags;
GList *member_list;
- GString *buffer;
- const gchar *id;
- const gchar *changeset;
- const gchar *version;
+ const char *id_string;
+ guint64 id;
+ const char *changeset_string;
+ guint64 changeset;
+ const char *version_string;
+ guint version;
- doc = _read_xml_doc (content, length);
+ MapsOSMRelation *result;
+
+ doc = read_xml_doc (content, length);
if (!doc) {
return NULL;
}
- relation = _get_sub_node (doc, "relation");
+ relation = get_sub_node (doc, "relation");
if (!relation) {
xmlFreeDoc (doc);
return NULL;
}
- attributes = _parse_attributes (relation);
- id = g_hash_table_lookup (attributes, "id");
- changeset = g_hash_table_lookup (attributes, "changeset");
- version = g_hash_table_lookup (attributes, "version");
+ attributes = parse_attributes (relation);
+ id_string = g_hash_table_lookup (attributes, "id");
+ changeset_string = g_hash_table_lookup (attributes, "changeset");
+ version_string = g_hash_table_lookup (attributes, "version");
- if (!id || !changeset || !version) {
+ if (!id_string || !changeset_string || !version_string) {
g_error ("Missing required attributes\n");
xmlFreeDoc (doc);
xmlFreeNode (relation);
@@ -450,28 +470,24 @@ gchar *maps_osm_parse_relation (const gchar *content, guint length)
return NULL;
}
- buffer = g_string_new (NULL);
+ g_hash_table_destroy (attributes);
- g_string_append (buffer, "{\n");
- g_string_append_printf (buffer, "\t\"id\": \"%s\",\n", id);
- g_string_append_printf (buffer, "\t\"changeset\": \"%s\",\n", changeset);
- g_string_append_printf (buffer, "\t\"version\": \"%s\",\n", version);
+ id = g_ascii_strtoull (id_string, NULL, 10);
+ changeset = g_ascii_strtoull (changeset_string, NULL, 10);
+ version = g_ascii_strtoull (version_string, NULL, 10);
- g_hash_table_destroy (attributes);
+ result = maps_osm_relation_new (id, changeset, version);
- tag_list = _parse_tags (relation->children);
- _fill_tags (buffer, tag_list);
- g_string_append (buffer, "\t,\n");
- g_list_free_full (tag_list, g_free);
+ tags = parse_tags (relation->children);
+ fill_tags (MAPS_OSMOBJECT (result), tags);
+ g_hash_table_destroy (tags);
- member_list = _parse_members (relation->children);
- _fill_members (buffer, member_list);
+ member_list = parse_members (relation->children);
+ fill_members (result, member_list);
g_list_free_full (member_list, (GDestroyNotify) g_hash_table_destroy);
- g_string_append (buffer, "}\n");
-
xmlFreeDoc (doc);
xmlFreeNode (relation);
- return g_string_free (buffer, FALSE);
+ return result;
}
diff --git a/lib/maps-osm.h b/lib/maps-osm.h
index 6728ae6..d9b84bb 100644
--- a/lib/maps-osm.h
+++ b/lib/maps-osm.h
@@ -12,23 +12,25 @@
* for more details.
*
* You should have received a copy of the GNU General Public License along
- * with GNOME Maps; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>
*
* Author: Marcus Lundblad <ml update uu se>
*/
-#ifndef __MAPSC_OSM_H__
-#define __MAPSC_OSM_H__
+#ifndef __MAPS_OSM_H__
+#define __MAPS_OSM_H__
#include <glib.h>
+#include "maps-osm-node.h"
+#include "maps-osm-way.h"
+#include "maps-osm-relation.h"
+
void maps_osm_init (void);
void maps_osm_finalize (void);
-gchar *maps_osm_parse_node (const gchar *content, guint length);
-gchar *maps_osm_parse_way (const gchar *content, guint length);
-gchar *maps_osm_parse_relation (const gchar *content, guint length);
+MapsOSMNode *maps_osm_parse_node (const char *content, guint length);
+MapsOSMWay *maps_osm_parse_way (const char *content, guint length);
+MapsOSMRelation *maps_osm_parse_relation (const char *content, guint length);
#endif
-
diff --git a/src/mapBubble.js b/src/mapBubble.js
index 18841ac..fdd1fbc 100644
--- a/src/mapBubble.js
+++ b/src/mapBubble.js
@@ -211,7 +211,7 @@ const MapBubble = new Lang.Class({
_initOSMEditor: function() {
this._nameEntry.connect('changed', (function() {
- this._osmObject.setTag('name', this._nameEntry.text);
+ this._osmObject.set_tag('name', this._nameEntry.text);
this._saveButton.sensitive = true;
}).bind(this));
@@ -219,19 +219,20 @@ const MapBubble = new Lang.Class({
this._cancelButton.connect('clicked', this._onCancelClicked.bind(this));
},
- _onObjectFetched: function(success, status, data) {
+ _onObjectFetched: function(success, status, osmObject, osmType) {
if (success) {
this._editGrid.sensitive = true;
- this._loadOSMData(data);
+ this._loadOSMData(osmObject, osmType);
// keep the save button insensitive until the user has done a change
this._saveButton.sensitive = false;
} else
this._showError(status);
},
- _loadOSMData: function(data) {
- this._osmObject = data;
- this._nameEntry.text = this._osmObject.getTag('name');
+ _loadOSMData: function(osmObject, osmType) {
+ this._osmObject = osmObject;
+ this._osmType = osmType;
+ this._nameEntry.text = this._osmObject.get_tag('name');
},
_showError: function(status) {
@@ -240,6 +241,7 @@ const MapBubble = new Lang.Class({
_onSaveClicked: function() {
Application.osmEditManager.uploadObject(this._osmObject,
+ this._osmType,
null, // TODO: add comment editing
null,
this._uploadObjectCB.bind(this));
diff --git a/src/osmConnection.js b/src/osmConnection.js
index 43e7f72..f61efc4 100644
--- a/src/osmConnection.js
+++ b/src/osmConnection.js
@@ -20,11 +20,6 @@
* Author: Marcus Lundblad <ml update uu se>
*/
-const OSMChangeset = imports.osmChangeset;
-const OSMNode = imports.osmNode;
-const OSMRelation = imports.osmRelation;
-const OSMWay = imports.osmWay;
-
const Lang = imports.lang;
const GLib = imports.gi.GLib;
const Maps = imports.gi.GnomeMaps;
@@ -84,18 +79,14 @@ const OSMConnection = new Lang.Class({
if (this._useTestApi)
type = GLib.getenv('OSM_MOCK_TYPE');
- let json = this._parseXML(type, message.response_body);
- let object = null;
+ let object = this._parseXML(type, message.response_body);
- if (json != null)
- object = this._createObject(type, json);
-
if (object == null)
- callback(false, message.status_code, null);
+ callback(false, message.status_code, null, type);
else
callback(true,
message.status_code,
- object);
+ object, type);
}).bind(this));
},
@@ -116,46 +107,30 @@ const OSMConnection = new Lang.Class({
},
_parseXML: function(type, body) {
- let jsonString;
+ let object;
switch (type) {
case 'node':
- jsonString = Maps.osm_parse_node(body.data, body.length);
+ object = Maps.osm_parse_node(body.data, body.length);
break;
case 'way':
- jsonString = Maps.osm_parse_way(body.data, body.length);
+ object = Maps.osm_parse_way(body.data, body.length);
break;
case 'relation':
- jsonString = Maps.osm_parse_relation(body.data, body.length);
+ object = Maps.osm_parse_relation(body.data, body.length);
break;
default:
GLib.error('unknown OSM type: ' + type);
}
- print ('parsed XML to JSON: ' + jsonString);
-
- if (jsonString !== null)
- return JSON.parse(jsonString);
- else
- return null;
- },
-
- _createObject: function(type, json) {
- switch (type) {
- case 'node':
- return new OSMNode.OSMNode(json);
- case 'way':
- return new OSMWay.OSMWay(json);
- case 'relation':
- return new OSMRelation.OSMRelation(json);
- default:
- return null;
- }
+ return object;
},
openChangeset: function(comment, source, callback) {
- let changeset = new OSMChangeset.OSMChangeset(comment, source);
- let xml = changeset.toXML();
+ print('before create changeset');
+ let changeset = Maps.OSMChangeset.new(comment, source);
+ print('before serializing changeset');
+ let xml = changeset.serialize();
print('about open changeset:\n' + xml + '\n');
@@ -173,18 +148,20 @@ const OSMConnection = new Lang.Class({
}
print ('data received: ' + message.response_body.data);
- callback(true, message.status_code, message.response_body.data);
+ let changesetId = GLib.ascii_strtoull (message.response_body.data,
+ '', 10);
+ callback(true, message.status_code, changesetId);
}));
},
- uploadObject: function(object, changeset, callback) {
+ uploadObject: function(object, type, changeset, callback) {
object.changeset = changeset;
- let xml = object.toXML();
+ let xml = object.serialize();
print('about to upload object:\n' + xml + '\n');
- let url = this._getCreateOrUpdateUrl(object);
+ let url = this._getCreateOrUpdateUrl(object, type);
let uri = new Soup.URI(url);
let msg = new Soup.Message({ method: 'PUT',
uri: uri });
@@ -235,12 +212,12 @@ const OSMConnection = new Lang.Class({
changesetId + '/close';
},
- _getCreateOrUpdateUrl: function(object) {
+ _getCreateOrUpdateUrl: function(object, type) {
if (object.id)
- return this._getBaseUrl() + '/' + API_VERSION + '/' + object.type +
+ return this._getBaseUrl() + '/' + API_VERSION + '/' + type +
'/' + object.id;
else
- return this._getBaseUrl() + '/' + API_VERSION + '/' + object.type +
+ return this._getBaseUrl() + '/' + API_VERSION + '/' + type +
'/create';
},
diff --git a/src/osmEdit.js b/src/osmEdit.js
index cbde7d4..908ae05 100644
--- a/src/osmEdit.js
+++ b/src/osmEdit.js
@@ -46,11 +46,13 @@ const OSMEditManager = new Lang.Class({
let osmType = this._getOSMTypeName(place);
this._osmConnection.getOSMObject(osmType, place.osm_id,
- (function(success, status, data) {
+ (function(success, status, data,
+ type) {
print('success: ' + success);
print('status: ' + status);
print('data: ' + data);
- callback(success, status, data);
+ callback(success, status, data,
+ type);
}), cancellable);
},
@@ -76,7 +78,7 @@ const OSMEditManager = new Lang.Class({
return osmType;
},
- uploadObject: function(object, comment, source, callback) {
+ uploadObject: function(object, type, comment, source, callback) {
this._osmConnection.openChangeset(comment, source,
function(success, status,
changesetId) {
@@ -86,6 +88,7 @@ const OSMEditManager = new Lang.Class({
print('changeset: ' + changesetId);
if (success)
this._uploadObject(object,
+ type,
changesetId,
callback);
else
@@ -93,8 +96,8 @@ const OSMEditManager = new Lang.Class({
}.bind(this));
},
- _uploadObject: function(object, changesetId, callback) {
- this._osmConnection.uploadObject(object, changesetId,
+ _uploadObject: function(object, type, changesetId, callback) {
+ this._osmConnection.uploadObject(object, type, changesetId,
function(success, status,
response) {
print('upload object CB:');
diff --git a/src/placeBubble.js b/src/placeBubble.js
index 6202094..2867d0b 100644
--- a/src/placeBubble.js
+++ b/src/placeBubble.js
@@ -43,7 +43,7 @@ const PlaceBubble = new Lang.Class({
params.buttons = (MapBubble.Button.ROUTE |
MapBubble.Button.SHARE |
MapBubble.Button.FAVORITE |
- MapBubble.Button.SEND_TO |;
+ MapBubble.Button.SEND_TO |
MapBubble.Button.EDIT);
// We do not serialize contacts to file, so adding them
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]