[evolution-patches] Populating backend cache with cal objects from GW server
- From: Harish Krishnaswamy <kharish novell com>
- To: evo-patch <evolution-patches lists ximian com>
- Cc: rodrigo <rodrigo ximian com>
- Subject: [evolution-patches] Populating backend cache with cal objects from GW server
- Date: Thu, 08 Jan 2004 22:35:30 +0530
pop_cache.diff - code to obtain the contents of 'Calendar' Folder in GW
and populate the cache with the same.
This also includes code in icaltime to allow separators in ISO 8601
strings.
pop_cache_libsoup - added a couple of lines to ignore Header elements
while creating response objects.
regards,
harish
Index: e-cal-backend-groupwise.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/backends/groupwise/e-cal-backend-groupwise.c,v
retrieving revision 1.13
diff -u -p -r1.13 e-cal-backend-groupwise.c
--- e-cal-backend-groupwise.c 7 Jan 2004 18:15:25 -0000 1.13
+++ e-cal-backend-groupwise.c 8 Jan 2004 16:48:47 -0000
@@ -27,7 +27,12 @@
#include <string.h>
#include <libgnomevfs/gnome-vfs-uri.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libedataserver/e-xml-hash-utils.h>
#include <libedata-cal/e-cal-backend-cache.h>
+#include <libedata-cal/e-cal-backend-util.h>
+#include <libecal/e-cal-component.h>
+#include <libecal/e-cal-time-util.h>
#include "e-cal-backend-groupwise.h"
#include "e-gw-connection.h"
@@ -35,7 +40,6 @@
struct _ECalBackendGroupwisePrivate {
/* A mutex to control access to the private structure */
GMutex *mutex;
-
EGwConnection *cnc;
ECalBackendCache *cache;
gboolean read_only;
@@ -43,6 +47,7 @@ struct _ECalBackendGroupwisePrivate {
char *username;
char *password;
CalMode mode;
+ icaltimezone *default_zone;
};
static void e_cal_backend_groupwise_dispose (GObject *object);
@@ -51,6 +56,9 @@ static void e_cal_backend_groupwise_fina
#define PARENT_TYPE E_TYPE_CAL_BACKEND_SYNC
static ECalBackendClass *parent_class = NULL;
+/* Time interval in milliseconds for obtaining changes from server and refresh the cache. */
+#define CACHE_REFRESH_INTERVAL 600000
+
/* Dispose handler for the file backend */
static void
e_cal_backend_groupwise_dispose (GObject *object)
@@ -111,7 +119,6 @@ e_cal_backend_groupwise_finalize (GObjec
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
}
-
/* Calendar backend methods */
/* Is_read_only handler for the file backend */
@@ -187,49 +194,58 @@ convert_uri (const char *gw_uri)
return vuri;
}
+/* FIXME: This method is also in the file backend. Can be moved to ECalComponent. */
+static const char *
+get_rid_string (ECalComponent *comp)
+{
+ ECalComponentRange range;
+ struct icaltimetype tt;
+
+ e_cal_component_get_recurid (comp, &range);
+ if (!range.datetime.value)
+ return "0";
+ tt = *range.datetime.value;
+ e_cal_component_free_range (&range);
+
+ return icaltime_is_valid_time (tt) && !icaltime_is_null_time (tt) ?
+ icaltime_as_ical_string (tt) : "0";
+}
+
/* Initialy populate the cache from the server */
-//static EGwConnectionStatus
static EGwConnectionStatus
populate_cache (ECalBackendGroupwisePrivate *priv)
{
EGwConnectionStatus status;
- SoupSoapParameter *param;
+ ECalComponent *comp;
const char *uid;
const char *rid;
- const char *calobj;
GSList *list = NULL, *l;
/* get all the objects from the server */
- status = e_gw_connection_get_items (priv->cnc, &list);
+ status = e_gw_connection_get_items (priv->cnc, NULL, &list);
if (status != E_GW_CONNECTION_STATUS_OK)
return status;
-
/* update the cache */
g_mutex_lock (priv->mutex);
- for (l = list; l; l = l->next) {
- param = (SoupSoapParameter *) l->data;
- uid = soup_soap_parameter_get_first_child_by_name (param, "iCalId");
- rid = soup_soap_parameter_get_first_child_by_name (param, "recurrance");
- calobj = soup_soap_parameter_get_string_value (param);
- e_cal_backend_cache_put_component (priv->cache, uid, rid, calobj);
+ for (l = list; l != NULL; l = g_slist_next(l)) {
+ comp = E_CAL_COMPONENT (l);
+ e_cal_component_get_uid (comp, &uid);
+ rid = g_strdup (get_rid_string (comp));
+ /* l contains e-cal-components*/
+ e_cal_backend_cache_put_component (priv->cache, uid, rid,
+ e_cal_component_get_as_string (comp));
}
-
- g_mutex_unlock (priv->mutex);
-
+ g_mutex_unlock (priv->mutex);
return E_GW_CONNECTION_STATUS_OK;
}
-static void
+static EGwConnectionStatus
update_cache (gpointer *data)
{
- EGwConnection *cnc;
-
- cnc = E_GW_CONNECTION (data);
- /* FIXME: Get all changes from the server since last poll */
- /* FIXME: parse the response and update the cache*/
- /*status = e_gw_connection_get_items_with_Filter (cnc, &list);*/
+ /* FIXME: to implemented using the getDeltas call */
+ return E_GW_CONNECTION_STATUS_OK;
}
/* Open handler for the file backend */
@@ -260,7 +276,8 @@ e_cal_backend_groupwise_open (ECalBacken
priv->mode = CAL_MODE_LOCAL;
priv->username = g_strdup (username);
priv->password = g_strdup (password);
-
+ priv->default_zone = icaltimezone_get_utc_timezone ();
+
g_mutex_unlock (priv->mutex);
return GNOME_Evolution_Calendar_Success;
@@ -361,8 +378,7 @@ e_cal_backend_groupwise_set_mode (ECalBa
GNOME_Evolution_Calendar_CalListener_MODE_NOT_SET,
GNOME_Evolution_Calendar_MODE_REMOTE);
} else {
- /* FIXME : add a symbolic constant for the time-out */
- g_timeout_add (600000, (GSourceFunc) update_cache, (gpointer) cbgw);
+ g_timeout_add (CACHE_REFRESH_INTERVAL, (GSourceFunc) update_cache, (gpointer) cbgw);
priv->mode = CAL_MODE_REMOTE;
e_cal_backend_notify_mode (backend, GNOME_Evolution_Calendar_CalListener_MODE_SET,
@@ -404,9 +420,6 @@ e_cal_backend_groupwise_get_default_obje
case ICAL_VTODO_COMPONENT:
e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
break;
- case ICAL_VJOURNAL_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
- break;
default:
g_object_unref (comp);
return GNOME_Evolution_Calendar_ObjectNotFound;
@@ -418,7 +431,7 @@ e_cal_backend_groupwise_get_default_obje
return GNOME_Evolution_Calendar_Success;
}
-/* Get_object_component handler for the file backend */
+/* Get_object_component handler for the groupwise backend */
static ECalBackendSyncStatus
e_cal_backend_groupwise_get_object (ECalBackendSync *backend, EDataCal *cal, const char *uid, const char *rid, char **object)
{
@@ -443,17 +456,17 @@ e_cal_backend_groupwise_get_object (ECal
return GNOME_Evolution_Calendar_ObjectNotFound;
}
-/* Get_timezone_object handler for the file backend */
+/* Get_timezone_object handler for the groupwise backend */
static ECalBackendSyncStatus
e_cal_backend_groupwise_get_timezone (ECalBackendSync *backend, EDataCal *cal, const char *tzid, char **object)
{
- ECalBackendGroupwise *cbfile;
+ ECalBackendGroupwise *cbgw;
ECalBackendGroupwisePrivate *priv;
icaltimezone *zone;
icalcomponent *icalcomp;
- cbfile = E_CAL_BACKEND_GROUPWISE (backend);
- priv = cbfile->priv;
+ cbgw = E_CAL_BACKEND_GROUPWISE (backend);
+ priv = cbgw->priv;
g_return_val_if_fail (tzid != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
@@ -547,6 +560,7 @@ e_cal_backend_groupwise_send_objects (EC
{
}
+
/* Object initialization function for the file backend */
static void
e_cal_backend_groupwise_init (ECalBackendGroupwise *cbgw, ECalBackendGroupwiseClass *class)
Index: e-gw-connection.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/backends/groupwise/e-gw-connection.c,v
retrieving revision 1.21
diff -u -p -r1.21 e-gw-connection.c
--- e-gw-connection.c 5 Jan 2004 17:07:13 -0000 1.21
+++ e-gw-connection.c 8 Jan 2004 16:49:11 -0000
@@ -24,8 +24,10 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+#include <string.h>
#include <libsoup/soup-session-sync.h>
#include <libsoup/soup-soap-message.h>
+#include <libecal/e-cal-component.h>
#include "e-gw-connection.h"
#include "e-gw-message.h"
@@ -364,17 +366,154 @@ e_gw_connection_logout (EGwConnection *c
return E_GW_CONNECTION_STATUS_OK;
}
+static ECalComponent*
+get_e_cal_component_from_soap_parameter (SoupSoapParameter *param)
+{
+ SoupSoapParameter *subparam;
+ const char *item_type;
+ const char *classification;
+ const char *accept_level;
+ ECalComponent *comp;
+ ECalComponentDateTime *dt;
+ struct icaltimetype *t;
+ int type = 0; /* type : stores enum value of ECalcomponentVType for local access*/
+ /* FIXME: should add support for notes. */
+ /* FIXME: need to add some validation code*/
+ comp = e_cal_component_new();
+ item_type = xmlGetProp (param, "type");
+ if ( !g_ascii_strcasecmp (item_type, "Appointment")) {
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
+ type = 1;
+ }
+ else if (!g_ascii_strcasecmp (item_type, "Task")) {
+ type = 2;
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
+ }
+ else { /* FIXME: Should this be an error. */
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_NO_TYPE);
+ return NULL;
+ }
+ subparam = soup_soap_parameter_get_first_child_by_name (param, "iCalId");
+ if (!subparam)
+ return NULL;
+ e_cal_component_set_uid (comp, soup_soap_parameter_get_string_value (subparam));
+ /* Create icaltimetype from param*/
+ subparam = soup_soap_parameter_get_first_child_by_name (param, "created");
+ if (!subparam)
+ return NULL;
+ t = (icaltimetype *)g_malloc ( sizeof (icaltimetype));
+ *t = icaltime_from_string (soup_soap_parameter_get_string_value (subparam));
+ e_cal_component_set_created (comp, t);
+ e_cal_component_set_dtstamp (comp, t);
+
+ dt = (ECalComponentDateTime *)g_malloc (sizeof (ECalComponentDateTime));
+ subparam = soup_soap_parameter_get_first_child_by_name (param, "endDate");
+ if (!subparam)
+ return NULL;
+ t = (icaltimetype *)g_malloc ( sizeof (icaltimetype));
+ *t = icaltime_from_string (soup_soap_parameter_get_string_value (subparam));
+ dt->value = t;
+ dt->tzid = g_strdup("UTC");
+ e_cal_component_set_dtend (comp, dt);
+
+ dt = (ECalComponentDateTime *)g_malloc (sizeof (ECalComponentDateTime));
+ subparam = soup_soap_parameter_get_first_child_by_name (param, "startDate");
+ if (!subparam)
+ return NULL;
+ t = (icaltimetype *)g_malloc ( sizeof (icaltimetype));
+ *t = icaltime_from_string (soup_soap_parameter_get_string_value (subparam));
+ dt->value = t;
+ dt->tzid = g_strdup("UTC");
+ e_cal_component_set_dtstart (comp, dt);
+
+ /* Classification */
+ classification = soup_soap_parameter_get_string_value (soup_soap_parameter_get_first_child_by_name (param, "class"));
+ if ( !g_ascii_strcasecmp (classification, "Public"))
+ e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_PUBLIC);
+ else
+ e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_UNKNOWN);
+ /* Transparency */
+ accept_level = soup_soap_parameter_get_string_value (soup_soap_parameter_get_first_child_by_name (param, "acceptLevel"));
+ if ( !g_ascii_strcasecmp (accept_level, "Busy"))
+ e_cal_component_set_transparency (comp, E_CAL_COMPONENT_TRANSP_OPAQUE);
+ else
+ e_cal_component_set_transparency (comp, E_CAL_COMPONENT_TRANSP_TRANSPARENT);
+ /* EVENT -specific properties */
+ if (type == 1)
+ e_cal_component_set_location (comp,
+ soup_soap_parameter_get_string_value (soup_soap_parameter_get_first_child_by_name (param, "place")));
+
+ return comp;
+}
+
EGwConnectionStatus
-e_gw_connection_get_items (EGwConnection *cnc, GSList **list)
+e_gw_connection_get_items (EGwConnection *cnc, const char * filter, GSList **list)
{
SoupSoapMessage *msg;
SoupSoapResponse *response;
EGwConnectionStatus status;
- SoupSoapParameter *param;
- GList *l;
+ SoupSoapParameter *param, *subparam;
+ const char *calendar_uid;
g_return_val_if_fail (E_IS_GW_CONNECTION (cnc), E_GW_CONNECTION_STATUS_INVALID_OBJECT);
+ /* FIXME: Make this a separate function. obtain the uid for the container - 'Calendar' */
+ msg = e_gw_message_new_with_header (cnc->priv->uri, cnc->priv->session_id, "getContainerListRequest");
+ if (!msg) {
+ g_warning (G_STRLOC ": Could not build SOAP message");
+ return E_GW_CONNECTION_STATUS_UNKNOWN;
+ }
+
+ e_gw_message_write_string_parameter (msg, "parent", NULL, "folders");
+ e_gw_message_write_string_parameter (msg, "recursive", NULL, "true");
+ e_gw_message_write_footer (msg);
+
+ /* send message to server */
+ response = e_gw_connection_send_message (cnc, msg);
+ if (!response) {
+ g_object_unref (msg);
+ return E_GW_CONNECTION_STATUS_INVALID_RESPONSE;
+ }
+
+ status = parse_response_status (response);
+ if (status != E_GW_CONNECTION_STATUS_OK) {
+ g_object_unref (response);
+ return status;
+ }
+
+ /* if status is OK - parse result. return the list */
+ param = soup_soap_response_get_first_parameter_by_name (response, "folders");
+
+ if (!param) {
+ g_object_unref (response);
+ g_object_unref (msg);
+ return E_GW_CONNECTION_STATUS_INVALID_RESPONSE;
+ } else {
+ SoupSoapParameter *subparam, *name, *id;
+ for (subparam = soup_soap_parameter_get_first_child_by_name (param, "Folder");
+ subparam != NULL;
+ subparam = soup_soap_parameter_get_next_child_by_name (subparam, "Folder")) {
+ name = soup_soap_parameter_get_first_child_by_name (subparam, "name");
+ if (name && (!strcmp (soup_soap_parameter_get_string_value (name), "Calendar"))) {
+ id = soup_soap_parameter_get_first_child_by_name (subparam, "id");
+ if (id)
+ calendar_uid = g_strdup (soup_soap_parameter_get_string_value (id));
+ else
+ return E_GW_CONNECTION_STATUS_INVALID_RESPONSE;
+
+ break;
+ }
+
+ }
+ if (!subparam) {
+ g_object_unref (response);
+ g_object_unref (msg);
+ return E_GW_CONNECTION_STATUS_INVALID_RESPONSE;
+ }
+
+ }
+
+
/* build the SOAP message */
msg = e_gw_message_new_with_header (cnc->priv->uri, cnc->priv->session_id, "getItemsRequest");
if (!msg) {
@@ -382,8 +521,9 @@ e_gw_connection_get_items (EGwConnection
return E_GW_CONNECTION_STATUS_UNKNOWN;
}
- /* FIXME: Need to obtain the uid for calendar and use here */
- e_gw_message_write_string_parameter (msg, "container", NULL, "A dom1 po1 100 0 1 0 1 19");
+ e_gw_message_write_string_parameter (msg, "container", NULL, calendar_uid);
+ if (filter)
+ e_gw_message_write_string_parameter (msg, "Filter", NULL, filter);
e_gw_message_write_footer (msg);
/* send message to server */
@@ -407,14 +547,22 @@ e_gw_connection_get_items (EGwConnection
return E_GW_CONNECTION_STATUS_INVALID_RESPONSE;
}
- /* FIXME: iterate through the response and populate the list */
- l = (GList *) soup_soap_response_get_parameters (response);
-
+ /* parse these parameters into ecalcomponents*/
+ for (subparam = soup_soap_parameter_get_first_child_by_name (param, "item");
+ subparam != NULL;
+ subparam = soup_soap_parameter_get_next_child_by_name (subparam, "item")) {
+ ECalComponent *comp = NULL;
+ comp = get_e_cal_component_from_soap_parameter (subparam);
+ if (comp)
+ g_slist_append (*list, comp);
+ else
+ continue; /*FIXME: skips element if error. need to generate proper error*/
+ }
+
/* free memory */
g_object_unref (response);
g_object_unref (msg);
- /* FIXME: when will the cache be cleared ? */
return E_GW_CONNECTION_STATUS_OK;
}
Index: e-gw-connection.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/backends/groupwise/e-gw-connection.h,v
retrieving revision 1.6
diff -u -p -r1.6 e-gw-connection.h
--- e-gw-connection.h 24 Dec 2003 13:17:29 -0000 1.6
+++ e-gw-connection.h 8 Jan 2004 16:49:22 -0000
@@ -62,7 +62,7 @@ typedef enum {
SoupSoapResponse *e_gw_connection_send_message (EGwConnection *cnc, SoupSoapMessage *msg);
EGwConnectionStatus e_gw_connection_logout (EGwConnection *cnc);
-EGwConnectionStatus e_gw_connection_get_items (EGwConnection *cnc, GSList **list);
+EGwConnectionStatus e_gw_connection_get_items (EGwConnection *cnc, const char *filter, GSList **list);
const char *e_gw_connection_get_user_email (EGwConnection *cnc);
Index: icaltime.c
===================================================================
RCS file: /cvs/gnome/libical/src/libical/icaltime.c,v
retrieving revision 1.28
diff -u -p -r1.28 icaltime.c
--- icaltime.c 7 Jan 2004 06:32:33 -0000 1.28
+++ icaltime.c 8 Jan 2004 16:50:49 -0000
@@ -449,27 +449,44 @@ struct icaltimetype icaltime_from_string
size = strlen(str);
- if(size == 15) { /* floating time */
+ if ((size == 15) || (size == 19)) { /* floating time with/without separators*/
tt.is_utc = 0;
tt.is_date = 0;
- } else if (size == 16) { /* UTC time, ends in 'Z'*/
- if(str[15] != 'Z')
+ } else if ((size == 16) || (size == 20)) { /* UTC time, ends in 'Z'*/
+ if ((str[15] != 'Z') && (str[19] != 'Z'))
goto FAIL;
tt.is_utc = 1;
tt.zone = icaltimezone_get_utc_timezone();
tt.is_date = 0;
- } else if (size == 8) { /* A DATE */
+ } else if ((size == 8) || (size == 10)) { /* A DATE */
tt.is_utc = 1;
tt.is_date = 1;
} else { /* error */
goto FAIL;
}
- if(tt.is_date == 1){
- if (sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day) < 3)
+ if (tt.is_date == 1){
+ if (size == 10) {
+ char dsep1, dsep2;
+ if (sscanf(str,"%04d%c%02d%c%02d",&tt.year,&dsep1,&tt.month,&dsep2,&tt.day) < 5)
+ goto FAIL;
+ if ((dsep1 != '-') || (dsep2 != '-'))
+ goto FAIL;
+ } else if (sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day) < 3) {
goto FAIL;
+ }
} else {
+ if (size > 16 ) {
+ char dsep1, dsep2, tsep, tsep1, tsep2;
+ if (sscanf(str,"%04d%c%02d%c%02d%c%02d%c%02d%c%02d",&tt.year,&dsep1,&tt.month,&dsep2,
+ &tt.day,&tsep,&tt.hour,&tsep1,&tt.minute,&tsep2,&tt.second) < 11)
+ goto FAIL;
+
+ if((tsep != 'T') || (dsep1 != '-') || (dsep2 != '-'))
+ goto FAIL;
+
+ } else {
char tsep;
if (sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day,
&tsep,&tt.hour,&tt.minute,&tt.second) < 7)
@@ -477,6 +494,7 @@ struct icaltimetype icaltime_from_string
if(tsep != 'T')
goto FAIL;
+ }
}
return tt;
Index: soup-soap-response.c
===================================================================
RCS file: /cvs/gnome/libsoup/libsoup/soup-soap-response.c,v
retrieving revision 1.8
diff -u -p -r1.8 soup-soap-response.c
--- soup-soap-response.c 16 Dec 2003 17:42:56 -0000 1.8
+++ soup-soap-response.c 8 Jan 2004 16:35:32 -0000
@@ -174,6 +174,8 @@ soup_soap_response_from_string (SoupSoap
if (xml_root->xmlChildrenNode != NULL) {
xml_body = xml_root->xmlChildrenNode;
+ if (strcmp (xml_body->name, "Header") == 0)
+ xml_body = xml_root->xmlChildrenNode->next;
if (strcmp (xml_body->name, "Body") != 0) {
xmlFreeDoc (response->priv->xmldoc);
response->priv->xmldoc = old_doc;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]