[tracker/wip/carlosg/domain-ontologies: 6/20] libtracker-common: Add TrackerDomainOntology helper



commit 82495bd8ef11cb2bbb202521aae4e85048c5baf2
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Jun 19 15:33:42 2017 +0200

    libtracker-common: Add TrackerDomainOntology helper
    
    This just wraps the information that can be extracted from a
    domain ontology rule file.

 src/libtracker-common/Makefile.am               |    2 +
 src/libtracker-common/libtracker-common.vapi    |    9 +
 src/libtracker-common/tracker-common.h          |    1 +
 src/libtracker-common/tracker-domain-ontology.c |  378 +++++++++++++++++++++++
 src/libtracker-common/tracker-domain-ontology.h |   44 +++
 5 files changed, 434 insertions(+), 0 deletions(-)
---
diff --git a/src/libtracker-common/Makefile.am b/src/libtracker-common/Makefile.am
index 09d8282..8b00ee8 100644
--- a/src/libtracker-common/Makefile.am
+++ b/src/libtracker-common/Makefile.am
@@ -23,6 +23,7 @@ libtracker_common_la_SOURCES = \
        $(BUILT_SOURCES) \
        tracker-date-time.c \
        tracker-dbus.c \
+       tracker-domain-ontology.c \
        tracker-file-utils.c \
        tracker-ioprio.c \
        tracker-log.c \
@@ -41,6 +42,7 @@ noinst_HEADERS = \
        tracker-log.h \
        tracker-common.h \
        tracker-date-time.h \
+       tracker-domain-ontology.h \
        tracker-file-utils.h \
        tracker-sched.h \
        tracker-seccomp.h \
diff --git a/src/libtracker-common/libtracker-common.vapi b/src/libtracker-common/libtracker-common.vapi
index 65c2e43..6f0a8e0 100644
--- a/src/libtracker-common/libtracker-common.vapi
+++ b/src/libtracker-common/libtracker-common.vapi
@@ -88,6 +88,15 @@ namespace Tracker {
                public static void enable_client_lookup (bool enable);
        }
 
+       [CCode (cheader_filename = "libtracker-common/tracker-domain-ontology.h")]
+       public class DomainOntology : GLib.Object, GLib.Initable {
+               public DomainOntology (string? name, GLib.Cancellable? cancellable) throws GLib.Error;
+               public GLib.File get_cache ();
+               public GLib.File? get_journal ();
+               public GLib.File get_ontology ();
+               public string get_domain (string? suffix = null);
+       }
+
        [CCode (cheader_filename = "libtracker-common/tracker-common.h")]
        public void ioprio_init ();
 
diff --git a/src/libtracker-common/tracker-common.h b/src/libtracker-common/tracker-common.h
index 2434b7f..47191fd 100644
--- a/src/libtracker-common/tracker-common.h
+++ b/src/libtracker-common/tracker-common.h
@@ -30,6 +30,7 @@
 
 #include "tracker-date-time.h"
 #include "tracker-dbus.h"
+#include "tracker-domain-ontology.h"
 #include "tracker-file-utils.h"
 #include "tracker-ioprio.h"
 #include "tracker-language.h"
diff --git a/src/libtracker-common/tracker-domain-ontology.c b/src/libtracker-common/tracker-domain-ontology.c
new file mode 100644
index 0000000..07b4401
--- /dev/null
+++ b/src/libtracker-common/tracker-domain-ontology.c
@@ -0,0 +1,378 @@
+#include "config.h"
+
+#include <string.h>
+#include "tracker-domain-ontology.h"
+
+typedef struct {
+       /* DomainOntologies section */
+       GFile *cache_location;
+       GFile *journal_location;
+       GFile *ontology_location;
+       gchar *name;
+       gchar *domain;
+       gchar *ontology_name;
+} TrackerDomainOntologyPrivate;
+
+enum {
+       PROP_0,
+       PROP_NAME
+};
+
+struct {
+       const gchar *var;
+       const gchar *(*func) (void);
+} lookup_dirs[] = {
+       { "HOME", g_get_home_dir },
+       { "XDG_CACHE_HOME", g_get_user_cache_dir },
+       { "XDG_DATA_HOME", g_get_user_data_dir },
+       { "XDG_RUNTIME_DIR", g_get_user_runtime_dir },
+};
+
+struct {
+       const gchar *var;
+       GUserDirectory user_directory;
+} lookup_special_dirs[] = {
+       { "XDG_DESKTOP_DIR", G_USER_DIRECTORY_DESKTOP },
+       { "XDG_DOCUMENTS_DIR", G_USER_DIRECTORY_DOCUMENTS },
+       { "XDG_DOWNLOAD_DIR", G_USER_DIRECTORY_DOWNLOAD },
+       { "XDG_MUSIC_DIR", G_USER_DIRECTORY_MUSIC },
+       { "XDG_PICTURES_DIR", G_USER_DIRECTORY_PICTURES },
+       { "XDG_PICTURES_DIR", G_USER_DIRECTORY_PICTURES },
+       { "XDG_PUBLICSHARE_DIR", G_USER_DIRECTORY_PUBLIC_SHARE },
+       { "XDG_VIDEOS_DIR", G_USER_DIRECTORY_VIDEOS },
+       { "XDG_VIDEOS_DIR", G_USER_DIRECTORY_VIDEOS },
+};
+
+#define DOMAIN_ONTOLOGY_SECTION "DomainOntology"
+
+#define CACHE_KEY "CacheLocation"
+#define JOURNAL_KEY "JournalLocation"
+#define ONTOLOGY_KEY "OntologyLocation"
+#define ONTOLOGY_NAME_KEY "OntologyName"
+#define DOMAIN_KEY "Domain"
+
+static void tracker_domain_ontology_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (TrackerDomainOntology, tracker_domain_ontology, G_TYPE_OBJECT,
+                         G_ADD_PRIVATE (TrackerDomainOntology)
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, 
tracker_domain_ontology_initable_iface_init))
+
+static void
+tracker_domain_ontology_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+       TrackerDomainOntology *domain_ontology;
+       TrackerDomainOntologyPrivate *priv;
+
+       domain_ontology = TRACKER_DOMAIN_ONTOLOGY (object);
+       priv = tracker_domain_ontology_get_instance_private (domain_ontology);
+
+       switch (prop_id) {
+       case PROP_NAME:
+               priv->name = g_value_dup_string (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_domain_ontology_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+       TrackerDomainOntology *domain_ontology;
+       TrackerDomainOntologyPrivate *priv;
+
+       domain_ontology = TRACKER_DOMAIN_ONTOLOGY (object);
+       priv = tracker_domain_ontology_get_instance_private (domain_ontology);
+
+       switch (prop_id) {
+       case PROP_NAME:
+               g_value_set_string (value, priv->name);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_domain_ontology_finalize (GObject *object)
+{
+       TrackerDomainOntology *domain_ontology;
+       TrackerDomainOntologyPrivate *priv;
+
+       domain_ontology = TRACKER_DOMAIN_ONTOLOGY (object);
+       priv = tracker_domain_ontology_get_instance_private (domain_ontology);
+
+       g_clear_object (&priv->cache_location);
+       g_clear_object (&priv->journal_location);
+       g_clear_object (&priv->ontology_location);
+       g_free (priv->name);
+       g_free (priv->domain);
+
+       G_OBJECT_CLASS (tracker_domain_ontology_parent_class)->finalize (object);
+}
+
+static void
+tracker_domain_ontology_class_init (TrackerDomainOntologyClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->set_property = tracker_domain_ontology_set_property;
+       object_class->get_property = tracker_domain_ontology_get_property;
+       object_class->finalize = tracker_domain_ontology_finalize;
+
+       g_object_class_install_property (object_class,
+                                        PROP_NAME,
+                                        g_param_spec_string ("name",
+                                                             "Name",
+                                                             "Name",
+                                                             NULL,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+tracker_domain_ontology_init (TrackerDomainOntology *domain_ontology)
+{
+}
+
+static const gchar *
+lookup_dir (const gchar *variable,
+            gsize        variable_len)
+{
+       gint i;
+
+       for (i = 0; i < G_N_ELEMENTS (lookup_dirs); i++) {
+               if (strncmp (lookup_dirs[i].var, variable, variable_len) == 0) {
+                       return lookup_dirs[i].func ();
+               }
+       }
+
+       for (i = 0; i < G_N_ELEMENTS (lookup_special_dirs); i++) {
+               if (strncmp (lookup_special_dirs[i].var, variable, variable_len) == 0) {
+                       return g_get_user_special_dir (lookup_special_dirs[i].user_directory);
+               }
+       }
+
+       return NULL;
+}
+
+static GFile *
+key_file_get_location (GKeyFile     *key_file,
+                       const gchar  *section,
+                       const gchar  *key,
+                       gboolean      essential,
+                       gboolean      must_exist,
+                       GError      **error)
+{
+       GError *inner_error = NULL;
+       gchar *value;
+       GFile *file;
+
+       value = g_key_file_get_string (key_file, section, key, &inner_error);
+       if (inner_error) {
+               if (essential)
+                       g_propagate_error (error, inner_error);
+               else
+                       g_error_free (inner_error);
+
+               return NULL;
+       }
+
+       if (value[0] == '$') {
+               const gchar *var_end, *prefix;
+               gchar *path;
+
+               /* This is a path relative from a xdg dir */
+               var_end = strchr (value, '/');
+               if (!var_end) {
+                       /* We must take $VAR/subdir values */
+                       g_set_error (error,
+                                    G_KEY_FILE_ERROR,
+                                    G_KEY_FILE_ERROR_INVALID_VALUE,
+                                    "Path in key '%s' can not consist solely of a variable",
+                                    key);
+                       g_free (value);
+                       return NULL;
+               }
+
+               prefix = lookup_dir (&value[1], (var_end - &value[1]));
+               if (!prefix) {
+                       g_set_error (error,
+                                    G_KEY_FILE_ERROR,
+                                    G_KEY_FILE_ERROR_INVALID_VALUE,
+                                    "Unrecognized variable in '%s'", key);
+                       g_free (value);
+                       return NULL;
+               }
+
+               path = g_strconcat (prefix, var_end, NULL);
+               file = g_file_new_for_path (path);
+               g_free (path);
+       } else {
+               file = g_file_new_for_uri (value);
+       }
+
+       g_free (value);
+
+       if (must_exist && file &&
+           g_file_query_file_type (file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                   NULL) != G_FILE_TYPE_DIRECTORY) {
+               gchar *uri = g_file_get_uri (file);
+               g_set_error (error,
+                            G_KEY_FILE_ERROR,
+                            G_KEY_FILE_ERROR_INVALID_VALUE,
+                            "Uri '%s' is not a directory or does not exist", uri);
+               g_free (uri);
+               return NULL;
+       }
+
+       return file;
+}
+
+static gboolean
+tracker_domain_ontology_initable_init (GInitable     *initable,
+                                       GCancellable  *cancellable,
+                                       GError       **error)
+{
+       TrackerDomainOntology *domain_ontology;
+       TrackerDomainOntologyPrivate *priv;
+       GError *inner_error = NULL;
+       GKeyFile *key_file;
+       gchar *rulename, *path;
+
+       domain_ontology = TRACKER_DOMAIN_ONTOLOGY (initable);
+       priv = tracker_domain_ontology_get_instance_private (domain_ontology);
+
+       rulename = g_strconcat (priv->name ? priv->name : "default", ".rule", NULL);
+       path = g_build_filename (SHAREDIR, "tracker", "domain-ontologies",
+                                rulename, NULL);
+       key_file = g_key_file_new ();
+       g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &inner_error);
+
+       g_free (rulename);
+       g_free (path);
+
+       if (inner_error)
+               goto end;
+
+       priv->domain = g_key_file_get_string (key_file, DOMAIN_ONTOLOGY_SECTION,
+                                             DOMAIN_KEY, &inner_error);
+       if (inner_error)
+               goto end;
+
+       priv->cache_location =
+               key_file_get_location (key_file, DOMAIN_ONTOLOGY_SECTION,
+                                      CACHE_KEY, TRUE, FALSE, &inner_error);
+       if (inner_error)
+               goto end;
+
+       priv->journal_location =
+               key_file_get_location (key_file, DOMAIN_ONTOLOGY_SECTION,
+                                      JOURNAL_KEY, FALSE, FALSE, &inner_error);
+       if (inner_error)
+               goto end;
+
+       priv->ontology_location =
+               key_file_get_location (key_file, DOMAIN_ONTOLOGY_SECTION,
+                                      ONTOLOGY_KEY, FALSE, TRUE, &inner_error);
+       if (inner_error)
+               goto end;
+
+       priv->ontology_name = g_key_file_get_string (key_file, DOMAIN_ONTOLOGY_SECTION,
+                                                    ONTOLOGY_NAME_KEY, NULL);
+
+       /* Consistency check, we need one of OntologyLocation and OntologyName,
+        * no more, no less.
+        */
+       if ((priv->ontology_name && priv->ontology_location) ||
+           (!priv->ontology_name && !priv->ontology_location)) {
+               inner_error = g_error_new (G_KEY_FILE_ERROR,
+                                          G_KEY_FILE_ERROR_INVALID_VALUE,
+                                          "One of OntologyLocation and OntologyName must be provided");
+       }
+
+       /* Build ontology location from name if necessary */
+       if (!priv->ontology_location) {
+               gchar *ontology_path;
+
+               ontology_path = g_build_filename (SHAREDIR, "tracker", "ontologies",
+                                                 priv->ontology_name, NULL);
+               priv->ontology_location = g_file_new_for_path (ontology_path);
+               g_free (ontology_path);
+       }
+
+end:
+       g_key_file_free (key_file);
+
+       if (inner_error) {
+               g_propagate_error (error, inner_error);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void
+tracker_domain_ontology_initable_iface_init (GInitableIface *iface)
+{
+       iface->init = tracker_domain_ontology_initable_init;
+}
+
+TrackerDomainOntology *
+tracker_domain_ontology_new (const gchar   *domain_name,
+                             GCancellable  *cancellable,
+                             GError       **error)
+{
+       return g_initable_new (TRACKER_TYPE_DOMAIN_ONTOLOGY,
+                              cancellable, error,
+                              "name", domain_name,
+                              NULL);
+}
+
+GFile *
+tracker_domain_ontology_get_cache (TrackerDomainOntology *domain_ontology)
+{
+       TrackerDomainOntologyPrivate *priv;
+
+       priv = tracker_domain_ontology_get_instance_private (domain_ontology);
+       return priv->cache_location;
+}
+
+GFile *
+tracker_domain_ontology_get_journal (TrackerDomainOntology *domain_ontology)
+{
+       TrackerDomainOntologyPrivate *priv;
+
+       priv = tracker_domain_ontology_get_instance_private (domain_ontology);
+       return priv->journal_location;
+}
+
+GFile *
+tracker_domain_ontology_get_ontology (TrackerDomainOntology *domain_ontology)
+{
+       TrackerDomainOntologyPrivate *priv;
+
+       priv = tracker_domain_ontology_get_instance_private (domain_ontology);
+       return priv->ontology_location;
+}
+
+gchar *
+tracker_domain_ontology_get_domain (TrackerDomainOntology *domain_ontology,
+                                    const gchar           *suffix)
+{
+       TrackerDomainOntologyPrivate *priv;
+
+       priv = tracker_domain_ontology_get_instance_private (domain_ontology);
+       if (suffix)
+               return g_strconcat (priv->domain, ".Tracker1.", suffix, NULL);
+       else
+               return g_strconcat (priv->domain, ".Tracker1", NULL);
+}
diff --git a/src/libtracker-common/tracker-domain-ontology.h b/src/libtracker-common/tracker-domain-ontology.h
new file mode 100644
index 0000000..eb65145
--- /dev/null
+++ b/src/libtracker-common/tracker-domain-ontology.h
@@ -0,0 +1,44 @@
+#ifndef __TRACKER_DOMAIN_ONTOLOGY_H__
+#define __TRACKER_DOMAIN_ONTOLOGY_H__
+
+#if !defined (__LIBTRACKER_MINER_H_INSIDE__) && !defined (TRACKER_COMPILATION)
+#error "Only <libtracker-miner/tracker-miner.h> can be included directly."
+#endif
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#define TRACKER_TYPE_DOMAIN_ONTOLOGY         (tracker_domain_ontology_get_type())
+#define TRACKER_DOMAIN_ONTOLOGY(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_DOMAIN_ONTOLOGY, 
TrackerDomainOntology))
+#define TRACKER_DOMAIN_ONTOLOGY_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    TRACKER_TYPE_DOMAIN_ONTOLOGY, 
TrackerDomainOntologyClass))
+#define TRACKER_IS_DOMAIN_ONTOLOGY(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_DOMAIN_ONTOLOGY))
+#define TRACKER_IS_DOMAIN_ONTOLOGY_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c),    TRACKER_TYPE_DOMAIN_ONTOLOGY))
+#define TRACKER_DOMAIN_ONTOLOGY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),  TRACKER_TYPE_DOMAIN_ONTOLOGY, 
TrackerDomainOntologyClass))
+
+typedef struct _TrackerDomainOntology TrackerDomainOntology;
+typedef struct _TrackerDomainOntologyClass TrackerDomainOntologyClass;
+
+struct _TrackerDomainOntology {
+       GObject parent_instance;
+};
+
+struct _TrackerDomainOntologyClass {
+       GObjectClass parent_class;
+       /*<private>*/
+       gpointer padding[10];
+};
+
+GType                   tracker_domain_ontology_get_type (void) G_GNUC_CONST;
+
+TrackerDomainOntology * tracker_domain_ontology_new      (const gchar   *name,
+                                                          GCancellable  *cancellable,
+                                                          GError       **error);
+
+GFile * tracker_domain_ontology_get_cache    (TrackerDomainOntology *domain_ontology);
+GFile * tracker_domain_ontology_get_journal  (TrackerDomainOntology *domain_ontology);
+GFile * tracker_domain_ontology_get_ontology (TrackerDomainOntology *domain_ontology);
+
+gchar * tracker_domain_ontology_get_domain   (TrackerDomainOntology *domain_ontology,
+                                              const gchar           *suffix);
+
+#endif /* __TRACKER_MINER_PROXY_H__ */


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