[folks] Write support for URLs in Edsf.Persona



commit f4f596bddedcc64670be03ec2ffa46e0d142a720
Author: Travis Reitter <travis reitter collabora co uk>
Date:   Sat Aug 13 12:33:39 2011 +0200

    Write support for URLs in Edsf.Persona
    
    Closes: bgo#655609 - Implement setter for URLs

 NEWS                                     |    1 +
 backends/eds/lib/edsf-persona-store.vala |   92 ++++++++++++++
 backends/eds/lib/edsf-persona.vala       |   39 ++++++-
 folks/utils.vala                         |   38 ++++++
 tests/eds/Makefile.am                    |    6 +
 tests/eds/set-urls.vala                  |  197 ++++++++++++++++++++++++++++++
 6 files changed, 370 insertions(+), 3 deletions(-)
---
diff --git a/NEWS b/NEWS
index 7e5bce9..a52fd91 100644
--- a/NEWS
+++ b/NEWS
@@ -47,6 +47,7 @@ Bugs fixed:
   parameters
 * Bug 655922 â Rebase UrlDetails.urls upon an AbstractFieldDetails-derived class
 * Bug 648818 â Support the EDS backend being a primary
+* Bug 655609 â Implement setter for URLs
 
 API changes:
 * Swf.Persona retains and exposes its libsocialweb Contact
diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
index 9234f27..1de7ea3 100644
--- a/backends/eds/lib/edsf-persona-store.vala
+++ b/backends/eds/lib/edsf-persona-store.vala
@@ -214,6 +214,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
    * - PersonaStore.detail_key (PersonaDetail.LOCAL_IDS)
    * - PersonaDetail.detail_key (PersonaDetail.WEB_SERVICE_ADDRESSES)
    * - PersonaStore.detail_key (PersonaDetail.NOTES)
+   * - PersonaStore.detail_key (PersonaDetail.URL)
    *
    * See { link Folks.PersonaStore.add_persona_from_details}.
    *
@@ -299,6 +300,11 @@ public class Edsf.PersonaStore : Folks.PersonaStore
               var gender = (Gender) v.get_enum ();
               yield this._set_contact_gender (contact, gender);
             }
+          else if (k == Folks.PersonaStore.detail_key (PersonaDetail.URLS))
+            {
+              Set<UrlFieldDetails> urls = (Set<UrlFieldDetails>) v.get_object ();
+              yield this._set_contact_urls (contact, urls);
+            }
         }
 
       Edsf.Persona? persona = null;
@@ -710,6 +716,92 @@ public class Edsf.PersonaStore : Folks.PersonaStore
       contact.add_attribute (attr_n);
     }
 
+  internal async void _set_urls (Edsf.Persona persona,
+      Set<UrlFieldDetails> urls)
+    {
+      if (Utils.set_afd_equal (persona.urls, urls))
+        return;
+
+      try
+        {
+          E.Contact contact = ((Edsf.Persona) persona).contact;
+          yield this._set_contact_urls (contact, urls);
+          yield this._addressbook.modify_contact (contact);
+        }
+      catch (GLib.Error e)
+        {
+          GLib.warning ("Can't set urls: %s", e.message);
+        }
+    }
+
+  private async void _set_contact_urls (E.Contact contact,
+      Set<UrlFieldDetails> urls)
+    {
+      var vcard = (E.VCard) contact;
+      vcard.remove_attributes (null, "X-URIS");
+
+      foreach (var u in urls)
+        {
+          bool homepage = false;
+          bool blog = false;
+          bool fburl = false;
+          bool video = false;
+
+          var attr = new E.VCardAttribute (null, "X-URIS");
+          attr.add_value (u.value);
+          foreach (var param_name in u.parameters.get_keys ())
+            {
+              var param = new E.VCardAttributeParam (param_name.up ());
+              foreach (var param_val in u.parameters.get (param_name))
+                {
+                  if (param_name == "type")
+                    {
+                      /* Keep in sync with Edsf.Persona.url_properties */
+                      if (param_val == "homepage_url")
+                        {
+                          homepage = true;
+                        }
+                      else if (param_val == "blog_url")
+                        {
+                          blog = true;
+                        }
+                      else if (param_val == "fburl")
+                        {
+                          fburl = true;
+                        }
+                      else if (param_val == "video_url")
+                        {
+                          video = true;
+                        }
+                    }
+                  param.add_value (param_val);
+                }
+              attr.add_param (param);
+            }
+
+          if (homepage)
+            {
+              contact.set (E.Contact.field_id ("homepage_url"), u.value);
+            }
+          else if (blog)
+            {
+              contact.set (E.Contact.field_id ("blog_url"), u.value);
+            }
+          else if (fburl)
+            {
+              contact.set (E.Contact.field_id ("fburl"), u.value);
+            }
+          else if (video)
+            {
+              contact.set (E.Contact.field_id ("video_url"), u.value);
+            }
+          else
+            {
+              contact.add_attribute (attr);
+            }
+        }
+    }
+
   internal async void _set_local_ids (Edsf.Persona persona,
       Set<string> local_ids)
     {
diff --git a/backends/eds/lib/edsf-persona.vala b/backends/eds/lib/edsf-persona.vala
index 523a016..cf3330c 100644
--- a/backends/eds/lib/edsf-persona.vala
+++ b/backends/eds/lib/edsf-persona.vala
@@ -349,7 +349,7 @@ public class Edsf.Persona : Folks.Persona,
       get { return this._urls_ro; }
       set
         {
-          GLib.warning ("Urls setting not supported yet\n");
+          ((Edsf.PersonaStore) this.store)._set_urls (this, value);
         }
     }
 
@@ -802,17 +802,50 @@ public class Edsf.Persona : Folks.Persona,
   private void _update_urls ()
     {
       this._urls.clear ();
+      var urls_temp = new HashSet<UrlFieldDetails> ();
 
+      /* First we get the standard Evo urls.. */
       foreach (string url_property in this.url_properties)
         {
           string u = (string) this._get_property (url_property);
           if (u != null && u != "")
             {
-              this._urls.add (new UrlFieldDetails (u));
+              var fd_u = new UrlFieldDetails (u);
+              fd_u.set_parameter("type", url_property);
+              urls_temp.add (fd_u);
             }
         }
 
-      this.notify_property ("urls");
+      /* Now we go for extra URLs */
+      var vcard = (E.VCard) this.contact;
+      foreach (unowned E.VCardAttribute attr in vcard.get_attributes ())
+        {
+          if (attr.get_name () == "X-URIS")
+            {
+              var url_fd = new UrlFieldDetails (attr.get_value ());
+              foreach (var param in attr.get_params ())
+                {
+                  string param_name = param.get_name ().down ();
+                  foreach (var param_value in param.get_values ())
+                    {
+                      url_fd.add_parameter (param_name, param_value);
+                    }
+                }
+              urls_temp.add (url_fd);
+            }
+        }
+
+      if (!Utils.set_afd_equal (urls_temp, this._urls))
+        {
+          this._urls.clear ();
+
+          foreach (var url_fd in urls_temp)
+            {
+              this._urls.add (url_fd);
+            }
+
+         this.notify_property ("urls");
+        }
     }
 
   private void _update_im_addresses ()
diff --git a/folks/utils.vala b/folks/utils.vala
index ccf69ce..318c722 100644
--- a/folks/utils.vala
+++ b/folks/utils.vala
@@ -127,4 +127,42 @@ public class Folks.Utils : Object
 
       return true;
     }
+
+  /**
+   * Check whether a set of strings to AbstractFieldDetails are equal.
+   *
+   * This performs a deep check for equality, checking whether both sets are of
+   * the same size, and that each key maps to the same set of values in both
+   * maps.
+   *
+   * @param a a set to compare
+   * @param b another set to compare
+   * @return `true` if the sets are equal, `false` otherwise
+   *
+   * @since UNRELEASED
+   */
+  public static bool set_afd_equal (
+      Set<AbstractFieldDetails> a,
+      Set<AbstractFieldDetails> b)
+    {
+      if (a == b)
+        return true;
+
+      if (a.size == b.size)
+        {
+          foreach (var val in a)
+            {
+              if (!b.contains (val))
+                {
+                  return false;
+                }
+            }
+        }
+      else
+        {
+          return false;
+        }
+
+      return true;
+    }
 }
diff --git a/tests/eds/Makefile.am b/tests/eds/Makefile.am
index ec0f530..d5db601 100644
--- a/tests/eds/Makefile.am
+++ b/tests/eds/Makefile.am
@@ -66,6 +66,7 @@ noinst_PROGRAMS = \
 	set-notes \
 	add-contacts-stress-test \
 	set-gender \
+	set-urls \
 	$(NULL)
 
 RUN_WITH_PRIVATE_BUS = $(top_srcdir)/tests/tools/with-session-bus-eds.sh
@@ -176,6 +177,10 @@ set_gender_SOURCES = \
 	set-gender.vala \
 	$(NULL)
 
+set_urls_SOURCES = \
+	set-urls.vala \
+	$(NULL)
+
 CLEANFILES = \
         *.pid \
         *.address \
@@ -207,6 +212,7 @@ MAINTAINERCLEANFILES = \
         set_notes_vala.stamp \
 	add_contacts_stress_test_vala.stamp \
 	set_gender_vala.stamp \
+	set_urls_vala.stamp \
         $(NULL)
 
 EXTRA_DIST = \
diff --git a/tests/eds/set-urls.vala b/tests/eds/set-urls.vala
new file mode 100644
index 0000000..7af273d
--- /dev/null
+++ b/tests/eds/set-urls.vala
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2011 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: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class SetUrlsTests : Folks.TestCase
+{
+  private EdsTest.Backend _eds_backend;
+  private IndividualAggregator _aggregator;
+  private GLib.MainLoop _main_loop;
+  private bool _found_before_update;
+  private bool _found_url_extra_1;
+  private bool _found_url_extra_2;
+  private bool _found_url_home;
+  private bool _found_url_blog;
+  private string _url_extra_1 = "http://example.org";;
+  private string _url_extra_2 = "http://extra.example.org";;
+  private string _url_home = "http://home.example.org";;
+  private string _url_blog = "http://blog.example.org";;
+
+
+  public SetUrlsTests ()
+    {
+      base ("SetUrls");
+
+      this._eds_backend = new EdsTest.Backend ();
+
+      this.add_test ("setting urls on e-d-s persona",
+          this.test_set_urls);
+    }
+
+  public override void set_up ()
+    {
+      this._eds_backend.set_up ();
+    }
+
+  public override void tear_down ()
+    {
+      this._eds_backend.tear_down ();
+    }
+
+  void test_set_urls ()
+    {
+      Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+      this._main_loop = new GLib.MainLoop (null, false);
+      Value? v;
+
+      this._found_before_update = false;
+      this._found_url_extra_1 = false;
+      this._found_url_extra_2 = false;
+      this._found_url_home = false;
+      this._found_url_blog = false;
+
+      this._eds_backend.reset ();
+
+      v = Value (typeof (string));
+      v.set_string ("Albus Percival Wulfric Brian Dumbledore");
+      c1.set ("full_name", (owned) v);
+      this._eds_backend.add_contact (c1);
+
+      this._test_set_urls_async ();
+
+      Timeout.add_seconds (5, () => {
+            this._main_loop.quit ();
+            assert_not_reached ();
+          });
+
+      this._main_loop.run ();
+
+      assert (this._found_before_update);
+      assert (this._found_url_extra_1);
+      assert (this._found_url_extra_2);
+      assert (this._found_url_home);
+      assert (this._found_url_blog);
+    }
+
+  private async void _test_set_urls_async ()
+    {
+      yield this._eds_backend.commit_contacts_to_addressbook ();
+
+      var store = BackendStore.dup ();
+      yield store.prepare ();
+      this._aggregator = new IndividualAggregator ();
+      this._aggregator.individuals_changed.connect
+          (this._individuals_changed_cb);
+      try
+        {
+          yield this._aggregator.prepare ();
+        }
+      catch (GLib.Error e)
+        {
+          GLib.warning ("Error when calling prepare: %s\n", e.message);
+        }
+    }
+
+  private void _individuals_changed_cb
+      (Set<Individual> added,
+       Set<Individual> removed,
+       string? message,
+       Persona? actor,
+       GroupDetails.ChangeReason reason)
+    {
+      assert (removed.size == 0);
+
+      foreach (Individual i in added)
+        {
+          var name = (Folks.NameDetails) i;
+
+          if (name.full_name == "Albus Percival Wulfric Brian Dumbledore")
+            {
+              i.notify["urls"].connect (this._notify_urls_cb);
+              this._found_before_update = true;
+
+              foreach (var p in i.personas)
+                {
+                  var urls = new HashSet<UrlFieldDetails> ();
+
+                  var p1 = new UrlFieldDetails (this._url_extra_1);
+                  urls.add (p1);
+                  var p2 = new UrlFieldDetails (this._url_extra_2);
+                  urls.add (p2);
+                  var p3 = new UrlFieldDetails (this._url_home);
+                  p3.set_parameter("type", "homepage_url");
+                  urls.add (p3);
+                  var p4 = new UrlFieldDetails (this._url_blog);
+                  p4.set_parameter("type", "blog_url");
+                  urls.add (p4);
+
+                  ((UrlDetails) p).urls = urls;
+                }
+            }
+        }
+    }
+
+  private void _notify_urls_cb (Object individual_obj, ParamSpec ps)
+    {
+      Folks.Individual i = (Folks.Individual) individual_obj;
+      foreach (var url in i.urls)
+        {
+          if (url.value == this._url_extra_1)
+            {
+              this._found_url_extra_1 = true;
+            }
+          else if (url.value == this._url_extra_2)
+            {
+              this._found_url_extra_2 = true;
+            }
+          else if (url.value == this._url_home)
+            {
+              this._found_url_home = true;
+            }
+          else if (url.value == this._url_blog)
+            {
+              this._found_url_blog = true;
+            }
+        }
+
+      if (this._found_url_extra_1 &&
+          this._found_url_extra_2 &&
+          this._found_url_home &&
+          this._found_url_blog)
+        {
+          this._main_loop.quit ();
+        }
+    }
+}
+
+public int main (string[] args)
+{
+  Test.init (ref args);
+
+  TestSuite root = TestSuite.get_root ();
+  root.add_suite (new SetUrlsTests ().get_suite ());
+
+  Test.run ();
+
+  return 0;
+}



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