[folks] libsocialweb: add new backend



commit bdbb67519d99610b3cc5937c6f7e79227d6cfc18
Author: Marco Barisione <marco barisione org>
Date:   Mon Nov 1 13:58:08 2010 +0000

    libsocialweb: add new backend
    
    Based on patches from:
     Marco Barisione <marco barisione org>
    Reworked by:
     Alban Crequy <alban crequy collabora co uk>

 backends/Makefile.am                          |    5 +
 backends/libsocialweb/Makefile.am             |   55 ++++++
 backends/libsocialweb/sw-backend-factory.vala |   59 +++++++
 backends/libsocialweb/sw-backend.vala         |  130 ++++++++++++++
 backends/libsocialweb/sw-persona-store.vala   |  229 +++++++++++++++++++++++++
 backends/libsocialweb/sw-persona.vala         |  104 +++++++++++
 configure.ac                                  |    9 +
 7 files changed, 591 insertions(+), 0 deletions(-)
---
diff --git a/backends/Makefile.am b/backends/Makefile.am
index e3cd064..ba51ad5 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -3,6 +3,10 @@ SUBDIRS = \
 	key-file \
 	$(NULL)
 
+if ENABLE_LIBSOCIALWEB
+SUBDIRS += libsocialweb
+endif
+
 if ENABLE_TRACKER
 SUBDIRS += tracker
 endif
@@ -11,6 +15,7 @@ DIST_SUBDIRS = \
 	telepathy \
 	key-file \
 	tracker \
+	libsocialweb \
 	$(NULL)
 
 -include $(top_srcdir)/git.mk
diff --git a/backends/libsocialweb/Makefile.am b/backends/libsocialweb/Makefile.am
new file mode 100644
index 0000000..d0da9a7
--- /dev/null
+++ b/backends/libsocialweb/Makefile.am
@@ -0,0 +1,55 @@
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/folks \
+	-include $(CONFIG_HEADER) \
+	-DPACKAGE_DATADIR=\"$(pkgdatadir)\" \
+	-DG_LOG_DOMAIN=\"LibSocialWebBackend\" \
+	$(NULL)
+
+VALAFLAGS += \
+	--vapidir=. \
+	--vapidir=$(top_srcdir)/folks \
+	$(addprefix --pkg ,$(folks_backend_libsocialweb_deps)) \
+	$(NULL)
+
+backenddir = $(BACKEND_DIR)/libsocialweb
+backend_LTLIBRARIES = libfolks-backend-libsocialweb.la
+
+libfolks_backend_libsocialweb_la_SOURCES = \
+	sw-backend.vala \
+	sw-backend-factory.vala \
+	sw-persona-store.vala \
+	sw-persona.vala \
+	$(NULL)
+
+folks_backend_libsocialweb_deps = \
+	folks \
+	gee-1.0 \
+	gio-2.0 \
+	gobject-2.0 \
+	libsocialweb-client \
+	$(NULL)
+
+libfolks_backend_libsocialweb_la_CFLAGS = \
+	$(GIO_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	$(GEE_CFLAGS) \
+	$(SW_CLIENT_CFLAGS) \
+	$(NULL)
+
+libfolks_backend_libsocialweb_la_LIBADD = \
+	$(GIO_LIBS) \
+	$(GLIB_LIBS) \
+	$(GEE_LIBS) \
+	$(top_builddir)/folks/libfolks.la \
+	$(SW_CLIENT_LIBS) \
+	$(NULL)
+
+libfolks_backend_libsocialweb_la_LDFLAGS = -shared -fPIC -module -avoid-version
+
+GITIGNOREFILES = \
+	folks-backend-libsocialweb.vapi \
+	$(libfolks_backend_libsocialweb_la_SOURCES:.vala=.c) \
+	libfolks_backend_libsocialweb_la_vala.stamp \
+	$(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/backends/libsocialweb/sw-backend-factory.vala b/backends/libsocialweb/sw-backend-factory.vala
new file mode 100644
index 0000000..14ede90
--- /dev/null
+++ b/backends/libsocialweb/sw-backend-factory.vala
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *          Travis Reitter <travis reitter collabora co uk>
+ *          Marco Barisione <marco barisione collabora co uk>
+ *
+ * This file was originally part of Rygel.
+ */
+
+using Folks;
+using Folks.Backends.Sw;
+
+private BackendFactory backend_factory = null;
+
+/**
+ * The libsocialweb backend module entry point.
+ */
+public void module_init (BackendStore backend_store)
+{
+  backend_factory = new BackendFactory (backend_store);
+}
+
+/**
+ * The libsocialweb backend module exit point.
+ */
+public void module_finalize (BackendStore backend_store)
+{
+  backend_factory = null;
+}
+
+/**
+ * A backend factory to create a single { link Backend}.
+ */
+public class Folks.Backends.Sw.BackendFactory : Object
+{
+  /**
+   * { inheritDoc}
+   */
+  public BackendFactory (BackendStore backend_store)
+    {
+      backend_store.add_backend (new Backend ());
+    }
+}
diff --git a/backends/libsocialweb/sw-backend.vala b/backends/libsocialweb/sw-backend.vala
new file mode 100644
index 0000000..739cb2c
--- /dev/null
+++ b/backends/libsocialweb/sw-backend.vala
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *       Travis Reitter <travis reitter collabora co uk>
+ *       Marco Barisione <marco barisione collabora co uk>
+ */
+
+using GLib;
+using Folks;
+using Folks.Backends.Sw;
+using SocialWebClient;
+
+extern const string BACKEND_NAME;
+
+/**
+ * A backend which connects to libsocialweb and creates a { link PersonaStore}
+ * for each service.
+ */
+public class Folks.Backends.Sw.Backend : Folks.Backend
+{
+  private bool _is_prepared = false;
+  private Client _client;
+  private HashTable<string, PersonaStore> _persona_stores =
+	  new HashTable<string, PersonaStore> (str_hash, str_equal);
+
+  /**
+   * { inheritDoc}
+   */
+  public override string name { get { return BACKEND_NAME; } }
+
+  /**
+   * { inheritDoc}
+   */
+  public override HashTable<string, PersonaStore> persona_stores
+    {
+      get { return this._persona_stores; }
+    }
+
+
+  /**
+   * { inheritDoc}
+   */
+  public Backend ()
+    {
+    }
+
+  /**
+   * Whether this Backend has been prepared.
+   *
+   * See { link Folks.Backend.is_prepared}.
+   */
+  public override bool is_prepared
+    {
+      get { return this._is_prepared; }
+    }
+
+  /**
+   * { inheritDoc}
+   */
+  public override async void prepare () throws GLib.Error
+    {
+      lock (this._is_prepared)
+        {
+          if (!this._is_prepared)
+            {
+              this._client = new Client();
+              this._client.get_services((client, services) =>
+                {
+                  foreach (var service_name in services)
+                    this.add_service (service_name);
+
+                  this._is_prepared = true;
+                  this.notify_property ("is-prepared");
+                });
+            }
+        }
+    }
+
+  /**
+   * { inheritDoc}
+   */
+  public override async void unprepare () throws GLib.Error
+    {
+      this._persona_stores.foreach ((k, v) =>
+        {
+          PersonaStore store = v;
+          store.removed.disconnect (this.store_removed_cb);
+          this.persona_store_removed (store);
+        });
+
+      this._client = null;
+
+      this._persona_stores.remove_all ();
+      this.notify_property ("persona-stores");
+
+      this._is_prepared = false;
+      this.notify_property ("is-prepared");
+    }
+
+  private void add_service (string service_name)
+    {
+      if (this._persona_stores.lookup (service_name) != null)
+        return;
+
+      var store = new PersonaStore (this._client.get_service (service_name));
+      this._persona_stores.insert (store.id, store);
+      store.removed.connect (this.store_removed_cb);
+      this.persona_store_added (store);
+    }
+
+  private void store_removed_cb (Folks.PersonaStore store)
+    {
+      this.persona_store_removed (store);
+      this._persona_stores.remove (store.id);
+    }
+}
diff --git a/backends/libsocialweb/sw-persona-store.vala b/backends/libsocialweb/sw-persona-store.vala
new file mode 100644
index 0000000..afeee59
--- /dev/null
+++ b/backends/libsocialweb/sw-persona-store.vala
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *       Travis Reitter <travis reitter collabora co uk>
+ *       Philip Withnall <philip withnall collabora co uk>
+ *       Marco Barisione <marco barisione collabora co uk>
+ */
+
+using GLib;
+using Folks;
+using SocialWebClient;
+
+/**
+ * A persona store which is associated with a single libsocialweb service.
+ * It will create { link Persona}s for each of the contacts known to that
+ * service.
+ */
+public class Folks.Backends.Sw.PersonaStore : Folks.PersonaStore
+{
+  private HashTable<string, Persona> _personas;
+  private bool _is_prepared = false;
+  private ClientService _service;
+  private ClientItemView _item_view;
+
+  /**
+   * The type of persona store this is.
+   *
+   * See { link Folks.PersonaStore.type_id}.
+   */
+  public override string type_id { get { return "libsocialweb"; } }
+
+  /**
+   * Whether this PersonaStore can add { link Folks.Persona}s.
+   *
+   * See { link Folks.PersonaStore.can_add_personas}.
+   *
+   * @since 0.3.1
+   */
+  public override MaybeBool can_add_personas
+    {
+      get { return MaybeBool.FALSE; }
+    }
+
+  /**
+   * Whether this PersonaStore can set the alias of { link Folks.Persona}s.
+   *
+   * See { link Folks.PersonaStore.can_alias_personas}.
+   *
+   * @since 0.3.1
+   */
+  public override MaybeBool can_alias_personas
+    {
+      get { return MaybeBool.FALSE; }
+    }
+
+  /**
+   * Whether this PersonaStore can set the groups of { link Folks.Persona}s.
+   *
+   * See { link Folks.PersonaStore.can_group_personas}.
+   *
+   * @since 0.3.1
+   */
+  public override MaybeBool can_group_personas
+    {
+      get { return MaybeBool.FALSE; }
+    }
+
+  /**
+   * Whether this PersonaStore can remove { link Folks.Persona}s.
+   *
+   * See { link Folks.PersonaStore.can_remove_personas}.
+   *
+   * @since 0.3.1
+   */
+  public override MaybeBool can_remove_personas
+    {
+      get { return MaybeBool.FALSE; }
+    }
+
+  /**
+   * Whether this PersonaStore has been prepared.
+   *
+   * See { link Folks.PersonaStore.is_prepared}.
+   *
+   * @since 0.3.0
+   */
+  public override bool is_prepared
+    {
+      get { return this._is_prepared; }
+    }
+
+  /**
+   * The { link Persona}s exposed by this PersonaStore.
+   *
+   * See { link Folks.PersonaStore.personas}.
+   */
+  public override HashTable<string, Persona> personas
+    {
+      get { return this._personas; }
+    }
+
+  /**
+   * Create a new PersonaStore.
+   *
+   * Create a new persona store to store the { link Persona}s for the contacts
+   * provided by the `service`.
+   */
+  public PersonaStore (ClientService service)
+    {
+      Object (display_name: service.get_display_name(),
+              id: service.get_name ());
+
+      this.trust_level = PersonaStoreTrust.PARTIAL;
+      this._service = service;
+      this._personas = new HashTable<string, Persona> (str_hash, str_equal);
+    }
+
+  /**
+   * Add a new { link Persona} to the PersonaStore.
+   *
+   * See { link Folks.PersonaStore.add_persona_from_details}.
+   */
+  public override async Folks.Persona? add_persona_from_details (
+      HashTable<string, Value?> details) throws Folks.PersonaStoreError
+    {
+      // FIXME: There is no better error for this.
+      throw new PersonaStoreError.UNSUPPORTED_ON_USER (
+          "Personas cannot be added to this store.");
+    }
+
+  /**
+   * Remove a { link Persona} from the PersonaStore.
+   *
+   * See { link Folks.PersonaStore.remove_persona}.
+   */
+  public override async void remove_persona (Folks.Persona persona)
+      throws Folks.PersonaStoreError
+    {
+      // FIXME: There is no better error for this.
+      throw new PersonaStoreError.UNSUPPORTED_ON_USER (
+          "Personas cannot be removed from this store.");
+    }
+
+  /**
+   * Prepare the PersonaStore for use.
+   *
+   * See { link Folks.PersonaStore.prepare}.
+   */
+  public override async void prepare ()
+    {
+      lock (this._is_prepared)
+        {
+          if (!this._is_prepared)
+            {
+              var parameters = new HashTable<weak string, weak string> (
+                  str_hash, str_equal);
+              this._service.query_open_view("people", parameters,
+                  (query, item_view) =>
+                    {
+                      item_view.items_added.connect (this.items_added_cb);
+                      item_view.items_changed.connect (this.items_changed_cb);
+                      item_view.items_removed.connect (this.items_removed_cb);
+
+                      this._item_view = item_view;
+                      this._is_prepared = true;
+                      this.notify_property ("is-prepared");
+
+                      this._item_view.start ();
+                    });
+            }
+        }
+    }
+
+  private void items_added_cb (List<unowned Item> items)
+    {
+      var added_personas = new Queue<Persona> ();
+      foreach (var item in items)
+        {
+          var persona = new Persona(this, item);
+          _personas.insert(persona.iid, persona);
+          added_personas.push_tail(persona);
+        }
+
+      if (added_personas.length > 0)
+        this.personas_changed (added_personas.head, null, null, null, 0);
+    }
+
+  private void items_changed_cb (List<unowned Item> items)
+    {
+      foreach (var item in items)
+        {
+          var persona = _personas.lookup(Persona.get_item_id (item));
+          if (persona != null)
+            persona.update (item);
+        }
+    }
+
+  private void items_removed_cb (List<unowned Item> items)
+    {
+      var removed_personas = new Queue<Persona> ();
+      foreach (var item in items)
+        {
+          var persona = _personas.lookup(Persona.get_item_id (item));
+          if (persona != null)
+            {
+              removed_personas.push_tail(persona);
+              _personas.remove(persona.iid);
+            }
+        }
+
+      if (removed_personas.length > 0)
+        this.personas_changed (null, removed_personas.head, null, null, 0);
+    }
+
+}
diff --git a/backends/libsocialweb/sw-persona.vala b/backends/libsocialweb/sw-persona.vala
new file mode 100644
index 0000000..909e7fb
--- /dev/null
+++ b/backends/libsocialweb/sw-persona.vala
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *       Travis Reitter <travis reitter collabora co uk>
+ *       Marco Barisione <marco barisione collabora co uk>
+ */
+
+using GLib;
+using Folks;
+using SocialWebClient;
+
+/**
+ * A persona subclass which represents a single libsocialweb contact.
+ */
+internal class Folks.Backends.Sw.Persona : Folks.Persona,
+    Aliasable,
+    AvatarDetails
+{
+  private const string[] _linkable_properties = {};
+
+  /**
+   * The names of the Persona's linkable properties.
+   *
+   * See { link Folks.Persona.linkable_properties}.
+   */
+  public override string[] linkable_properties
+    {
+      get { return this._linkable_properties; }
+    }
+
+  /**
+   * An avatar for the Persona.
+   *
+   * See { link Folks.HasAvatar.avatar}.
+   */
+  public File avatar { get; set; }
+
+  /**
+   * An alias for the Persona.
+   *
+   * See { link Folks.Aliasable.alias}.
+   */
+  public string alias { get; private set; }
+
+  /**
+   * Create a new persona.
+   *
+   * Create a new persona for the { link PersonaStore} `store`, representing
+   * the libsocialweb contact given by `item`.
+   */
+  public Persona (PersonaStore store, Item item)
+    {
+      var id = get_item_id (item);
+      var uid = this.build_uid ("folks", store.id, id);
+      debug ("Creating new Sw.Persona '%s' for %s UID '%s': %p",
+          uid, store.display_name, id, this);
+      Object (alias: item.get_value ("name"),
+              display_id: id,
+              uid: uid,
+              iid: store.id + ":" + id,
+              store: store,
+              is_user: false);
+      update (item);
+    }
+
+  ~Persona ()
+    {
+      debug ("Destroying Sw.Persona '%s': %p", this.uid, this);
+    }
+
+  public static string? get_item_id (Item item)
+    {
+      return item.get_value ("id");
+    }
+
+  public void update (Item item)
+    {
+      var name = item.get_value ("name");
+      if (name != null && name != alias)
+        alias = name;
+
+      var avatar_path = item.get_value ("icon");
+      if (avatar_path != null)
+        {
+          var avatar_file = File.new_for_path (avatar_path);
+          if (avatar != avatar_file)
+            avatar = avatar_file;
+        }
+    }
+}
diff --git a/configure.ac b/configure.ac
index 95b3bc2..5ad65c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,6 +84,7 @@ VALA_REQUIRED=0.11.6
 VALADOC_REQUIRED=0.2.1
 TRACKER_SPARQL_REQUIRED=0.10
 GCONF2_REQUIRED=2.31
+SW_CLIENT_REQUIRED=0.25
 
 PKG_CHECK_MODULES([GLIB],
                   [glib-2.0 >= $GLIB_REQUIRED
@@ -102,6 +103,13 @@ if test x$enable_tracker_backend = xyes; then
                           [tracker-sparql-0.10 >= $TRACKER_SPARQL_REQUIRED])
 fi
 
+PKG_CHECK_MODULES([SW_CLIENT], [libsocialweb-client >= $SW_CLIENT_REQUIRED])
+VALA_CHECK_PACKAGES([telepathy-glib
+                     dbus-glib-1
+                     gio-2.0
+                     gee-1.0
+                     libsocialweb-client])
+
 #
 # Vala building options -- allows tarball builds without installing Vala
 #
@@ -358,6 +366,7 @@ AC_CONFIG_FILES([
     Makefile
     backends/Makefile
     backends/key-file/Makefile
+    backends/libsocialweb/Makefile
     backends/telepathy/Makefile
     backends/telepathy/lib/Makefile
     backends/tracker/Makefile



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