Merge lp:~rodrigo-moya/evolution-couchdb/dont-lose-uuids into lp:evolution-couchdb

Proposed by Rodrigo Moya
Status: Merged
Approved by: Elliot Murphy
Approved revision: 52
Merge reported by: Rodrigo Moya
Merged at revision: not available
Proposed branch: lp:~rodrigo-moya/evolution-couchdb/dont-lose-uuids
Merge into: lp:evolution-couchdb
Diff against target: None lines
To merge this branch: bzr merge lp:~rodrigo-moya/evolution-couchdb/dont-lose-uuids
Reviewer Review Type Date Requested Status
Elliot Murphy (community) Approve
Review via email: mp+10148@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Rodrigo Moya (rodrigo-moya) wrote :

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

Revision history for this message
Elliot Murphy (statik) wrote :

nice!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'addressbook/e-book-backend-couchdb.c'
2--- addressbook/e-book-backend-couchdb.c 2009-08-05 12:09:30 +0000
3+++ addressbook/e-book-backend-couchdb.c 2009-08-14 12:18:22 +0000
4@@ -25,6 +25,9 @@
5 #include <libedata-book/e-data-book-view.h>
6 #include <dbus/dbus-glib.h>
7
8+#define COUCHDB_REVISION_PROP "X-COUCHDB-REVISION"
9+#define COUCHDB_UUID_PROP "X-COUCHDB-UUID"
10+
11 G_DEFINE_TYPE (EBookBackendCouchDB, e_book_backend_couchdb, E_TYPE_BOOK_BACKEND);
12
13 static char *
14@@ -45,20 +48,33 @@
15 e_contact_set (contact, E_CONTACT_FAMILY_NAME,
16 (const gpointer) couchdb_document_contact_get_last_name (document));
17
18+ e_vcard_add_attribute_with_value (E_VCARD (contact),
19+ e_vcard_attribute_new (NULL, COUCHDB_REVISION_PROP),
20+ couchdb_document_get_revision (document));
21+
22 /* parse email addresses */
23 attr_list = NULL;
24
25 list = couchdb_document_contact_get_email_addresses (document);
26 while (list != NULL) {
27- const char *email_str, *description_str;
28+ const char *email_str, *description_str, *uuid_str;
29 EVCardAttribute *attr;
30 CouchDBStructField *email_address = (CouchDBStructField *) list->data;
31
32 email_str = couchdb_document_contact_email_get_address (email_address);
33 description_str = couchdb_document_contact_email_get_description (email_address);
34-
35- attr = e_vcard_attribute_new ("", e_contact_vcard_attribute (E_CONTACT_EMAIL));
36- if (description_str) {
37+ uuid_str = couchdb_struct_field_get_uuid (email_address);
38+
39+ attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_EMAIL));
40+
41+ if (uuid_str != NULL) {
42+ EVCardAttributeParam *param;
43+
44+ param = e_vcard_attribute_param_new (COUCHDB_UUID_PROP);
45+ e_vcard_attribute_add_param_with_value (attr, param, uuid_str);
46+ }
47+
48+ if (description_str != NULL) {
49 EVCardAttributeParam *param;
50
51 param = e_vcard_attribute_param_new (EVC_TYPE);
52@@ -87,18 +103,112 @@
53 /* parse phone numbers */
54 list = couchdb_document_contact_get_phone_numbers (document);
55 while (list != NULL) {
56- const char *phone_str, *description_str;
57+ const char *phone_str, *description_str, *uuid_str;
58+ EVCardAttribute *attr;
59 CouchDBStructField *phone_number = (CouchDBStructField *) list->data;
60
61 phone_str = couchdb_document_contact_phone_get_number (phone_number);
62 description_str = couchdb_document_contact_phone_get_description (phone_number);
63-
64- if (!g_ascii_strcasecmp (description_str, "home"))
65- e_contact_set (contact, E_CONTACT_PHONE_HOME, (const gpointer) phone_str);
66- else if (!g_ascii_strcasecmp (description_str, "work"))
67- e_contact_set (contact, E_CONTACT_PHONE_BUSINESS, (const gpointer) phone_str);
68- else
69- e_contact_set (contact, E_CONTACT_PHONE_OTHER, (const gpointer) phone_str);
70+ uuid_str = couchdb_struct_field_get_uuid (phone_number);
71+
72+ if (description_str != NULL) {
73+ if (!g_ascii_strcasecmp (description_str, "home"))
74+ attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_PHONE_HOME));
75+ else if (!g_ascii_strcasecmp (description_str, "work"))
76+ attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_PHONE_BUSINESS));
77+ else
78+ attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_PHONE_OTHER));
79+ } else
80+ attr = e_vcard_attribute_new (NULL, e_contact_vcard_attribute (E_CONTACT_PHONE_OTHER));
81+
82+ if (uuid_str != NULL) {
83+ EVCardAttributeParam *param;
84+
85+ param = e_vcard_attribute_param_new (COUCHDB_UUID_PROP);
86+ e_vcard_attribute_add_param_with_value (attr, param, uuid_str);
87+ }
88+
89+ if (description_str) {
90+ if (!g_ascii_strcasecmp (description_str, "home")) {
91+ e_vcard_attribute_add_param_with_value (attr,
92+ e_vcard_attribute_param_new (EVC_TYPE),
93+ "HOME");
94+ e_vcard_attribute_add_param_with_value (attr,
95+ e_vcard_attribute_param_new (EVC_TYPE),
96+ "VOICE");
97+ } else if (!g_ascii_strcasecmp (description_str, "work")) {
98+ e_vcard_attribute_add_param_with_value (attr,
99+ e_vcard_attribute_param_new (EVC_TYPE),
100+ "WORK");
101+ e_vcard_attribute_add_param_with_value (attr,
102+ e_vcard_attribute_param_new (EVC_TYPE),
103+ "VOICE");
104+ } else if (!g_ascii_strcasecmp (description_str, "home fax")) {
105+ e_vcard_attribute_add_param_with_value (attr,
106+ e_vcard_attribute_param_new (EVC_TYPE),
107+ "HOME");
108+ e_vcard_attribute_add_param_with_value (attr,
109+ e_vcard_attribute_param_new (EVC_TYPE),
110+ "FAX");
111+ } else if (!g_ascii_strcasecmp (description_str, "work fax")) {
112+ e_vcard_attribute_add_param_with_value (attr,
113+ e_vcard_attribute_param_new (EVC_TYPE),
114+ "WORK");
115+ e_vcard_attribute_add_param_with_value (attr,
116+ e_vcard_attribute_param_new (EVC_TYPE),
117+ "FAX");
118+ } else if (!g_ascii_strcasecmp (description_str, "other fax")) {
119+ e_vcard_attribute_add_param_with_value (attr,
120+ e_vcard_attribute_param_new (EVC_TYPE),
121+ "FAX");
122+ } else if (!g_ascii_strcasecmp (description_str, "pager")) {
123+ e_vcard_attribute_add_param_with_value (attr,
124+ e_vcard_attribute_param_new (EVC_TYPE),
125+ "PAGER");
126+ } else if (!g_ascii_strcasecmp (description_str, "mobile")) {
127+ e_vcard_attribute_add_param_with_value (attr,
128+ e_vcard_attribute_param_new (EVC_TYPE),
129+ "CELL");
130+ } else if (!g_ascii_strcasecmp (description_str, "assistant")) {
131+ e_vcard_attribute_add_param_with_value (attr,
132+ e_vcard_attribute_param_new (EVC_TYPE),
133+ EVC_X_ASSISTANT);
134+ } else if (!g_ascii_strcasecmp (description_str, "callback")) {
135+ e_vcard_attribute_add_param_with_value (attr,
136+ e_vcard_attribute_param_new (EVC_TYPE),
137+ EVC_X_CALLBACK);
138+ } else if (!g_ascii_strcasecmp (description_str, "car")) {
139+ e_vcard_attribute_add_param_with_value (attr,
140+ e_vcard_attribute_param_new (EVC_TYPE),
141+ "CAR");
142+ } else if (!g_ascii_strcasecmp (description_str, "primary")) {
143+ e_vcard_attribute_add_param_with_value (attr,
144+ e_vcard_attribute_param_new (EVC_TYPE),
145+ "PREF");
146+ } else if (!g_ascii_strcasecmp (description_str, "radio")) {
147+ e_vcard_attribute_add_param_with_value (attr,
148+ e_vcard_attribute_param_new (EVC_TYPE),
149+ EVC_X_RADIO);
150+ } else if (!g_ascii_strcasecmp (description_str, "telex")) {
151+ e_vcard_attribute_add_param_with_value (attr,
152+ e_vcard_attribute_param_new (EVC_TYPE),
153+ EVC_X_TELEX);
154+ } else if (!g_ascii_strcasecmp (description_str, "company")) {
155+ e_vcard_attribute_add_param_with_value (attr,
156+ e_vcard_attribute_param_new (EVC_TYPE),
157+ EVC_X_COMPANY);
158+ } else {
159+ //e_vcard_attribute_add_param_with_value (attr,
160+ // e_vcard_attribute_param_new (EVC_TYPE),
161+ // "OTHER");
162+ e_vcard_attribute_add_param_with_value (attr,
163+ e_vcard_attribute_param_new (EVC_TYPE),
164+ "VOICE");
165+ }
166+ }
167+
168+ e_vcard_attribute_add_value (attr, phone_str);
169+ e_vcard_add_attribute (E_VCARD (contact), attr);
170
171 /* remove phones from list */
172 list = g_slist_remove (list, phone_number);
173@@ -156,6 +266,117 @@
174 return str;
175 }
176
177+static CouchDBStructField *
178+contact_email_to_struct_field (EVCardAttribute *attr)
179+{
180+ const gchar *email;
181+ GList *params, *pl;
182+ const gchar *description = NULL, *uuid = NULL;
183+
184+ email = e_vcard_attribute_get_value (attr);
185+ if (email == NULL)
186+ return NULL;
187+
188+ params = e_vcard_attribute_get_params (attr);
189+ if (!params)
190+ return couchdb_document_contact_email_new (NULL, email, NULL);
191+
192+ for (pl = params; pl != NULL; pl = pl->next) {
193+ GList *v;
194+ EVCardAttributeParam *p = pl->data;
195+
196+ if (!g_strcmp0 (EVC_TYPE, e_vcard_attribute_param_get_name (p)) != 0) {
197+ v = e_vcard_attribute_param_get_values (p);
198+ while (v && v->data) {
199+ if (g_ascii_strcasecmp ((const gchar *) v->data, "HOME") == 0) {
200+ description = "home";
201+ break;
202+ } else if (g_ascii_strcasecmp ((const gchar *) v->data, "WORK") == 0) {
203+ description = "work";
204+ break;
205+ }
206+
207+ v = v->next;
208+ }
209+ } else if (!g_strcmp0 (COUCHDB_UUID_PROP, e_vcard_attribute_param_get_name (p)) != 0) {
210+ v = e_vcard_attribute_param_get_values (p);
211+ uuid = (const gchar *) v->data;
212+ }
213+ }
214+
215+ return couchdb_document_contact_email_new (uuid, email, description);
216+}
217+
218+static CouchDBStructField *
219+contact_phone_to_struct_field (EVCardAttribute *attr)
220+{
221+ const gchar *phone;
222+ GList *params, *pl;
223+ CouchDBStructField *sf;
224+ gchar *final_description = NULL;
225+ const gchar *description = NULL, *uuid = NULL, *kind = NULL;
226+
227+ phone = e_vcard_attribute_get_value (attr);
228+ if (!phone)
229+ return NULL;
230+
231+ params = e_vcard_attribute_get_params (attr);
232+ if (!params)
233+ return couchdb_document_contact_phone_new (NULL, phone, NULL, /* FIXME */ 0);
234+
235+ for (pl = params; pl != NULL; pl = pl->next) {
236+ GList *v;
237+ EVCardAttributeParam *p = pl->data;
238+
239+ if (!g_strcmp0 (EVC_TYPE, e_vcard_attribute_param_get_name (p)) != 0) {
240+ v = e_vcard_attribute_param_get_values (p);
241+ while (v && v->data) {
242+ if (g_ascii_strcasecmp ((const gchar *) v->data, "HOME") == 0)
243+ description = "home";
244+ else if (g_ascii_strcasecmp ((const gchar *) v->data, "WORK") == 0)
245+ description = "work";
246+ else if (g_ascii_strcasecmp ((const gchar *) v->data, "OTHER") == 0)
247+ description = "other";
248+ else if (g_ascii_strcasecmp ((const gchar *) v->data, "PAGER") == 0)
249+ description = "pager";
250+ else if (g_ascii_strcasecmp ((const gchar *) v->data, "CELL") == 0)
251+ description = "mobile";
252+ else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_ASSISTANT) == 0)
253+ description = "assistant";
254+ else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_CALLBACK) == 0)
255+ description = "callback";
256+ else if (g_ascii_strcasecmp ((const gchar *) v->data, "CAR") == 0)
257+ description = "car";
258+ else if (g_ascii_strcasecmp ((const gchar *) v->data, "PREF") == 0)
259+ description = "primary";
260+ else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_RADIO) == 0)
261+ description = "radio";
262+ else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_TELEX) == 0)
263+ description = "telex";
264+ else if (g_ascii_strcasecmp ((const gchar *) v->data, EVC_X_COMPANY) == 0)
265+ description = "company";
266+ else if (g_ascii_strcasecmp ((const gchar *) v->data, "FAX") == 0)
267+ kind = "fax";
268+
269+ v = v->next;
270+ }
271+ } else if (!g_strcmp0 (COUCHDB_UUID_PROP, e_vcard_attribute_param_get_name (p)) != 0) {
272+ v = e_vcard_attribute_param_get_values (p);
273+ uuid = (const gchar *) v->data;
274+ }
275+ }
276+
277+ if (kind == NULL)
278+ final_description = g_strdup (description);
279+ else
280+ final_description = g_strdup_printf ("%s %s", description, kind);
281+
282+ sf = couchdb_document_contact_phone_new (uuid, phone, final_description, /* FIXME */ 0);
283+ g_free (final_description);
284+
285+ return sf;
286+}
287+
288 static CouchDBDocument *
289 couch_document_from_contact (EBookBackendCouchDB *couchdb_backend, EContact *contact)
290 {
291@@ -164,6 +385,7 @@
292 GList *attr_list, *al;
293 const char *str;
294 CouchDBDocument *document;
295+ gint i;
296 const EContactAddress *contact_address;
297
298 /* create the CouchDBDocument to put on the database */
299@@ -173,6 +395,10 @@
300 if (str)
301 couchdb_document_set_id (document, str);
302
303+ str = e_vcard_attribute_get_value (e_vcard_get_attribute (E_VCARD (contact), COUCHDB_REVISION_PROP));
304+ if (str)
305+ couchdb_document_set_revision (document, str);
306+
307 couchdb_document_contact_set_first_name (document, (const char *) e_contact_get_const (contact, E_CONTACT_GIVEN_NAME));
308 couchdb_document_contact_set_last_name (document, (const char *) e_contact_get_const (contact, E_CONTACT_FAMILY_NAME));
309
310@@ -180,44 +406,12 @@
311 list = NULL;
312 attr_list = e_contact_get_attributes (contact, E_CONTACT_EMAIL);
313 for (al = attr_list; al != NULL; al = al->next) {
314- const gchar *email;
315+ CouchDBStructField *sf;
316 EVCardAttribute *attr = (EVCardAttribute *) al->data;
317
318- email = e_vcard_attribute_get_value (attr);
319- if (email) {
320- CouchDBStructField *sf;
321- GList *params;
322- const gchar *description = NULL;
323-
324- params = e_vcard_attribute_get_params (attr);
325- if (params) {
326- GList *pl;
327-
328- for (pl = params; pl != NULL; pl = pl->next) {
329- GList *v;
330- EVCardAttributeParam *p = pl->data;
331-
332- if (g_strcmp0 (EVC_TYPE, e_vcard_attribute_param_get_name (p)) != 0)
333- continue;
334-
335- v = e_vcard_attribute_param_get_values (p);
336- while (v && v->data) {
337- if (g_ascii_strcasecmp ((const gchar *) v->data, "HOME") == 0) {
338- description = "home";
339- break;
340- } else if (g_ascii_strcasecmp ((const gchar *) v->data, "WORK") == 0) {
341- description = "work";
342- break;
343- }
344-
345- v = v->next;
346- }
347- }
348- }
349-
350- sf = couchdb_document_contact_email_new (/* FIXME */ NULL, email, description);
351+ sf = contact_email_to_struct_field (attr);
352+ if (sf)
353 list = g_slist_append (list, sf);
354- }
355 }
356
357 if (list) {
358@@ -229,28 +423,16 @@
359
360 /* phone numbers */
361 list = NULL;
362- str = e_contact_get_const (contact, E_CONTACT_PHONE_HOME);
363- if (str) {
364- CouchDBStructField *sf;
365-
366- sf = couchdb_document_contact_phone_new (/* FIXME */ NULL, str, "home", /* FIXME */ 0);
367- list = g_slist_append (list, sf);
368- }
369-
370- str = e_contact_get_const (contact, E_CONTACT_PHONE_BUSINESS);
371- if (str) {
372- CouchDBStructField *sf;
373-
374- sf = couchdb_document_contact_phone_new (/* FIXME */ NULL, str, "work", /* FIXME */ 0);
375- list = g_slist_append (list, sf);
376- }
377-
378- str = e_contact_get_const (contact, E_CONTACT_PHONE_OTHER);
379- if (str) {
380- CouchDBStructField *sf;
381-
382- sf = couchdb_document_contact_phone_new (/* FIXME */ NULL, str, "other", /* FIXME */ 0);
383- list = g_slist_append (list, sf);
384+ attr_list = e_vcard_get_attributes (E_VCARD (contact));
385+ for (al = attr_list; al != NULL; al = al->next) {
386+ CouchDBStructField *sf;
387+ EVCardAttribute *attr = (EVCardAttribute *) al->data;
388+
389+ if (g_strcmp0 (e_vcard_attribute_get_name (attr), EVC_TEL) == 0) {
390+ sf = contact_phone_to_struct_field (attr);
391+ if (sf)
392+ list = g_slist_append (list, sf);
393+ }
394 }
395
396 if (list) {
397@@ -374,6 +556,7 @@
398
399 /* Free memory */
400 g_object_unref (G_OBJECT (proxy));
401+ dbus_g_connection_unref (bus);
402
403 if (success)
404 uri = g_strdup_printf ("http://localhost:%d", port);
405@@ -457,8 +640,17 @@
406
407 /* save the contact into the DB */
408 if (couchdb_document_put (document, couchdb_backend->dbname, &error)) {
409- e_contact_set (contact, E_CONTACT_UID, (const gpointer) couchdb_document_get_id (document));
410- e_data_book_respond_create (book, opid, GNOME_Evolution_Addressbook_Success, contact);
411+ EContact *new_contact;
412+ char *vcard_str;
413+
414+ /* couchdb_document_put sets the ID for new documents, so need to send that back */
415+ vcard_str = vcard_from_couch_document (document);
416+ new_contact = e_contact_new_from_vcard (vcard_str);
417+
418+ e_data_book_respond_create (book, opid, GNOME_Evolution_Addressbook_Success, new_contact);
419+
420+ g_free (vcard_str);
421+ g_object_unref (new_contact);
422 } else
423 e_data_book_respond_create (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
424
425@@ -693,18 +885,36 @@
426 GList *fields = NULL;
427 gint i;
428
429- /* we support everything */
430+ /* Basic fields */
431 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_UID)));
432 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_GIVEN_NAME)));
433 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_FAMILY_NAME)));
434 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_FULL_NAME)));
435+
436+ /* Email addresses */
437 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_1)));
438 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_2)));
439 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_3)));
440 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_4)));
441+
442+ /* Phone numbers */
443 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_HOME)));
444+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_HOME_FAX)));
445 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_BUSINESS)));
446+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_BUSINESS_FAX)));
447 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_OTHER)));
448+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_OTHER_FAX)));
449+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_PAGER)));
450+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_MOBILE)));
451+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_ASSISTANT)));
452+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_CALLBACK)));
453+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_CAR)));
454+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_PRIMARY)));
455+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_RADIO)));
456+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_TELEX)));
457+ fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_COMPANY)));
458+
459+ /* Postal addresses */
460 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_ADDRESS_HOME)));
461 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_ADDRESS_WORK)));
462 fields = g_list_append (fields, g_strdup (e_contact_field_name (E_CONTACT_ADDRESS_OTHER)));

Subscribers

People subscribed via source and target branches