[tracker/wip/sam/resource: 9/15] libtracker-sparql: Fix tracker-resource Turtle generation
- From: Sam Thursfield <sthursfield src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/sam/resource: 9/15] libtracker-sparql: Fix tracker-resource Turtle generation
- Date: Mon, 18 Apr 2016 16:58:38 +0000 (UTC)
commit cd5ef0e9d53ecd54437238b8293776d31c5587b8
Author: Sam Thursfield <ssssam gmail com>
Date: Sun Apr 10 22:16:55 2016 +0100
libtracker-sparql: Fix tracker-resource Turtle generation
src/libtracker-sparql/tracker-resource.c | 306 ++++++++++++++++++------------
1 files changed, 180 insertions(+), 126 deletions(-)
---
diff --git a/src/libtracker-sparql/tracker-resource.c b/src/libtracker-sparql/tracker-resource.c
index 289e15e..a5e627d 100644
--- a/src/libtracker-sparql/tracker-resource.c
+++ b/src/libtracker-sparql/tracker-resource.c
@@ -562,6 +562,186 @@ tracker_resource_compare (TrackerResource *a,
};
+/* Helper function for serialization code. This allows you to selectively
+ * populate 'interned_namespaces' from 'all_namespaces' based on when a
+ * particular prefix is actually used. This is quite inefficient compared
+ * to just dumping all known namespaces, but it makes the serializated
+ * output more readable.
+ */
+static void
+maybe_intern_prefix_of_compact_uri (TrackerNamespaceManager *all_namespaces,
+ TrackerNamespaceManager *interned_namespaces,
+ const char *uri)
+{
+ /* The TrackerResource API doesn't distinguish between compact URIs and full
+ * URIs. This is fine as long as users don't add prefixes that can be
+ * confused with URIs. Both URIs and CURIEs can have anything following
+ * the ':', so without hardcoding knowledge of well-known protocols here,
+ * we can't really tell if the user has done something dumb like defining a
+ * "urn" prefix.
+ */
+ char *prefix = g_uri_parse_scheme (uri);
+
+ if (prefix == NULL) {
+ g_warning ("Invalid URI or compact URI: %s", uri);
+ return;
+ }
+
+ if (tracker_namespace_manager_has_prefix (all_namespaces, prefix)) {
+ if (!tracker_namespace_manager_has_prefix (interned_namespaces, prefix)) {
+ const char *namespace = tracker_namespace_manager_lookup_prefix (all_namespaces,
prefix);
+ tracker_namespace_manager_add_prefix (interned_namespaces, prefix, namespace);
+ }
+ }
+}
+
+
+typedef struct {
+ TrackerNamespaceManager *all_namespaces, *our_namespaces;
+ GString *string;
+ GList *done_list;
+} GenerateTurtleData;
+
+void generate_turtle (TrackerResource *resource, GenerateTurtleData *data);
+
+void
+generate_turtle_resources_foreach (gpointer key,
+ gpointer value_ptr,
+ gpointer user_data)
+{
+ const char *property = key;
+ const GValue *value = value_ptr;
+ GenerateTurtleData *data = user_data;
+
+ if (G_VALUE_HOLDS (value, TRACKER_TYPE_RESOURCE)) {
+ TrackerResource *resource = g_value_get_object (value);
+ if (g_list_find_custom (data->done_list, resource, (GCompareFunc) tracker_resource_compare)
== NULL) {
+ generate_turtle (resource, data);
+ g_string_append (data->string, "\n");
+ data->done_list = g_list_prepend (data->done_list, resource);
+ }
+ }
+}
+
+static void
+generate_turtle_value (const GValue *value,
+ GenerateTurtleData *data)
+{
+ GType type = G_VALUE_TYPE (value);
+ if (type == TRACKER_TYPE_URI) {
+ const char *uri = g_value_get_string (value);
+ maybe_intern_prefix_of_compact_uri (data->all_namespaces, data->our_namespaces, uri);
+ g_string_append_printf(data->string, "%s", uri);
+ } else if (type == TRACKER_TYPE_RESOURCE) {
+ TrackerResource *relation = TRACKER_RESOURCE (g_value_get_object (value));
+ g_string_append_printf(data->string, "<%s>", tracker_resource_get_identifier (relation));
+ } else if (type == G_TYPE_STRING) {
+ g_string_append_printf(data->string, "\"%s\"", g_value_get_string (value));
+ } else {
+ GValue str_value = G_VALUE_INIT;
+ g_value_init (&str_value, G_TYPE_STRING);
+ if (g_value_transform (value, &str_value)) {
+ g_string_append (data->string, g_value_get_string (&str_value));
+ } else {
+ g_warning ("Cannot serialize value of type %s to Turtle", G_VALUE_TYPE_NAME (value));
+ }
+ g_value_unset (&str_value);
+ }
+}
+
+void
+generate_turtle_property (const char *property,
+ const GValue *value,
+ GenerateTurtleData *data)
+{
+ g_string_append (data->string, property);
+ g_string_append (data->string, " ");
+ if (G_VALUE_HOLDS (value, G_TYPE_PTR_ARRAY)) {
+ int i;
+ GPtrArray *array = g_value_get_boxed (value);
+ if (array->len > 0) {
+ generate_turtle_value (g_ptr_array_index (array, i), data);
+ for (i = 1; i < array->len; i++) {
+ g_string_append (data->string, " , ");
+ generate_turtle_value (g_ptr_array_index (array, i), data);
+ }
+ }
+ } else {
+ generate_turtle_value (value, data);
+ }
+}
+
+void
+generate_turtle (TrackerResource *resource,
+ GenerateTurtleData *data)
+{
+ TrackerResourcePrivate *priv = GET_PRIVATE (resource);
+ GString *result;
+ GHashTableIter iter;
+ const char *property;
+ const GValue *value;
+
+ g_hash_table_foreach (priv->properties, generate_turtle_resources_foreach, data);
+
+ g_string_append_printf (data->string, "<%s> ", priv->identifier);
+
+ g_hash_table_iter_init (&iter, priv->properties);
+ if (g_hash_table_iter_next (&iter, (gpointer *)&property, (gpointer *)&value))
+ while (TRUE) {
+ generate_turtle_property (property, value, data);
+
+ maybe_intern_prefix_of_compact_uri (data->all_namespaces, data->our_namespaces,
property);
+
+ if (g_hash_table_iter_next (&iter, (gpointer *)&property, (gpointer *)&value)) {
+ g_string_append (data->string, " ;\n ");
+ } else {
+ g_string_append (data->string, " .\n");
+ break;
+ }
+ }
+}
+
+/**
+ * tracker_resource_print_turtle:
+ * @resource: a #TrackerResource
+ * @error: address where an error can be returned
+ *
+ * Serialize all the information in @resource as a Turtle document.
+ *
+ * The generated Turtle should correspond to this standard:
+ * <https://www.w3.org/TR/2014/REC-turtle-20140225/>
+ *
+ * Returns: a newly-allocated string
+ *
+ * Since: 1.10
+ */
+char *
+tracker_resource_print_turtle (TrackerResource *self,
+ TrackerNamespaceManager *namespaces)
+{
+ GenerateTurtleData context;
+ char *prefixes;
+
+ context.all_namespaces = namespaces;
+ context.our_namespaces = tracker_namespace_manager_new ();
+ context.string = g_string_new ("");
+ context.done_list = NULL;
+
+ maybe_intern_prefix_of_compact_uri (context.all_namespaces, context.our_namespaces,
tracker_resource_get_identifier(self));
+
+ generate_turtle (self, &context);
+
+ prefixes = tracker_namespace_manager_print_turtle (context.our_namespaces);
+ g_string_prepend (context.string, "\n");
+ g_string_prepend (context.string, prefixes);
+
+ g_object_unref (context.our_namespaces);
+ g_free (prefixes);
+
+ return g_string_free (context.string, FALSE);
+}
+
+
static void generate_jsonld_foreach (gpointer key, gpointer value_ptr, gpointer user_data);
/* FIXME: this could hit an infinite loop if there are circular resource
@@ -704,132 +884,6 @@ tracker_resource_print_jsonld (TrackerResource *resource,
return result;
}
-typedef struct {
- TrackerNamespaceManager *namespaces;
- GString *string;
- GList *done_list;
-} GenerateTurtleData;
-
-void generate_turtle (TrackerResource *resource, GenerateTurtleData *data);
-
-void
-generate_turtle_resources_foreach (gpointer key,
- gpointer value_ptr,
- gpointer user_data)
-{
- const char *property = key;
- const GValue *value = value_ptr;
- GenerateTurtleData *data = user_data;
-
- if (G_VALUE_HOLDS (value, TRACKER_TYPE_RESOURCE)) {
- TrackerResource *resource = g_value_get_object (value);
- if (g_list_find_custom (data->done_list, resource, (GCompareFunc) tracker_resource_compare)
== NULL) {
- generate_turtle (resource, data);
- g_string_append (data->string, "\n");
- data->done_list = g_list_prepend (data->done_list, resource);
- }
- }
-}
-
-static void
-append_value_to_turtle_string (const GValue *value,
- GString *string)
-{
- GType type = G_VALUE_TYPE (value);
- if (type == TRACKER_TYPE_URI) {
- g_string_append_printf(string, "%s", g_value_get_string (value));
- } else if (type == TRACKER_TYPE_RESOURCE) {
- TrackerResource *relation = TRACKER_RESOURCE (g_value_get_object (value));
- g_string_append_printf(string, "<%s>", tracker_resource_get_identifier (relation));
- } else if (type == G_TYPE_STRING) {
- g_string_append_printf(string, "\"%s\"", g_value_get_string (value));
- } else {
- GValue str_value = G_VALUE_INIT;
- g_value_init (&str_value, G_TYPE_STRING);
- if (g_value_transform (value, &str_value)) {
- g_string_append (string, g_value_get_string (&str_value));
- } else {
- g_warning ("Cannot serialize value of type %s to Turtle", G_VALUE_TYPE_NAME (value));
- }
- g_value_unset (&str_value);
- }
-}
-
-void
-generate_turtle_property (const char *property,
- const GValue *value,
- GenerateTurtleData *data)
-{
- g_string_append (data->string, property);
- g_string_append (data->string, " ");
- if (G_VALUE_HOLDS (value, G_TYPE_PTR_ARRAY)) {
- int i;
- GPtrArray *array = g_value_get_boxed (value);
- for (i = 0; i < array->len; i++) {
- append_value_to_turtle_string (g_ptr_array_index (array, i), data->string);
- g_string_append (data->string, ", ");
- }
- } else {
- append_value_to_turtle_string (value, data->string);
- }
-}
-
-void
-generate_turtle (TrackerResource *resource,
- GenerateTurtleData *data)
-{
- TrackerResourcePrivate *priv = GET_PRIVATE (resource);
- GString *result;
- GHashTableIter iter;
- const char *property;
- const GValue *value;
-
- g_hash_table_foreach (priv->properties, generate_turtle_resources_foreach, data);
-
- g_string_append_printf (data->string, "<%s> ", priv->identifier);
-
- g_hash_table_iter_init (&iter, priv->properties);
- if (g_hash_table_iter_next (&iter, (gpointer *)&property, (gpointer *)&value))
- while (TRUE) {
- generate_turtle_property (property, value, data);
- if (g_hash_table_iter_next (&iter, (gpointer *)&property, (gpointer *)&value)) {
- g_string_append (data->string, ";\n ");
- } else {
- g_string_append (data->string, ".\n");
- break;
- }
- }
-}
-
-/**
- * tracker_resource_print_turtle:
- * @resource: a #TrackerResource
- * @error: address where an error can be returned
- *
- * Serialize all the information in @resource as a Turtle document.
- *
- * The generated Turtle should correspond to this standard:
- * <https://www.w3.org/TR/2014/REC-turtle-20140225/>
- *
- * Returns: a newly-allocated string
- *
- * Since: 1.10
- */
-char *
-tracker_resource_print_turtle(TrackerResource *self,
- TrackerNamespaceManager *namespaces)
-{
- GenerateTurtleData context;
-
- context.namespaces = namespaces;
- context.string = g_string_new ("");
- context.done_list = NULL;
-
- generate_turtle (self, &context);
-
- return g_string_free (context.string, FALSE);
-}
-
typedef struct {
TrackerNamespaceManager *namespaces;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]