[libgdata] Build query URIs for GDataCalendarQuery
- From: Philip Withnall <pwithnall src gnome org>
- To: svn-commits-list gnome org
- Subject: [libgdata] Build query URIs for GDataCalendarQuery
- Date: Fri, 24 Apr 2009 02:32:23 -0400 (EDT)
commit 78634a3d84a8f4717e1a5d9d1b5393bb567f0536
Author: Philip Withnall <philip tecnocode co uk>
Date: Fri Apr 24 07:31:14 2009 +0100
Build query URIs for GDataCalendarQuery
GDataCalendarQuery can now put its properties into a query URI, as the
gdata_query_get_query_uri function has been virtualised. A test case for
calendar query URIs has been added.
---
gdata/gdata-query.c | 174 +++++++++++++-----------
gdata/gdata-query.h | 2 +
gdata/services/calendar/gdata-calendar-event.c | 8 +-
gdata/services/calendar/gdata-calendar-query.c | 104 ++++++++++++++-
gdata/tests/calendar.c | 70 ++++++++++
5 files changed, 270 insertions(+), 88 deletions(-)
diff --git a/gdata/gdata-query.c b/gdata/gdata-query.c
index 7cf0090..c85f5f6 100644
--- a/gdata/gdata-query.c
+++ b/gdata/gdata-query.c
@@ -56,6 +56,7 @@ typedef enum {
static void gdata_query_finalize (GObject *object);
static void gdata_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
static void gdata_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
+static void get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started);
struct _GDataQueryPrivate {
guint parameter_mask; /* GDataQueryParam */
@@ -110,6 +111,8 @@ gdata_query_class_init (GDataQueryClass *klass)
gobject_class->get_property = gdata_query_get_property;
gobject_class->finalize = gdata_query_finalize;
+ klass->get_query_uri = get_query_uri;
+
/**
* GDataQuery:q:
*
@@ -405,93 +408,22 @@ gdata_query_set_property (GObject *object, guint property_id, const GValue *valu
}
}
-/**
- * gdata_query_new:
- * @q: a query string
- *
- * Creates a new #GDataQuery with its #GDataQuery:q property set to @q.
- *
- * Return value: a new #GDataQuery
- **/
-GDataQuery *
-gdata_query_new (const gchar *q)
-{
- return g_object_new (GDATA_TYPE_QUERY, "q", q, NULL);
-}
-
-/**
- * gdata_query_new_with_limits:
- * @q: a query string
- * @start_index: a one-based start index for the results
- * @max_results: the maximum number of results to return
- *
- * Creates a new #GDataQuery with its #GDataQuery:q property set to @q, and the limits @start_index and @max_results
- * applied.
- *
- * Return value: a new #GDataQuery
- **/
-GDataQuery *
-gdata_query_new_with_limits (const gchar *q, gint start_index, gint max_results)
-{
- return g_object_new (GDATA_TYPE_QUERY,
- "q", q,
- "start-index", start_index,
- "max-results", max_results,
- NULL);
-}
-
-/**
- * gdata_query_new_for_id:
- * @entry_id: an entry URN ID
- *
- * Creates a new #GDataQuery to query for @entry_id.
- *
- * Return value: a new #GDataQuery
- **/
-GDataQuery *
-gdata_query_new_for_id (const gchar *entry_id)
-{
- return g_object_new (GDATA_TYPE_QUERY, "entry-id", entry_id, NULL);
-}
-
-/**
- * gdata_query_get_query_uri:
- * @self: a #GDataQuery
- * @feed_uri: the feed URI on which to build the query URI
- *
- * Builds a query URI from the given base feed URI, using the properties of the #GDataQuery. This function will take care
- * of all necessary URI escaping, so it should <emphasis>not</emphasis> be done beforehand.
- *
- * The query URI is what functions like gdata_service_query() use to query the online service.
- *
- * Return value: a query URI; free with g_free()
- **/
-gchar *
-gdata_query_get_query_uri (GDataQuery *self, const gchar *feed_uri)
+static void
+get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started)
{
GDataQueryPrivate *priv = self->priv;
- GString *query_uri;
- gboolean params_started = FALSE;
-
- #define APPEND_SEP g_string_append_c (query_uri, (params_started == FALSE) ? '?' : '&'); params_started = TRUE;
- /* Check to see if we're paginating first */
- if (priv->use_next_uri == TRUE)
- return g_strdup (priv->next_uri);
- if (priv->use_previous_uri == TRUE)
- return g_strdup (priv->previous_uri);
+ #define APPEND_SEP g_string_append_c (query_uri, (*params_started == FALSE) ? '?' : '&'); *params_started = TRUE;
/* Check to see if any parameters have been set */
if ((priv->parameter_mask & GDATA_QUERY_PARAM_ALL) == 0)
- return g_strdup (feed_uri);
-
- query_uri = g_string_new (feed_uri);
+ return;
/* If we've been provided with an entry ID, only append that */
if (priv->entry_id != NULL) {
g_string_append_c (query_uri, '/');
g_string_append_uri_escaped (query_uri, priv->entry_id, NULL, TRUE);
- return g_string_free (query_uri, FALSE);
+ return;
}
if (priv->categories != NULL) {
@@ -501,10 +433,7 @@ gdata_query_get_query_uri (GDataQuery *self, const gchar *feed_uri)
/* If that's it, return */
if ((priv->parameter_mask & (GDATA_QUERY_PARAM_ALL ^ GDATA_QUERY_PARAM_ENTRY_ID ^ GDATA_QUERY_PARAM_CATEGORIES)) == 0)
- return g_string_free (query_uri, FALSE);
-
- /* Determine whether the first param has already been appended (e.g. it exists in the feed_uri) */
- params_started = (strstr (feed_uri, "?") != NULL) ? TRUE : FALSE;
+ return;
/* q param */
if (priv->q != NULL) {
@@ -573,6 +502,91 @@ gdata_query_get_query_uri (GDataQuery *self, const gchar *feed_uri)
APPEND_SEP
g_string_append_printf (query_uri, "max-results=%d", priv->max_results);
}
+}
+
+/**
+ * gdata_query_new:
+ * @q: a query string
+ *
+ * Creates a new #GDataQuery with its #GDataQuery:q property set to @q.
+ *
+ * Return value: a new #GDataQuery
+ **/
+GDataQuery *
+gdata_query_new (const gchar *q)
+{
+ return g_object_new (GDATA_TYPE_QUERY, "q", q, NULL);
+}
+
+/**
+ * gdata_query_new_with_limits:
+ * @q: a query string
+ * @start_index: a one-based start index for the results
+ * @max_results: the maximum number of results to return
+ *
+ * Creates a new #GDataQuery with its #GDataQuery:q property set to @q, and the limits @start_index and @max_results
+ * applied.
+ *
+ * Return value: a new #GDataQuery
+ **/
+GDataQuery *
+gdata_query_new_with_limits (const gchar *q, gint start_index, gint max_results)
+{
+ return g_object_new (GDATA_TYPE_QUERY,
+ "q", q,
+ "start-index", start_index,
+ "max-results", max_results,
+ NULL);
+}
+
+/**
+ * gdata_query_new_for_id:
+ * @entry_id: an entry URN ID
+ *
+ * Creates a new #GDataQuery to query for @entry_id.
+ *
+ * Return value: a new #GDataQuery
+ **/
+GDataQuery *
+gdata_query_new_for_id (const gchar *entry_id)
+{
+ return g_object_new (GDATA_TYPE_QUERY, "entry-id", entry_id, NULL);
+}
+
+/**
+ * gdata_query_get_query_uri:
+ * @self: a #GDataQuery
+ * @feed_uri: the feed URI on which to build the query URI
+ *
+ * Builds a query URI from the given base feed URI, using the properties of the #GDataQuery. This function will take care
+ * of all necessary URI escaping, so it should <emphasis>not</emphasis> be done beforehand.
+ *
+ * The query URI is what functions like gdata_service_query() use to query the online service.
+ *
+ * Return value: a query URI; free with g_free()
+ **/
+gchar *
+gdata_query_get_query_uri (GDataQuery *self, const gchar *feed_uri)
+{
+ GDataQueryClass *klass;
+ GString *query_uri;
+ gboolean params_started;
+
+ /* Check to see if we're paginating first */
+ if (self->priv->use_next_uri == TRUE)
+ return g_strdup (self->priv->next_uri);
+ if (self->priv->use_previous_uri == TRUE)
+ return g_strdup (self->priv->previous_uri);
+
+ klass = GDATA_ENTRY_GET_CLASS (self);
+ g_assert (klass->get_query_uri != NULL);
+
+ /* Determine whether the first param has already been appended (e.g. it exists in the feed_uri) */
+ params_started = (strstr (feed_uri, "?") != NULL) ? TRUE : FALSE;
+
+ /* Build the query URI */
+ query_uri = g_string_new (feed_uri);
+ klass->get_query_uri (self, feed_uri, query_uri, ¶ms_started);
return g_string_free (query_uri, FALSE);
}
diff --git a/gdata/gdata-query.h b/gdata/gdata-query.h
index 22f7440..7e45abe 100644
--- a/gdata/gdata-query.h
+++ b/gdata/gdata-query.h
@@ -52,6 +52,8 @@ typedef struct {
typedef struct {
/*< private >*/
GObjectClass parent;
+
+ void (*get_query_uri) (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started);
} GDataQueryClass;
GType gdata_query_get_type (void) G_GNUC_CONST;
diff --git a/gdata/services/calendar/gdata-calendar-event.c b/gdata/services/calendar/gdata-calendar-event.c
index 450a39a..63548f6 100644
--- a/gdata/services/calendar/gdata-calendar-event.c
+++ b/gdata/services/calendar/gdata-calendar-event.c
@@ -58,10 +58,10 @@ struct _GDataCalendarEventPrivate {
guint sequence;
GList *times; /* GDataGDWhen */
GList *reminders;
- gboolean guests_can_modify; /* TODO: Merge these four somehow? */
- gboolean guests_can_invite_others;
- gboolean guests_can_see_guests;
- gboolean anyone_can_add_self;
+ guint guests_can_modify : 1;
+ guint guests_can_invite_others : 1;
+ guint guests_can_see_guests : 1;
+ guint anyone_can_add_self : 1;
GList *people; /* GDataGDWho */
GList *places; /* GDataGDWhere */
};
diff --git a/gdata/services/calendar/gdata-calendar-query.c b/gdata/services/calendar/gdata-calendar-query.c
index 5f69e38..e3ab2a1 100644
--- a/gdata/services/calendar/gdata-calendar-query.c
+++ b/gdata/services/calendar/gdata-calendar-query.c
@@ -38,13 +38,11 @@
#include "gdata-calendar-query.h"
#include "gdata-query.h"
-/* Reference: http://code.google.com/apis/calendar/docs/2.0/reference.html#Parameters */
-
static void gdata_calendar_query_finalize (GObject *object);
static void gdata_calendar_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
static void gdata_calendar_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
+static void get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started);
-/* TODO: Actually override GDataQuery's get_query_uri function to return a URI including all our custom parameters */
struct _GDataCalendarQueryPrivate {
gboolean future_events;
gchar *order_by; /* TODO: enum? #defined values? */
@@ -76,6 +74,7 @@ static void
gdata_calendar_query_class_init (GDataCalendarQueryClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GDataQueryClass *query_class = GDATA_QUERY_CLASS (klass);
g_type_class_add_private (klass, sizeof (GDataCalendarQueryPrivate));
@@ -83,6 +82,8 @@ gdata_calendar_query_class_init (GDataCalendarQueryClass *klass)
gobject_class->get_property = gdata_calendar_query_get_property;
gobject_class->finalize = gdata_calendar_query_finalize;
+ query_class->get_query_uri = get_query_uri;
+
/**
* GDataCalendarQuery:future-events:
*
@@ -296,6 +297,87 @@ gdata_calendar_query_set_property (GObject *object, guint property_id, const GVa
}
}
+static void
+get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started)
+{
+ GDataCalendarQueryPrivate *priv = GDATA_CALENDAR_QUERY (self)->priv;
+
+ #define APPEND_SEP g_string_append_c (query_uri, (*params_started == FALSE) ? '?' : '&'); *params_started = TRUE;
+
+ /* Chain up to the parent class */
+ GDATA_QUERY_CLASS (gdata_calendar_query_parent_class)->get_query_uri (self, feed_uri, query_uri, params_started);
+
+ APPEND_SEP
+ if (priv->future_events == TRUE)
+ g_string_append (query_uri, "futureevents=true");
+ else
+ g_string_append (query_uri, "futureevents=false");
+
+ if (priv->order_by != NULL) {
+ APPEND_SEP
+ g_string_append (query_uri, "orderby=");
+ g_string_append_uri_escaped (query_uri, priv->order_by, NULL, TRUE);
+ }
+
+ if (priv->recurrence_expansion_start.tv_sec != 0 || priv->recurrence_expansion_start.tv_usec != 0) {
+ gchar *recurrence_expansion_start;
+
+ APPEND_SEP
+ g_string_append (query_uri, "recurrence-expansion-start=");
+ recurrence_expansion_start = g_time_val_to_iso8601 (&(priv->recurrence_expansion_start));
+ g_string_append (query_uri, recurrence_expansion_start);
+ g_free (recurrence_expansion_start);
+ }
+
+ if (priv->recurrence_expansion_end.tv_sec != 0 || priv->recurrence_expansion_end.tv_usec != 0) {
+ gchar *recurrence_expansion_end;
+
+ APPEND_SEP
+ g_string_append (query_uri, "recurrence-expansion-end=");
+ recurrence_expansion_end = g_time_val_to_iso8601 (&(priv->recurrence_expansion_end));
+ g_string_append (query_uri, recurrence_expansion_end);
+ g_free (recurrence_expansion_end);
+ }
+
+ APPEND_SEP
+ if (priv->single_events == TRUE)
+ g_string_append (query_uri, "singleevents=true");
+ else
+ g_string_append (query_uri, "singleevents=false");
+
+ if (priv->sort_order != NULL) {
+ APPEND_SEP
+ g_string_append (query_uri, "sortorder=");
+ g_string_append_uri_escaped (query_uri, priv->sort_order, NULL, TRUE);
+ }
+
+ if (priv->start_min.tv_sec != 0 || priv->start_min.tv_usec != 0) {
+ gchar *start_min;
+
+ APPEND_SEP
+ g_string_append (query_uri, "start-min=");
+ start_min = g_time_val_to_iso8601 (&(priv->start_min));
+ g_string_append (query_uri, start_min);
+ g_free (start_min);
+ }
+
+ if (priv->start_max.tv_sec != 0 || priv->start_max.tv_usec != 0) {
+ gchar *start_max;
+
+ APPEND_SEP
+ g_string_append (query_uri, "start-max=");
+ start_max = g_time_val_to_iso8601 (&(priv->start_max));
+ g_string_append (query_uri, start_max);
+ g_free (start_max);
+ }
+
+ if (priv->timezone != NULL) {
+ APPEND_SEP
+ g_string_append (query_uri, "ctz=");
+ g_string_append_uri_escaped (query_uri, priv->timezone, NULL, TRUE);
+ }
+}
+
/**
* gdata_calendar_query_new:
* @q: a query string
@@ -653,6 +735,20 @@ gdata_calendar_query_set_timezone (GDataCalendarQuery *self, const gchar *_timez
g_return_if_fail (GDATA_IS_CALENDAR_QUERY (self));
g_free (self->priv->timezone);
- self->priv->timezone = g_strdup (_timezone);
+
+ /* Replace all spaces with underscores */
+ if (_timezone != NULL) {
+ gchar *zone, *i;
+
+ zone = g_strdup (_timezone);
+ for (i = zone; *i != '\0'; i++) {
+ if (*i == ' ')
+ *i = '_';
+ }
+ self->priv->timezone = zone;
+ } else {
+ self->priv->timezone = NULL;
+ }
+
g_object_notify (G_OBJECT (self), "timezone");
}
diff --git a/gdata/tests/calendar.c b/gdata/tests/calendar.c
index f59b848..9ebd977 100644
--- a/gdata/tests/calendar.c
+++ b/gdata/tests/calendar.c
@@ -372,6 +372,75 @@ test_xml_dates (void)
g_object_unref (event);
}
+static void
+test_query_uri (void)
+{
+ GTimeVal time_val, time_val2;
+ gchar *query_uri;
+ GDataCalendarQuery *query = gdata_calendar_query_new ("q");
+
+ gdata_calendar_query_set_future_events (query, TRUE);
+ g_assert (gdata_calendar_query_get_future_events (query) == TRUE);
+
+ gdata_calendar_query_set_order_by (query, "starttime");
+ g_assert_cmpstr (gdata_calendar_query_get_order_by (query), ==, "starttime");
+
+ g_time_val_from_iso8601 ("2009-04-17T15:00:00.000Z", &time_val);
+ gdata_calendar_query_set_recurrence_expansion_start (query, &time_val);
+ gdata_calendar_query_get_recurrence_expansion_start (query, &time_val2);
+ g_assert_cmpint (time_val.tv_sec, ==, time_val2.tv_sec);
+ g_assert_cmpint (time_val.tv_usec, ==, time_val2.tv_usec);
+
+ g_time_val_from_iso8601 ("2010-04-17T15:00:00.000Z", &time_val);
+ gdata_calendar_query_set_recurrence_expansion_end (query, &time_val);
+ gdata_calendar_query_get_recurrence_expansion_end (query, &time_val2);
+ g_assert_cmpint (time_val.tv_sec, ==, time_val2.tv_sec);
+ g_assert_cmpint (time_val.tv_usec, ==, time_val2.tv_usec);
+
+ gdata_calendar_query_set_single_events (query, TRUE);
+ g_assert (gdata_calendar_query_get_single_events (query) == TRUE);
+
+ gdata_calendar_query_set_sort_order (query, "descending");
+ g_assert_cmpstr (gdata_calendar_query_get_sort_order (query), ==, "descending");
+
+ g_time_val_from_iso8601 ("2009-04-17T15:00:00.000Z", &time_val);
+ gdata_calendar_query_set_start_min (query, &time_val);
+ gdata_calendar_query_get_start_min (query, &time_val2);
+ g_assert_cmpint (time_val.tv_sec, ==, time_val2.tv_sec);
+ g_assert_cmpint (time_val.tv_usec, ==, time_val2.tv_usec);
+
+ g_time_val_from_iso8601 ("2010-04-17T15:00:00.000Z", &time_val);
+ gdata_calendar_query_set_start_max (query, &time_val);
+ gdata_calendar_query_get_start_max (query, &time_val2);
+ g_assert_cmpint (time_val.tv_sec, ==, time_val2.tv_sec);
+ g_assert_cmpint (time_val.tv_usec, ==, time_val2.tv_usec);
+
+ gdata_calendar_query_set_timezone (query, "America/Los Angeles");
+ g_assert_cmpstr (gdata_calendar_query_get_timezone (query), ==, "America/Los_Angeles");
+
+ /* Check the built query URI with a normal feed URI */
+ query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com");
+ g_assert_cmpstr (query_uri, ==, "http://example.com?q=q&futureevents=true&orderby=starttime&recurrence-expansion-start=2009-04-17T15:00:00Z"
+ "&recurrence-expansion-end=2010-04-17T15:00:00Z&singleevents=true&sortorder=descending"
+ "&start-min=2009-04-17T15:00:00Z&start-max=2010-04-17T15:00:00Z&ctz=America%2FLos_Angeles");
+ g_free (query_uri);
+
+ /* â?¦with a feed URI with a trailing slash */
+ query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com/");
+ g_assert_cmpstr (query_uri, ==, "http://example.com/?q=q&futureevents=true&orderby=starttime&recurrence-expansion-start=2009-04-17T15:00:00Z"
+ "&recurrence-expansion-end=2010-04-17T15:00:00Z&singleevents=true&sortorder=descending"
+ "&start-min=2009-04-17T15:00:00Z&start-max=2010-04-17T15:00:00Z&ctz=America%2FLos_Angeles");
+ g_free (query_uri);
+
+ /* â?¦with a feed URI with pre-existing arguments */
+ query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com/bar/?test=test&this=that");
+ g_assert_cmpstr (query_uri, ==, "http://example.com/bar/?test=test&this=that&q=q&futureevents=true&orderby=starttime"
+ "&recurrence-expansion-start=2009-04-17T15:00:00Z&recurrence-expansion-end=2010-04-17T15:00:00Z"
+ "&singleevents=true&sortorder=descending&start-min=2009-04-17T15:00:00Z&start-max=2010-04-17T15:00:00Z"
+ "&ctz=America%2FLos_Angeles");
+ g_free (query_uri);
+}
+
int
main (int argc, char *argv[])
{
@@ -395,6 +464,7 @@ main (int argc, char *argv[])
if (g_test_slow () == TRUE)
g_test_add_func ("/calendar/insert/simple", test_insert_simple);
g_test_add_func ("/calendar/xml/dates", test_xml_dates);
+ g_test_add_func ("/calendar/query/uri", test_query_uri);
retval = g_test_run ();
if (service != NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]