[evolution-patches] Populating backend cache with cal objects from GW server



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]