[folks/wip/arbitrary-field-interface] Add ExtendedInfo interface and implementation in EDS backend
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks/wip/arbitrary-field-interface] Add ExtendedInfo interface and implementation in EDS backend
- Date: Wed, 17 Dec 2014 11:57:05 +0000 (UTC)
commit 6223e5c7781ab9f6bb1c8cba5354563c3f3e3850
Author: Rodrigo Moya <rodrigo gnome-db org>
Date: Wed Jul 3 12:57:25 2013 +0200
Add ExtendedInfo interface and implementation in EDS backend
Implement ExtendedInfo in Individual
Add ExtendedInfo interface EDS test
https://bugzilla.gnome.org/show_bug.cgi?id=641211
backends/eds/lib/edsf-persona-store.vala | 48 +++++++++++
backends/eds/lib/edsf-persona.vala | 22 +++++
folks/Makefile.am | 1 +
folks/extended-info.vala | 114 ++++++++++++++++++++++++++
folks/individual.vala | 77 +++++++++++++++++
folks/persona-store.vala | 10 ++-
po/POTFILES.in | 1 +
po/POTFILES.skip | 1 +
tests/eds/Makefile.am | 5 +
tests/eds/extended-info.vala | 131 ++++++++++++++++++++++++++++++
10 files changed, 409 insertions(+), 1 deletions(-)
---
diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
index 9f9a400..c439b1c 100644
--- a/backends/eds/lib/edsf-persona-store.vala
+++ b/backends/eds/lib/edsf-persona-store.vala
@@ -888,6 +888,9 @@ public class Edsf.PersonaStore : Folks.PersonaStore
}
}
+ /* Add extended_info field */
+ prop_set.add ((!) Folks.PersonaStore.detail_key (PersonaDetail.EXTENDED_INFO));
+
/* Convert the property set to an array. We can't use .to_array()
* here because it fails to null-terminate the array. Sigh. */
this._always_writeable_properties = new string[prop_set.size];
@@ -1597,6 +1600,51 @@ public class Edsf.PersonaStore : Folks.PersonaStore
yield this._commit_modified_property (persona, "email-addresses");
}
+ internal ExtendedFieldDetails? _get_extended_field (Edsf.Persona persona, string name)
+ {
+ unowned VCardAttribute? attr = persona.contact.get_attribute (name);
+ if (attr != null)
+ {
+ ExtendedFieldDetails details = new ExtendedFieldDetails (attr.get_value (), null);
+
+ foreach (unowned E.VCardAttributeParam param in attr.get_params ())
+ {
+ string param_name = param.get_name ();
+ foreach (unowned string param_value in param.get_values ())
+ {
+ details.add_parameter (param_name, param_value);
+ }
+ }
+
+ return details;
+ }
+
+ return null;
+ }
+
+ internal async void _change_extended_field (Edsf.Persona persona,
+ string name, ExtendedFieldDetails details) throws PropertyError
+ {
+ var vcard = (E.VCard) persona.contact;
+ unowned E.VCardAttribute? prev_attr = vcard.get_attribute (name);
+
+ if (prev_attr != null)
+ persona.contact.remove_attribute (prev_attr);
+
+ E.VCardAttribute new_attr = new E.VCardAttribute ("", name);
+ new_attr.add_value (details.value);
+
+ persona.contact.add_attribute (new_attr);
+
+ try
+ {
+ yield ((!) this._addressbook).modify_contact (persona.contact, null);
+ }
+ catch (GLib.Error e)
+ {
+ }
+ }
+
internal async void _set_phones (Edsf.Persona persona,
Set<PhoneFieldDetails> phones) throws PropertyError
{
diff --git a/backends/eds/lib/edsf-persona.vala b/backends/eds/lib/edsf-persona.vala
index 4a8d505..ef7266a 100644
--- a/backends/eds/lib/edsf-persona.vala
+++ b/backends/eds/lib/edsf-persona.vala
@@ -40,6 +40,7 @@ public class Edsf.Persona : Folks.Persona,
AvatarDetails,
BirthdayDetails,
EmailDetails,
+ ExtendedInfo,
FavouriteDetails,
GenderDetails,
GroupDetails,
@@ -362,6 +363,27 @@ public class Edsf.Persona : Folks.Persona,
email_addresses);
}
+ /**
+ * { inheritDoc}
+ *
+ * @since UNRELEASED
+ */
+ public ExtendedFieldDetails? get_extended_field (string name)
+ {
+ return ((Edsf.PersonaStore) this.store)._get_extended_field (this, name);
+ }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since UNRELEASED
+ */
+ public async void change_extended_field (
+ string name, ExtendedFieldDetails value) throws PropertyError
+ {
+ yield ((Edsf.PersonaStore) this.store)._change_extended_field (this, name, value);
+ }
+
private SmallSet<NoteFieldDetails>? _notes = null;
private Set<NoteFieldDetails>? _notes_ro = null;
diff --git a/folks/Makefile.am b/folks/Makefile.am
index a4af6aa..cfcc200 100644
--- a/folks/Makefile.am
+++ b/folks/Makefile.am
@@ -77,6 +77,7 @@ libfolks_la_SOURCES = \
backend-store.vala \
birthday-details.vala \
email-details.vala \
+ extended-info.vala \
favourite-details.vala \
folks-namespace.vala \
gender-details.vala \
diff --git a/folks/extended-info.vala b/folks/extended-info.vala
new file mode 100644
index 0000000..4652c48
--- /dev/null
+++ b/folks/extended-info.vala
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013 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:
+ * Rodrigo Moya <rodrigo gnome org>
+ */
+
+using GLib;
+using Gee;
+
+/**
+ * Object representing an arbitrary field that can have some parameters
+ * associated with it.
+ *
+ * See { link Folks.AbstractFieldDetails} for details on common parameter names
+ * and values.
+ *
+ * @since UNRELEASED
+ */
+public class Folks.ExtendedFieldDetails : AbstractFieldDetails<string>
+{
+ /**
+ * Create a new ExtendedFieldDetails.
+ *
+ * @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 ExtendedFieldDetails
+ *
+ * @since UNRELEASED
+ */
+ public ExtendedFieldDetails (string value,
+ MultiMap<string, string>? parameters = null)
+ {
+ if (value == "")
+ {
+ warning ("Empty value passed to ExtendedFieldDetails.");
+ }
+
+ this.value = value;
+ if (parameters != null)
+ this.parameters = (!) parameters;
+ }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.6.0
+ */
+ public override bool equal (AbstractFieldDetails<string> that)
+ {
+ return base.equal (that);
+ }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since 0.6.0
+ */
+ public override uint hash ()
+ {
+ return base.hash ();
+ }
+}
+
+/**
+ * Arbitrary field interface.
+ *
+ * This interface allows clients to store arbitrary fields for contacts in backends
+ * that support it.
+ *
+ * @since UNRELEASED
+ */
+public interface Folks.ExtendedInfo : Object
+{
+ /**
+ * Retrieve the value for an arbitrary field.
+ *
+ * @since UNRELEASED
+ */
+ public abstract ExtendedFieldDetails? get_extended_field (string name);
+
+ /**
+ * Change the value of an arbitrary field.
+ *
+ * @param name name of the arbitrary field to change value
+ * @param value new value for the arbitrary field
+ * @throws PropertyError if setting the value failed
+ *
+ * @since UNRELEASED
+ */
+ public virtual async void change_extended_field (
+ string name, ExtendedFieldDetails value) throws PropertyError
+ {
+ /* Default implementation */
+ throw new PropertyError.NOT_WRITEABLE (
+ _("Extended fields are not writeable on this contact."));
+ }
+}
diff --git a/folks/individual.vala b/folks/individual.vala
index d090cbd..a35c742 100644
--- a/folks/individual.vala
+++ b/folks/individual.vala
@@ -86,6 +86,7 @@ public class Folks.Individual : Object,
AvatarDetails,
BirthdayDetails,
EmailDetails,
+ ExtendedInfo,
FavouriteDetails,
GenderDetails,
GroupDetails,
@@ -984,6 +985,82 @@ public class Folks.Individual : Object,
}
/**
+ * { inheritDoc}
+ *
+ * @since UNRELEASED
+ */
+ public ExtendedFieldDetails? get_extended_field (string name)
+ {
+ debug ("Getting extended field '%s' on '%s'ā¦", name, this.id);
+
+ /* Try to get it from the writeable Personas which have "extended-info"
+ * as a writeable property. */
+ foreach (var p in this._persona_set)
+ {
+ if ("extended-info" in p.writeable_properties)
+ {
+ var e = p as ExtendedInfo;
+ return e.get_extended_field (name);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * { inheritDoc}
+ *
+ * @since UNRELEASED
+ */
+ public async void change_extended_field (
+ string name, ExtendedFieldDetails value) throws PropertyError
+ {
+ debug ("Setting extended field '%s' on '%s'ā¦", name, this.id);
+
+ PropertyError? persona_error = null;
+ var prop_changed = false;
+
+ /* Try to write it to only the writeable Personas which have "extended-info"
+ * as a writeable property. */
+ foreach (var p in this._persona_set)
+ {
+ if ("extended-info" in p.writeable_properties)
+ {
+ var e = p as ExtendedInfo;
+ try
+ {
+ yield e.change_extended_field (name, value);
+ debug (" written to writeable persona '%s'", p.uid);
+ prop_changed = true;
+ }
+ catch (PropertyError e)
+ {
+ /* Store the first error so we can throw it if setting the
+ * nickname fails on every other persona. */
+ if (persona_error == null)
+ {
+ persona_error = e;
+ }
+ }
+ }
+ }
+
+ /* Failure? Changing the property failed on every suitable persona found
+ * (and potentially zero suitable personas were found). */
+ if (prop_changed == false)
+ {
+ if (persona_error == null)
+ {
+ persona_error = new PropertyError.NOT_WRITEABLE (
+ _("Failed to change property ā%sā: No suitable personas were found."),
+ "extended_info");
+ }
+
+ throw persona_error;
+ }
+ }
+
+ /**
* The set of { link Persona}s encapsulated by this Individual.
*
* There must always be at least one Persona in this set.
diff --git a/folks/persona-store.vala b/folks/persona-store.vala
index 400e3d7..bf437f1 100644
--- a/folks/persona-store.vala
+++ b/folks/persona-store.vala
@@ -312,6 +312,13 @@ public enum Folks.PersonaDetail
* @since 0.7.3
*/
ANTI_LINKS,
+
+ /**
+ * Field for { link ExtendedFieldDetails}.
+ *
+ * @since UNRELEASED
+ */
+ EXTENDED_INFO,
}
/**
@@ -372,7 +379,8 @@ public abstract class Folks.PersonaStore : Object
"last-im-interaction-datetime",
"call-interaction-count",
"last-call-interaction-datetime",
- "anti-links"
+ "anti-links",
+ "extended-info"
};
/**
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 8d8e71a..17ab450 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -17,6 +17,7 @@ folks/avatar-details.vala
folks/backend-store.vala
folks/birthday-details.vala
folks/email-details.vala
+folks/extended-info.vala
folks/favourite-details.vala
folks/gender-details.vala
folks/group-details.vala
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index d7a74b0..cb7fa2a 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -16,6 +16,7 @@ folks/avatar-details.c
folks/backend-store.c
folks/birthday-details.c
folks/email-details.c
+folks/extended-info.c
folks/favourite-details.c
folks/gender-details.c
folks/group-details.c
diff --git a/tests/eds/Makefile.am b/tests/eds/Makefile.am
index 1f2d346..fcafa97 100644
--- a/tests/eds/Makefile.am
+++ b/tests/eds/Makefile.am
@@ -76,6 +76,7 @@ TESTS = \
enable-disable-stores \
set-is-favourite \
perf \
+ extended-info \
$(NULL)
noinst_PROGRAMS = \
@@ -225,6 +226,10 @@ perf_SOURCES = \
perf.vala \
$(NULL)
+extended_info_SOURCES = \
+ extended-info.vala
+ $(NULL)
+
helper_create_many_contacts_SOURCES = \
helper-create-many-contacts.vala \
$(NULL)
diff --git a/tests/eds/extended-info.vala b/tests/eds/extended-info.vala
new file mode 100644
index 0000000..fa3e122
--- /dev/null
+++ b/tests/eds/extended-info.vala
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2013 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: Rodrigo Moya <rodrigo moya collabora co uk>
+ *
+ */
+
+using EdsTest;
+using Folks;
+using Gee;
+
+public class ExtendedInfoTests : EdsTest.TestCase
+{
+ private GLib.MainLoop _main_loop;
+ private IndividualAggregator _aggregator;
+ private string _full_name;
+ private bool _found_field_1;
+ private bool _found_field_2;
+
+ public ExtendedInfoTests ()
+ {
+ base ("ExtendedInfo");
+
+ this.add_test ("extended info interface", this.test_extended_info);
+ }
+
+ public void test_extended_info ()
+ {
+ this._main_loop = new GLib.MainLoop (null, false);
+ this._full_name = "persona #1";
+ Gee.HashMap<string, Value?> c1 = new Gee.HashMap<string, Value?> ();
+ Value? v;
+
+ this.eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string (this._full_name);
+ c1.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string ("X-FIELD-1=value1,X-FIELD-2=value2");
+ c1.set ("extended_info", (owned) v);
+
+ this.eds_backend.add_contact (c1);
+
+ this._found_field_1 = false;
+ this._found_field_2 = false;
+
+ this._test_extended_info_async.begin ();
+
+ TestUtils.loop_run_with_timeout (this._main_loop);
+
+ assert (this._found_field_1 == true);
+ assert (this._found_field_2 == true);
+ }
+
+ private async void _test_extended_info_async ()
+ {
+ yield this.eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed_detailed.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 (
+ MultiMap<Individual?, Individual?> changes)
+ {
+ var added = changes.get_values ();
+ var removed = changes.get_keys ();
+
+ foreach (var i in added)
+ {
+ assert (i != null);
+
+ string full_name = i.full_name;
+ if (full_name == this._full_name);
+ {
+ if (i.get_extended_field ("X-FIELD-1") != null)
+ this._found_field_1 = true;
+ if (i.get_extended_field ("X-FIELD-2") != null)
+ this._found_field_2 = true;
+ }
+ }
+
+ assert (removed.size == 1);
+
+ foreach (var i in removed)
+ {
+ assert (i == null);
+ }
+
+ if (this._found_field_1 == true &&
+ this._found_field_2 == true)
+ this._main_loop.quit ();
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ var tests = new ExtendedInfoTests ();
+ tests.register ();
+ Test.run ();
+ tests.final_tear_down ();
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]