[folks] Implement web-service-details for Trf.Personas



commit 82f365cd94112ef2f1572372dabe1a362fcc60f0
Author: Raul Gutierrez Segales <raul gutierrez segales collabora co uk>
Date:   Fri Apr 8 16:02:20 2011 +0100

    Implement web-service-details for Trf.Personas

 backends/tracker/lib/trf-persona-store.vala |  206 +++++++++++++++++++++++----
 backends/tracker/lib/trf-persona.vala       |   39 +++++-
 2 files changed, 215 insertions(+), 30 deletions(-)
---
diff --git a/backends/tracker/lib/trf-persona-store.vala b/backends/tracker/lib/trf-persona-store.vala
index 378d762..622ad52 100644
--- a/backends/tracker/lib/trf-persona-store.vala
+++ b/backends/tracker/lib/trf-persona-store.vala
@@ -22,6 +22,7 @@
  */
 
 using Folks;
+using Gee;
 using GLib;
 using Tracker;
 using Tracker.Sparql;
@@ -155,6 +156,8 @@ private const char _REMOVE_EMAILS      = 0x10;
  */
 public class Trf.PersonaStore : Folks.PersonaStore
 {
+  private const string _LOCAL_ID_PROPERTY_NAME = "folks-linking-ids";
+  private const string _WSD_PROPERTY_NAME = "folks-linking-ws-addrs";
   private const string _OBJECT_NAME = "org.freedesktop.Tracker1";
   private const string _OBJECT_IFACE = "org.freedesktop.Tracker1.Resources";
   private const string _OBJECT_PATH = "/org/freedesktop/Tracker1/Resources";
@@ -389,6 +392,7 @@ public class Trf.PersonaStore : Folks.PersonaStore
    * - PersonaStore.detail_key (PersonaDetail.POSTAL_ADDRESSES)
    * - PersonaStore.detail_key (PersonaDetail.ROLES)
    * - PersonaStore.detail_key (PersonaDetail.URL)
+   * - PersonaStore.detail_key (PersonaDetail.WEB_SERVICE_ADDRESSES)
    *
    * See { link Folks.PersonaStore.add_persona_from_details}.
    */
@@ -696,7 +700,7 @@ public class Trf.PersonaStore : Folks.PersonaStore
               builder.predicate ("a");
               builder.object (Trf.OntologyDefs.NAO_PROPERTY);
               builder.predicate (Trf.OntologyDefs.NAO_PROPERTY_NAME);
-              builder.object_string ("folks-linking-ids");
+              builder.object_string (this._LOCAL_ID_PROPERTY_NAME);
               builder.predicate (Trf.OntologyDefs.NAO_PROPERTY_VALUE);
               builder.object_string (ids);
 
@@ -704,6 +708,27 @@ public class Trf.PersonaStore : Folks.PersonaStore
               builder.predicate (Trf.OntologyDefs.NAO_HAS_PROPERTY);
               builder.object ("_:folks_ids");
             }
+          else if (k ==
+              Folks.PersonaStore.detail_key (
+                  PersonaDetail.WEB_SERVICE_ADDRESSES))
+            {
+              HashMap<string, LinkedHashSet<string>> ws_obj =
+                (HashMap<string, LinkedHashSet<string>>) v.get_object ();
+
+              var ws_addrs = Trf.PersonaStore.serialize_web_services (ws_obj);
+
+              builder.subject ("_:folks_ws_ids");
+              builder.predicate ("a");
+              builder.object (Trf.OntologyDefs.NAO_PROPERTY);
+              builder.predicate (Trf.OntologyDefs.NAO_PROPERTY_NAME);
+              builder.object_string (this._WSD_PROPERTY_NAME);
+              builder.predicate (Trf.OntologyDefs.NAO_PROPERTY_VALUE);
+              builder.object_string (ws_addrs);
+
+              builder.subject ("_:p");
+              builder.predicate (Trf.OntologyDefs.NAO_HAS_PROPERTY);
+              builder.object ("_:folks_ws_ids");
+            }
           else
             {
               throw new PersonaStoreError.INVALID_ARGUMENT (
@@ -725,7 +750,7 @@ public class Trf.PersonaStore : Folks.PersonaStore
             {
               string filter = " FILTER(?_contact = <%s>) ".printf (contact_urn);
               string query = this._INITIAL_QUERY.printf (filter);
-              Queue<Persona> ret_personas;
+              GLib.Queue<Persona> ret_personas;
               ret_personas = yield this._do_add_contacts (query);
               ret = ret_personas.pop_head ();
             }
@@ -739,6 +764,73 @@ public class Trf.PersonaStore : Folks.PersonaStore
     }
 
  /**
+   * Returns "service1:addr1,addr2;service2:addr3,.."
+   *
+   * @since UNRELEASED
+   */
+   public static string serialize_web_services (HashMap<string,
+      LinkedHashSet<string>> ws_obj)
+    {
+      var str = "";
+
+      foreach (var service in ws_obj.keys)
+        {
+          if (str != "")
+            {
+              str += ";";
+            }
+
+          str += service + ":";
+
+          var addrs = ws_obj.get (service);
+          bool first = true;
+          foreach (var addr in addrs)
+            {
+              if (first == false)
+                {
+                  str += ",";
+                }
+
+              str += addr;
+              first = false;
+            }
+        }
+
+      return str;
+    }
+
+ /**
+   * Transforms "service1:addr1,addr2;service2:addr3,.." to
+   *   --->  HashMap<string, LinkedHashSet<string>>
+   *
+   * @since UNRELEASED
+   */
+  public static HashMap<string, LinkedHashSet<string>> unserialize_web_services
+      (string ws_addrs)
+    {
+      HashMap<string, LinkedHashSet<string>> ret =
+        new HashMap<string, LinkedHashSet<string>> ();
+
+      var services = ws_addrs.split (";");
+      foreach (var service_line in services)
+          {
+            var service_t = service_line.split (":");
+            var service_name = service_t[0];
+            var addrs = service_t[1].split (",");
+
+            var addrs_list = new LinkedHashSet<string> ();
+
+            ret.set (service_name, addrs_list);
+            foreach (var a in addrs)
+              {
+                addrs_list.add (a);
+              }
+          }
+
+      return ret;
+    }
+
+ /**
    * Transform HashSet<string> to "id1,id2,.."
    *
    * @since UNRELEASED
@@ -1105,7 +1197,7 @@ public class Trf.PersonaStore : Folks.PersonaStore
 
   private async void _handle_delete_events (owned VariantIter iter_del)
     {
-      var removed_personas = new Queue<Persona> ();
+      var removed_personas = new GLib.Queue<Persona> ();
       var nco_person_id =
           this._prefix_tracker_id.get (Trf.OntologyDefs.NCO_PERSON);
       var rdf_type_id = this._prefix_tracker_id.get (Trf.OntologyDefs.RDF_TYPE);
@@ -1146,7 +1238,7 @@ public class Trf.PersonaStore : Folks.PersonaStore
 
   private async void _handle_insert_events (owned VariantIter iter_ins)
     {
-      var added_personas = new Queue<Persona> ();
+      var added_personas = new GLib.Queue<Persona> ();
       Event e = Event ();
 
       while (iter_ins.next
@@ -1174,9 +1266,9 @@ public class Trf.PersonaStore : Folks.PersonaStore
         }
     }
 
-  private async Queue<Persona> _do_add_contacts (string query)
+  private async GLib.Queue<Persona> _do_add_contacts (string query)
     {
-      var added_personas = new Queue<Persona> ();
+      var added_personas = new GLib.Queue<Persona> ();
 
      try {
         Sparql.Cursor cursor = yield this._connection.query_async (query);
@@ -1440,12 +1532,35 @@ public class Trf.PersonaStore : Folks.PersonaStore
       else if (e.pred_id == this._prefix_tracker_id.get
           (Trf.OntologyDefs.NAO_PROPERTY))
         {
-          string local_ids = "";
+          /* WARNING:
+           *  nao:Properties shouldn't be abused since we have to reset
+           *  them all when there is a DELETE. Plus, the Tracker devs
+           *  say nao:Property is by nature slow. */
           if (adding)
             {
-              local_ids = yield this._get_local_ids (e.subject_id);
+              string[] prop_info =  yield this._get_nao_property_by_prop_id (
+                  e.object_id);
+              if (prop_info[0] == this._LOCAL_ID_PROPERTY_NAME)
+                {
+                  p._set_local_ids (prop_info[1]);
+                }
+              else if (prop_info[0] == this._WSD_PROPERTY_NAME)
+                {
+                  p._set_web_service_addrs (prop_info[1]);
+                }
+            }
+          else
+            {
+              string local_ids = yield this._get_nao_property_by_person_id (
+                  e.subject_id,
+                  this._LOCAL_ID_PROPERTY_NAME);
+              string ws_addrs = yield this._get_nao_property_by_person_id (
+                  e.subject_id,
+                  this._WSD_PROPERTY_NAME);
+
+              p._set_local_ids (local_ids);
+              p._set_web_service_addrs (ws_addrs);
             }
-          p._set_local_ids (local_ids);
         }
     }
 
@@ -1464,21 +1579,38 @@ public class Trf.PersonaStore : Folks.PersonaStore
       return yield this._single_value_query (query);
     }
 
-  private async string _get_local_ids (int subject_tracker_id)
+  private async string _get_nao_property_by_person_id (int nco_person_id,
+      string prop_name)
     {
       const string query_t = "SELECT " +
-      " ?prop_value " +
-      "WHERE { " +
-      " ?p a " + Trf.OntologyDefs.NCO_PERSON + " ; " +
+        " ?prop_value " +
+        "WHERE { " +
+        " ?p a " + Trf.OntologyDefs.NCO_PERSON + " ; " +
         Trf.OntologyDefs.NAO_HAS_PROPERTY + " ?prop . " +
-      " ?prop " + Trf.OntologyDefs.NAO_PROPERTY_NAME + " ?prop_name . " +
-      " ?prop " + Trf.OntologyDefs.NAO_PROPERTY_VALUE + " ?prop_value . " +
-      " FILTER (tracker:id(?p) = %d && ?prop_name = 'folks-linking-ids' ) } ";
+        " ?prop " + Trf.OntologyDefs.NAO_PROPERTY_NAME + " ?prop_name . " +
+        " ?prop " + Trf.OntologyDefs.NAO_PROPERTY_VALUE + " ?prop_value . " +
+        " FILTER (tracker:id(?p) = %d && ?prop_name = '%s') } ";
 
-      string query = query_t.printf(subject_tracker_id);
+      string query = query_t.printf(nco_person_id, prop_name);
       return yield this._single_value_query (query);
     }
 
+  private async string[] _get_nao_property_by_prop_id (int nao_prop_id)
+    {
+      const string query_t = "SELECT " +
+        " fn:concat(?prop_name, '\t', ?prop_value)" +
+        "WHERE { " +
+        " ?p a " + Trf.OntologyDefs.NCO_PERSON + " ; " +
+        Trf.OntologyDefs.NAO_HAS_PROPERTY + " ?prop . " +
+        " ?prop " + Trf.OntologyDefs.NAO_PROPERTY_NAME + " ?prop_name . " +
+        " ?prop " + Trf.OntologyDefs.NAO_PROPERTY_VALUE + " ?prop_value . " +
+        " FILTER (tracker:id(?prop) = %d) } ";
+
+      string query = query_t.printf(nao_prop_id);
+      var ret = yield this._single_value_query (query);
+      return ret.split ("\t");
+    }
+
   /*
    * This should be kept in sync with Trf.AfflInfoFields
    */
@@ -1562,7 +1694,7 @@ public class Trf.PersonaStore : Folks.PersonaStore
               var country = cursor.get_string
                   (Trf.AfflInfoFields.AFFL_COUNTRY).dup ();
 
-              List<string> types = new List<string> ();
+              GLib.List<string> types = new GLib.List<string> ();
 
               affl_info.postal_address = new Folks.PostalAddress (
                   po_box, extension, street, locality, region, postal_code,
@@ -1713,16 +1845,35 @@ public class Trf.PersonaStore : Folks.PersonaStore
   internal async void _set_local_ids (Trf.Persona persona,
       Gee.HashSet<string> local_ids)
     {
+      string ids = Trf.PersonaStore.serialize_local_ids (local_ids);
+      yield this._set_tracker_property (persona,
+          this._LOCAL_ID_PROPERTY_NAME, ids,
+          "_set_local_ids");
+    }
+
+  internal async void _set_web_service_addrs (Trf.Persona persona,
+      HashMap<string, LinkedHashSet<string>> ws_obj)
+    {
+      var ws_addrs = Trf.PersonaStore.serialize_web_services (ws_obj);
+      yield this._set_tracker_property (persona,
+          this._WSD_PROPERTY_NAME, ws_addrs,
+          "_set_web_service_addrs");
+    }
+
+  private async void _set_tracker_property(Trf.Persona persona,
+      string prop_name, string prop_value, string callers_name)
+    {
       const string query_t = "DELETE " +
       " { ?p " + Trf.OntologyDefs.NAO_HAS_PROPERTY + " ?prop } " +
       "WHERE { " +
       " ?p a " + Trf.OntologyDefs.NCO_PERSON + " ; " +
-        Trf.OntologyDefs.NAO_HAS_PROPERTY + " ?prop . " +
+      Trf.OntologyDefs.NAO_HAS_PROPERTY + " ?prop . " +
       " ?prop " + Trf.OntologyDefs.NAO_PROPERTY_NAME + " ?prop_name . " +
-      " FILTER (tracker:id(?p) = %s && ?name = 'folks-linking-ids' ) } " +
+      " FILTER (tracker:id(?p) = %s && ?name = '%s' ) } " +
       "INSERT { " +
       " _:prop a " + Trf.OntologyDefs.NAO_PROPERTY + " ; " +
-      Trf.OntologyDefs.NAO_PROPERTY_NAME + " 'folks-linking-ids' ; " +
+      Trf.OntologyDefs.NAO_PROPERTY_NAME +
+      " '%s' ; " +
       Trf.OntologyDefs.NAO_PROPERTY_VALUE + " '%s' . " +
       " ?p " + Trf.OntologyDefs.NAO_HAS_PROPERTY + " _:prop " +
       "} " +
@@ -1730,11 +1881,9 @@ public class Trf.PersonaStore : Folks.PersonaStore
       " ?p a nco:PersonContact . " +
       "FILTER (tracker:id(?p) = %s) } ";
 
-      string ids = Trf.PersonaStore.serialize_local_ids (local_ids);
-
-      string query = query_t.printf (persona.tracker_id (), ids,
-          persona.tracker_id ());
-      yield this._tracker_update (query, "_set_local_ids");
+      string query = query_t.printf (persona.tracker_id (), prop_name,
+          prop_name, prop_value, persona.tracker_id ());
+      yield this._tracker_update (query, callers_name);
     }
 
   internal async void _set_is_favourite (Folks.Persona persona,
@@ -2155,7 +2304,8 @@ public class Trf.PersonaStore : Folks.PersonaStore
           else if (what == Trf.Attrib.URLS)
             {
               fd = (FieldDetails) p;
-              unowned List<string> type_p = fd.get_parameter_values ("type");
+              unowned GLib.List<string> type_p =
+                fd.get_parameter_values ("type");
               if (type_p.length () > 0)
                 {
                   if (type_p.nth_data (0) == "blog")
@@ -2182,7 +2332,7 @@ public class Trf.PersonaStore : Folks.PersonaStore
               if (what == Trf.Attrib.IM_ADDRESSES)
                 {
                   builder.predicate (related_prop_2);
-                  unowned List<string> im_params =
+                  unowned GLib.List<string> im_params =
                       fd.get_parameter_values ("proto");
                   builder.object_string (im_params.nth_data (0));
                 }
diff --git a/backends/tracker/lib/trf-persona.vala b/backends/tracker/lib/trf-persona.vala
index 92f5686..1101b0c 100644
--- a/backends/tracker/lib/trf-persona.vala
+++ b/backends/tracker/lib/trf-persona.vala
@@ -43,12 +43,13 @@ public class Trf.Persona : Folks.Persona,
     PhoneDetails,
     PostalAddressDetails,
     RoleDetails,
-    UrlDetails
+    UrlDetails,
+    WebServiceDetails
 {
   private string _alias;
   private bool _is_favourite;
   private const string[] _linkable_properties =
-      {"im-addresses", "local-ids"};
+      {"im-addresses", "local-ids", "web-service-addresses"};
   private GLib.List<FieldDetails> _phone_numbers;
   private GLib.List<FieldDetails> _email_addresses;
   private weak Sparql.Cursor _cursor;
@@ -328,6 +329,20 @@ public class Trf.Persona : Folks.Persona,
         }
     }
 
+  private HashMap<string, LinkedHashSet<string>> _web_service_addresses =
+      new HashMap<string, LinkedHashSet<string>> (str_hash, str_equal);
+  /**
+   * { inheritDoc}
+   */
+  public HashMap<string, LinkedHashSet<string>> web_service_addresses
+    {
+      get { return this._web_service_addresses; }
+      set
+        {
+          ((Trf.PersonaStore) this.store)._set_web_service_addrs (this, value);
+        }
+    }
+
   /**
    * Build a IID.
    *
@@ -416,6 +431,18 @@ public class Trf.Persona : Folks.Persona,
               callback (id);
             }
         }
+      else if (prop_name == "web-service-addresses")
+        {
+          foreach (var entry in this.web_service_addresses.entries)
+            {
+              unowned string web_service = (string) entry.key;
+              unowned LinkedHashSet<string> web_service_addresses =
+                  (LinkedHashSet<string>) entry.value;
+
+              foreach (string address in web_service_addresses)
+                  callback (web_service + ":" + address);
+            }
+        }
       else
         {
           /* Chain up */
@@ -799,6 +826,14 @@ public class Trf.Persona : Folks.Persona,
       return true;
     }
 
+  internal bool _set_web_service_addrs (string ws_addrs)
+    {
+      this._web_service_addresses =
+        Trf.PersonaStore.unserialize_web_services (ws_addrs);
+      this.notify_property ("web-service-addresses");
+      return true;
+    }
+
   private void _update_im_addresses ()
     {
       string addresses = this._cursor.get_string (



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