[tracker/sparql-ontology-tree] WIP
- From: Martyn James Russell <mr src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/sparql-ontology-tree] WIP
- Date: Tue, 18 Feb 2014 13:32:58 +0000 (UTC)
commit d819f0a6f6f116597cc2eea885fa5f451edfc21c
Author: Martyn Russell <martyn lanedo com>
Date: Tue Feb 18 13:31:27 2014 +0000
WIP
src/tracker-utils/tracker-sparql.c | 261 +++++++++++++++++++++++++++++++++++-
1 files changed, 259 insertions(+), 2 deletions(-)
---
diff --git a/src/tracker-utils/tracker-sparql.c b/src/tracker-utils/tracker-sparql.c
index 201915d..8d7970d 100644
--- a/src/tracker-utils/tracker-sparql.c
+++ b/src/tracker-utils/tracker-sparql.c
@@ -56,6 +56,7 @@ static gboolean list_class_prefixes;
static gchar *list_properties;
static gchar *list_notifies;
static gchar *list_indexes;
+static gchar *tree;
static gboolean print_version;
static gchar *search;
@@ -89,9 +90,13 @@ static GOptionEntry entries[] = {
N_("CLASS"),
},
{ "list-indexes", 'i', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, parse_list_indexes,
- N_("Retrieve indexes used in database to improve performance (PROPERTY is optional) "),
+ N_("Retrieve indexes used in database to improve performance (PROPERTY is optional)"),
N_("PROPERTY"),
},
+ { "tree", 't', 0, G_OPTION_ARG_STRING, &tree,
+ N_("Describe subclasses, superclasses and their properties for the given CLASS"),
+ N_("CLASS"),
+ },
{ "search", 's', 0, G_OPTION_ARG_STRING, &search,
N_("Search for a class or property and display more information (e.g. Document)"),
N_("CLASS/PROPERTY"),
@@ -429,6 +434,253 @@ print_cursor (TrackerSparqlCursor *cursor,
}
}
+static GNode *root = NULL;
+
+typedef struct {
+ gchar *class;
+ guint parent_known:1;
+} NodeData;
+
+static inline NodeData *
+tree_node_data_new (const gchar *class,
+ gboolean parent_known)
+{
+ NodeData *data;
+
+ data = g_slice_new0 (NodeData);
+ data->class = g_strdup (class);
+ data->parent_known = parent_known;
+
+ return data;
+}
+
+static inline void
+tree_node_data_free (NodeData *data)
+{
+ if (!data) {
+ return;
+ }
+
+ g_free (data->class);
+ g_slice_free (NodeData, data);
+}
+
+static gboolean
+tree_node_data_equal (GNode *node,
+ const gchar *class)
+{
+ NodeData *data;
+
+ data = node->data;
+
+ return strcmp (class, data->class) == 0 ? TRUE : FALSE;
+}
+
+static GNode *
+tree_node_lookup (GNode *tree,
+ const gchar *class,
+ GNode **parent_node)
+{
+ GNode *parent, *node_found, *parent_found;
+
+ node_found = parent_found = NULL;
+
+ if (parent_node) {
+ *parent_node = NULL;
+ }
+
+ if (!tree) {
+ return NULL;
+ }
+
+ parent = tree;
+
+ while (parent) {
+ GNode *child, *next = NULL;
+
+ for (child = g_node_first_child (parent);
+ child != NULL;
+ child = g_node_next_sibling (child)) {
+ if (tree_node_data_equal (child, class)) {
+ next = child;
+ break;
+ }
+ }
+
+ if (next) {
+ /* Exact match */
+ node_found = next;
+ parent_found = parent;
+ break;
+ } else {
+ /* Descent down the child */
+ parent = next;
+ }
+ }
+
+ if (parent_node) {
+ *parent_node = parent_found;
+ }
+
+ return node_found;
+}
+
+static GNode *
+tree_add_class (const gchar *class,
+ const gchar *parent,
+ gboolean parent_known)
+{
+ GNode *node, *parent_node;
+
+ g_debug ("Adding class '%s', parent '%s', parent known: %s",
+ class, parent, parent_known ? "yes" : "no");
+
+ // Check init...
+ if (!root) {
+ root = g_node_new (NULL);
+ }
+
+ // Look up class node
+ node = parent_node = NULL;
+
+ if (class) {
+ // If there is no class, node is root
+ node = tree_node_lookup (root, class, &parent_node);
+ }
+
+ if (!node) {
+ // Create node
+ NodeData *data;
+
+ data = tree_node_data_new (class, parent_known);
+ node = g_node_new (data);
+
+ if (!parent_known || !parent) {
+ // Add to root node
+ g_node_append (root, node);
+
+ // If node is currently an orphan, add to root
+ // and we will reorder it when we know more...
+ } else {
+
+ // Lookup parent node and add to that.
+ parent_node = tree_node_lookup (root, parent, NULL);
+
+ if (!parent_node) {
+ // Create parent node.
+ parent_node = tree_add_class (parent, NULL, FALSE);
+ g_assert (parent_node != NULL);
+ }
+
+ g_node_append (parent_node, node);
+ }
+ } else {
+ // Lookup parent node and add to that.
+ parent_node = tree_node_lookup (root, parent, NULL);
+
+ // Reparent found node, if we need to
+ if (parent_node) {
+ NodeData *parent_data;
+
+ parent_data = parent_node->data;
+
+ if (!parent_data->parent_known) {
+ // Add to right parent.
+ g_node_append (parent_node, node);
+ parent_data->parent_known = TRUE;
+ }
+ }
+ }
+
+ return node;
+}
+
+static void
+tree_print (GNode *tree,
+ GHashTable *prefixes)
+{
+ GNode *parent;
+
+ if (!tree) {
+ return;
+ }
+
+ // Print, depth first
+
+ parent = tree;
+
+ if (!parent->data) {
+ // Handle root
+ g_print ("ROOT\n");
+ }
+
+ while (parent) {
+ GNode *child, *next = NULL;
+
+ for (child = g_node_first_child (parent);
+ child != NULL;
+ child = g_node_next_sibling (child)) {
+ NodeData *data;
+ gchar *shorthand = NULL;
+
+ data = child->data;
+
+ if (prefixes) {
+ shorthand = get_shorthand_for_offsets (prefixes, data->class);
+ }
+
+ g_print ("%*s-> %s\n",
+ (g_node_depth (child) - 1) * 2,
+ " ",
+ shorthand ? shorthand : data->class);
+ g_free (shorthand);
+
+ tree_print (child, prefixes);
+ }
+
+ if (!next) {
+ /* Descent down the child */
+ parent = next;
+ }
+ }
+}
+
+static gint
+tree_get (TrackerSparqlConnection *connection,
+ const gchar *class_lookup)
+{
+ TrackerSparqlCursor *cursor;
+ GHashTable *prefixes;
+ GError *error = NULL;
+ gchar *query;
+
+ /* Get subclasses of classes */
+ query = "select ?p ?c where { ?c a rdfs:Class . OPTIONAL { ?c rdfs:subClassOf ?p } }";
+ cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
+
+ if (error) {
+ g_printerr ("%s, %s\n",
+ _("Could not create tree: subclass query failed"),
+ error->message);
+ g_error_free (error);
+ g_object_unref (connection);
+
+ return EXIT_FAILURE;
+ }
+
+ while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
+ const gchar *parent = tracker_sparql_cursor_get_string (cursor, 0, NULL);
+ const gchar *class = tracker_sparql_cursor_get_string (cursor, 1, NULL);
+ tree_add_class (class, parent, TRUE);
+ }
+
+ prefixes = get_prefixes (connection);
+ tree_print (root, prefixes);
+ g_hash_table_unref (prefixes);
+
+ return EXIT_SUCCESS;
+}
+
int
main (int argc, char **argv)
{
@@ -457,7 +709,8 @@ main (int argc, char **argv)
}
if (!list_classes && !list_class_prefixes && !list_properties &&
- !list_notifies && !list_indexes && !search && !file && !query) {
+ !list_notifies && !list_indexes && !tree && !search &&
+ !file && !query) {
error_message = _("An argument must be supplied");
} else if (file && query) {
error_message = _("File and query can not be used together");
@@ -670,6 +923,10 @@ main (int argc, char **argv)
print_cursor (cursor, _("No indexes were found"), _("Indexes"), TRUE);
}
+ if (tree) {
+ return tree_get (connection, tree);
+ }
+
if (search) {
gchar *query;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]