[tracker/miner-gdata] Add GData miner
- From: Adrien Bustany <abustany src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/miner-gdata] Add GData miner
- Date: Thu, 14 Jul 2011 17:58:56 +0000 (UTC)
commit b2e3668ad497cc5b4e32361b66331efabbe45418
Author: Adrien Bustany <abustany gnome org>
Date: Fri Mar 5 20:53:59 2010 -0300
Add GData miner
So far the miner only exploits the PicasaWeb service
configure.ac | 34 ++
data/dbus/Makefile.am | 5 +
...freedesktop.Tracker1.Miner.PicasaWeb.service.in | 3 +
data/miners/Makefile.am | 6 +
data/miners/tracker-miner-picasaweb.desktop.in | 7 +
src/miners/Makefile.am | 4 +
src/miners/gdata/Makefile.am | 67 +++
src/miners/gdata/tracker-config.vala | 101 ++++
src/miners/gdata/tracker-miner-gdata.vala | 87 ++++
src/miners/gdata/tracker-miner-picasaweb.vala | 511 ++++++++++++++++++++
10 files changed, 825 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index ec10dd5..38b88dc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -211,6 +211,7 @@ GNOME_KEYRING_REQUIRED=2.26
LIBGRSS_REQUIRED=0.3
REST_REQUIRED=0.6
NETWORK_MANAGER_REQUIRED=0.8
+LIBGDATA_REQUIRED=0.6
# 3.6.11 for sqlite_backup API
# 3.6.16 to fix test failures
@@ -411,6 +412,14 @@ PKG_CHECK_MODULES(TRACKER_MINER_FLICKR, [$TRACKER_MINER_FLICKR_REQUIRED],
TRACKER_MINER_FLICKR_LIBS="$TRACKER_MINER_FLICKR_LIBS -lz -lm"
+# Check requirements for tracker-miner-gdata
+TRACKER_MINER_GDATA_REQUIRED="glib-2.0 >= $GLIB_REQUIRED
+ libgdata >= $LIBGDATA_REQUIRED"
+
+PKG_CHECK_MODULES(TRACKER_MINER_GDATA, [$TRACKER_MINER_GDATA_REQUIRED],
+ [have_tracker_miner_gdata=yes],
+ [have_tracker_miner_gdata=no])
+
# Check requirements for tracker-utils
TRACKER_UTILS_REQUIRED="glib-2.0 >= $GLIB_REQUIRED
gio-unix-2.0 >= $GLIB_REQUIRED
@@ -1112,6 +1121,29 @@ fi
AM_CONDITIONAL(HAVE_TRACKER_MINER_FLICKR, test "x$have_tracker_miner_flickr" = "xyes")
##################################################################
+# Check for tracker-miner-gdata
+##################################################################
+
+AC_ARG_ENABLE(miner_gdata,
+ AS_HELP_STRING([--enable-miner-gdata],
+ [enable GData miner [[default=auto]]]),,
+ [enable_tracker_miner_gdata=auto])
+
+enable_tracker_miner_gdata=$enable_miner_gdata
+
+if test "x$enable_tracker_miner_gdata" = "xyes"; then
+ if test "x$have_tracker_miner_gdata" != "xyes"; then
+ AC_MSG_ERROR([Couldn't find tracker-miner-gdata dependencies ($TRACKER_MINER_GDATA_REQUIRED).])
+ fi
+else
+ if test "x$enable_tracker_miner_gdata" = "xno"; then
+ have_tracker_miner_gdata="no (disabled)"
+ fi
+fi
+
+AM_CONDITIONAL(HAVE_TRACKER_MINER_GDATA, test "x$have_tracker_miner_gdata" = "xyes")
+
+##################################################################
# Check for tracker-miner-rss
##################################################################
@@ -2057,6 +2089,7 @@ AC_CONFIG_FILES([
src/Makefile
src/miners/Makefile
src/miners/fs/Makefile
+ src/miners/gdata/Makefile
src/miners/rss/Makefile
src/miners/flickr/Makefile
src/tracker-store/Makefile
@@ -2209,6 +2242,7 @@ Data Miners:
RSS: $have_tracker_miner_rss
Evolution: $have_tracker_miner_evolution ($tracker_miner_evolution_install_dir)
Flickr: $have_tracker_miner_flickr
+ GData: $have_tracker_miner_gdata
Plugins:
diff --git a/data/dbus/Makefile.am b/data/dbus/Makefile.am
index 4549048..e6cb85f 100644
--- a/data/dbus/Makefile.am
+++ b/data/dbus/Makefile.am
@@ -23,6 +23,7 @@ service_in_files = \
org.freedesktop.Tracker1.Miner.Files.service.in \
org.freedesktop.Tracker1.Miner.Flickr.service.in \
org.freedesktop.Tracker1.Miner.RSS.service.in \
+ org.freedesktop.Tracker1.Miner.PicasaWeb.service.in \
org.freedesktop.Tracker1.Extract.service.in
%.service: %.service.in
@@ -48,6 +49,10 @@ if HAVE_TRACKER_MINER_FLICKR
service_DATA += org.freedesktop.Tracker1.Miner.Flickr.service
endif
+if HAVE_TRACKER_MINER_GDATA
+service_DATA += org.freedesktop.Tracker1.Miner.PicasaWeb.service
+endif
+
EXTRA_DIST = \
$(service_in_files) \
diff --git a/data/dbus/org.freedesktop.Tracker1.Miner.PicasaWeb.service.in b/data/dbus/org.freedesktop.Tracker1.Miner.PicasaWeb.service.in
new file mode 100644
index 0000000..520ecdc
--- /dev/null
+++ b/data/dbus/org.freedesktop.Tracker1.Miner.PicasaWeb.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.Tracker1.Miner.PicasaWeb
+Exec= libexecdir@/tracker-miner-gdata
diff --git a/data/miners/Makefile.am b/data/miners/Makefile.am
index be36aa4..a1c08ff 100644
--- a/data/miners/Makefile.am
+++ b/data/miners/Makefile.am
@@ -5,6 +5,7 @@ desktop_in_in_files = \
tracker-miner-evolution.desktop.in.in \
tracker-miner-files.desktop.in.in \
tracker-miner-flickr.desktop.in.in \
+ tracker-miner-picasaweb.desktop.in \
tracker-miner-rss.desktop.in.in
desktop_in_files = \
@@ -12,6 +13,7 @@ desktop_in_files = \
tracker-miner-evolution.desktop.in \
tracker-miner-files.desktop.in \
tracker-miner-flickr.desktop.in \
+ tracker-miner-picasaweb.desktop \
tracker-miner-rss.desktop.in
tracker_minersdir = $(datadir)/tracker/miners
@@ -32,6 +34,10 @@ if HAVE_TRACKER_MINER_FLICKR
tracker_miners_DATA += tracker-miner-flickr.desktop
endif
+if HAVE_TRACKER_MINER_GDATA
+tracker_miners_DATA += tracker-miner-picasaweb.desktop
+endif
+
@INTLTOOL_DESKTOP_RULE@
%.desktop.in: %.desktop.in.in
diff --git a/data/miners/tracker-miner-picasaweb.desktop.in b/data/miners/tracker-miner-picasaweb.desktop.in
new file mode 100644
index 0000000..c115942
--- /dev/null
+++ b/data/miners/tracker-miner-picasaweb.desktop.in
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=PicasaWeb
+_Comment=PicasaWeb miner
+DBusName=org.freedesktop.Tracker1.Miner.PicasaWeb
+DBusPath=/org/freedesktop/Tracker1/Miner/PicasaWeb
+AuthenticationMethod=UserPass
diff --git a/src/miners/Makefile.am b/src/miners/Makefile.am
index 0cf41ea..20bc33a 100644
--- a/src/miners/Makefile.am
+++ b/src/miners/Makefile.am
@@ -9,3 +9,7 @@ endif
if HAVE_TRACKER_MINER_FLICKR
SUBDIRS += flickr
endif
+
+if HAVE_TRACKER_MINER_GDATA
+SUBDIRS += gdata
+endif
diff --git a/src/miners/gdata/Makefile.am b/src/miners/gdata/Makefile.am
new file mode 100644
index 0000000..01a9185
--- /dev/null
+++ b/src/miners/gdata/Makefile.am
@@ -0,0 +1,67 @@
+include $(top_srcdir)/Makefile.decl
+
+INCLUDES = \
+ -Wall \
+ -DSHAREDIR=\""$(datadir)"\" \
+ -DPKGLIBDIR=\""$(libdir)/tracker"\" \
+ -DLOCALEDIR=\""$(localedir)"\" \
+ -DLIBEXEC_PATH=\""$(libexecdir)"\" \
+ -DG_LOG_DOMAIN=\"Tracker\" \
+ -DTRACKER_COMPILATION \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/libtracker-sparql \
+ $(WARN_CFLAGS) \
+ $(GMODULE_CFLAGS) \
+ $(PANGO_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(TRACKER_MINER_GDATA_CFLAGS) \
+ $(GCOV_CFLAGS)
+
+VALAFLAGS = \
+ --pkg gio-2.0 \
+ --pkg posix \
+ --pkg libgdata \
+ --thread
+
+libexec_PROGRAMS = tracker-miner-gdata
+
+tracker_miner_gdata_VALASOURCES = \
+ $(top_srcdir)/src/libtracker-common/libtracker-common.vapi \
+ tracker-config.vala \
+ tracker-miner-gdata.vala \
+ tracker-miner-picasaweb.vala \
+ $(top_srcdir)/src/libtracker-sparql/tracker-sparql- TRACKER_API_VERSION@.vapi
+
+tracker_miner_gdata_SOURCES = \
+ $(tracker_miner_gdata_VALASOURCES:.vala=.c)
+
+tracker_miner_gdata_LDADD = \
+ $(top_builddir)/src/libtracker-miner/libtracker-miner- TRACKER_API_VERSION@.la \
+ $(top_builddir)/src/libtracker-sparql/libtracker-sparql.la \
+ $(DBUS_LIBS) \
+ $(GMODULE_LIBS) \
+ $(GTHREAD_LIBS) \
+ $(GIO_LIBS) \
+ $(GCOV_LIBS) \
+ $(GLIB2_LIBS) \
+ $(TRACKER_MINER_GDATA_LIBS) \
+ -lz \
+ -lm
+
+vapi_sources = \
+ $(top_srcdir)/src/libtracker-miner/tracker-miner- TRACKER_API_VERSION@.vapi
+
+tracker-miner-gdata.vala.stamp: $(tracker_miner_gdata_VALASOURCES) $(vapi_sources)
+ $(AM_V_GEN)$(VALAC) $(GCOV_VALAFLAGS) -C $(VALAFLAGS) $^
+ touch $@
+
+
+BUILT_SOURCES = tracker-miner-gdata.vala.stamp
+
+MAINTAINERCLEANFILES = \
+ tracker-miner-gdata.vala.stamp \
+ $(tracker_miner_gdata_VALASOURCES:.vala=.c)
+
+EXTRA_DIST = \
+ $(tracker_miner_gdata_VALASOURCES) \
+ tracker-miner-gdata.vala.stamp
diff --git a/src/miners/gdata/tracker-config.vala b/src/miners/gdata/tracker-config.vala
new file mode 100644
index 0000000..7806ca4
--- /dev/null
+++ b/src/miners/gdata/tracker-config.vala
@@ -0,0 +1,101 @@
+public class Tracker.Config : Tracker.ConfigFile {
+ public enum DownloadBehaviour {
+ GPRS, /* Download if connected via GPRS, EDGE, 3G or LAN */
+ EDGE, /* Download if connected via EDGE, 3G or LAN */
+ @3G, /* Download if connected via 3G or LAN */
+ LAN /* Download only if connected to a LAN */
+ }
+
+ /* GLib.KeyFile defines */
+ public static const string GROUP_GENERAL = "General";
+ public static const string GROUP_NETWORK = "Network";
+
+ private struct ConfigKey {
+ GLib.Type type;
+ string property;
+ string group;
+ string key;
+
+ ConfigKey (GLib.Type type, string property, string group, string key) {
+ this.type = type;
+ this.property = property;
+ this.group = group;
+ this.key = key;
+ }
+ }
+
+ static List<ConfigKey?> config_keys = new List<ConfigKey?> ();
+
+ /* Default values */
+ public static const uint DEFAULT_DOWNLOAD_BEHAVIOUR = (uint)DownloadBehaviour 3G;
+
+ private uint _download_behaviour = DEFAULT_DOWNLOAD_BEHAVIOUR;
+ public uint download_behaviour {
+ get {
+ return _download_behaviour;
+ }
+ set {
+ if (value < (uint)DownloadBehaviour.LAN || value > (uint)DownloadBehaviour.GPRS) {
+ return;
+ }
+ _download_behaviour = value;
+ }
+ }
+
+ static construct {
+ config_keys.append(ConfigKey (typeof (int), "download-behaviour", GROUP_NETWORK, "DownloadBehaviour"));
+ }
+
+ construct {
+ domain = "tracker-miner-gdata";
+ base.constructed ();
+
+ load (true);
+ }
+
+ public override void changed () {
+ load (false);
+ }
+
+ public void load (bool use_defaults) {
+ if (use_defaults) {
+ create_with_defaults ();
+ }
+
+ if (!file_exists) {
+ base.save ();
+ }
+
+ foreach (unowned ConfigKey key in config_keys) {
+ if (key.type == typeof (int)) {
+ KeyfileObject.load_int (this, key.property, key_file, key.group, key.key);
+ } else {
+ assert_not_reached ();
+ }
+ }
+ }
+
+ public new bool save () {
+ if (key_file == null) {
+ critical ("Could not save config, GKeyFile was NULL, has the config been loaded?");
+ return false;
+ }
+
+ KeyfileObject.save_int (this, "download-behaviour", key_file, GROUP_NETWORK, "DownloadBehaviour");
+
+ return base.save ();
+ }
+
+ private void create_with_defaults () {
+ try {
+ key_file.has_key (GROUP_NETWORK, "DownloadBehaviour");
+ } catch (Error e) {
+ if (!(e is KeyFileError.KEY_NOT_FOUND) && !(e is KeyFileError.GROUP_NOT_FOUND)) {
+ critical ("Could not load config default: %s", e.message);
+ } else {
+ key_file.set_integer (GROUP_NETWORK, "DownloadBehaviour",
+ DownloadBehaviour 3G);
+ }
+ }
+ }
+}
diff --git a/src/miners/gdata/tracker-miner-gdata.vala b/src/miners/gdata/tracker-miner-gdata.vala
new file mode 100644
index 0000000..dfd42a5
--- /dev/null
+++ b/src/miners/gdata/tracker-miner-gdata.vala
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010, Adrien Bustany <abustany gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+namespace Tracker {
+
+public class MinerGData {
+ private static MinerPicasaweb miner_picasaweb;
+ private static const string NMM_PHOTO = "http://www.tracker-project.org/temp/nmm#Photo";
+
+ private static MainLoop main_loop;
+
+ private static bool in_loop = false;
+ private static void signal_handler (int signo) {
+ if (in_loop) {
+ Posix.exit (Posix.EXIT_FAILURE);
+ }
+
+ switch (signo) {
+ case Posix.SIGINT:
+ case Posix.SIGTERM:
+ in_loop = true;
+ main_loop.quit ();
+ break;
+ }
+ }
+
+ private static void init_signals () {
+#if G_OS_WIN32
+#else
+ Posix.sigaction_t act = Posix.sigaction_t ();
+ Posix.sigset_t empty_mask = Posix.sigset_t ();
+ Posix.sigemptyset (empty_mask);
+ act.sa_handler = signal_handler;
+ act.sa_mask = empty_mask;
+ act.sa_flags = 0;
+
+ Posix.sigaction (Posix.SIGTERM, act, null);
+ Posix.sigaction (Posix.SIGINT, act, null);
+#endif
+ }
+
+// private static void writeback_cb (GLib.HashTable<string, void*> resources) {
+// List<weak string> uris = (List<weak string>)resources.get_keys ();
+// weak string[] rdf_classes;
+//
+// foreach (string uri in uris) {
+// rdf_classes = (string[])resources.lookup (uri);
+//
+// for (uint i = 0 ; rdf_classes[i] != null ; i++) {
+// if (rdf_classes[i] == NMM_PHOTO) {
+// //miner_picasaweb.writeback (uri);
+// return;
+// }
+// }
+// }
+// }
+
+ public static void main (string[] args) {
+ Environment.set_application_name ("GData tracker miner");
+ miner_picasaweb = new MinerPicasaweb ();
+
+ init_signals ();
+
+ main_loop = new MainLoop (null, false);
+ main_loop.run ();
+
+ miner_picasaweb.shutdown ();
+ }
+}
+
+} // End namespace Tracker
diff --git a/src/miners/gdata/tracker-miner-picasaweb.vala b/src/miners/gdata/tracker-miner-picasaweb.vala
new file mode 100644
index 0000000..928399a
--- /dev/null
+++ b/src/miners/gdata/tracker-miner-picasaweb.vala
@@ -0,0 +1,511 @@
+/*
+ * Copyright (C) 2010, Adrien Bustany <abustany gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+namespace Tracker {
+
+public class MinerPicasaweb : Tracker.MinerWeb {
+ private static const string API_KEY = "ABQIAAAAISU_TtyUrVg0N9RGhb8pTxRI3KVolA1NVmS0lLG3RQFyztcosBSHs5rHiQHsmL41EbX1SehKnf1rrw";
+ private static const string DATASOURCE_URN = "urn:nepomuk:datasource:682654ec-b59d-4e99-9b0f-7559fc9c5d42";
+ private static const string MINER_NAME = "PicasaWeb";
+ private static const string SERVICE_DESCRIPTION = "Tracker miner for PicasaWeb";
+ private static const uint PULL_INTERVAL = 5*60; /* seconds */
+ private uint pull_timeout_handle;
+
+ private GData.PicasaWebService service = null;
+
+ private Config config;
+ private Sparql.Connection tracker;
+
+ construct {
+ name = MINER_NAME;
+ associated = false;
+ status = "Not authenticated";
+ progress = 0.0;
+ }
+
+ public MinerPicasaweb () {
+ config = new Config ();
+
+ service = new GData.PicasaWebService (API_KEY);
+
+ try {
+ tracker = Sparql.Connection.get ();
+ } catch (Error e) {
+ critical ("Couldn't connect to Tracker: %s", e.message);
+ }
+
+ this.notify["associated"].connect (association_status_changed);
+
+ authenticate ();
+ }
+
+ private void association_status_changed (Object source, ParamSpec pspec) {
+ if (associated) {
+ if (pull_timeout_handle != 0)
+ return;
+
+ message ("Miner is now associated. Initiating periodic pull.");
+ pull_timeout_handle = Timeout.add_seconds (PULL_INTERVAL, pull_timeout_cb);
+ Idle.add ( () => { pull_timeout_cb (); return false; });
+ } else {
+ if (pull_timeout_handle == 0)
+ return;
+
+ Source.remove (pull_timeout_handle);
+ }
+ }
+
+ private bool pull_timeout_cb () {
+ NetworkProviderStatus network_status = NetworkProvider.get ().get_status ();
+ if (network_status == NetworkProviderStatus.DISCONNECTED) {
+ return true;
+ }
+
+ if (network_status == NetworkProviderStatus.GPRS &&
+ (uint)config.download_behaviour > (uint)Config.DownloadBehaviour.GPRS) {
+ return true;
+ }
+
+ if (network_status == NetworkProviderStatus.EDGE &&
+ (uint)config.download_behaviour > (uint)Config.DownloadBehaviour.EDGE) {
+ return true;
+ }
+
+ if (network_status == NetworkProviderStatus 3G &&
+ (uint)config.download_behaviour > (uint)Config DownloadBehaviour 3G) {
+ return true;
+ }
+
+ status = "Refreshing data";
+ progress = 0.0;
+
+ service.query_all_albums_async (null, service.get_username (), null, albums_cb, pull_finished_cb);
+ return true;
+ }
+
+ private void albums_cb (GData.Entry entry, uint entry_key, uint entry_count) {
+ GData.Feed feed_files;
+ GData.PicasaWebAlbum album = entry as GData.PicasaWebAlbum;
+ GData.PicasaWebFile current_file;
+ string current_file_url;
+ string current_file_urn;
+ string current_file_identifier;
+ string current_album_urn;
+ string current_album_identifier;
+ bool resource_created;
+ Sparql.Builder builder;
+ List<string> album_files_urls;
+ TimeVal tv = TimeVal ();
+
+ try {
+ feed_files = service.query_files (album, null, null, null);
+ } catch (Error service_error) {
+ warning ("Couldn't get files for album %s: %s", album.title, service_error.message);
+ return;
+ }
+
+ set ("status", "Refreshing album \"%s\"".printf (album.get_title ()));
+
+ album_files_urls = new List<string> ();
+
+ foreach (GData.Entry current_entry in feed_files.get_entries ()) {
+ current_file = current_entry as GData.PicasaWebFile;
+ current_file_url = ((GData.MediaContent)current_file.get_contents ().first ().data).get_uri ();
+ // The cast to GData.Entry is necessary to get the right id due to
+ // a bug in current libgdata (gdata <= 0.6.1)
+ current_file_identifier = ((GData.Entry)current_file).get_id ();
+ try {
+ current_file_urn = get_resource (current_file_url,
+ {"nmm:Photo", "nfo:RemoteDataObject", "nfo:MediaFileListEntry"},
+ current_file_identifier,
+ out resource_created);
+ } catch (Error e) {
+ warning ("Couldn't get resource for picture %s: %s", current_file_url, e.message);
+ continue;
+ }
+
+ builder = new Sparql.Builder.update ();
+
+ if (resource_created) {
+ builder.insert_open (current_file_url);
+ builder.subject_iri (current_file_urn);
+ builder.predicate ("nie:dataSource");
+ builder.object_iri (DATASOURCE_URN);
+ builder.predicate ("nie:url");
+ builder.object_string (current_file_url);
+ }
+
+ update_triple_string (builder,
+ current_file_url,
+ current_file_urn,
+ "nie:title",
+ (current_file.get_caption () != null ? current_file.get_caption () : current_file.get_title ()));
+
+ current_file.get_timestamp (tv);
+ update_triple_string (builder,
+ current_file_url,
+ current_file_urn,
+ "nie:contentCreated",
+ tv.to_iso8601 ());
+
+ current_file.get_edited (tv);
+ update_triple_string (builder,
+ current_file_url,
+ current_file_urn,
+ "nie:contentLastModified",
+ tv.to_iso8601 ());
+
+ update_triple_int64 (builder,
+ current_file_url,
+ current_file_urn,
+ "nfo:width",
+ (int64)current_file.get_width ());
+
+ update_triple_int64 (builder,
+ current_file_url,
+ current_file_urn,
+ "nfo:height",
+ (int64)current_file.get_height ());
+
+ if (current_file.get_tags () != null) {
+ builder.insert_open (current_file_url);
+ builder.subject_iri (current_file_urn);
+
+ foreach (string tag_label in current_file.get_tags ().split (",")) {
+ builder.predicate ("nao:hasTag");
+ builder.object_blank_open ();
+ builder.predicate ("a");
+ builder.object ("nao:Tag");
+ builder.predicate ("nao:prefLabel");
+ builder.object_string (tag_label);
+ builder.object_blank_close ();
+ }
+
+ builder.insert_close ();
+ }
+
+ try {
+ tracker.update (builder.result);
+ album_files_urls.prepend (current_file_url);
+ } catch (Error e) {
+ warning ("Couldn't import picture %s: %s", current_file_url, e.message);
+ }
+ }
+
+ builder = new Sparql.Builder.update ();
+
+ current_album_identifier = ((GData.Entry)album).get_id ();
+ try {
+ current_album_urn = get_resource (DATASOURCE_URN,
+ {"nmm:ImageList", "nfo:RemoteDataObject"},
+ current_album_identifier,
+ out resource_created);
+ } catch (Error e) {
+ warning ("Coudln't get resource for album %s: %s", album.get_title (), e.message);
+ return;
+ }
+
+ if (resource_created) {
+ builder.predicate ("nie:dataSource");
+ builder.object_iri (DATASOURCE_URN);
+ }
+
+ update_triple_string (builder,
+ DATASOURCE_URN,
+ current_album_urn,
+ "nie:title",
+ album.get_title ());
+
+ if (album.get_summary () != null) {
+ update_triple_string (builder,
+ DATASOURCE_URN,
+ current_album_urn,
+ "rdfs:comment",
+ album.get_summary ());
+ }
+
+ if (album.get_tags () != null) {
+ foreach (string tag_label in album.get_tags ().split (",")) {
+ builder.predicate ("nao:hasTag");
+ builder.object_blank_open ();
+ builder.predicate ("nao:prefLabel");
+ builder.object_string (tag_label);
+ builder.object_blank_close ();
+ }
+ }
+
+ update_triple_int64 (builder,
+ DATASOURCE_URN,
+ current_album_urn,
+ "nfo:entryCounter",
+ (int64)album.get_num_photos ());
+
+ album.get_timestamp (tv);
+ update_triple_string (builder,
+ DATASOURCE_URN,
+ current_album_urn,
+ "nie:contentCreated",
+ tv.to_iso8601 ());
+
+ album.get_edited (tv);
+ update_triple_string (builder,
+ DATASOURCE_URN,
+ current_album_urn,
+ "nie:contentLastModified",
+ tv.to_iso8601 ());
+
+ if (album_files_urls.length () > 0) {
+ builder.insert_open (current_album_urn);
+ builder.subject_iri (current_album_urn);
+
+ foreach (string current_url in album_files_urls) {
+ builder.predicate ("nfo:hasMediaFileListEntry");
+ builder.object_blank_open ();
+ builder.predicate ("a");
+ builder.object ("nmm:Photo");
+ builder.predicate ("a");
+ builder.object ("nfo:MediaFileListEntry");
+ builder.predicate ("a");
+ builder.object ("nfo:RemoteDataObject");
+ builder.predicate ("nie:url");
+ builder.object_string (current_url);
+ builder.object_blank_close ();
+ }
+
+ builder.insert_close ();
+ }
+
+ try {
+ tracker.update (builder.result);
+ } catch (Error e) {
+ warning ("Couldn't save album %s: %s", album.title, e.message);
+ }
+
+ progress = (1.0 + entry_key)/entry_count;
+ }
+
+ private void pull_finished_cb () {
+ status = Idle;
+ progress = 1.0;
+ }
+
+ private string get_resource (string? graph, string[] types, string identifier, out bool created) throws GLib.Error {
+ string inner_query;
+ string select_query;
+ string insert_query;
+ Variant query_results;
+ HashTable<string, string> anonymous_nodes;
+
+
+ select_query = "";
+ inner_query = "";
+ created = false;
+
+ foreach (string type in types) {
+ inner_query += " a %s; ".printf (type);
+ }
+ inner_query += "nao:identifier \"%s\"".printf (identifier);
+
+ select_query = "select ?urn where { ?urn %s }".printf (inner_query);
+
+ try {
+ Sparql.Cursor cursor = tracker.query (select_query);
+
+ if (cursor.next ()) {
+ return cursor.get_string (0);
+ }
+ } catch (Error tracker_error) {
+ throw tracker_error;
+ }
+
+ if (graph == null) {
+ insert_query = "insert { _:res %s }".printf (inner_query);
+ } else {
+ insert_query = "insert into <%s> { _:res %s }".printf (graph, inner_query);
+ }
+
+ try {
+ created = true;
+ query_results = tracker.update_blank (insert_query);
+ anonymous_nodes = (HashTable<string, string>) query_results.get_child_value (0).get_child_value(0);
+ return anonymous_nodes.lookup ("res");
+ } catch (Error tracker_error) {
+ throw tracker_error;
+ }
+ }
+
+ public void update_triple_string (Sparql.Builder builder, string graph, string urn, string property, string new_value) {
+ builder.delete_open (graph);
+ builder.subject_iri (urn);
+ builder.predicate (property);
+ builder.object_string (new_value);
+ builder.delete_close ();
+
+ builder.insert_open (graph);
+ builder.subject_iri (urn);
+ builder.predicate (property);
+ builder.object_string (new_value);
+ builder.insert_close ();
+ }
+
+ public void update_triple_int64 (Sparql.Builder builder, string graph, string urn, string property, int64 new_value) {
+ builder.delete_open (graph);
+ builder.subject_iri (urn);
+ builder.predicate (property);
+ builder.object_int64 (new_value);
+ builder.delete_close ();
+
+ builder.insert_open (graph);
+ builder.subject_iri (urn);
+ builder.predicate (property);
+ builder.object_int64 (new_value);
+ builder.insert_close ();
+ }
+
+ public void shutdown () {
+ set ("associated", false);
+ }
+
+ public override void authenticate () throws MinerWebError {
+ PasswordProvider password_provider;
+ string username;
+ string password;
+ bool verified = false;
+
+ password_provider = PasswordProvider.get ();
+
+ set ("associated", false);
+
+ try {
+ password = password_provider.get_password (MINER_NAME, out username);
+ } catch (Error e) {
+ if (e is PasswordProviderError.NOTFOUND) {
+ throw new MinerWebError.NO_CREDENTIALS ("Miner is not associated");
+ }
+ throw new MinerWebError.KEYRING (e.message);
+ }
+
+ try {
+ verified = service.authenticate (username, password, null);
+ } catch (Error service_error) {
+ throw new MinerWebError.SERVICE (service_error.message);
+ }
+
+ if (!verified) {
+ throw new MinerWebError.WRONG_CREDENTIALS ("Wrong username and/or password");
+ }
+
+ message ("Authentication successful");
+ set ("associated", true);
+ }
+
+ public override void dissociate () throws MinerWebError {
+ var password_provider = PasswordProvider.get ();
+
+ try {
+ password_provider.forget_password (MINER_NAME);
+ } catch (Error e) {
+ if (e is PasswordProviderError.SERVICE) {
+ throw new MinerWebError.KEYRING (e.message);
+ }
+
+ critical ("Internal error: %s", e.message);
+ return;
+ }
+
+ set ("associated", false);
+ }
+
+ public override void associate (HashTable<string, string> association_data) throws Tracker.MinerWebError {
+ assert (association_data.lookup ("username") != null && association_data.lookup ("password") != null);
+
+ var password_provider = PasswordProvider.get ();
+
+ try {
+ password_provider.store_password (MINER_NAME,
+ SERVICE_DESCRIPTION,
+ association_data.lookup ("username"),
+ association_data.lookup ("password"));
+ } catch (Error e) {
+ if (e is PasswordProviderError.SERVICE) {
+ throw new MinerWebError.KEYRING (e.message);
+ }
+
+ critical ("Internal error: %s", e.message);
+ return;
+ }
+ }
+
+ public override GLib.HashTable get_association_data () throws Tracker.MinerWebError {
+ return new HashTable<string, string>(str_hash, str_equal);
+ }
+
+// public async void writeback (string uri) {
+// weak PtrArray results;
+// weak string[][] triples;
+// GData.Query query;
+// GData.PicasaWebFile file;
+// string[] local_tags = new string[] {};
+//
+// try {
+// results = yield execute_sparql (("select ?photo_id ?tag where {"
+// + "<%s> nie:dataSource <%s> ;"
+// + "nao:identifier ?photo_id ;"
+// + "nao:hasTag ?t ."
+// + " ?t nao:prefLabel ?tag }").printf (uri, DATASOURCE_URN));
+// } catch (Error tracker_error) {
+// warning ("Tracker error while doing writeback for photo %s: %s", uri, tracker_error.message);
+// return;
+// }
+//
+// message ("writeback for %s", uri);
+//
+// if (results.len == 0)
+// return;
+//
+// triples = (string[][])results.pdata;
+//
+// for (uint i = 0 ; i < results.len ; ++i) {
+// // See http://code.google.com/apis/picasaweb/docs/2.0/developers_guide_protocol.html#Tags
+// local_tags += triples[i][1].replace (",", "%2C");
+// }
+//
+// try {
+// file = service.query_single_entry (triples[0][0], null, typeof (GData.PicasaWebFile), null) as GData.PicasaWebFile;
+// } catch (Error gdata_error) {
+// warning ("GData error while doing writeback for photo %s: %s", uri, gdata_error.message);
+// return;
+// }
+//
+// if (file == null) {
+// warning ("Could not writeback photo %s: file not found on remote service", uri);
+// return;
+// }
+//
+// file.tags = local_tags;
+//
+// try {
+// service.update_entry (file, null);
+// } catch (Error update_error) {
+// warning ("Could not writeback photo %s: %s", uri, update_error.message);
+// }
+// }
+}
+
+} // End namespace Tracker
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]