[evolution-couchdb] Don't loose UUIDs when converting to EContact.



commit 5b494812ccf230a841db242f6b721e8051bf42c7
Author: Rodrigo Moya <rodrigo gnome-db org>
Date:   Sat Aug 15 13:08:59 2009 +0200

    Don't loose UUIDs when converting to EContact.
    Store revision of document in EContact, so that updates work.
    Add lots of new phone fields we support now.
    Return the correct EContact when PUTing documents so that Evolution gets the
    document as it is in the database

 addressbook/e-book-backend-couchdb.c |  346 +++++++++++++++++++++++++++-------
 1 files changed, 278 insertions(+), 68 deletions(-)
---
diff --git a/addressbook/e-book-backend-couchdb.c b/addressbook/e-book-backend-couchdb.c
index 0dec23c..76f56db 100644
--- a/addressbook/e-book-backend-couchdb.c
+++ b/addressbook/e-book-backend-couchdb.c
@@ -25,6 +25,9 @@
 #include <libedata-book/e-data-book-view.h>
 #include <dbus/dbus-glib.h>
 
+#define COUCHDB_REVISION_PROP "X-COUCHDB-REVISION"
+#define COUCHDB_UUID_PROP     "X-COUCHDB-UUID"
+
 G_DEFINE_TYPE (EBookBackendCouchDB, e_book_backend_couchdb, E_TYPE_BOOK_BACKEND);
 
 static char *
@@ -45,20 +48,33 @@ vcard_from_couch_document (CouchDBDocument *document)
 	e_contact_set (contact, E_CONTACT_FAMILY_NAME,
 		       (const gpointer) couchdb_document_contact_get_last_name (document));
 
+	e_vcard_add_attribute_with_value (E_VCARD (contact),
+					  e_vcard_attribute_new (NULL, COUCHDB_REVISION_PROP),
+					  couchdb_document_get_revision (document));
+
 	/* parse email addresses */
 	attr_list = NULL;
 
 	list = couchdb_document_contact_get_email_addresses (document);
 	while (list != NULL) {
-		const char *email_str, *description_str;
+		const char *email_str, *description_str, *uuid_str;
 		EVCardAttribute *attr;
 		CouchDBStructField *email_address = (CouchDBStructField *) list->data;
 
 		email_str = couchdb_document_contact_email_get_address (email_address);
 		description_str = couchdb_document_contact_email_get_description (email_address);
+		uuid_str = couchdb_struct_field_get_uuid (email_address);
 
-		attr = e_vcard_attribute_new ("", e_contact_vcard_attribute (E_CONTACT_EMAIL));
-		if (description_str) {
+		attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_EMAIL));
+
+		if (uuid_str != NULL) {
+			EVCardAttributeParam *param;
+
+			param = e_vcard_attribute_param_new (COUCHDB_UUID_PROP);
+			e_vcard_attribute_add_param_with_value (attr, param, uuid_str);
+		}
+
+		if (description_str != NULL) {
 			EVCardAttributeParam *param;
 
 			param = e_vcard_attribute_param_new (EVC_TYPE);
@@ -87,18 +103,112 @@ vcard_from_couch_document (CouchDBDocument *document)
 	/* parse phone numbers */
 	list = couchdb_document_contact_get_phone_numbers (document);
 	while (list != NULL) {
-		const char *phone_str, *description_str;
+		const char *phone_str, *description_str, *uuid_str;
+		EVCardAttribute *attr;
 		CouchDBStructField *phone_number = (CouchDBStructField *) list->data;
 
 		phone_str = couchdb_document_contact_phone_get_number (phone_number);
 		description_str = couchdb_document_contact_phone_get_description (phone_number);
+		uuid_str = couchdb_struct_field_get_uuid (phone_number);
 
-		if (!g_ascii_strcasecmp (description_str, "home"))
-			e_contact_set (contact, E_CONTACT_PHONE_HOME, (const gpointer) phone_str);
-		else if (!g_ascii_strcasecmp (description_str, "work"))
-			e_contact_set (contact, E_CONTACT_PHONE_BUSINESS, (const gpointer) phone_str);
-		else
-			e_contact_set (contact, E_CONTACT_PHONE_OTHER, (const gpointer) phone_str);
+		if (description_str != NULL) {
+			if (!g_ascii_strcasecmp (description_str, "home"))
+				attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_PHONE_HOME));
+			else if (!g_ascii_strcasecmp (description_str, "work"))
+				attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_PHONE_BUSINESS));
+			else
+				attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_PHONE_OTHER));
+		} else
+			attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_PHONE_OTHER));
+
+		if (uuid_str != NULL) {
+			EVCardAttributeParam *param;
+
+			param = e_vcard_attribute_param_new (COUCHDB_UUID_PROP);
+			e_vcard_attribute_add_param_with_value (attr, param, uuid_str);
+		}
+
+		if (description_str) {
+			if (!g_ascii_strcasecmp (description_str, "home")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"HOME");
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"VOICE");
+			} else if (!g_ascii_strcasecmp (description_str, "work")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"WORK");
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"VOICE");
+			} else if (!g_ascii_strcasecmp (description_str, "home fax")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"HOME");
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"FAX");
+			} else if (!g_ascii_strcasecmp (description_str, "work fax")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"WORK");
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"FAX");
+		        } else if (!g_ascii_strcasecmp (description_str, "other fax")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"FAX");
+		        } else if (!g_ascii_strcasecmp (description_str, "pager")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"PAGER");
+			} else if (!g_ascii_strcasecmp (description_str, "mobile")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"CELL");
+                        } else if (!g_ascii_strcasecmp (description_str, "assistant")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									EVC_X_ASSISTANT);
+                        } else if (!g_ascii_strcasecmp (description_str, "callback")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									EVC_X_CALLBACK);
+                        } else if (!g_ascii_strcasecmp (description_str, "car")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"CAR");
+                        } else if (!g_ascii_strcasecmp (description_str, "primary")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"PREF");
+			} else if (!g_ascii_strcasecmp (description_str, "radio")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									EVC_X_RADIO);
+                        } else if (!g_ascii_strcasecmp (description_str, "telex")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									EVC_X_TELEX);
+                        } else if (!g_ascii_strcasecmp (description_str, "company")) {
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									EVC_X_COMPANY);
+			} else {
+				//e_vcard_attribute_add_param_with_value (attr,
+				//					e_vcard_attribute_param_new (EVC_TYPE),
+				//					"OTHER");
+				e_vcard_attribute_add_param_with_value (attr,
+									e_vcard_attribute_param_new (EVC_TYPE),
+									"VOICE");
+			}
+		}
+
+		e_vcard_attribute_add_value (attr, phone_str);
+		e_vcard_add_attribute (E_VCARD (contact), attr);
 
 		/* remove phones from list */
 		list = g_slist_remove (list, phone_number);
@@ -156,6 +266,117 @@ vcard_from_couch_document (CouchDBDocument *document)
 	return str;
 }
 
+static CouchDBStructField *
+contact_email_to_struct_field (EVCardAttribute *attr)
+{
+	const gchar *email;
+	GList *params, *pl;
+	const gchar *description = NULL, *uuid = NULL;
+
+	email = e_vcard_attribute_get_value (attr);
+	if (email == NULL)
+		return NULL;
+
+	params = e_vcard_attribute_get_params (attr);
+	if (!params)
+		return couchdb_document_contact_email_new (NULL, email, NULL);
+
+	for (pl = params; pl != NULL; pl = pl->next) {
+		GList *v;
+		EVCardAttributeParam *p = pl->data;
+
+		if (!g_strcmp0 (EVC_TYPE, e_vcard_attribute_param_get_name (p)) != 0) {
+			v = e_vcard_attribute_param_get_values (p);
+			while (v && v->data) {
+				if (g_ascii_strcasecmp ((const gchar *) v->data, "HOME") == 0) {
+					description = "home";
+					break;
+				} else if (g_ascii_strcasecmp ((const gchar *) v->data, "WORK") == 0) {
+					description = "work";
+					break;
+				}
+
+				v = v->next;
+			}
+		} else if (!g_strcmp0 (COUCHDB_UUID_PROP, e_vcard_attribute_param_get_name (p)) != 0) {
+			v = e_vcard_attribute_param_get_values (p);
+			uuid = (const gchar *) v->data;
+		}
+	}
+
+	return couchdb_document_contact_email_new (uuid, email, description);
+}
+
+static CouchDBStructField *
+contact_phone_to_struct_field (EVCardAttribute *attr)
+{
+	const gchar *phone;
+	GList *params, *pl;
+	CouchDBStructField *sf;
+	gchar *final_description = NULL;
+	const gchar *description = NULL, *uuid = NULL, *kind = NULL;
+
+	phone = e_vcard_attribute_get_value (attr);
+	if (!phone)
+		return NULL;
+
+	params = e_vcard_attribute_get_params (attr);
+	if (!params)
+		return couchdb_document_contact_phone_new (NULL, phone, NULL, /* FIXME */ 0);
+
+	for (pl = params; pl != NULL; pl = pl->next) {
+		GList *v;
+		EVCardAttributeParam *p = pl->data;
+
+		if (!g_strcmp0 (EVC_TYPE, e_vcard_attribute_param_get_name (p)) != 0) {
+			v = e_vcard_attribute_param_get_values (p);
+			while (v && v->data) {
+				if (g_ascii_strcasecmp ((const gchar *) v->data, "HOME") == 0)
+					description = "home";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, "WORK") == 0)
+					description = "work";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, "OTHER") == 0)
+					description = "other";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, "PAGER") == 0)
+					description = "pager";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, "CELL") == 0)
+					description = "mobile";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_ASSISTANT) == 0)
+					description = "assistant";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_CALLBACK) == 0)
+					description = "callback";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, "CAR") == 0)
+					description = "car";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, "PREF") == 0)
+					description = "primary";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_RADIO) == 0)
+					description = "radio";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_TELEX) == 0)
+					description = "telex";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_COMPANY) == 0)
+					description = "company";
+				else if (g_ascii_strcasecmp ((const gchar *) v->data, "FAX") == 0)
+					kind = "fax";
+
+				v = v->next;
+			}
+		} else if (!g_strcmp0 (COUCHDB_UUID_PROP, e_vcard_attribute_param_get_name (p)) != 0) {
+			v = e_vcard_attribute_param_get_values (p);
+			uuid = (const gchar *) v->data;
+		}
+	}
+
+	if (kind == NULL)
+		final_description = g_strdup (description);
+	else
+		final_description = g_strdup_printf ("%s %s", description, kind);
+
+	sf = couchdb_document_contact_phone_new (uuid, phone, final_description, /* FIXME */ 0);
+	g_free (final_description);
+
+	return sf;
+}
+
 static CouchDBDocument *
 couch_document_from_contact (EBookBackendCouchDB *couchdb_backend, EContact *contact)
 {
@@ -164,6 +385,7 @@ couch_document_from_contact (EBookBackendCouchDB *couchdb_backend, EContact *con
 	GList *attr_list, *al;
 	const char *str;
 	CouchDBDocument *document;
+	gint i;
 	const EContactAddress *contact_address;
 
 	/* create the CouchDBDocument to put on the database */
@@ -173,6 +395,10 @@ couch_document_from_contact (EBookBackendCouchDB *couchdb_backend, EContact *con
 	if (str)
 		couchdb_document_set_id (document, str);
 
+	str = e_vcard_attribute_get_value (e_vcard_get_attribute (E_VCARD (contact), COUCHDB_REVISION_PROP));
+	if (str)
+		couchdb_document_set_revision (document, str);
+
 	couchdb_document_contact_set_first_name (document, (const char *) e_contact_get_const (contact, E_CONTACT_GIVEN_NAME));
 	couchdb_document_contact_set_last_name (document, (const char *) e_contact_get_const (contact, E_CONTACT_FAMILY_NAME));
 
@@ -180,44 +406,12 @@ couch_document_from_contact (EBookBackendCouchDB *couchdb_backend, EContact *con
 	list = NULL;
 	attr_list = e_contact_get_attributes (contact, E_CONTACT_EMAIL);
 	for (al = attr_list; al != NULL; al = al->next) {
-		const gchar *email;
+		CouchDBStructField *sf;
 		EVCardAttribute *attr = (EVCardAttribute *) al->data;
 
-		email = e_vcard_attribute_get_value (attr);
-		if (email) {
-			CouchDBStructField *sf;
-			GList *params;
-			const gchar *description = NULL;
-
-			params = e_vcard_attribute_get_params (attr);
-			if (params) {
-				GList *pl;
-
-				for (pl = params; pl != NULL; pl = pl->next) {
-					GList *v;
-					EVCardAttributeParam *p = pl->data;
-
-					if (g_strcmp0 (EVC_TYPE, e_vcard_attribute_param_get_name (p)) != 0)
-						continue;
-
-					v = e_vcard_attribute_param_get_values (p);
-					while (v && v->data) {
-						if (g_ascii_strcasecmp ((const gchar *) v->data, "HOME") == 0) {
-							description = "home";
-							break;
-						} else if (g_ascii_strcasecmp ((const gchar *) v->data, "WORK") == 0) {
-							description = "work";
-							break;
-						}
-
-						v = v->next;
-					}
-				}
-			}
-
-			sf = couchdb_document_contact_email_new (/* FIXME */ NULL, email, description);
+		sf = contact_email_to_struct_field (attr);
+		if (sf)
 			list = g_slist_append (list, sf);
-		}
 	}
 
 	if (list) {
@@ -229,28 +423,16 @@ couch_document_from_contact (EBookBackendCouchDB *couchdb_backend, EContact *con
 
 	/* phone numbers */
 	list = NULL;
-	str = e_contact_get_const (contact, E_CONTACT_PHONE_HOME);
-	if (str) {
-		CouchDBStructField *sf;
-
-		sf = couchdb_document_contact_phone_new (/* FIXME */ NULL, str, "home", /* FIXME */ 0);
-		list = g_slist_append (list, sf);
-	}
-
-	str = e_contact_get_const (contact, E_CONTACT_PHONE_BUSINESS);
-	if (str) {
-		CouchDBStructField *sf;
-
-		sf = couchdb_document_contact_phone_new (/* FIXME */ NULL, str, "work", /* FIXME */ 0);
-		list = g_slist_append (list, sf);
-	}
-
-	str = e_contact_get_const (contact, E_CONTACT_PHONE_OTHER);
-	if (str) {
+	attr_list = e_vcard_get_attributes (E_VCARD (contact));
+	for (al = attr_list; al != NULL; al = al->next) {
 		CouchDBStructField *sf;
+		EVCardAttribute *attr = (EVCardAttribute *) al->data;
 
-		sf = couchdb_document_contact_phone_new (/* FIXME */ NULL, str, "other", /* FIXME */ 0);
-		list = g_slist_append (list, sf);
+		if (g_strcmp0 (e_vcard_attribute_get_name (attr), EVC_TEL) == 0) {
+			sf = contact_phone_to_struct_field (attr);
+			if (sf)
+				list = g_slist_append (list, sf);
+		}
 	}
 
 	if (list) {
@@ -374,6 +556,7 @@ e_book_backend_couchdb_load_source (EBookBackend *backend,
 
 		/* Free memory */
 		g_object_unref (G_OBJECT (proxy));
+		dbus_g_connection_unref (bus);
 
 		if (success)
 			uri = g_strdup_printf ("http://localhost:%d";, port);
@@ -457,8 +640,17 @@ e_book_backend_couchdb_create_contact (EBookBackend *backend,
 
 	/* save the contact into the DB */
 	if (couchdb_document_put (document, couchdb_backend->dbname, &error)) {
-		e_contact_set (contact, E_CONTACT_UID, (const gpointer) couchdb_document_get_id (document));
-		e_data_book_respond_create (book, opid, GNOME_Evolution_Addressbook_Success, contact);
+		EContact *new_contact;
+		char *vcard_str;
+
+		/* couchdb_document_put sets the ID for new documents, so need to send that back */
+		vcard_str = vcard_from_couch_document (document);
+		new_contact = e_contact_new_from_vcard (vcard_str);
+
+		e_data_book_respond_create (book, opid, GNOME_Evolution_Addressbook_Success, new_contact);
+
+		g_free (vcard_str);
+		g_object_unref (new_contact);
 	} else
 		e_data_book_respond_create (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
 
@@ -693,18 +885,36 @@ e_book_backend_couchdb_get_supported_fields (EBookBackend *backend,
 	GList *fields = NULL;
 	gint i;
 
-	/* we support everything */
+	/* Basic fields */
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_UID)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_GIVEN_NAME)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_FAMILY_NAME)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_FULL_NAME)));
+
+	/* Email addresses */
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_1)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_2)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_3)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_4)));
+
+	/* Phone numbers */
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_HOME)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_HOME_FAX)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_BUSINESS)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_BUSINESS_FAX)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_OTHER)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_OTHER_FAX)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_PAGER)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_MOBILE)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_ASSISTANT)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_CALLBACK)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_CAR)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_PRIMARY)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_RADIO)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_TELEX)));
+	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_COMPANY)));
+
+	/* Postal addresses */
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_ADDRESS_HOME)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_ADDRESS_WORK)));
 	fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_ADDRESS_OTHER)));



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