[evolution-data-server/wip/offline-cache] Make it possible to provide 'object' within ECalMetaBackendInfo



commit fedfa967425061f7160fb0e845db063157885945
Author: Milan Crha <mcrha redhat com>
Date:   Tue Mar 21 17:58:53 2017 +0100

    Make it possible to provide 'object' within ECalMetaBackendInfo
    
    plus some other miscellaneous changes.

 src/calendar/backends/http/e-cal-backend-http.c |   12 ++-
 src/calendar/libecal/e-cal-util.c               |  164 +++++++++++++++++++++++
 src/calendar/libecal/e-cal-util.h               |   12 ++
 src/calendar/libedata-cal/e-cal-meta-backend.c  |   44 +++++--
 src/calendar/libedata-cal/e-cal-meta-backend.h  |    4 +-
 tests/libedata-cal/test-cal-meta-backend.c      |    2 +-
 6 files changed, 222 insertions(+), 16 deletions(-)
---
diff --git a/src/calendar/backends/http/e-cal-backend-http.c b/src/calendar/backends/http/e-cal-backend-http.c
index 6d806c5..57d1087 100644
--- a/src/calendar/backends/http/e-cal-backend-http.c
+++ b/src/calendar/backends/http/e-cal-backend-http.c
@@ -570,7 +570,7 @@ ecb_http_list_existing_sync (ECalMetaBackend *meta_backend,
                icalcomponent *icalcomp = value;
                ECalMetaBackendInfo *nfo;
                const gchar *uid;
-               gchar *revision;
+               gchar *revision, *object;
 
                if (icalcomp && icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT)
                        icalcomp = icalcomponent_get_first_component (icalcomp, kind);
@@ -580,15 +580,23 @@ ecb_http_list_existing_sync (ECalMetaBackend *meta_backend,
 
                uid = icalcomponent_get_uid (icalcomp);
                revision = e_cal_cache_dup_component_revision (cal_cache, icalcomp);
+               object = icalcomponent_as_ical_string_r (value);
+
+               nfo = e_cal_meta_backend_info_new (uid, NULL, revision, object);
 
-               nfo = e_cal_meta_backend_info_new (uid, NULL, revision);
                *out_existing_objects = g_slist_prepend (*out_existing_objects, nfo);
 
                g_free (revision);
+               g_free (object);
        }
 
        g_object_unref (cal_cache);
 
+       g_hash_table_destroy (cbhttp->priv->components);
+       cbhttp->priv->components = NULL;
+
+       ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
+
        return TRUE;
 }
 
diff --git a/src/calendar/libecal/e-cal-util.c b/src/calendar/libecal/e-cal-util.c
index 689fab6..653f03b 100644
--- a/src/calendar/libecal/e-cal-util.c
+++ b/src/calendar/libecal/e-cal-util.c
@@ -1672,3 +1672,167 @@ e_cal_util_get_component_occur_times (ECalComponent *comp,
        }
 }
 
+/**
+ * e_cal_util_find_x_property:
+ * @icalcomp: an icalcomponent
+ * @x_name: name of the X property
+ *
+ * Searches for an X property named @x_name within X properties
+ * of @icalcomp and returns it.
+ *
+ * Returns: (nullable) (transfer none): the first X icalproperty named
+ *    @x_name, or %NULL, when none found. The returned structure is owned
+ *    by @icalcomp.
+ *
+ * Since: 3.26
+ **/
+icalproperty *
+e_cal_util_find_x_property (icalcomponent *icalcomp,
+                           const gchar *x_name)
+{
+       icalproperty *prop;
+
+       g_return_val_if_fail (icalcomp != NULL, NULL);
+       g_return_val_if_fail (x_name != NULL, NULL);
+
+       for (prop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
+            prop;
+            prop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY)) {
+               const gchar *prop_name = icalproperty_get_x_name (prop);
+
+               if (g_strcmp0 (prop_name, x_name) == 0)
+                       break;
+       }
+
+       return prop;
+}
+
+/**
+ * e_cal_util_dup_x_property:
+ * @icalcomp: an icalcomponent
+ * @x_name: name of the X property
+ *
+ * Searches for an X property named @x_name within X properties
+ * of @icalcomp and returns its value as a newly allocated string.
+ * Free it with g_free(), when no longer needed.
+ *
+ * Returns: (nullable) (transfer full): Newly allocated value of the first @x_name
+ *    X property in @icalcomp, or %NULL, if not found.
+ *
+ * Since: 3.26
+ **/
+gchar *
+e_cal_util_dup_x_property (icalcomponent *icalcomp,
+                          const gchar *x_name)
+{
+       icalproperty *prop;
+
+       g_return_val_if_fail (icalcomp != NULL, NULL);
+       g_return_val_if_fail (x_name != NULL, NULL);
+
+       prop = e_cal_util_find_x_property (icalcomp, x_name);
+
+       if (!prop)
+               return NULL;
+
+       return icalproperty_get_value_as_string_r (prop);
+}
+
+/**
+ * e_cal_util_get_x_property:
+ * @icalcomp: an icalcomponent
+ * @x_name: name of the X property
+ *
+ * Searches for an X property named @x_name within X properties
+ * of @icalcomp and returns its value. The returned string is
+ * owned by libical. See e_cal_util_dup_x_property().
+ *
+ * Returns: (nullable) (transfer none): Value of the first @x_name
+ *    X property in @icalcomp, or %NULL, if not found.
+ *
+ * Since: 3.26
+ **/
+const gchar *
+e_cal_util_get_x_property (icalcomponent *icalcomp,
+                          const gchar *x_name)
+{
+       icalproperty *prop;
+
+       g_return_val_if_fail (icalcomp != NULL, NULL);
+       g_return_val_if_fail (x_name != NULL, NULL);
+
+       prop = e_cal_util_find_x_property (icalcomp, x_name);
+
+       if (!prop)
+               return NULL;
+
+       return icalproperty_get_value_as_string (prop);
+}
+
+/**
+ * e_cal_util_set_x_property:
+ * @icalcomp: an icalcomponent
+ * @x_name: name of the X property
+ * @value: (nullable): a value to set, or %NULL
+ *
+ * Sets a value of the first X property named @x_name in @icalcomp,
+ * if any such already exists, or adds a new property with this name
+ * and value. As a special case, if @value is %NULL, then removes
+ * the first X property names @x_name from @icalcomp instead.
+ *
+ * Since: 3.26
+ **/
+void
+e_cal_util_set_x_property (icalcomponent *icalcomp,
+                          const gchar *x_name,
+                          const gchar *value)
+{
+       icalproperty *prop;
+
+       g_return_if_fail (icalcomp != NULL);
+       g_return_if_fail (x_name != NULL);
+
+       if (!value) {
+               e_cal_util_remove_x_property (icalcomp, x_name);
+               return;
+       }
+
+       prop = e_cal_util_find_x_property (icalcomp, x_name);
+       if (prop) {
+               icalproperty_set_value_from_string (prop, value, "NO");
+       } else {
+               prop = icalproperty_new_x (value);
+               icalproperty_set_x_name (prop, x_name);
+               icalcomponent_add_property (icalcomp, prop);
+       }
+}
+
+/**
+ * e_cal_util_remove_x_property:
+ * @icalcomp: an icalcomponent
+ * @x_name: name of the X property
+ *
+ * Removes the first X property named @x_name in @icalcomp.
+ *
+ * Returns: %TRUE, when any such had been found and removed, %FALSE otherwise.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_cal_util_remove_x_property (icalcomponent *icalcomp,
+                             const gchar *x_name)
+{
+       icalproperty *prop;
+
+       g_return_val_if_fail (icalcomp != NULL, FALSE);
+       g_return_val_if_fail (x_name != NULL, FALSE);
+
+       prop = e_cal_util_find_x_property (icalcomp, x_name);
+       if (!prop)
+               return FALSE;
+
+       icalcomponent_remove_property (icalcomp, prop);
+       icalproperty_free (prop);
+
+       return TRUE;
+}
diff --git a/src/calendar/libecal/e-cal-util.h b/src/calendar/libecal/e-cal-util.h
index 86c90cd..ce4caab 100644
--- a/src/calendar/libecal/e-cal-util.h
+++ b/src/calendar/libecal/e-cal-util.h
@@ -248,6 +248,18 @@ void               e_cal_util_get_component_occur_times
                                                 const icaltimezone *default_timezone,
                                                 icalcomponent_kind kind);
 
+icalproperty * e_cal_util_find_x_property      (icalcomponent *icalcomp,
+                                                const gchar *x_name);
+gchar *                e_cal_util_dup_x_property       (icalcomponent *icalcomp,
+                                                const gchar *x_name);
+const gchar *  e_cal_util_get_x_property       (icalcomponent *icalcomp,
+                                                const gchar *x_name);
+void           e_cal_util_set_x_property       (icalcomponent *icalcomp,
+                                                const gchar *x_name,
+                                                const gchar *value);
+gboolean       e_cal_util_remove_x_property    (icalcomponent *icalcomp,
+                                                const gchar *x_name);
+
 #ifndef EDS_DISABLE_DEPRECATED
 /* Used for mode stuff */
 typedef enum {
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.c b/src/calendar/libedata-cal/e-cal-meta-backend.c
index 7ee31aa..7bb8cec 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.c
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.c
@@ -98,6 +98,7 @@ static void ecmb_schedule_go_offline (ECalMetaBackend *meta_backend);
 static gboolean ecmb_load_component_wrapper_sync (ECalMetaBackend *meta_backend,
                                                  ECalCache *cal_cache,
                                                  const gchar *uid,
+                                                 const gchar *preloaded_object,
                                                  GCancellable *cancellable,
                                                  GError **error);
 static gboolean ecmb_save_component_wrapper_sync (ECalMetaBackend *meta_backend,
@@ -116,18 +117,20 @@ static gboolean ecmb_save_component_wrapper_sync (ECalMetaBackend *meta_backend,
  * @uid: a component UID; cannot be %NULL
  * @rid: (nullable): a component Recurrence-ID; can be %NULL
  * @revision: (nullable): the component revision; can be %NULL
+ * @object: (nullable): the component object as an iCalendar string; can be %NULL
  *
  * Creates a new #ECalMetaBackendInfo prefilled with the given values.
  *
  * Returns: (transfer full): A new #ECalMetaBackendInfo. Free it with
- *    e_cal_meta_backend_info_new() when no longer needed.
+ *    e_cal_meta_backend_info_free() when no longer needed.
  *
  * Since: 3.26
  **/
 ECalMetaBackendInfo *
 e_cal_meta_backend_info_new (const gchar *uid,
                             const gchar *rid,
-                            const gchar *revision)
+                            const gchar *revision,
+                            const gchar *object)
 {
        ECalMetaBackendInfo *info;
 
@@ -137,6 +140,7 @@ e_cal_meta_backend_info_new (const gchar *uid,
        info->uid = g_strdup (uid);
        info->rid = g_strdup (rid && *rid ? rid : NULL);
        info->revision = g_strdup (revision);
+       info->object = g_strdup (object);
 
        return info;
 }
@@ -157,7 +161,7 @@ e_cal_meta_backend_info_copy (const ECalMetaBackendInfo *src)
        if (src)
                return NULL;
 
-       return e_cal_meta_backend_info_new (src->uid, src->rid, src->revision);
+       return e_cal_meta_backend_info_new (src->uid, src->rid, src->revision, src->object);
 }
 
 /**
@@ -178,6 +182,7 @@ e_cal_meta_backend_info_free (gpointer ptr)
                g_free (info->uid);
                g_free (info->rid);
                g_free (info->revision);
+               g_free (info->object);
                g_free (info);
        }
 }
@@ -457,7 +462,7 @@ ecmb_get_changes_sync (ECalMetaBackend *meta_backend,
                                continue;
                }
 
-               nfo = e_cal_meta_backend_info_new (id->uid, id->rid, revision);
+               nfo = e_cal_meta_backend_info_new (id->uid, id->rid, revision, NULL);
                *out_removed_objects = g_slist_prepend (*out_removed_objects, nfo);
        }
 
@@ -727,7 +732,7 @@ ecmb_refresh_thread_func (ECalBackend *cal_backend,
 
                                g_hash_table_insert (covered_uids, nfo->uid, NULL);
 
-                               success = ecmb_load_component_wrapper_sync (meta_backend, cal_cache, 
nfo->uid, cancellable, error);
+                               success = ecmb_load_component_wrapper_sync (meta_backend, cal_cache, 
nfo->uid, nfo->object, cancellable, error);
                        }
 
                        g_hash_table_remove_all (covered_uids);
@@ -741,7 +746,7 @@ ecmb_refresh_thread_func (ECalBackend *cal_backend,
                                        continue;
                                }
 
-                               success = ecmb_load_component_wrapper_sync (meta_backend, cal_cache, 
nfo->uid, cancellable, error);
+                               success = ecmb_load_component_wrapper_sync (meta_backend, cal_cache, 
nfo->uid, nfo->object, cancellable, error);
                        }
 
                        g_hash_table_destroy (covered_uids);
@@ -1075,6 +1080,7 @@ static gboolean
 ecmb_load_component_wrapper_sync (ECalMetaBackend *meta_backend,
                                  ECalCache *cal_cache,
                                  const gchar *uid,
+                                 const gchar *preloaded_object,
                                  GCancellable *cancellable,
                                  GError **error)
 {
@@ -1084,8 +1090,14 @@ ecmb_load_component_wrapper_sync (ECalMetaBackend *meta_backend,
        gchar *extra = NULL;
        gboolean success = TRUE;
 
-       if (!e_cal_meta_backend_load_component_sync (meta_backend, uid, &icalcomp, &extra, cancellable, 
error) ||
-           !icalcomp) {
+       if (preloaded_object && *preloaded_object) {
+               icalcomp = icalcomponent_new_from_string (preloaded_object);
+               if (!icalcomp) {
+                       g_propagate_error (error, e_data_cal_create_error (InvalidObject, _("Preloaded object 
is invalid")));
+                       return FALSE;
+               }
+       } else if (!e_cal_meta_backend_load_component_sync (meta_backend, uid, &icalcomp, &extra, 
cancellable, error) ||
+                  !icalcomp) {
                g_free (extra);
                return FALSE;
        }
@@ -1176,7 +1188,7 @@ ecmb_save_component_wrapper_sync (ECalMetaBackend *meta_backend,
                instances ? instances : in_instances, extra, &new_uid, cancellable, error);
 
        if (success && new_uid) {
-               success = ecmb_load_component_wrapper_sync (meta_backend, cal_cache, new_uid, cancellable, 
error);
+               success = ecmb_load_component_wrapper_sync (meta_backend, cal_cache, new_uid, NULL, 
cancellable, error);
 
                if (success && g_strcmp0 (new_uid, orig_uid) != 0)
                    success = ecmb_maybe_remove_from_cache (meta_backend, cal_cache, E_CACHE_IS_ONLINE, 
orig_uid, cancellable, error);
@@ -1282,7 +1294,7 @@ ecmb_get_object_sync (ECalBackendSync *sync_backend,
                /* Ignore errors here, just try whether it's on the remote side, but not in the local cache */
                if (e_backend_get_online (E_BACKEND (meta_backend)) &&
                    ecmb_connect_wrapper_sync (meta_backend, cancellable, NULL) &&
-                   ecmb_load_component_wrapper_sync (meta_backend, cal_cache, uid, cancellable, NULL)) {
+                   ecmb_load_component_wrapper_sync (meta_backend, cal_cache, uid, NULL, cancellable, NULL)) 
{
                        found = e_cal_cache_get_component_as_string (cal_cache, uid, rid, calobj, 
cancellable, NULL);
                }
 
@@ -3777,6 +3789,10 @@ e_cal_meta_backend_disconnect_sync (ECalMetaBackend *meta_backend,
  * function again with the @out_new_sync_tag as the @last_sync_tag, but also
  * notifies about the found changes immediately.
  *
+ * The descendant can populate also ECalMetaBackendInfo::object of
+ * the @out_created_objects and @out_modified_objects, if known, in which
+ * case this will be used instead of loading it with e_cal_meta_backend_load_component_sync().
+ *
  * It is optional to implement this virtual method by the descendant.
  * The default implementation calls e_cal_meta_backend_list_existing_sync()
  * and then compares the list with the current content of the local cache
@@ -3836,9 +3852,13 @@ e_cal_meta_backend_get_changes_sync (ECalMetaBackend *meta_backend,
  * @error: return location for a #GError, or %NULL
  *
  * Used to get list of all existing objects on the remote side. The descendant
- * can optionally provide @out_new_sync_tag, which will be stored if not %NULL.
+ * can optionally provide @out_new_sync_tag, which will be stored on success, if
+ * not %NULL. The descendant can populate also ECalMetaBackendInfo::object of
+ * the @out_existing_objects, if known, in which case this will be used instead
+ * of loading it with e_cal_meta_backend_load_component_sync().
  *
- * It is mandatory to implement this virtual method by the descendant.
+ * It is mandatory to implement this virtual method by the descendant, unless
+ * it implements its own get_changes_sync().
  *
  * The @out_existing_objects #GSList should be freed with
  * g_slist_free_full (objects, e_cal_meta_backend_info_free);
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.h b/src/calendar/libedata-cal/e-cal-meta-backend.h
index d135b14..463d268 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.h
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.h
@@ -52,6 +52,7 @@ typedef struct _ECalMetaBackendInfo {
        gchar *uid;
        gchar *rid;
        gchar *revision;
+       gchar *object;
 } ECalMetaBackendInfo;
 
 #define E_TYPE_CAL_META_BACKEND_INFO (e_cal_meta_backend_info_get_type ())
@@ -61,7 +62,8 @@ GType         e_cal_meta_backend_info_get_type
 ECalMetaBackendInfo *
                e_cal_meta_backend_info_new     (const gchar *uid,
                                                 const gchar *rid,
-                                                const gchar *revision);
+                                                const gchar *revision,
+                                                const gchar *object);
 ECalMetaBackendInfo *
                e_cal_meta_backend_info_copy    (const ECalMetaBackendInfo *src);
 void           e_cal_meta_backend_info_free    (gpointer ptr /* ECalMetaBackendInfo * */);
diff --git a/tests/libedata-cal/test-cal-meta-backend.c b/tests/libedata-cal/test-cal-meta-backend.c
index ccb34a5..d7fb6fc 100644
--- a/tests/libedata-cal/test-cal-meta-backend.c
+++ b/tests/libedata-cal/test-cal-meta-backend.c
@@ -395,7 +395,7 @@ e_cal_meta_backend_test_list_existing_sync (ECalMetaBackend *meta_backend,
                uid = icalcomponent_get_uid (icalcomp);
                revision = e_cal_cache_dup_component_revision (cal_cache, icalcomp);
 
-               nfo = e_cal_meta_backend_info_new (uid, NULL, revision);
+               nfo = e_cal_meta_backend_info_new (uid, NULL, revision, NULL);
                *out_existing_objects = g_slist_prepend (*out_existing_objects, nfo);
 
                g_free (revision);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]