[folks] Support vCard-like parameters for IM addresses



commit 5fa28ed5366fcf9d435fd2b746c6fa5530b26fed
Author: Travis Reitter <travis reitter collabora co uk>
Date:   Thu Jul 14 11:08:43 2011 -0700

    Support vCard-like parameters for IM addresses
    
    Helps: bug#653680 - Change ImDetails.im_addresses to support vCard-like
    arbitrary parameters

 NEWS                                        |    3 ++
 backends/eds/lib/edsf-persona-store.vala    |   22 ++++++------
 backends/eds/lib/edsf-persona.vala          |   27 ++++++++------
 backends/key-file/kf-persona-store.vala     |    4 +-
 backends/key-file/kf-persona.vala           |   26 ++++++++-----
 backends/libsocialweb/lib/swf-persona.vala  |   10 +++--
 backends/telepathy/lib/tpf-persona.vala     |   23 ++++++++----
 backends/tracker/lib/trf-persona-store.vala |   27 ++++++--------
 backends/tracker/lib/trf-persona.vala       |   20 ++++++----
 folks/im-details.vala                       |   53 ++++++++++++++++++++++++++-
 folks/individual-aggregator.vala            |    7 +++-
 folks/individual.vala                       |    7 ++--
 tests/eds/add-persona.vala                  |   18 +++++-----
 tests/eds/im-details.vala                   |    8 +++--
 tests/eds/link-personas.vala                |   24 ++++++++-----
 tests/eds/set-im-addresses.vala             |   12 ++++--
 tests/tracker/add-persona.vala              |   14 ++++---
 tests/tracker/im-details-interface.vala     |   20 +++++++---
 tests/tracker/imaddresses-updates.vala      |   24 +++++++++++-
 tests/tracker/link-personas.vala            |   20 ++++++----
 tests/tracker/match-im-addresses.vala       |   20 ++++++----
 tests/tracker/set-im-addresses.vala         |   21 +++++++----
 22 files changed, 272 insertions(+), 138 deletions(-)
---
diff --git a/NEWS b/NEWS
index 9026590..e3823b7 100644
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,8 @@ Bugs fixed:
 * Bug 653619 â Add company details
 * Bug 653679 â Change PostalAddressDetails.postal_addresses to support
   vCard-like arbitrary parameters
+* Bug 653680 â Change ImDetails.im_addresses to support vCard-like arbitrary
+  parameters
 
 API changes:
 * Swf.Persona retains and exposes its libsocialweb Contact
@@ -58,6 +60,7 @@ API changes:
 * Add parameters as an optional argument for the FieldDetails constructor
 * Use PostalAddressFieldDetails for PostalAddressDetails.postal_addresses
 * Remove PostalAddress.types (obsoleted by PostalAddressFieldDetails.parameters)
+* Add and use ImFieldDetails for ImDetails.im_addresses
 
 Overview of changes from libfolks 0.5.1 to libfolks 0.5.2
 =========================================================
diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
index 7e0abae..e692099 100644
--- a/backends/eds/lib/edsf-persona-store.vala
+++ b/backends/eds/lib/edsf-persona-store.vala
@@ -249,8 +249,8 @@ public class Edsf.PersonaStore : Folks.PersonaStore
           else if (k == Folks.PersonaStore.detail_key (
                 PersonaDetail.IM_ADDRESSES))
             {
-              var im_addresses = (MultiMap<string, string>) v.get_object ();
-              yield this._set_contact_im_addrs (contact, im_addresses);
+              var im_fds = (MultiMap<string, ImFieldDetails>) v.get_object ();
+              yield this._set_contact_im_fds (contact, im_fds);
             }
           else if (k == Folks.PersonaStore.detail_key (
                 PersonaDetail.PHONE_NUMBERS))
@@ -988,16 +988,16 @@ public class Edsf.PersonaStore : Folks.PersonaStore
       contact.set (E.Contact.field_id ("name"), contact_name);
     }
 
-  internal async void _set_im_addrs  (Edsf.Persona persona,
-      MultiMap<string, string> im_addrs)
+  internal async void _set_im_fds  (Edsf.Persona persona,
+      MultiMap<string, ImFieldDetails> im_fds)
     {
-      if (Utils.multi_map_str_str_equal (persona.im_addresses, im_addrs))
+      if (Utils.multi_map_str_afd_equal (persona.im_addresses, im_fds))
         return;
 
       try
         {
           E.Contact contact = ((Edsf.Persona) persona).contact;
-          yield this._set_contact_im_addrs (contact, im_addrs);
+          yield this._set_contact_im_fds (contact, im_fds);
           yield this._addressbook.modify_contact (contact);
         }
       catch (GLib.Error error)
@@ -1007,8 +1007,8 @@ public class Edsf.PersonaStore : Folks.PersonaStore
     }
 
   /* TODO: this could be smarter & more efficient. */
-  private async void _set_contact_im_addrs (E.Contact contact,
-      MultiMap<string, string> im_addrs)
+  private async void _set_contact_im_fds (E.Contact contact,
+      MultiMap<string, ImFieldDetails> im_fds)
     {
       var im_eds_map = Edsf.Persona._get_im_eds_map ();
 
@@ -1022,16 +1022,16 @@ public class Edsf.PersonaStore : Folks.PersonaStore
             }
         }
 
-     foreach (var proto in im_addrs.get_keys ())
+     foreach (var proto in im_fds.get_keys ())
        {
          var attributes = new GLib.List <E.VCardAttribute>();
          var attrib_name = ("X-" + proto).up ();
          bool added = false;
 
-         foreach (var im in im_addrs.get (proto))
+         foreach (var im_fd in im_fds.get (proto))
            {
              var attr_n = new E.VCardAttribute (null, attrib_name);
-             attr_n.add_value (im);
+             attr_n.add_value (im_fd.value);
              attributes.prepend (attr_n);
              added = true;
            }
diff --git a/backends/eds/lib/edsf-persona.vala b/backends/eds/lib/edsf-persona.vala
index 6b58eac..cfc3804 100644
--- a/backends/eds/lib/edsf-persona.vala
+++ b/backends/eds/lib/edsf-persona.vala
@@ -353,20 +353,22 @@ public class Edsf.Persona : Folks.Persona,
         }
     }
 
-  private HashMultiMap<string, string> _im_addresses =
-      new HashMultiMap<string, string> ();
+  private HashMultiMap<string, ImFieldDetails> _im_addresses =
+      new HashMultiMap<string, ImFieldDetails> (null, null,
+          (GLib.HashFunc) ImFieldDetails.hash,
+          (GLib.EqualFunc) ImFieldDetails.equal);
 
   /**
    * { inheritDoc}
    *
    * @since 0.5.UNRELEASED
    */
-  public MultiMap<string, string> im_addresses
+  public MultiMap<string, ImFieldDetails> im_addresses
     {
       get { return this._im_addresses; }
       set
         {
-          ((Edsf.PersonaStore) this.store)._set_im_addrs (this, value);
+          ((Edsf.PersonaStore) this.store)._set_im_fds (this, value);
         }
     }
 
@@ -515,10 +517,10 @@ public class Edsf.Persona : Folks.Persona,
         {
           foreach (var protocol in this._im_addresses.get_keys ())
             {
-              var im_addresses = this._im_addresses.get (protocol);
+              var im_fds = this._im_addresses.get (protocol);
 
-              foreach (string address in im_addresses)
-                  callback (protocol + ":" + address);
+              foreach (var im_fd in im_fds)
+                  callback (protocol + ":" + im_fd.value);
             }
         }
       else if (prop_name == "local-ids")
@@ -805,18 +807,19 @@ public class Edsf.Persona : Folks.Persona,
       var im_eds_map = this._get_im_eds_map ();
       this._im_addresses.clear ();
 
-      foreach (var proto in im_eds_map.get_keys ())
+      foreach (var im_proto in im_eds_map.get_keys ())
         {
           var addresses = this.contact.get_attributes (
-              im_eds_map.lookup (proto));
+              im_eds_map.lookup (im_proto));
           foreach (var attr in addresses)
             {
               try
                 {
                   var addr = attr.get_value ();
-                  string address = (owned) ImDetails.normalise_im_address (addr,
-                      proto);
-                  this._im_addresses.set (proto, address);
+                  string normalised_addr =
+                    (owned) ImDetails.normalise_im_address (addr, im_proto);
+                  var im_fd = new ImFieldDetails (normalised_addr);
+                  this._im_addresses.set (im_proto, im_fd);
                 }
               catch (Folks.ImDetailsError e)
                 {
diff --git a/backends/key-file/kf-persona-store.vala b/backends/key-file/kf-persona-store.vala
index f495980..722fce1 100644
--- a/backends/key-file/kf-persona-store.vala
+++ b/backends/key-file/kf-persona-store.vala
@@ -306,9 +306,9 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore
     {
       unowned Value? val = details.lookup (Folks.PersonaStore.detail_key (
             PersonaDetail.IM_ADDRESSES));
-      MultiMap<string, string> im_addresses
+      MultiMap<string, ImFieldDetails> im_addresses
           = val != null
-          ? (MultiMap<string, string>) val.get_object ()
+          ? (MultiMap<string, ImFieldDetails>) val.get_object ()
           : null;
       unowned Value? val2 = details.lookup
           (this.detail_key (PersonaDetail.WEB_SERVICE_ADDRESSES));
diff --git a/backends/key-file/kf-persona.vala b/backends/key-file/kf-persona.vala
index 934ad3c..724a37c 100644
--- a/backends/key-file/kf-persona.vala
+++ b/backends/key-file/kf-persona.vala
@@ -34,7 +34,7 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
     WebServiceDetails
 {
   private unowned GLib.KeyFile _key_file;
-  private HashMultiMap<string, string> _im_addresses;
+  private HashMultiMap<string, ImFieldDetails> _im_addresses;
   private HashMultiMap<string, string> _web_service_addresses;
   private string _alias;
   private const string[] _linkable_properties =
@@ -93,7 +93,7 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
   /**
    * { inheritDoc}
    */
-  public MultiMap<string, string> im_addresses
+  public MultiMap<string, ImFieldDetails> im_addresses
     {
       get
         { return this._im_addresses; }
@@ -116,20 +116,23 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
 
           /* Add the new IM addresses to the key file and build a normalised
            * table of them to set as the new property value */
-          var im_addresses = new HashMultiMap<string, string> ();
+          var im_addresses = new HashMultiMap<string, ImFieldDetails> (
+              null, null,
+              (GLib.HashFunc) ImFieldDetails.hash,
+              (GLib.EqualFunc) ImFieldDetails.equal);
 
           foreach (var protocol in value.get_keys ())
             {
               var addresses = value.get (protocol);
               var normalised_addresses = new HashSet<string> ();
 
-              foreach (string address in addresses)
+              foreach (var im_fd in addresses)
                 {
                   string normalised_address;
                   try
                     {
                       normalised_address = ImDetails.normalise_im_address (
-                          address, protocol);
+                          im_fd.value, protocol);
                     }
                   catch (ImDetailsError e)
                     {
@@ -141,7 +144,8 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
                     }
 
                   normalised_addresses.add (normalised_address);
-                  im_addresses.set (protocol, normalised_address);
+                  var new_im_fd = new ImFieldDetails (normalised_address);
+                  im_addresses.set (protocol, new_im_fd);
                 }
 
               string[] addrs = (string[]) normalised_addresses.to_array ();
@@ -229,7 +233,8 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
           id);
 
       this._key_file = key_file;
-      this._im_addresses = new HashMultiMap<string, string> ();
+      this._im_addresses = new HashMultiMap<string, ImFieldDetails> (
+          null, null, ImFieldDetails.hash, (EqualFunc) ImFieldDetails.equal);
       this._web_service_addresses = new HashMultiMap<string, string> ();
 
       /* Load the IM addresses from the key file */
@@ -285,7 +290,8 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
                       continue;
                     }
 
-                  this._im_addresses.set (protocol, address);
+                  var im_fd = new ImFieldDetails (address);
+                  this._im_addresses.set (protocol, im_fd);
                 }
             }
         }
@@ -315,8 +321,8 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
             {
               var im_addresses = this._im_addresses.get (protocol);
 
-              foreach (string address in im_addresses)
-                  callback (protocol + ":" + address);
+              foreach (var im_fd in im_addresses)
+                  callback (protocol + ":" + im_fd.value);
             }
         }
       else if (prop_name == "web-service-addresses")
diff --git a/backends/libsocialweb/lib/swf-persona.vala b/backends/libsocialweb/lib/swf-persona.vala
index 489dac6..b5676c9 100644
--- a/backends/libsocialweb/lib/swf-persona.vala
+++ b/backends/libsocialweb/lib/swf-persona.vala
@@ -116,8 +116,9 @@ public class Swf.Persona : Folks.Persona,
         }
     }
 
-  private HashMultiMap<string, string> _im_addresses =
-      new HashMultiMap<string, string> ();
+  private HashMultiMap<string, ImFieldDetails> _im_addresses =
+      new HashMultiMap<string, ImFieldDetails> (null, null,
+          ImFieldDetails.hash, (EqualFunc) ImFieldDetails.equal);
 
   private HashMultiMap<string, string> _web_service_addresses =
       new HashMultiMap<string, string> ();
@@ -125,7 +126,7 @@ public class Swf.Persona : Folks.Persona,
   /**
    * { inheritDoc}
    */
-  public MultiMap<string, string> im_addresses
+  public MultiMap<string, ImFieldDetails> im_addresses
     {
       get { return this._im_addresses; }
       private set {}
@@ -239,8 +240,9 @@ public class Swf.Persona : Folks.Persona,
               var normalised_addr = (owned) normalise_im_address
                   ((owned) facebook_jid_copy, "jabber");
               string im_proto = "jabber";
+              var im_fd = new ImFieldDetails (normalised_addr);
 
-              this._im_addresses.set (im_proto, normalised_addr);
+              this._im_addresses.set (im_proto, im_fd);
             }
           catch (ImDetailsError e)
             {
diff --git a/backends/telepathy/lib/tpf-persona.vala b/backends/telepathy/lib/tpf-persona.vala
index 5566379..05663a2 100644
--- a/backends/telepathy/lib/tpf-persona.vala
+++ b/backends/telepathy/lib/tpf-persona.vala
@@ -39,7 +39,7 @@ public class Tpf.Persona : Folks.Persona,
   private Set<string> _groups_ro;
   private bool _is_favourite;
   private string _alias;
-  private HashMultiMap<string, string> _im_addresses;
+  private HashMultiMap<string, ImFieldDetails> _im_addresses;
   private const string[] _linkable_properties = { "im-addresses" };
   private const string[] _writeable_properties =
     {
@@ -163,7 +163,7 @@ public class Tpf.Persona : Folks.Persona,
    *
    * See { link Folks.ImDetails.im_addresses}.
    */
-  public MultiMap<string, string> im_addresses
+  public MultiMap<string, ImFieldDetails> im_addresses
     {
       get { return this._im_addresses; }
       private set {}
@@ -287,12 +287,17 @@ public class Tpf.Persona : Folks.Persona,
       this._is_constructed = true;
 
       /* Set our single IM address */
-      this._im_addresses = new HashMultiMap<string, string> ();
+      this._im_addresses = new HashMultiMap<string, ImFieldDetails> (
+          null, null,
+          (GLib.HashFunc) ImFieldDetails.hash,
+          (GLib.EqualFunc) ImFieldDetails.equal);
 
       try
         {
-          this._im_addresses.set (account.get_protocol (),
-              ImDetails.normalise_im_address (id, account.get_protocol ()));
+          var im_addr = ImDetails.normalise_im_address (id,
+              account.get_protocol ());
+          var im_fd = new ImFieldDetails (im_addr);
+          this._im_addresses.set (account.get_protocol (), im_fd);
         }
       catch (ImDetailsError e)
         {
@@ -389,8 +394,12 @@ public class Tpf.Persona : Folks.Persona,
       debug ("Creating new Tpf.Persona '%s' from cache: %p", uid, this);
 
       // IM addresses
-      this._im_addresses = new HashMultiMap<string, string> ();
-      this._im_addresses.set (protocol, im_address);
+      this._im_addresses = new HashMultiMap<string, ImFieldDetails> (null, null,
+          (GLib.HashFunc) ImFieldDetails.hash,
+          (GLib.EqualFunc) ImFieldDetails.equal);
+
+      var im_fd = new ImFieldDetails (im_address);
+      this._im_addresses.set (protocol, im_fd);
 
       // Groups
       this._groups = groups;
diff --git a/backends/tracker/lib/trf-persona-store.vala b/backends/tracker/lib/trf-persona-store.vala
index 4ef6fc2..199f2aa 100644
--- a/backends/tracker/lib/trf-persona-store.vala
+++ b/backends/tracker/lib/trf-persona-store.vala
@@ -499,14 +499,15 @@ public class Trf.PersonaStore : Folks.PersonaStore
           else if (k == Folks.PersonaStore.detail_key (
                 PersonaDetail.IM_ADDRESSES))
             {
-              var im_addresses = (MultiMap<string, string>) v.get_object ();
+              var im_addresses =
+                  (MultiMap<string, ImFieldDetails>) v.get_object ();
 
               int im_cnt = 0;
               foreach (var proto in im_addresses.get_keys ())
                 {
                   var addrs_a = im_addresses.get (proto);
 
-                  foreach (var addr in addrs_a)
+                  foreach (var im_fd in addrs_a)
                     {
                       var im_affl = "_:im_affl%d".printf (im_cnt);
                       var im = "_:im%d".printf (im_cnt);
@@ -515,7 +516,7 @@ public class Trf.PersonaStore : Folks.PersonaStore
                       builder.predicate ("a");
                       builder.object (Trf.OntologyDefs.NCO_IMADDRESS);
                       builder.predicate (Trf.OntologyDefs.NCO_IMID);
-                      builder.object_string (addr);
+                      builder.object_string (im_fd.value);
                       builder.predicate (Trf.OntologyDefs.NCO_IMPROTOCOL);
                       builder.object_string (proto);
 
@@ -2000,21 +2001,17 @@ public class Trf.PersonaStore : Folks.PersonaStore
     }
 
   internal async void _set_im_addresses (Folks.Persona persona,
-      MultiMap<string, string> im_addresses)
+      MultiMap<string, ImFieldDetails> im_addresses)
     {
-      /* FIXME:
-       * - this conversion should go away once we've switched to use the
-       *   same data structure for each property that is a list of something.
-       *   See: https://bugzilla.gnome.org/show_bug.cgi?id=646079 */
-      var ims = new HashSet<FieldDetails> ();
+      var ims = new HashSet<ImFieldDetails> ();
       foreach (var proto in im_addresses.get_keys ())
         {
           var addrs = im_addresses.get (proto);
-          foreach (var a in addrs)
+          foreach (var im_fd in addrs)
             {
-              var fd = new FieldDetails (a);
-              fd.set_parameter ("proto", proto);
-              ims.add (fd);
+              var new_im_fd = new ImFieldDetails (im_fd.value);
+              new_im_fd.set_parameter ("proto", proto);
+              ims.add (new_im_fd);
             }
         }
 
@@ -2395,13 +2392,13 @@ public class Trf.PersonaStore : Folks.PersonaStore
                 break;
               case Trf.Attrib.IM_ADDRESSES:
               default:
-                fd = (FieldDetails) p;
+                fd = (ImFieldDetails) p;
                 attr = "_:p%d".printf (i);
                 builder.subject (attr);
                 builder.predicate ("a");
                 builder.object (related_attrib);
                 builder.predicate (related_prop);
-                builder.object_string (fd.value);
+                builder.object_string (((ImFieldDetails) fd).value);
 
                 if (what == Trf.Attrib.IM_ADDRESSES)
                   {
diff --git a/backends/tracker/lib/trf-persona.vala b/backends/tracker/lib/trf-persona.vala
index 5ca1fab..227310c 100644
--- a/backends/tracker/lib/trf-persona.vala
+++ b/backends/tracker/lib/trf-persona.vala
@@ -277,13 +277,15 @@ public class Trf.Persona : Folks.Persona,
   private HashMap<string, HashMap<string, string>> _tracker_ids_ims =
       new HashMap<string, HashMap<string, string>> ();
 
-  private HashMultiMap<string, string> _im_addresses =
-      new HashMultiMap<string, string> ();
+  private HashMultiMap<string, ImFieldDetails> _im_addresses =
+      new HashMultiMap<string, ImFieldDetails> (null, null,
+          (GLib.HashFunc) ImFieldDetails.hash,
+          (GLib.EqualFunc) ImFieldDetails.equal);
 
   /**
    * { inheritDoc}
    */
-  public MultiMap<string, string> im_addresses
+  public MultiMap<string, ImFieldDetails> im_addresses
     {
       get { return this._im_addresses; }
       public set
@@ -450,10 +452,10 @@ public class Trf.Persona : Folks.Persona,
         {
           foreach (var protocol in this._im_addresses.get_keys ())
             {
-              var im_addresses = this._im_addresses.get (protocol);
+              var im_fds = this._im_addresses.get (protocol);
 
-              foreach (string address in im_addresses)
-                  callback (protocol + ":" + address);
+              foreach (var im_fd in im_fds)
+                  callback (protocol + ":" + im_fd.value);
             }
         }
       else if (prop_name == "local-ids")
@@ -910,8 +912,9 @@ public class Trf.Persona : Folks.Persona,
           var account_id_copy = account_id.dup ();
           var normalised_addr = (owned) normalise_im_address
               ((owned) account_id_copy, im_proto);
+          var im_fd = new ImFieldDetails (normalised_addr);
 
-          this._im_addresses.set (im_proto, normalised_addr);
+          this._im_addresses.set (im_proto, im_fd);
 
           var im_proto_map = new HashMap<string, string> ();
           im_proto_map.set (im_proto, account_id);
@@ -948,8 +951,9 @@ public class Trf.Persona : Folks.Persona,
           break;
         }
 
+      var im_fd = new ImFieldDetails (im_addr);
       if (proto != null && im_addr != null &&
-          this._im_addresses.remove (proto, im_addr))
+          this._im_addresses.remove (proto, im_fd))
         {
           this._tracker_ids_ims.unset (tracker_id);
           if (notify)
diff --git a/folks/im-details.vala b/folks/im-details.vala
index 71bda5f..3b705c5 100644
--- a/folks/im-details.vala
+++ b/folks/im-details.vala
@@ -33,6 +33,57 @@ public errordomain Folks.ImDetailsError
 }
 
 /**
+ * Object representing an IM address value that can have some parameters
+ * associated with it.
+ *
+ * See { link Folks.AbstractFieldDetails}.
+ *
+ * @since UNRELEASED
+ */
+public class Folks.ImFieldDetails : AbstractFieldDetails<string>
+{
+  /**
+   * Create a new ImFieldDetails.
+   *
+   * @param value the value of the field
+   * @param parameters initial parameters. See
+   * { link AbstractFieldDetails.parameters}. A `null` value is equivalent to an
+   * empty map of parameters.
+   *
+   * @return a new ImFieldDetails
+   *
+   * @since UNRELEASED
+   */
+  public ImFieldDetails (string value,
+      MultiMap<string, string>? parameters = null)
+    {
+      this.value = value;
+      if (parameters != null)
+        this.parameters = parameters;
+    }
+
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public override bool equal (AbstractFieldDetails<string> that)
+    {
+      return base.equal<string> (that);
+    }
+
+  /**
+   * { inheritDoc}
+   *
+   * @since UNRELEASED
+   */
+  public override uint hash ()
+    {
+      return base.hash ();
+    }
+}
+
+/**
  * IM addresses exposed by an object implementing { link PresenceDetails}.
  *
  * @since 0.1.13
@@ -53,7 +104,7 @@ public interface Folks.ImDetails : Object
    *
    * @since 0.5.1
    */
-  public abstract MultiMap<string, string> im_addresses
+  public abstract MultiMap<string, ImFieldDetails> im_addresses
     {
       get; set;
     }
diff --git a/folks/individual-aggregator.vala b/folks/individual-aggregator.vala
index 39151dc..ec10d28 100644
--- a/folks/individual-aggregator.vala
+++ b/folks/individual-aggregator.vala
@@ -63,6 +63,7 @@ public class Folks.IndividualAggregator : Object
   private HashTable<string, Individual> _link_map;
   private bool _linking_enabled = true;
   private bool _is_prepared = false;
+  private bool _prepare_pending = false;
   private Debug _debug;
   private string _configured_writeable_store_type_id;
   private string _configured_writeable_store_id;
@@ -341,10 +342,12 @@ public class Folks.IndividualAggregator : Object
 
       lock (this._is_prepared)
         {
-          if (!this._is_prepared)
+          if (!this._is_prepared && !this._prepare_pending)
             {
+              this._prepare_pending = true;
               yield this._backend_store.load_backends ();
               this._is_prepared = true;
+              this._prepare_pending = false;
               this.notify_property ("is-prepared");
             }
         }
@@ -1149,7 +1152,7 @@ public class Folks.IndividualAggregator : Object
           this._configured_writeable_store_type_id);
 
       /* `protocols_addrs_set` will be passed to the new Kf.Persona */
-      var protocols_addrs_set = new HashMultiMap<string, string> ();
+      var protocols_addrs_set = new HashMultiMap<string, ImFieldDetails> ();
       var web_service_addrs_set = new HashMultiMap<string, string> ();
 
       /* List of local_ids */
diff --git a/folks/individual.vala b/folks/individual.vala
index d4f8595..b7a4f5f 100644
--- a/folks/individual.vala
+++ b/folks/individual.vala
@@ -96,7 +96,7 @@ public class Folks.Individual : Object,
   /* The number of Personas in this Individual which have
    * Persona.is_user == true. Iff this is > 0, Individual.is_user == true. */
   private uint _persona_user_count = 0;
-  private HashMultiMap<string, string> _im_addresses;
+  private HashMultiMap<string, ImFieldDetails> _im_addresses;
   private HashMultiMap<string, string> _web_service_addresses;
   private string _nickname = "";
 
@@ -497,7 +497,7 @@ public class Folks.Individual : Object,
   /**
    * { inheritDoc}
    */
-  public MultiMap<string, string> im_addresses
+  public MultiMap<string, ImFieldDetails> im_addresses
     {
       get { return this._im_addresses; }
       private set {}
@@ -687,7 +687,8 @@ public class Folks.Individual : Object,
       debug ("Creating new Individual with %u Personas: %p",
           (personas != null ? personas.size : 0), this);
 
-      this._im_addresses = new HashMultiMap<string, string> ();
+      this._im_addresses = new HashMultiMap<string, ImFieldDetails> (
+          null, null, ImFieldDetails.hash, (EqualFunc) ImFieldDetails.equal);
       this._web_service_addresses = new HashMultiMap<string, string> ();
       this._persona_set =
           new HashSet<Persona> (direct_hash, direct_equal);
diff --git a/tests/eds/add-persona.vala b/tests/eds/add-persona.vala
index c2f98a5..486e248 100644
--- a/tests/eds/add-persona.vala
+++ b/tests/eds/add-persona.vala
@@ -170,11 +170,11 @@ public class AddPersonaTests : Folks.TestCase
       details.insert (Folks.PersonaStore.detail_key (PersonaDetail.AVATAR),
           (owned) v3);
 
-      Value? v4 = Value (typeof (MultiMap<string, string>));
-      var im_addrs = new HashMultiMap<string, string> ();
-      im_addrs.set ("jabber", this._im_addr_1);
-      im_addrs.set ("yahoo", this._im_addr_2);
-      v4.set_object (im_addrs);
+      Value? v4 = Value (typeof (MultiMap<string, ImFieldDetails>));
+      var im_fds = new HashMultiMap<string, ImFieldDetails> ();
+      im_fds.set ("jabber", new ImFieldDetails (this._im_addr_1));
+      im_fds.set ("yahoo", new ImFieldDetails (this._im_addr_2));
+      v4.set_object (im_fds);
       details.insert (
          Folks.PersonaStore.detail_key (PersonaDetail.IM_ADDRESSES), v4);
 
@@ -312,12 +312,12 @@ public class AddPersonaTests : Folks.TestCase
 
       foreach (var proto in i.im_addresses.get_keys ())
         {
-          var addrs = i.im_addresses.get (proto);
-          foreach (var a in addrs)
+          var im_fds = i.im_addresses.get (proto);
+          foreach (var im_fd in im_fds)
             {
-              if (a == this._im_addr_1)
+              if (im_fd.value == this._im_addr_1)
                 this._properties_found.replace ("im-addr-1", true);
-              else if (a == this._im_addr_2)
+              else if (im_fd.value == this._im_addr_2)
                 this._properties_found.replace ("im-addr-2", true);
             }
         }
diff --git a/tests/eds/im-details.vala b/tests/eds/im-details.vala
index 565c717..d7dd449 100644
--- a/tests/eds/im-details.vala
+++ b/tests/eds/im-details.vala
@@ -127,9 +127,10 @@ public class ImDetailsTests : Folks.TestCase
                 {
                   var addrs = i.im_addresses.get (proto);
 
-                 if (proto == "jabber")
+                  if (proto == "jabber")
                     {
-                      if (addrs.contains ("test1 example org"))
+                      if (addrs.contains (
+                            new ImFieldDetails ("test1 example org")))
                         {
                           this._found_addr_1 = true;
                           this._num_addrs++;
@@ -137,7 +138,8 @@ public class ImDetailsTests : Folks.TestCase
                     }
                   else if (proto == "yahoo")
                     {
-                      if (addrs.contains ("test2 example org"))
+                      if (addrs.contains (
+                            new ImFieldDetails ("test2 example org")))
                         {
                           this._found_addr_2 = true;
                           this._num_addrs++;
diff --git a/tests/eds/link-personas.vala b/tests/eds/link-personas.vala
index 5acf6ca..d3556f5 100644
--- a/tests/eds/link-personas.vala
+++ b/tests/eds/link-personas.vala
@@ -201,9 +201,12 @@ public class LinkPersonasTests : Folks.TestCase
 
       if (this._linking_method == LinkingMethod.IM_ADDRESSES)
         {
-          v1 = Value (typeof (MultiMap<string, string>));
-          var im_addrs1 = new HashMultiMap<string, string> ();
-          im_addrs1.set ("jabber", this._im_address_1);
+          v1 = Value (typeof (MultiMap<string,  ImFieldDetails>));
+          var im_addrs1 = new HashMultiMap<string, ImFieldDetails> (
+              null, null,
+              (GLib.HashFunc) ImFieldDetails.hash,
+              (GLib.EqualFunc) ImFieldDetails.equal);
+          im_addrs1.set ("jabber", new ImFieldDetails (this._im_address_1));
           v1.set_object (im_addrs1);
           details1.insert ("im-addresses", (owned) v1);
         }
@@ -227,8 +230,11 @@ public class LinkPersonasTests : Folks.TestCase
       if (this._linking_method == LinkingMethod.IM_ADDRESSES)
         {
           v3 = Value (typeof (MultiMap<string, string>));
-          var im_addrs2 = new HashMultiMap<string, string> ();
-          im_addrs2.set ("yahoo", this._im_address_2);
+          var im_addrs2 = new HashMultiMap<string, ImFieldDetails> (
+              null, null,
+              (GLib.HashFunc) ImFieldDetails.hash,
+              (GLib.EqualFunc) ImFieldDetails.equal);
+          im_addrs2.set ("yahoo", new ImFieldDetails (this._im_address_2));
           v3.set_object (im_addrs2);
           details2.insert ("im-addresses", (owned) v3);
         }
@@ -324,14 +330,14 @@ public class LinkPersonasTests : Folks.TestCase
             {
               foreach (var proto in i.im_addresses.get_keys ())
                 {
-                  var addrs = i.im_addresses.get (proto);
-                  foreach (var a in addrs)
+                  var im_fds = i.im_addresses.get (proto);
+                  foreach (var im_fd in im_fds)
                     {
-                      if (a == this._linking_props.get ("prop1"))
+                      if (im_fd.value == this._linking_props.get ("prop1"))
                         {
                           this._linking_props.unset ("prop1");
                         }
-                      else if (a == this._linking_props.get ("prop2"))
+                      else if (im_fd.value == this._linking_props.get ("prop2"))
                         {
                           this._linking_props.unset ("prop2");
                         }
diff --git a/tests/eds/set-im-addresses.vala b/tests/eds/set-im-addresses.vala
index 4fc44f7..c199c81 100644
--- a/tests/eds/set-im-addresses.vala
+++ b/tests/eds/set-im-addresses.vala
@@ -116,8 +116,12 @@ public class SetIMAddressesTests : Folks.TestCase
 
               foreach (var p in i.personas)
                 {
-                  var im_addrs = new HashMultiMap<string, string> ();
-                  im_addrs.set ("jabber", "bernie example org");
+                  var im_addrs = new HashMultiMap<string, ImFieldDetails> (
+                      null, null,
+                      (GLib.HashFunc) ImFieldDetails.hash,
+                      (GLib.EqualFunc) ImFieldDetails.equal);
+                  im_addrs.set ("jabber",
+                      new ImFieldDetails ("bernie example org"));
                   ((ImDetails) p).im_addresses = im_addrs;
                 }
             }
@@ -131,9 +135,9 @@ public class SetIMAddressesTests : Folks.TestCase
       Folks.Individual i = (Folks.Individual) individual_obj;
       foreach (var proto in i.im_addresses.get_keys ())
         {
-          foreach (var im in i.im_addresses.get (proto))
+          foreach (var im_fd in i.im_addresses.get (proto))
             {
-              if (im == "bernie example org")
+              if (im_fd.equal (new ImFieldDetails ("bernie example org")))
                 {
                   this._found_after_update = true;
                   this._main_loop.quit ();
diff --git a/tests/tracker/add-persona.vala b/tests/tracker/add-persona.vala
index 56efcc2..9c8138f 100644
--- a/tests/tracker/add-persona.vala
+++ b/tests/tracker/add-persona.vala
@@ -236,10 +236,12 @@ public class AddPersonaTests : Folks.TestCase
           Folks.PersonaStore.detail_key (PersonaDetail.EMAIL_ADDRESSES),
           (owned) v8);
 
-      Value? v9 = Value (typeof (MultiMap<string, string>));
-      var im_addrs = new HashMultiMap<string, string> ();
-      im_addrs.set ("jabber", this._im_addr_1);
-      im_addrs.set ("yahoo", this._im_addr_2);
+      Value? v9 = Value (typeof (MultiMap<string, ImFieldDetails>));
+      var im_addrs = new HashMultiMap<string, ImFieldDetails> (null, null,
+          (GLib.HashFunc) ImFieldDetails.hash,
+          (GLib.EqualFunc) ImFieldDetails.equal);
+      im_addrs.set ("jabber", new ImFieldDetails (this._im_addr_1));
+      im_addrs.set ("yahoo", new ImFieldDetails (this._im_addr_2));
       v9.set_object (im_addrs);
       details.insert (
           Folks.PersonaStore.detail_key (PersonaDetail.IM_ADDRESSES), v9);
@@ -440,9 +442,9 @@ public class AddPersonaTests : Folks.TestCase
           var addrs = i.im_addresses.get (proto);
           foreach (var a in addrs)
             {
-              if (a == this._im_addr_1)
+              if (a.value == this._im_addr_1)
                 this._properties_found.replace ("im-addr-1", true);
-              else if (a == this._im_addr_2)
+              else if (a.value == this._im_addr_2)
                 this._properties_found.replace ("im-addr-2", true);
             }
         }
diff --git a/tests/tracker/im-details-interface.vala b/tests/tracker/im-details-interface.vala
index f02f727..726a536 100644
--- a/tests/tracker/im-details-interface.vala
+++ b/tests/tracker/im-details-interface.vala
@@ -120,18 +120,26 @@ public class ImDetailsInterfaceTests : Folks.TestCase
 
                   if (proto == "jabber")
                     {
-                      if (addrs.contains ("test1 example org"))
+                      foreach (var im_fd in addrs)
                         {
-                          this._found_addr_1 = true;
-                          this._num_addrs++;
+                          if (im_fd.value == "test1 example org")
+                            {
+                              this._found_addr_1 = true;
+                              this._num_addrs++;
+                              break;
+                            }
                         }
                     }
                   else if (proto == "aim")
                     {
-                      if (addrs.contains ("test2 example org"))
+                      foreach (var im_fd in addrs)
                         {
-                          this._found_addr_2 = true;
-                          this._num_addrs++;
+                          if (im_fd.value == "test2 example org")
+                            {
+                              this._found_addr_2 = true;
+                              this._num_addrs++;
+                              break;
+                            }
                         }
                     }
                 }
diff --git a/tests/tracker/imaddresses-updates.vala b/tests/tracker/imaddresses-updates.vala
index f8e09e9..39326c0 100644
--- a/tests/tracker/imaddresses-updates.vala
+++ b/tests/tracker/imaddresses-updates.vala
@@ -126,7 +126,17 @@ public class IMAddressesUpdatesTests : Folks.TestCase
               foreach (var proto in i.im_addresses.get_keys ())
                 {
                   var addrs = i.im_addresses.get (proto);
-                  if (addrs.size == 1 && addrs.contains (this._imaddress_1))
+                  bool contains_addr_1 = false;
+                  foreach (var im_fd in addrs)
+                    {
+                      if (im_fd.value == this._imaddress_1)
+                        {
+                          contains_addr_1 = true;
+                          break;
+                        }
+                    }
+
+                  if (addrs.size == 1 && contains_addr_1)
                     {
                       i.notify["im-addresses"].connect (this._notify_im_cb);
                       this._initial_imaddress_found = true;
@@ -145,7 +155,17 @@ public class IMAddressesUpdatesTests : Folks.TestCase
       foreach (var proto in i.im_addresses.get_keys ())
         {
           var addrs = i.im_addresses.get (proto);
-          if (addrs.size == 1 && addrs.contains (this._imaddress_2))
+          bool contains_addr_2 = false;
+          foreach (var im_fd in addrs)
+            {
+              if (im_fd.value == this._imaddress_2)
+                {
+                  contains_addr_2 = true;
+                  break;
+                }
+            }
+
+          if (addrs.size == 1 && contains_addr_2)
             {
               this._updated_imaddr_found = true;
               this._main_loop.quit ();
diff --git a/tests/tracker/link-personas.vala b/tests/tracker/link-personas.vala
index 9f30701..277c0f4 100644
--- a/tests/tracker/link-personas.vala
+++ b/tests/tracker/link-personas.vala
@@ -167,9 +167,11 @@ public class LinkPersonasTests : Folks.TestCase
     {
       HashTable<string, Value?> details1 = new HashTable<string, Value?>
           (str_hash, str_equal);
-      Value? v1 = Value (typeof (MultiMap<string, string>));
-      var im_addrs1 = new HashMultiMap<string, string> ();
-      im_addrs1.set (this._proto, this._im_address_1);
+      Value? v1 = Value (typeof (MultiMap<string, ImFieldDetails>));
+      var im_addrs1 = new HashMultiMap<string, ImFieldDetails> (null, null,
+          (GLib.HashFunc) ImFieldDetails.hash,
+          (GLib.EqualFunc) ImFieldDetails.equal);
+      im_addrs1.set (this._proto, new ImFieldDetails (this._im_address_1));
       v1.set_object (im_addrs1);
       details1.insert ("im-addresses", (owned) v1);
 
@@ -179,9 +181,11 @@ public class LinkPersonasTests : Folks.TestCase
 
       HashTable<string, Value?> details2 = new HashTable<string, Value?>
           (str_hash, str_equal);
-      Value? v3 = Value (typeof (MultiMap<string, string>));
-      var im_addrs2 = new HashMultiMap<string, string> ();
-      im_addrs2.set (this._proto, this._im_address_2);
+      Value? v3 = Value (typeof (MultiMap<string, ImFieldDetails>));
+      var im_addrs2 = new HashMultiMap<string, ImFieldDetails> (null, null,
+          (GLib.HashFunc) ImFieldDetails.hash,
+          (GLib.EqualFunc) ImFieldDetails.equal);
+      im_addrs2.set (this._proto, new ImFieldDetails (this._im_address_2));
       v3.set_object (im_addrs2);
       details2.insert ("im-addresses", (owned) v3);
 
@@ -272,11 +276,11 @@ public class LinkPersonasTests : Folks.TestCase
               var addrs = i.im_addresses.get (proto);
               foreach (var a in addrs)
                 {
-                  if (a == this._linking_props.get ("prop1"))
+                  if (a.value == this._linking_props.get ("prop1"))
                     {
                       this._linking_props.unset ("prop1");
                     }
-                  else if (a == this._linking_props.get ("prop2"))
+                  else if (a.value == this._linking_props.get ("prop2"))
                     {
                       this._linking_props.unset ("prop2");
                     }
diff --git a/tests/tracker/match-im-addresses.vala b/tests/tracker/match-im-addresses.vala
index 1c5e4e4..49bf466 100644
--- a/tests/tracker/match-im-addresses.vala
+++ b/tests/tracker/match-im-addresses.vala
@@ -165,17 +165,19 @@ public class MatchIMAddressesTests : Folks.TestCase
       HashTable<string, Value?> details2 = new HashTable<string, Value?>
           (str_hash, str_equal);
       Value? val;
-      HashMultiMap<string, string> im_addrs;
+      HashMultiMap<string, ImFieldDetails> im_addrs;
 
       val = Value (typeof (string));
       val.set_string (this._persona_fullname_1);
       details1.insert (Folks.PersonaStore.detail_key (PersonaDetail.FULL_NAME),
           (owned) val);
 
-      val = Value (typeof (MultiMap<string, string>));
-      im_addrs = new HashMultiMap<string, string> ();
-      im_addrs.set ("jabber", this._im_addr_1);
-      im_addrs.set ("yahoo", this._im_addr_2);
+      val = Value (typeof (MultiMap<string, ImFieldDetails>));
+      im_addrs = new HashMultiMap<string, ImFieldDetails> (null, null,
+          (GLib.HashFunc) ImFieldDetails.hash,
+          (GLib.EqualFunc) ImFieldDetails.equal);
+      im_addrs.set ("jabber", new ImFieldDetails (this._im_addr_1));
+      im_addrs.set ("yahoo", new ImFieldDetails (this._im_addr_2));
       val.set_object (im_addrs);
       details1.insert (
           Folks.PersonaStore.detail_key (PersonaDetail.IM_ADDRESSES),
@@ -186,9 +188,11 @@ public class MatchIMAddressesTests : Folks.TestCase
       details2.insert (Folks.PersonaStore.detail_key (PersonaDetail.FULL_NAME),
           (owned) val);
 
-      val = Value (typeof (MultiMap<string, string>));
-      im_addrs = new HashMultiMap<string, string> ();
-      im_addrs.set ("jabber", this._im_addr_1);
+      val = Value (typeof (MultiMap<string, ImFieldDetails>));
+      im_addrs = new HashMultiMap<string, ImFieldDetails> (null, null,
+          (GLib.HashFunc) ImFieldDetails.hash,
+          (GLib.EqualFunc) ImFieldDetails.equal);
+      im_addrs.set ("jabber", new ImFieldDetails (this._im_addr_1));
       val.set_object (im_addrs);
       details2.insert (
           Folks.PersonaStore.detail_key (PersonaDetail.IM_ADDRESSES),
diff --git a/tests/tracker/set-im-addresses.vala b/tests/tracker/set-im-addresses.vala
index 1be7730..cf5788b 100644
--- a/tests/tracker/set-im-addresses.vala
+++ b/tests/tracker/set-im-addresses.vala
@@ -111,13 +111,18 @@ public class SetIMAddressesTests : Folks.TestCase
             {
               i.notify["im-addresses"].connect (this._notify_im_addresses_cb);
 
-              var im_addresses = new HashMultiMap<string, string> ();
+              var im_addresses = new HashMultiMap<string, ImFieldDetails> (
+                  null, null,
+                  (GLib.HashFunc)ImFieldDetails.hash,
+                  (GLib.EqualFunc) ImFieldDetails.equal);
 
-              im_addresses.set ("aim", "one example org");
-              im_addresses.set ("aim", "two example org");
+              im_addresses.set ("aim", new ImFieldDetails ("one example org"));
+              im_addresses.set ("aim", new ImFieldDetails ("two example org"));
 
-              im_addresses.set ("yahoo", "three example org");
-              im_addresses.set ("yahoo", "four example org");
+              im_addresses.set ("yahoo",
+                  new ImFieldDetails ("three example org"));
+              im_addresses.set ("yahoo",
+                  new ImFieldDetails ("four example org"));
 
               foreach (var p in i.personas)
                 {
@@ -136,12 +141,12 @@ public class SetIMAddressesTests : Folks.TestCase
         {
           foreach (var proto in i.im_addresses.get_keys ())
             {
-              var addrs = i.im_addresses.get (proto);
-              foreach (var a in addrs)
+              var im_fds = i.im_addresses.get (proto);
+              foreach (var im_fd in im_fds)
                 {
                   foreach (unowned string my_a in this._addresses)
                     {
-                      if (my_a == a)
+                      if (my_a == im_fd.value)
                         {
                           this._addresses.remove (my_a);
                           break;



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