*/
using GLib;
+using Gee;
using Folks;
using Folks.Backends.Kf;
*
* Accepted keys for `details` are:
* - PersonaStore.detail_key (PersonaDetail.IM_ADDRESSES)
+ * - PersonaStore.detail_key (PersonaDetail.WEB_SERVICE_ADDRESSES)
*
* See {@link Folks.PersonaStore.add_persona_from_details}.
*/
PersonaDetail.IM_ADDRESSES));
unowned HashTable<string, LinkedHashSet<string>> im_addresses =
(HashTable<string, LinkedHashSet<string>>) val.get_boxed ();
-
- if (im_addresses == null || im_addresses.size () == 0)
+ val = details.lookup (this.detail_key (PersonaDetail.WEB_SERVICE_ADDRESSES));
+ unowned HashMap<string, LinkedHashSet<string>> web_service_addresses =
+ (HashMap<string, LinkedHashSet<string>>) val.get_object ();
+ uint im_addresses_size = (im_addresses == null)
+ ? 0 : im_addresses.size ();
+ uint web_service_addresses_size = (web_service_addresses == null)
+ ? 0 : web_service_addresses.size;
+
+ if (im_addresses_size + web_service_addresses_size == 0)
{
throw new PersonaStoreError.INVALID_ARGUMENT (
/* Translators: the first two parameters are identifiers for the
}
while (this._key_file.has_group (persona_id) == true);
- /* Create a new persona and set its im-addresses property to update the
+ /* Create a new persona and set its addresses property to update the
* key file */
Persona persona = new Kf.Persona (this._key_file, persona_id, this);
this._personas.insert (persona.iid, persona);
- persona.im_addresses = im_addresses;
+ if (im_addresses_size > 0)
+ persona.im_addresses = im_addresses;
+ if (web_service_addresses_size > 0)
+ persona.web_service_addresses = web_service_addresses;
/* FIXME: GroupDetails.ChangeReason is not the right enum to use here */
GLib.List<Persona> personas = new GLib.List<Persona> ();
* GenericArray<string> here rather than just string[], as null-terminated
* arrays aren't supported as generic types. */
private HashTable<string, LinkedHashSet<string>> _im_addresses;
+ private HashMap<string, LinkedHashSet<string>> _web_service_addresses;
private string _alias;
- private const string[] _linkable_properties = { "im-addresses" };
+ private const string[] _linkable_properties =
+ {
+ "im-addresses",
+ "web-service-addresses"
+ };
/**
* {@inheritDoc}
}
/**
+ * {@inheritDoc}
+ */
+ public HashMap<string, LinkedHashSet<string>> web_service_addresses
+ {
+ get
+ { return this._web_service_addresses; }
+
+ set
+ {
+ /* Remove the current web service addresses from the key file */
+ foreach (var web_service in this._web_service_addresses.keys)
+ {
+ try
+ {
+ this._key_file.remove_key (this.display_id, "web-service." + web_service);
+ }
+ catch (KeyFileError e)
+ {
+ /* Ignore the error, since it's just a group or key not found
+ * error. */
+ }
+ }
+
+ /* Add the new web service addresses to the key file and build a
+ * table of them to set as the new property value */
+ HashMap<string, LinkedHashSet<string>> web_service_addresses =
+ new HashMap<string, LinkedHashSet<string>> (str_hash, str_equal);
+
+ foreach (var entry in value.entries)
+ {
+ unowned string web_service = (string) entry.key;
+ unowned LinkedHashSet<string?> addresses =
+ (LinkedHashSet<string?>) entry.value;
+
+ string[] addrs = (string[]) addresses.to_array ();
+ addrs.length = addresses.size;
+
+ this._key_file.set_string_list (this.display_id,
+ "web-service." + web_service, addrs);
+ web_service_addresses.set (web_service, addresses);
+ }
+
+ this._web_service_addresses = web_service_addresses;
+
+ /* Get the PersonaStore to save the key file */
+ ((Kf.PersonaStore) this.store).save_key_file.begin ();
+ }
+ }
+
+ /**
* Create a new persona.
*
* Create a new persona for the {@link PersonaStore} `store`, representing
this._key_file = key_file;
this._im_addresses = new HashTable<string, LinkedHashSet<string>> (
str_hash, str_equal);
+ this._web_service_addresses
+ = new HashMap<string, LinkedHashSet<string>> (str_hash,
+ str_equal);
/* Load the IM addresses from the key file */
try
continue;
}
+ /* Web service addresses */
+ var decomposed_key = key.split(".", 2);
+ if (decomposed_key.length == 2 &&
+ decomposed_key[0] == "web-service")
+ {
+ unowned string web_service = decomposed_key[1];
+ var web_service_addresses = this._key_file.get_string_list (
+ this.display_id, web_service);
+
+ var address_set = new LinkedHashSet<string> ();
+
+ foreach (var web_service_address in web_service_addresses)
+ {
+ address_set.add (web_service_address);
+ }
+
+ this._web_service_addresses.set (web_service, address_set);
+ continue;
+ }
+
/* IM addresses */
unowned string protocol = key;
var im_addresses = this._key_file.get_string_list (
warning (e.message);
continue;
}
- address_set.add (address);
+ address_set.add (address);
}
this._im_addresses.insert (protocol, address_set);
callback (protocol + ":" + address);
});
}
+ 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 */
*/
using GLib;
+using Gee;
using Folks;
using SocialWebClient;
GenderDetails,
ImDetails,
NameDetails,
- UrlDetails
+ UrlDetails,
+ WebServiceDetails
{
- private const string[] _linkable_properties = {};
+ private const string[] _linkable_properties =
+ {
+ "im-addresses",
+ "web-service-addresses"
+ };
/**
* The names of the Persona's linkable properties.
*/
public Gender gender { get; private set; }
- private List<FieldDetails> _urls;
+ private GLib.List<FieldDetails> _urls;
/**
* {@inheritDoc}
*/
- public List<FieldDetails> urls
+ public GLib.List<FieldDetails> urls
{
get { return this._urls; }
private set
{
- this._urls = new List<FieldDetails> ();
+ this._urls = new GLib.List<FieldDetails> ();
foreach (unowned FieldDetails ps in value)
this._urls.prepend (ps);
this._urls.reverse ();
private HashTable<string, LinkedHashSet<string>> _im_addresses =
new HashTable<string, LinkedHashSet<string>> (str_hash, str_equal);
+
+ private HashMap<string, LinkedHashSet<string>> _web_service_addresses =
+ new HashMap<string, LinkedHashSet<string>> (str_hash, str_equal);
+
/**
* {@inheritDoc}
*/
}
/**
+ * {@inheritDoc}
+ */
+ public HashMap<string, LinkedHashSet<string>> web_service_addresses
+ {
+ get { return this._web_service_addresses; }
+ private set {}
+ }
+
+ /**
* Build the Facebook JID.
*
* @param store_id the {@link PersonaStore.id}
public Persona (PersonaStore store, Contact contact)
{
var id = get_contact_id (contact);
+ var service = contact.service.dup();
var uid = this.build_uid (BACKEND_NAME, store.id, id);
var iid = this._build_iid (store.id, id);
}
}
+ var web_service_address_array = new LinkedHashSet<string> ();
+ web_service_address_array.add (id);
+ this._web_service_addresses.set ((owned) service,
+ (owned) web_service_address_array);
+
update (contact);
}
if (this.full_name != full_name)
this.full_name = full_name;
- var urls = new List<FieldDetails> ();
+ var urls = new GLib.List<FieldDetails> ();
var website = contact.get_value ("url");
if (website != null)
field-details.vala \
gender-details.vala \
group-details.vala \
+ web-service-details.vala \
im-details.vala \
name-details.vala \
note-details.vala \
/* `protocols_addrs_set` will be passed to the new Kf.Persona */
var protocols_addrs_set =
new HashTable<string, LinkedHashSet<string>> (str_hash, str_equal);
+ var web_service_addrs_set =
+ new HashMap<string, LinkedHashSet<string>> (str_hash, str_equal);
foreach (var persona in personas)
{
- if (!(persona is ImDetails))
- continue;
-
- ((ImDetails) persona).im_addresses.foreach ((k, v) =>
+ if (persona is ImDetails)
{
- unowned string protocol = (string) k;
- unowned LinkedHashSet<string> addresses =
- (LinkedHashSet<string>) v;
-
- var address_set = protocols_addrs_set.lookup (protocol);
-
- if (address_set == null)
+ ((ImDetails) persona).im_addresses.foreach ((k, v) =>
{
- address_set = new LinkedHashSet<string> ();
+ unowned string protocol = (string) k;
+ unowned LinkedHashSet<string> addresses =
+ (LinkedHashSet<string>) v;
+
+ var address_set = protocols_addrs_set.lookup (protocol);
+
+ if (address_set == null)
+ {
+ address_set = new LinkedHashSet<string> ();
+
+ protocols_addrs_set.insert (protocol, address_set);
+ }
+
+ address_set.add_all (addresses);
+ });
+ }
- protocols_addrs_set.insert (protocol, address_set);
+ if (persona is WebServiceDetails)
+ {
+ foreach (var entry in
+ ((WebServiceDetails) persona).web_service_addresses.entries)
+ {
+ unowned string web_service = (string) entry.key;
+ unowned LinkedHashSet<string> addresses =
+ (LinkedHashSet<string>) entry.value;
+
+ var address_set = web_service_addrs_set.get (web_service);
+
+ if (address_set == null)
+ {
+ address_set = new LinkedHashSet<string> ();
+
+ web_service_addrs_set.set (web_service, address_set);
+ }
+
+ address_set.add_all (addresses);
}
-
- address_set.add_all (addresses);
- });
+ }
}
- var addresses_value = Value (typeof (HashTable));
- addresses_value.set_boxed (protocols_addrs_set);
+ var im_addresses_value = Value (typeof (HashTable));
+ im_addresses_value.set_boxed (protocols_addrs_set);
+
+ var web_service_addresses_value = Value (typeof (HashMap));
+ web_service_addresses_value.set_object (web_service_addrs_set);
var details = new HashTable<string, Value?> (str_hash, str_equal);
- details.insert ("im-addresses", addresses_value);
+ details.insert (PersonaStore.detail_key (PersonaDetail.IM_ADDRESSES),
+ im_addresses_value);
+ details.insert (PersonaStore.detail_key
+ (PersonaDetail.WEB_SERVICE_ADDRESSES), web_service_addresses_value);
yield this.add_persona_from_details (null, this._writeable_store,
details);
PhoneDetails,
PostalAddressDetails,
RoleDetails,
- UrlDetails
+ UrlDetails,
+ WebServiceDetails
{
private bool _is_favourite;
private string _alias;
* Persona.is_user == true. Iff this is > 0, Individual.is_user == true. */
private uint _persona_user_count = 0;
private HashTable<string, LinkedHashSet<string>> _im_addresses;
+ private HashMap<string, LinkedHashSet<string>> _web_service_addresses;
/**
* The trust level of the Individual.
}
/**
+ * {@inheritDoc}
+ */
+ public HashMap<string, LinkedHashSet<string>> web_service_addresses
+ {
+ get { return this._web_service_addresses; }
+ private set {}
+ }
+
+ /**
* The set of {@link Persona}s encapsulated by this Individual.
*
* Changing the set of personas may cause updates to the aggregated properties
this._update_im_addresses ();
}
+ private void _notify_web_service_addresses_cb (Object obj, ParamSpec ps)
+ {
+ this._update_web_service_addresses ();
+ }
+
private void _notify_is_favourite_cb (Object obj, ParamSpec ps)
{
this._update_is_favourite ();
{
this._im_addresses =
new HashTable<string, LinkedHashSet<string>> (str_hash, str_equal);
+ this._web_service_addresses =
+ new HashMap<string, LinkedHashSet<string>> (str_hash, str_equal);
this._persona_set = new HashSet<Persona> (null, null);
this._stores = new HashMap<PersonaStore, uint> (null, null);
this._gender = Gender.UNSPECIFIED;
this._update_alias ();
this._update_trust_level ();
this._update_im_addresses ();
+ this._update_web_service_addresses ();
this._update_structured_name ();
this._update_full_name ();
this._update_nickname ();
this.notify_property ("im-addresses");
}
+ private void _update_web_service_addresses ()
+ {
+ /* populate the web service addresses as the union of our Personas' addresses */
+ foreach (var persona in this.personas)
+ {
+ if (persona is WebServiceDetails)
+ {
+ var web_service_details = (WebServiceDetails) persona;
+ foreach (var entry in
+ web_service_details.web_service_addresses.entries)
+ {
+ var cur_web_service = (string) entry.key;
+ var cur_addresses = (LinkedHashSet<string>) entry.value;
+ var web_service_set = this._web_service_addresses.get
+ (cur_web_service);
+
+ if (web_service_set == null)
+ {
+ web_service_set = new LinkedHashSet<string> ();
+ this._web_service_addresses.set (cur_web_service,
+ web_service_set);
+ }
+
+ web_service_set.add_all (cur_addresses);
+ }
+ }
+ }
+ this.notify_property ("web-service-addresses");
+ }
+
private void _connect_to_persona (Persona persona)
{
persona.notify["alias"].connect (this._notify_alias_cb);
persona.notify["presence-message"].connect (this._notify_presence_cb);
persona.notify["presence-type"].connect (this._notify_presence_cb);
persona.notify["im-addresses"].connect (this._notify_im_addresses_cb);
+ persona.notify["web-service-addresses"].connect
+ (this._notify_web_service_addresses_cb);
persona.notify["is-favourite"].connect (this._notify_is_favourite_cb);
persona.notify["structured-name"].connect (
this._notify_structured_name_cb);
persona.notify["presence-type"].disconnect (this._notify_presence_cb);
persona.notify["im-addresses"].disconnect (
this._notify_im_addresses_cb);
+ persona.notify["web-service-addresses"].disconnect (
+ this._notify_web_service_addresses_cb);
persona.notify["is-favourite"].disconnect (
this._notify_is_favourite_cb);
persona.notify["structured-name"].disconnect (
GENDER,
EMAIL_ADDRESSES,
IM_ADDRESSES,
+ WEB_SERVICE_ADDRESSES,
NOTES,
PHONE_NUMBERS,
POSTAL_ADDRESSES,
"gender",
"email-addresses",
"im-addresses",
+ "web-service-addresses",
"notes",
"phone-numbers",
"postal-addresses",
--- /dev/null
+/*
+ * 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:
+ * Alban Crequy <alban.crequy@collabora.co.uk>
+ */
+
+using Gee;
+
+/**
+ * web service addresses exposed by an object implementing
+ * {@link PresenceDetails}.
+ *
+ * @since UNRELEASED
+ */
+public interface Folks.WebServiceDetails : Object
+{
+ /**
+ * A mapping of web service to an ordered set of web service addresses.
+ *
+ * Each mapping is from an arbitrary web service identifier to a set of web
+ * service addresses for the contact, listed in preference order.
+ * The most-preferred web service address for each web service comes first
+ * in that web service's list.
+ *
+ * Web service addresses are guaranteed to be unique per web service, but
+ * not necessarily unique amongst all web services.
+ *
+ * @since UNRELEASED
+ */
+ public abstract Gee.HashMap<string, LinkedHashSet<string>>
+ web_service_addresses
+ {
+ get; set;
+ }
+}