From 663c169ef8a02c2900c56284b21055aa1aa67045 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Wed, 12 Dec 2012 00:09:24 +0100 Subject: [PATCH] libebook: Support phone number specific queries This adds new values to the EBookQueryTest enumeration: * E_BOOK_QUERY_EQUALS_PHONE_NUMBER * E_BOOK_QUERY_EQUALS_NATIONAL_PHONE_NUMBER * E_BOOK_QUERY_EQUALS_SHORT_PHONE_NUMBER This values get translated to the binary sexp functions "eqphone", "eqphone_national" and "eqphone_short". See: https://bugzilla.gnome.org/show_bug.cgi?id=689622 --- addressbook/libebook/e-book-query.c | 71 +++++++++++++++++---- addressbook/libebook/e-book-query.h | 18 +++++- addressbook/libedata-book/e-book-backend-sexp.c | 73 +++++++++++++++++++++- tests/libebook/client/test-client-custom-summary.c | 12 ++++ tests/libebook/data/vcards/custom-1.vcf | 2 +- tests/libebook/test-query.c | 18 ++++++ 6 files changed, 179 insertions(+), 15 deletions(-) diff --git a/addressbook/libebook/e-book-query.c b/addressbook/libebook/e-book-query.c index 1d845c4..7960b71 100644 --- a/addressbook/libebook/e-book-query.c +++ b/addressbook/libebook/e-book-query.c @@ -519,6 +519,33 @@ func_endswith (struct _ESExp *f, } static ESExpResult * +func_eqphone (struct _ESExp *f, + gint argc, + struct _ESExpResult **argv, + gpointer data) +{ + return func_field_test (E_BOOK_QUERY_EQUALS_PHONE_NUMBER, f, argc, argv, data); +} + +static ESExpResult * +func_eqphone_national (struct _ESExp *f, + gint argc, + struct _ESExpResult **argv, + gpointer data) +{ + return func_field_test (E_BOOK_QUERY_EQUALS_NATIONAL_PHONE_NUMBER, f, argc, argv, data); +} + +static ESExpResult * +func_eqphone_short (struct _ESExp *f, + gint argc, + struct _ESExpResult **argv, + gpointer data) +{ + return func_field_test (E_BOOK_QUERY_EQUALS_SHORT_PHONE_NUMBER, f, argc, argv, data); +} + +static ESExpResult * func_exists (struct _ESExp *f, gint argc, struct _ESExpResult **argv, @@ -578,6 +605,9 @@ static const struct { { "is", func_is, 0 }, { "beginswith", func_beginswith, 0 }, { "endswith", func_endswith, 0 }, + { "eqphone", func_eqphone, 0 }, + { "eqphone_national", func_eqphone_national, 0 }, + { "eqphone_short", func_eqphone_short, 0 }, { "exists", func_exists, 0 }, { "exists_vcard", func_exists_vcard, 0 } }; @@ -636,6 +666,29 @@ e_book_query_from_string (const gchar *query_string) return retval; } +static const char * +field_test_name (EBookQueryTest field_test) +{ + switch (field_test) { + case E_BOOK_QUERY_IS: + return "is"; + case E_BOOK_QUERY_CONTAINS: + return "contains"; + case E_BOOK_QUERY_BEGINS_WITH: + return "beginswith"; + case E_BOOK_QUERY_ENDS_WITH: + return "endswith"; + case E_BOOK_QUERY_EQUALS_PHONE_NUMBER: + return "eqphone"; + case E_BOOK_QUERY_EQUALS_NATIONAL_PHONE_NUMBER: + return "eqphone_national"; + case E_BOOK_QUERY_EQUALS_SHORT_PHONE_NUMBER: + return "eqphone_short"; + } + + return NULL; +} + /** * e_book_query_to_string: * @q: an #EBookQuery @@ -652,7 +705,6 @@ e_book_query_to_string (EBookQuery *q) GString *encoded = g_string_new (""); gint i; gchar *s = NULL; - const gchar *cs; switch (q->type) { case E_BOOK_QUERY_TYPE_AND: @@ -686,21 +738,18 @@ e_book_query_to_string (EBookQuery *q) } break; case E_BOOK_QUERY_TYPE_FIELD_TEST: - switch (q->query.field_test.test) { - case E_BOOK_QUERY_IS: cs = "is"; break; - case E_BOOK_QUERY_CONTAINS: cs = "contains"; break; - case E_BOOK_QUERY_BEGINS_WITH: cs = "beginswith"; break; - case E_BOOK_QUERY_ENDS_WITH: cs = "endswith"; break; - default: - g_assert_not_reached (); - break; + s = field_test_name (q->query.field_test.test); + + if (s == NULL) { + g_string_free (str, TRUE); + g_warn_if_reached (); + return NULL; } e_sexp_encode_string (encoded, q->query.field_test.value); g_string_append_printf ( - str, "%s \"%s\" %s", - cs, + str, "%s \"%s\" %s", s, q->query.field_test.field_name, encoded->str); break; diff --git a/addressbook/libebook/e-book-query.h b/addressbook/libebook/e-book-query.h index 59c8987..82342b4 100644 --- a/addressbook/libebook/e-book-query.h +++ b/addressbook/libebook/e-book-query.h @@ -20,14 +20,30 @@ typedef struct EBookQuery EBookQuery; * @E_BOOK_QUERY_CONTAINS: check if a field contains the test value * @E_BOOK_QUERY_BEGINS_WITH: check if a field starts with the test value * @E_BOOK_QUERY_ENDS_WITH: check if a field ends with the test value + * @E_BOOK_QUERY_EQUALS_PHONE_NUMBER: check that a field and the test value + * match exactly when interpreted as phone number, that is after stripping + * formatting like dashes, dots and spaces. See E_PHONE_NUMBER_MATCH_EXACT. + * @E_BOOK_QUERY_EQUALS_NATIONAL_PHONE_NUMBER: check that a field and the + * test value match when interpreted as phone number, except for the + * (omitted) country code. + * @E_BOOK_QUERY_EQUALS_SHORT_PHONE_NUMBER: check that a field and the test + * value match is the sense that both values appear to be phone numbers, + * and one might be a part (suffix) of the other. * * The kind of test a query created by e_book_query_field_test() shall perform. + * + * See also: E_PHONE_NUMBER_MATCH_EXACT, E_PHONE_NUMBER_MATCH_NATIONAL and + * E_PHONE_NUMBER_MATCH_SHORT. **/ typedef enum { E_BOOK_QUERY_IS, E_BOOK_QUERY_CONTAINS, E_BOOK_QUERY_BEGINS_WITH, - E_BOOK_QUERY_ENDS_WITH + E_BOOK_QUERY_ENDS_WITH, + + E_BOOK_QUERY_EQUALS_PHONE_NUMBER, + E_BOOK_QUERY_EQUALS_NATIONAL_PHONE_NUMBER, + E_BOOK_QUERY_EQUALS_SHORT_PHONE_NUMBER /* Consider these "coming soon". diff --git a/addressbook/libedata-book/e-book-backend-sexp.c b/addressbook/libedata-book/e-book-backend-sexp.c index 2789a73..5ef2ffb 100644 --- a/addressbook/libedata-book/e-book-backend-sexp.c +++ b/addressbook/libedata-book/e-book-backend-sexp.c @@ -18,10 +18,10 @@ * 02110-1301, USA. */ -#include - #include "e-book-backend-sexp.h" +#include + #define E_BOOK_BACKEND_SEXP_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_BOOK_BACKEND_SEXP, EBookBackendSExpPrivate)) @@ -745,6 +745,72 @@ func_beginswith (struct _ESExp *f, } static gboolean +eqphone_helper (const gchar *ps1, + const gchar *ps2, + EPhoneNumberMatch required_match) +{ + const EPhoneNumberMatch actual_match = + e_phone_number_compare_strings (ps1, ps2, NULL); + + return actual_match >= E_PHONE_NUMBER_MATCH_EXACT + && actual_match <= required_match; +} + +static gboolean +eqphone_exact_helper (const gchar *ps1, + const gchar *ps2) +{ + return eqphone_helper (ps1, ps2, E_PHONE_NUMBER_MATCH_EXACT); +} + +static gboolean +eqphone_national_helper (const gchar *ps1, + const gchar *ps2) +{ + return eqphone_helper (ps1, ps2, E_PHONE_NUMBER_MATCH_NATIONAL); +} + +static gboolean +eqphone_short_helper (const gchar *ps1, + const gchar *ps2) +{ + return eqphone_helper (ps1, ps2, E_PHONE_NUMBER_MATCH_SHORT); +} + +static ESExpResult * +func_eqphone (struct _ESExp *f, + gint argc, + struct _ESExpResult **argv, + gpointer data) +{ + SearchContext *ctx = data; + + return entry_compare (ctx, f, argc, argv, eqphone_exact_helper); +} + +static ESExpResult * +func_eqphone_national (struct _ESExp *f, + gint argc, + struct _ESExpResult **argv, + gpointer data) +{ + SearchContext *ctx = data; + + return entry_compare (ctx, f, argc, argv, eqphone_national_helper); +} + +static ESExpResult * +func_eqphone_short (struct _ESExp *f, + gint argc, + struct _ESExpResult **argv, + gpointer data) +{ + SearchContext *ctx = data; + + return entry_compare (ctx, f, argc, argv, eqphone_short_helper); +} + +static gboolean exists_helper (const gchar *ps1, const gchar *ps2) { @@ -895,6 +961,9 @@ static struct { { "is", func_is, 0 }, { "beginswith", func_beginswith, 0 }, { "endswith", func_endswith, 0 }, + { "eqphone", func_eqphone, 0 }, + { "eqphone_national", func_eqphone_national, 0 }, + { "eqphone_short", func_eqphone_short, 0 }, { "exists", func_exists, 0 }, { "exists_vcard", func_exists_vcard, 0 }, }; diff --git a/tests/libebook/client/test-client-custom-summary.c b/tests/libebook/client/test-client-custom-summary.c index c7f88f0..654fd5b 100644 --- a/tests/libebook/client/test-client-custom-summary.c +++ b/tests/libebook/client/test-client-custom-summary.c @@ -186,6 +186,18 @@ main (gint argc, "/client/search/suffix/email", search_test, e_book_query_field_test (E_CONTACT_EMAIL, E_BOOK_QUERY_ENDS_WITH, "jackson.com"), 2); + add_client_test ( + "/client/search/eqphone/exact/phone", search_test, + e_book_query_vcard_field_test(EVC_TEL, E_BOOK_QUERY_EQUALS_PHONE_NUMBER, "+1 221.542.3789"), + 1); + add_client_test ( + "/client/search/eqphone/national/phone", search_test, + e_book_query_vcard_field_test(EVC_TEL, E_BOOK_QUERY_EQUALS_NATIONAL_PHONE_NUMBER, "221.542.3789"), + 1); + add_client_test ( + "/client/search/eqphone/short/phone", search_test, + e_book_query_vcard_field_test(EVC_TEL, E_BOOK_QUERY_EQUALS_SHORT_PHONE_NUMBER, "5423789"), + 1); /* Add search tests that fetch uids */ add_client_test ( diff --git a/tests/libebook/data/vcards/custom-1.vcf b/tests/libebook/data/vcards/custom-1.vcf index bc9a23c..6d7241b 100644 --- a/tests/libebook/data/vcards/custom-1.vcf +++ b/tests/libebook/data/vcards/custom-1.vcf @@ -1,5 +1,5 @@ BEGIN:VCARD FN:Micheal Jackson -TEL;HOME:+1234567 +TEL;HOME:+1-221-5423789 EMAIL;TYPE=home,work:micheal@jackson.com END:VCARD diff --git a/tests/libebook/test-query.c b/tests/libebook/test-query.c index cc687c8..f2a155b 100644 --- a/tests/libebook/test-query.c +++ b/tests/libebook/test-query.c @@ -137,5 +137,23 @@ main (gint argc, "5423789"), "(endswith \"phone\" \"5423789\")"); + add_query_test ("/libebook/test-query/sexp/eqphone", + + e_book_query_orv (e_book_query_field_test (E_CONTACT_TEL, + E_BOOK_QUERY_EQUALS_PHONE_NUMBER, + "+1-2215423789"), + e_book_query_field_test (E_CONTACT_TEL, + E_BOOK_QUERY_EQUALS_NATIONAL_PHONE_NUMBER, + "2215423789"), + e_book_query_field_test (E_CONTACT_TEL, + E_BOOK_QUERY_EQUALS_SHORT_PHONE_NUMBER, + "5423789"), + NULL), + + "(or (eqphone \"phone\" \"+1-2215423789\")" + " (eqphone_national \"phone\" \"2215423789\")" + " (eqphone_short \"phone\" \"5423789\")" + " )"); + return g_test_run (); } -- 2.7.4