[evolution-data-server] google: Add a new custom vCard property containing Google system groups



commit 1cfc48f58873ee448f2bb7853c9d3c0f0f48caab
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sun Jun 24 09:55:46 2012 +0100

    google: Add a new custom vCard property containing Google system groups
    
    This can then be picked up by libfolks (and other interested clients) to
    allow them to detect which system groups a Google contact is in. Previously,
    they had to infer this from the categories the contact was in, which are
    localised. This was tricky and fragile.
    
    Helps: https://bugzilla.gnome.org/show_bug.cgi?id=676383

 .../backends/google/e-book-backend-google.c        |   23 +++++++++++++---
 addressbook/backends/google/e-book-google-utils.c  |   27 ++++++++++++++++++-
 addressbook/backends/google/e-book-google-utils.h  |    3 +-
 3 files changed, 45 insertions(+), 8 deletions(-)
---
diff --git a/addressbook/backends/google/e-book-backend-google.c b/addressbook/backends/google/e-book-backend-google.c
index 8c14f85..ab3a392 100644
--- a/addressbook/backends/google/e-book-backend-google.c
+++ b/addressbook/backends/google/e-book-backend-google.c
@@ -83,6 +83,8 @@ struct _EBookBackendGooglePrivate {
 	GHashTable *groups_by_name;
 	/* Mapping system_group_id to entry ID */
 	GHashTable *system_groups_by_id;
+	/* Mapping entry ID to system_group_id */
+	GHashTable *system_groups_by_entry_id;
 	/* Time when the groups were last queried */
 	GTimeVal last_groups_update;
 
@@ -165,13 +167,13 @@ cache_add_contact (EBookBackend *backend,
 
 	switch (priv->cache_type) {
 	case ON_DISK_CACHE:
-		contact = e_contact_new_from_gdata_entry (entry, priv->groups_by_id);
+		contact = e_contact_new_from_gdata_entry (entry, priv->groups_by_id, priv->system_groups_by_entry_id);
 		e_contact_add_gdata_entry_xml (contact, entry);
 		e_book_backend_cache_add_contact (priv->cache.on_disk, contact);
 		e_contact_remove_gdata_entry_xml (contact);
 		return contact;
 	case IN_MEMORY_CACHE:
-		contact = e_contact_new_from_gdata_entry (entry, priv->groups_by_id);
+		contact = e_contact_new_from_gdata_entry (entry, priv->groups_by_id, priv->system_groups_by_entry_id);
 		uid = e_contact_get_const (contact, E_CONTACT_UID);
 		g_hash_table_insert (priv->cache.in_memory.contacts, g_strdup (uid), g_object_ref (contact));
 		g_hash_table_insert (priv->cache.in_memory.gdata_entries, g_strdup (uid), g_object_ref (entry));
@@ -904,10 +906,19 @@ process_group (GDataEntry *entry,
 	if (system_group_id) {
 		__debug__ ("Processing %ssystem group %s, %s", is_deleted ? "(deleted) " : "", system_group_id, uid);
 
-		if (is_deleted)
+		if (is_deleted) {
+			gchar *entry_id = g_hash_table_lookup (priv->system_groups_by_id, system_group_id);
+			g_hash_table_remove (priv->system_groups_by_entry_id, entry_id);
 			g_hash_table_remove (priv->system_groups_by_id, system_group_id);
-		else
-			g_hash_table_replace (priv->system_groups_by_id, g_strdup (system_group_id), e_contact_sanitise_google_group_id (uid));
+		} else {
+			gchar *entry_id, *system_group_id_dup;
+
+			entry_id = e_contact_sanitise_google_group_id (uid);
+			system_group_id_dup = g_strdup (system_group_id);
+
+			g_hash_table_replace (priv->system_groups_by_entry_id, entry_id, system_group_id_dup);
+			g_hash_table_replace (priv->system_groups_by_id, system_group_id_dup, entry_id);
+		}
 
 		g_free (name);
 
@@ -2208,6 +2219,7 @@ e_book_backend_google_open (EBookBackend *backend,
 		priv->groups_by_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 		priv->groups_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 		priv->system_groups_by_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+		priv->system_groups_by_entry_id = g_hash_table_new (g_str_hash, g_str_equal); /* shares keys and values with system_groups_by_id */
 		priv->cancellables = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
 	}
 
@@ -2512,6 +2524,7 @@ e_book_backend_google_finalize (GObject *object)
 	if (priv->cancellables) {
 		g_hash_table_destroy (priv->groups_by_id);
 		g_hash_table_destroy (priv->groups_by_name);
+		g_hash_table_destroy (priv->system_groups_by_entry_id);
 		g_hash_table_destroy (priv->system_groups_by_id);
 		g_hash_table_destroy (priv->cancellables);
 	}
diff --git a/addressbook/backends/google/e-book-google-utils.c b/addressbook/backends/google/e-book-google-utils.c
index 8d63e66..ce8ab12 100644
--- a/addressbook/backends/google/e-book-google-utils.c
+++ b/addressbook/backends/google/e-book-google-utils.c
@@ -39,6 +39,8 @@
 #define GDATA_URIS_TYPE_PROFILE "X-PROFILE"
 #define GDATA_URIS_TYPE_FTP "X-FTP"
 
+#define GOOGLE_SYSTEM_GROUP_ATTR "X-GOOGLE-SYSTEM-GROUP-IDS"
+
 #define MULTIVALUE_ATTRIBUTE_SUFFIX "-MULTIVALUE"
 
 gboolean __e_book_google_utils_debug__;
@@ -509,10 +511,11 @@ foreach_extended_props_cb (const gchar *name,
 
 EContact *
 e_contact_new_from_gdata_entry (GDataEntry *entry,
-                                GHashTable *groups_by_id)
+                                GHashTable *groups_by_id,
+                                GHashTable *system_groups_by_entry_id)
 {
 	EVCard *vcard;
-	EVCardAttribute *attr;
+	EVCardAttribute *attr, *system_group_ids_attr;
 	EContactPhoto *photo;
 	const gchar *photo_etag;
 	GList *email_addresses, *im_addresses, *phone_numbers, *postal_addresses, *orgs, *category_names, *category_ids;
@@ -536,6 +539,9 @@ e_contact_new_from_gdata_entry (GDataEntry *entry,
 #endif
 #endif
 
+	g_return_val_if_fail (system_groups_by_entry_id != NULL, NULL);
+	g_return_val_if_fail (g_hash_table_size (system_groups_by_entry_id) > 0, FALSE);
+
 	uid = gdata_entry_get_id (entry);
 	if (NULL == uid)
 		return NULL;
@@ -652,8 +658,11 @@ e_contact_new_from_gdata_entry (GDataEntry *entry,
 	/* CATEGORIES */
 	category_ids = gdata_contacts_contact_get_groups (GDATA_CONTACTS_CONTACT (entry));
 	category_names = NULL;
+	system_group_ids_attr = e_vcard_attribute_new ("", GOOGLE_SYSTEM_GROUP_ATTR);
+
 	for (itr = category_ids; itr != NULL; itr = g_list_delete_link (itr, itr)) {
 		gchar *category_id, *category_name;
+		const gchar *system_group_id;
 
 		category_id = e_contact_sanitise_google_group_id (itr->data);
 		category_name = g_hash_table_lookup (groups_by_id, category_id);
@@ -664,12 +673,26 @@ e_contact_new_from_gdata_entry (GDataEntry *entry,
 		} else
 			g_warning ("Couldn't find name for category with ID '%s'.", category_id);
 
+		/* Maintain a list of the IDs of the system groups the contact is in. */
+		system_group_id = g_hash_table_lookup (system_groups_by_entry_id, category_id);
+		if (system_group_id != NULL) {
+			e_vcard_attribute_add_value (system_group_ids_attr, system_group_id);
+		}
+
 		g_free (category_id);
 	}
 
 	e_contact_set (E_CONTACT (vcard), E_CONTACT_CATEGORY_LIST, category_names);
 	g_list_free (category_names);
 
+	/* Expose the IDs of the system groups the contact is in so that libfolks (and other clients) can use the information
+	 * without having to reverse-engineer it from the (localised) category names on the contact. */
+	if (e_vcard_attribute_get_values (system_group_ids_attr) != NULL) {
+		e_vcard_add_attribute (vcard, system_group_ids_attr);
+	} else {
+		e_vcard_attribute_free (system_group_ids_attr);
+	}
+
 	/* Extended properties */
 	extended_props = gdata_contacts_contact_get_extended_properties (GDATA_CONTACTS_CONTACT (entry));
 	g_hash_table_foreach (extended_props, (GHFunc) foreach_extended_props_cb, vcard);
diff --git a/addressbook/backends/google/e-book-google-utils.h b/addressbook/backends/google/e-book-google-utils.h
index 2a758dd..fb0e371 100644
--- a/addressbook/backends/google/e-book-google-utils.h
+++ b/addressbook/backends/google/e-book-google-utils.h
@@ -36,7 +36,8 @@ gboolean gdata_entry_update_from_e_contact (GDataEntry *entry, EContact *contact
                                             GHashTable *system_groups_by_id,
                                             EContactGoogleCreateGroupFunc create_group, gpointer create_group_user_data);
 
-EContact *e_contact_new_from_gdata_entry (GDataEntry *entry, GHashTable *groups_by_id) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+EContact *e_contact_new_from_gdata_entry (GDataEntry *entry, GHashTable *groups_by_id,
+                                          GHashTable *system_groups_by_entry_id) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
 void e_contact_add_gdata_entry_xml (EContact *contact, GDataEntry *entry);
 void e_contact_remove_gdata_entry_xml (EContact *contact);
 const gchar *e_contact_get_gdata_entry_xml (EContact *contact, const gchar **edit_uri);



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