[libgdata] [core] Move all GTimeVal parsing into a single function
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgdata] [core] Move all GTimeVal parsing into a single function
- Date: Thu, 25 Mar 2010 00:36:04 +0000 (UTC)
commit 5c64f9db5a20fd4967a8e2190c9a719a1e04360e
Author: Philip Withnall <philip tecnocode co uk>
Date: Wed Mar 24 21:44:27 2010 +0000
[core] Move all GTimeVal parsing into a single function
gdata/gdata-entry.c | 75 +++++---------------
gdata/gdata-feed.c | 19 +-----
gdata/gdata-parser.c | 69 ++++++++++++++++++
gdata/gdata-parser.h | 7 ++-
gdata/gdata-private.h | 1 +
gdata/services/calendar/gdata-calendar-calendar.c | 29 +++-----
gdata/services/calendar/gdata-calendar-event.c | 43 +++++-------
gdata/services/contacts/gdata-contacts-contact.c | 55 ++++++---------
gdata/services/documents/gdata-documents-entry.c | 44 ++++++------
gdata/services/documents/gdata-documents-folder.c | 8 ++-
.../documents/gdata-documents-presentation.c | 8 ++-
.../documents/gdata-documents-spreadsheet.c | 8 ++-
gdata/services/documents/gdata-documents-text.c | 8 ++-
gdata/services/picasaweb/gdata-picasaweb-album.c | 26 +++----
gdata/services/picasaweb/gdata-picasaweb-file.c | 26 +++----
gdata/services/youtube/gdata-youtube-group.c | 18 +----
16 files changed, 216 insertions(+), 228 deletions(-)
---
diff --git a/gdata/gdata-entry.c b/gdata/gdata-entry.c
index 98ec252..e5ec364 100644
--- a/gdata/gdata-entry.c
+++ b/gdata/gdata-entry.c
@@ -373,73 +373,32 @@ static gboolean
parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
{
gboolean success;
- GDataEntry *self;
+ GDataEntryPrivate *priv = GDATA_ENTRY (parsable)->priv;
- g_return_val_if_fail (GDATA_IS_ENTRY (parsable), FALSE);
- g_return_val_if_fail (doc != NULL, FALSE);
- g_return_val_if_fail (node != NULL, FALSE);
-
- self = GDATA_ENTRY (parsable);
-
- if (xmlStrcmp (node->name, (xmlChar*) "title") == 0) {
- /* atom:title */
- xmlChar *title = xmlNodeListGetString (doc, node->children, TRUE);
-
- /* Title can be empty */
- self->priv->title = (title != NULL) ? (gchar*) title : g_strdup ("");
- } else if (xmlStrcmp (node->name, (xmlChar*) "id") == 0) {
- /* atom:id */
- g_free (self->priv->id);
- self->priv->id = (gchar*) xmlNodeListGetString (doc, node->children, TRUE);
- } else if (xmlStrcmp (node->name, (xmlChar*) "updated") == 0) {
- /* atom:updated */
- xmlChar *updated;
-
- updated = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) updated, &(self->priv->updated)) == FALSE) {
- /* Error */
- gdata_parser_error_not_iso8601_format (node, (gchar*) updated, error);
- xmlFree (updated);
- return FALSE;
- }
- xmlFree (updated);
- } else if (xmlStrcmp (node->name, (xmlChar*) "published") == 0) {
- /* atom:published */
- xmlChar *published;
-
- published = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) published, &(self->priv->published)) == FALSE) {
- /* Error */
- gdata_parser_error_not_iso8601_format (node, (gchar*) published, error);
- xmlFree (published);
- return FALSE;
- }
- xmlFree (published);
- } else if (gdata_parser_object_from_element_setter (node, "category", P_REQUIRED, GDATA_TYPE_CATEGORY,
- gdata_entry_add_category, self, &success, error) == TRUE ||
- gdata_parser_object_from_element_setter (node, "link", P_REQUIRED, GDATA_TYPE_LINK,
- gdata_entry_add_link, self, &success, error) == TRUE ||
- gdata_parser_object_from_element_setter (node, "author", P_REQUIRED, GDATA_TYPE_AUTHOR,
- gdata_entry_add_author, self, &success, error) == TRUE) {
+ if (gdata_parser_string_from_element (node, "title", P_DEFAULT, &(priv->title), &success, error) == TRUE ||
+ gdata_parser_string_from_element (node, "id", P_REQUIRED | P_NON_EMPTY | P_NO_DUPES, &(priv->id), &success, error) == TRUE ||
+ gdata_parser_string_from_element (node, "summary", P_NONE, &(priv->summary), &success, error) == TRUE ||
+ gdata_parser_string_from_element (node, "rights", P_NONE, &(priv->rights), &success, error) == TRUE ||
+ gdata_parser_time_val_from_element (node, "updated", P_REQUIRED | P_NO_DUPES, &(priv->updated), &success, error) == TRUE ||
+ gdata_parser_time_val_from_element (node, "published", P_REQUIRED | P_NO_DUPES, &(priv->published), &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "category", P_REQUIRED, GDATA_TYPE_CATEGORY,
+ gdata_entry_add_category, parsable, &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "link", P_REQUIRED, GDATA_TYPE_LINK,
+ gdata_entry_add_link, parsable, &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "author", P_REQUIRED, GDATA_TYPE_AUTHOR,
+ gdata_entry_add_author, parsable, &success, error) == TRUE) {
return success;
} else if (xmlStrcmp (node->name, (xmlChar*) "content") == 0) {
/* atom:content */
xmlChar *content = xmlNodeListGetString (doc, node->children, TRUE);
if (content == NULL)
content = xmlGetProp (node, (xmlChar*) "src");
- self->priv->content = (gchar*) content;
- } else if (xmlStrcmp (node->name, (xmlChar*) "summary") == 0) {
- /* atom:summary */
- self->priv->summary = (gchar*) xmlNodeListGetString (doc, node->children, TRUE);
- } else if (xmlStrcmp (node->name, (xmlChar*) "rights") == 0) {
- /* atom:rights */
- self->priv->rights = (gchar*) xmlNodeListGetString (doc, node->children, TRUE);
- } else if (GDATA_PARSABLE_CLASS (gdata_entry_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
- /* Error! */
- return FALSE;
+ priv->content = (gchar*) content;
+
+ return TRUE;
}
- return TRUE;
+ return GDATA_PARSABLE_CLASS (gdata_entry_parent_class)->parse_xml (parsable, doc, node, user_data, error);
}
static gboolean
diff --git a/gdata/gdata-feed.c b/gdata/gdata-feed.c
index e0740c1..65f91cf 100644
--- a/gdata/gdata-feed.c
+++ b/gdata/gdata-feed.c
@@ -440,25 +440,10 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
gdata_parser_object_from_element_setter (node, "author", P_REQUIRED, GDATA_TYPE_AUTHOR,
_gdata_feed_add_author, self, &success, error) == TRUE ||
gdata_parser_object_from_element (node, "generator", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_GENERATOR,
- &(self->priv->generator), &success, error) == TRUE) {
+ &(self->priv->generator), &success, error) == TRUE ||
+ gdata_parser_time_val_from_element (node, "updated", P_REQUIRED | P_NO_DUPES, &(self->priv->updated), &success, error) == TRUE) {
return success;
/*TODO for atom:id: xmlStrcmp (node->ns->href, (xmlChar*) "http://www.w3.org/2005/Atom") == 0) {*/
- } else if (xmlStrcmp (node->name, (xmlChar*) "updated") == 0) {
- /* atom:updated */
- xmlChar *updated_string;
-
- /* Duplicate checking */
- if (self->priv->updated.tv_sec != 0 || self->priv->updated.tv_usec != 0)
- return gdata_parser_error_duplicate_element (node, error);
-
- /* Parse the string */
- updated_string = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) updated_string, &(self->priv->updated)) == FALSE) {
- gdata_parser_error_not_iso8601_format (node, (gchar*) updated_string, error);
- xmlFree (updated_string);
- return FALSE;
- }
- xmlFree (updated_string);
} else if (xmlStrcmp (node->name, (xmlChar*) "totalResults") == 0) {
/* openSearch:totalResults */
xmlChar *total_results_string;
diff --git a/gdata/gdata-parser.c b/gdata/gdata-parser.c
index 039d44e..3cb9cc4 100644
--- a/gdata/gdata-parser.c
+++ b/gdata/gdata-parser.c
@@ -300,6 +300,8 @@ gdata_parser_string_from_element (xmlNode *element, const gchar *element_name, G
xmlFree (text);
*success = gdata_parser_error_required_content_missing (element, error);
return TRUE;
+ } else if (options & P_DEFAULT && (text == NULL || *text == '\0')) {
+ text = (xmlChar*) g_strdup ("");
}
/* Success! */
@@ -311,6 +313,73 @@ gdata_parser_string_from_element (xmlNode *element, const gchar *element_name, G
}
/*
+ * gdata_parser_time_val_from_element:
+ * @element: the element to check against
+ * @element_name: the name of the element to parse
+ * @options: a bitwise combination of parsing options from #GDataParserOptions, or %P_NONE
+ * @output: the return location for the parsed time value
+ * @success: the return location for a value which is %TRUE if the time val was parsed successfully, %FALSE if an error was encountered,
+ * and undefined if @element didn't match @element_name
+ * @error: a #GError, or %NULL
+ *
+ * Gets the time value of @element if its name is @element_name, subject to various checks specified by @options. It expects the text content
+ * of @element to be a date or time value in ISO 8601 format.
+ *
+ * If @element doesn't match @element_name, %FALSE will be returned, @error will be unset and @success will be unset.
+ *
+ * If @element matches @element_name but one of the checks specified by @options fails, %TRUE will be returned, @error will be set to a
+ * %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error and @success will be set to %FALSE.
+ *
+ * If @element matches @element_name and all of the checks specified by @options pass, %TRUE will be returned, @error will be unset and
+ * @success will be set to %TRUE.
+ *
+ * The reason for returning the success of the parsing in @success is so that calls to gdata_parser_time_val_from_element() can be chained
+ * together in a large "or" statement based on their return values, for the purposes of determining whether any of the calls matched
+ * a given @element. If any of the calls to gdata_parser_time_val_from_element() return %TRUE, the value of @success can be examined.
+ *
+ * Return value: %TRUE if @element matched @element_name, %FALSE otherwise
+ *
+ * Since: 0.7.0
+ */
+gboolean
+gdata_parser_time_val_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
+ GTimeVal *output, gboolean *success, GError **error)
+{
+ xmlChar *text;
+
+ /* Check it's the right element */
+ if (xmlStrcmp (element->name, (xmlChar*) element_name) != 0)
+ return FALSE;
+
+ /* Check if the output time val has already been set */
+ if (options & P_NO_DUPES && (output->tv_sec != 0 || output->tv_usec != 0)) {
+ *success = gdata_parser_error_duplicate_element (element, error);
+ return TRUE;
+ }
+
+ /* Get the string and check it for NULLness */
+ text = xmlNodeListGetString (element->doc, element->children, TRUE);
+ if (options & P_REQUIRED && text == NULL) {
+ xmlFree (text);
+ *success = gdata_parser_error_required_content_missing (element, error);
+ return TRUE;
+ }
+
+ /* Attempt to parse the string as a GTimeVal */
+ if (g_time_val_from_iso8601 ((gchar*) text, output) == FALSE) {
+ *success = gdata_parser_error_not_iso8601_format (element, (gchar*) text, error);
+ xmlFree (text);
+ return TRUE;
+ }
+
+ /* Success! */
+ xmlFree (text);
+ *success = TRUE;
+
+ return TRUE;
+}
+
+/*
* gdata_parser_object_from_element_setter:
* @element: the element to check against
* @element_name: the name of the element to parse
diff --git a/gdata/gdata-parser.h b/gdata/gdata-parser.h
index c8d9692..7938eca 100644
--- a/gdata/gdata-parser.h
+++ b/gdata/gdata-parser.h
@@ -44,6 +44,8 @@ gchar *gdata_parser_date_from_time_val (const GTimeVal *_time) G_GNUC_WARN_UNUSE
* @P_REQUIRED: the element content must not be %NULL if the element exists
* @P_NON_EMPTY: the element content must not be empty (i.e. a zero-length string) if the element exists;
* this only applies to gdata_parser_string_from_element()
+ * @P_DEFAULT: if the element content is %NULL or empty, return an empty value instead of erroring (this is mutually exclusive with %P_REQUIRED
+ * and %P_NON_EMPTY)
*
* Parsing options to be passed in a bitwise fashion to gdata_parser_string_from_element() or gdata_parser_object_from_element().
* Their names aren't namespaced as they aren't public, and brevity is important, since they're used frequently in the parsing code.
@@ -54,7 +56,8 @@ typedef enum {
P_NONE = 0,
P_NO_DUPES = 1 << 0,
P_REQUIRED = 1 << 1,
- P_NON_EMPTY = 1 << 2
+ P_NON_EMPTY = 1 << 2,
+ P_DEFAULT = 1 << 3
} GDataParserOptions;
typedef void (*GDataParserSetterFunc) (GDataParsable *parent_parsable, GDataParsable *parsable);
@@ -62,6 +65,8 @@ typedef void (*GDataParserSetterFunc) (GDataParsable *parent_parsable, GDataPars
gboolean gdata_parser_boolean_from_property (xmlNode *element, const gchar *property_name, gboolean *output, gint default_output, GError **error);
gboolean gdata_parser_string_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
gchar **output, gboolean *success, GError **error);
+gboolean gdata_parser_time_val_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
+ GTimeVal *output, gboolean *success, GError **error);
gboolean gdata_parser_object_from_element_setter (xmlNode *element, const gchar *element_name, GDataParserOptions options, GType object_type,
gpointer /* GDataParserSetterFunc */ _setter, gpointer /* GDataParsable * */ _parent_parsable,
gboolean *success, GError **error);
diff --git a/gdata/gdata-private.h b/gdata/gdata-private.h
index 68a4b7f..3fbf3dd 100644
--- a/gdata/gdata-private.h
+++ b/gdata/gdata-private.h
@@ -80,6 +80,7 @@ void _gdata_feed_call_progress_callback (GDataFeed *self, gpointer user_data, GD
GFile *_gdata_documents_entry_download_document (GDataDocumentsEntry *self, GDataService *service, gchar **content_type, const gchar *download_uri,
GFile *destination_directory, const gchar *file_extension, gboolean replace_file_if_exists,
GCancellable *cancellable, GError **error) G_GNUC_WARN_UNUSED_RESULT;
+void _gdata_documents_entry_init_edited (GDataDocumentsEntry *self);
#include "gdata/services/documents/gdata-documents-service.h"
diff --git a/gdata/services/calendar/gdata-calendar-calendar.c b/gdata/services/calendar/gdata-calendar-calendar.c
index df92a2e..265e6a8 100644
--- a/gdata/services/calendar/gdata-calendar-calendar.c
+++ b/gdata/services/calendar/gdata-calendar-calendar.c
@@ -276,19 +276,20 @@ gdata_calendar_calendar_set_property (GObject *object, guint property_id, const
GDataCalendarCalendar *
gdata_calendar_calendar_new (const gchar *id)
{
- return g_object_new (GDATA_TYPE_CALENDAR_CALENDAR, "id", id, NULL);
+ GDataCalendarCalendar *calendar = GDATA_CALENDAR_CALENDAR (g_object_new (GDATA_TYPE_CALENDAR_CALENDAR, "id", id, NULL));
+
+ /* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
+ * setting it from parse_xml() to fail (duplicate element). */
+ g_get_current_time (&(calendar->priv->edited));
+
+ return calendar;
}
static gboolean
parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
{
- GDataCalendarCalendar *self;
-
- g_return_val_if_fail (GDATA_IS_CALENDAR_CALENDAR (parsable), FALSE);
- g_return_val_if_fail (doc != NULL, FALSE);
- g_return_val_if_fail (node != NULL, FALSE);
-
- self = GDATA_CALENDAR_CALENDAR (parsable);
+ gboolean success;
+ GDataCalendarCalendar *self = GDATA_CALENDAR_CALENDAR (parsable);
if (xmlStrcmp (node->name, (xmlChar*) "timezone") == 0) {
/* gCal:timezone */
@@ -340,16 +341,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
self->priv->access_level = (gchar*) xmlGetProp (node, (xmlChar*) "value");
if (self->priv->access_level == NULL)
return gdata_parser_error_required_property_missing (node, "value", error);
- } else if (xmlStrcmp (node->name, (xmlChar*) "edited") == 0) {
- /* app:edited */
- xmlChar *edited = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) edited, &(self->priv->edited)) == FALSE) {
- /* Error */
- gdata_parser_error_not_iso8601_format (node, (gchar*) edited, error);
- xmlFree (edited);
- return FALSE;
- }
- xmlFree (edited);
+ } else if (gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
+ return success;
} else if (GDATA_PARSABLE_CLASS (gdata_calendar_calendar_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
/* Error! */
return FALSE;
diff --git a/gdata/services/calendar/gdata-calendar-event.c b/gdata/services/calendar/gdata-calendar-event.c
index 4c38582..8a73a9b 100644
--- a/gdata/services/calendar/gdata-calendar-event.c
+++ b/gdata/services/calendar/gdata-calendar-event.c
@@ -441,31 +441,29 @@ gdata_calendar_event_set_property (GObject *object, guint property_id, const GVa
GDataCalendarEvent *
gdata_calendar_event_new (const gchar *id)
{
- return g_object_new (GDATA_TYPE_CALENDAR_EVENT, "id", id, NULL);
+ GDataCalendarEvent *event = GDATA_CALENDAR_EVENT (g_object_new (GDATA_TYPE_CALENDAR_EVENT, "id", id, NULL));
+
+ /* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
+ * setting it from parse_xml() to fail (duplicate element). */
+ g_get_current_time (&(event->priv->edited));
+
+ return event;
}
static gboolean
parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
{
gboolean success;
- GDataCalendarEvent *self;
-
- g_return_val_if_fail (GDATA_IS_CALENDAR_EVENT (parsable), FALSE);
- g_return_val_if_fail (doc != NULL, FALSE);
- g_return_val_if_fail (node != NULL, FALSE);
-
- self = GDATA_CALENDAR_EVENT (parsable);
-
- if (xmlStrcmp (node->name, (xmlChar*) "edited") == 0) {
- /* app:edited */
- xmlChar *edited = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) edited, &(self->priv->edited)) == FALSE) {
- /* Error */
- gdata_parser_error_not_iso8601_format (node, (gchar*) edited, error);
- xmlFree (edited);
- return FALSE;
- }
- xmlFree (edited);
+ GDataCalendarEvent *self = GDATA_CALENDAR_EVENT (parsable);
+
+ if (gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "when", P_REQUIRED, GDATA_TYPE_GD_WHEN,
+ gdata_calendar_event_add_time, self, &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "who", P_REQUIRED, GDATA_TYPE_GD_WHO,
+ gdata_calendar_event_add_person, self, &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "where", P_REQUIRED, GDATA_TYPE_GD_WHERE,
+ gdata_calendar_event_add_place, self, &success, error) == TRUE) {
+ return success;
} else if (xmlStrcmp (node->name, (xmlChar*) "comments") == 0) {
/* gd:comments */
xmlChar *rel, *href, *count_hint;
@@ -529,13 +527,6 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
xmlFree (value);
gdata_calendar_event_set_sequence (self, value_uint);
- } else if (gdata_parser_object_from_element_setter (node, "when", P_REQUIRED, GDATA_TYPE_GD_WHEN,
- gdata_calendar_event_add_time, self, &success, error) == TRUE ||
- gdata_parser_object_from_element_setter (node, "who", P_REQUIRED, GDATA_TYPE_GD_WHO,
- gdata_calendar_event_add_person, self, &success, error) == TRUE ||
- gdata_parser_object_from_element_setter (node, "where", P_REQUIRED, GDATA_TYPE_GD_WHERE,
- gdata_calendar_event_add_place, self, &success, error) == TRUE) {
- return success;
} else if (xmlStrcmp (node->name, (xmlChar*) "guestsCanModify") == 0) {
/* gCal:guestsCanModify */
gboolean guests_can_modify;
diff --git a/gdata/services/contacts/gdata-contacts-contact.c b/gdata/services/contacts/gdata-contacts-contact.c
index 7e71a98..c14cbd4 100644
--- a/gdata/services/contacts/gdata-contacts-contact.c
+++ b/gdata/services/contacts/gdata-contacts-contact.c
@@ -189,9 +189,6 @@ gdata_contacts_contact_init (GDataContactsContact *self)
g_signal_connect (self, "notify::title", (GCallback) notify_title_cb, self);
g_signal_connect (self->priv->name, "notify::full-name", (GCallback) notify_full_name_cb, self);
- /* Set the edited property to the current time (creation time) */
- g_get_current_time (&(self->priv->edited));
-
/* Add the "contact" kind category */
category = gdata_category_new ("http://schemas.google.com/contact/2008#contact", "http://schemas.google.com/g/2005#kind", NULL);
gdata_entry_add_category (GDATA_ENTRY (self), category);
@@ -284,43 +281,33 @@ gdata_contacts_contact_set_property (GObject *object, guint property_id, const G
GDataContactsContact *
gdata_contacts_contact_new (const gchar *id)
{
- return g_object_new (GDATA_TYPE_CONTACTS_CONTACT, "id", id, NULL);
+ GDataContactsContact *contact = GDATA_CONTACTS_CONTACT (g_object_new (GDATA_TYPE_CONTACTS_CONTACT, "id", id, NULL));
+
+ /* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
+ * setting it from parse_xml() to fail (duplicate element). */
+ g_get_current_time (&(contact->priv->edited));
+
+ return contact;
}
static gboolean
parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
{
gboolean success;
- GDataContactsContact *self;
-
- g_return_val_if_fail (GDATA_IS_CONTACTS_CONTACT (parsable), FALSE);
- g_return_val_if_fail (doc != NULL, FALSE);
- g_return_val_if_fail (node != NULL, FALSE);
-
- self = GDATA_CONTACTS_CONTACT (parsable);
-
- if (xmlStrcmp (node->name, (xmlChar*) "edited") == 0) {
- /* app:edited */
- /* TODO: Should be in GDataEntry? */
- xmlChar *edited = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) edited, &(self->priv->edited)) == FALSE) {
- /* Error */
- gdata_parser_error_not_iso8601_format (node, (gchar*) edited, error);
- g_free (edited);
- return FALSE;
- }
- g_free (edited);
- } else if (gdata_parser_object_from_element_setter (node, "email", P_REQUIRED, GDATA_TYPE_GD_EMAIL_ADDRESS,
- gdata_contacts_contact_add_email_address, self, &success, error) == TRUE ||
- gdata_parser_object_from_element_setter (node, "im", P_REQUIRED, GDATA_TYPE_GD_IM_ADDRESS,
- gdata_contacts_contact_add_im_address, self, &success, error) == TRUE ||
- gdata_parser_object_from_element_setter (node, "phoneNumber", P_REQUIRED, GDATA_TYPE_GD_PHONE_NUMBER,
- gdata_contacts_contact_add_phone_number, self, &success, error) == TRUE ||
- gdata_parser_object_from_element_setter (node, "structuredPostalAddress", P_REQUIRED, GDATA_TYPE_GD_POSTAL_ADDRESS,
- gdata_contacts_contact_add_postal_address, self, &success, error) == TRUE ||
- gdata_parser_object_from_element_setter (node, "organization", P_REQUIRED, GDATA_TYPE_GD_ORGANIZATION,
- gdata_contacts_contact_add_organization, self, &success, error) == TRUE ||
- gdata_parser_object_from_element (node, "name", P_REQUIRED, GDATA_TYPE_GD_NAME, &(self->priv->name), &success, error) == TRUE) {
+ GDataContactsContact *self = GDATA_CONTACTS_CONTACT (parsable);
+
+ if (gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "email", P_REQUIRED, GDATA_TYPE_GD_EMAIL_ADDRESS,
+ gdata_contacts_contact_add_email_address, self, &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "im", P_REQUIRED, GDATA_TYPE_GD_IM_ADDRESS,
+ gdata_contacts_contact_add_im_address, self, &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "phoneNumber", P_REQUIRED, GDATA_TYPE_GD_PHONE_NUMBER,
+ gdata_contacts_contact_add_phone_number, self, &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "structuredPostalAddress", P_REQUIRED, GDATA_TYPE_GD_POSTAL_ADDRESS,
+ gdata_contacts_contact_add_postal_address, self, &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "organization", P_REQUIRED, GDATA_TYPE_GD_ORGANIZATION,
+ gdata_contacts_contact_add_organization, self, &success, error) == TRUE ||
+ gdata_parser_object_from_element (node, "name", P_REQUIRED, GDATA_TYPE_GD_NAME, &(self->priv->name), &success, error) == TRUE) {
return success;
} else if (xmlStrcmp (node->name, (xmlChar*) "extendedProperty") == 0) {
/* gd:extendedProperty */
diff --git a/gdata/services/documents/gdata-documents-entry.c b/gdata/services/documents/gdata-documents-entry.c
index e31467f..5833ca5 100644
--- a/gdata/services/documents/gdata-documents-entry.c
+++ b/gdata/services/documents/gdata-documents-entry.c
@@ -181,8 +181,22 @@ static void
gdata_documents_entry_init (GDataDocumentsEntry *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_DOCUMENTS_ENTRY, GDataDocumentsEntryPrivate);
+}
- /* Initialise the edited properties to the current time */
+/*
+ * _gdata_documents_entry_init_edited:
+ * @self: a #GDataDocumentsEntry
+ *
+ * Initialises the #GDataDocumentsEntry:edited property of @self to the current time. This is designed
+ * to be called from the public constructors of classes which derive #GDataDocumentsEntry; it can't be
+ * put in the init function of #GDataDocumentsEntry, as it would then be called even for entries parsed
+ * from XML from the server, which would break duplicate element detection for the app:edited element.
+ *
+ * Since: 0.7.0
+ */
+void
+_gdata_documents_entry_init_edited (GDataDocumentsEntry *self)
+{
g_get_current_time (&(self->priv->edited));
}
@@ -204,22 +218,13 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
gboolean success;
GDataDocumentsEntry *self = GDATA_DOCUMENTS_ENTRY (parsable);
- if (xmlStrcmp (node->name, (xmlChar*) "edited") == 0) {
- xmlChar *edited = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) edited, &(self->priv->edited)) == FALSE) {
- gdata_parser_error_not_iso8601_format (node, (gchar*) edited, error);
- xmlFree (edited);
- return FALSE;
- }
- xmlFree (edited);
- } else if (xmlStrcmp (node->name, (xmlChar*) "lastViewed") == 0) {
- xmlChar *last_viewed = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) last_viewed, &(self->priv->last_viewed)) == FALSE) {
- gdata_parser_error_not_iso8601_format (node, (gchar*) last_viewed, error);
- xmlFree (last_viewed);
- return FALSE;
- }
- xmlFree (last_viewed);
+ if (gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE ||
+ gdata_parser_time_val_from_element (node, "lastViewed", P_REQUIRED | P_NO_DUPES, &(self->priv->last_viewed), &success, error) == TRUE ||
+ gdata_parser_object_from_element_setter (node, "feedLink", P_REQUIRED, GDATA_TYPE_LINK,
+ gdata_entry_add_link, self, &success, error) == TRUE ||
+ gdata_parser_object_from_element (node, "lastModifiedBy", P_REQUIRED, GDATA_TYPE_AUTHOR,
+ &(self->priv->last_modified_by), &success, error) == TRUE) {
+ return success;
} else if (xmlStrcmp (node->name, (xmlChar*) "writersCanInvite") == 0) {
if (gdata_parser_boolean_from_property (node, "value", &(self->priv->writers_can_invite), -1, error) == FALSE)
return FALSE;
@@ -250,11 +255,6 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
self->priv->document_id = g_strdup (document_id_parts[1]);
g_strfreev (document_id_parts);
- } else if (gdata_parser_object_from_element_setter (node, "feedLink", P_REQUIRED, GDATA_TYPE_LINK,
- gdata_entry_add_link, self, &success, error) == TRUE ||
- gdata_parser_object_from_element (node, "lastModifiedBy", P_REQUIRED, GDATA_TYPE_AUTHOR,
- &(self->priv->last_modified_by), &success, error) == TRUE) {
- return success;
} else if (GDATA_PARSABLE_CLASS (gdata_documents_entry_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
/* Error! */
return FALSE;
diff --git a/gdata/services/documents/gdata-documents-folder.c b/gdata/services/documents/gdata-documents-folder.c
index 3a87bd9..377faf7 100644
--- a/gdata/services/documents/gdata-documents-folder.c
+++ b/gdata/services/documents/gdata-documents-folder.c
@@ -68,7 +68,13 @@ gdata_documents_folder_class_init (GDataDocumentsFolderClass *klass)
GDataDocumentsFolder *
gdata_documents_folder_new (const gchar *id)
{
- return g_object_new (GDATA_TYPE_DOCUMENTS_FOLDER, "id", id, NULL);
+ GDataDocumentsFolder *folder = GDATA_DOCUMENTS_FOLDER (g_object_new (GDATA_TYPE_DOCUMENTS_FOLDER, "id", id, NULL));
+
+ /* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
+ * setting it from parse_xml() to fail (duplicate element). */
+ _gdata_documents_entry_init_edited (GDATA_DOCUMENTS_ENTRY (folder));
+
+ return folder;
}
static void
diff --git a/gdata/services/documents/gdata-documents-presentation.c b/gdata/services/documents/gdata-documents-presentation.c
index 2239578..a8b85cd 100644
--- a/gdata/services/documents/gdata-documents-presentation.c
+++ b/gdata/services/documents/gdata-documents-presentation.c
@@ -96,7 +96,13 @@ get_xml (GDataParsable *parsable, GString *xml_string)
GDataDocumentsPresentation *
gdata_documents_presentation_new (const gchar *id)
{
- return g_object_new (GDATA_TYPE_DOCUMENTS_PRESENTATION, "id", id, NULL);
+ GDataDocumentsPresentation *presentation = GDATA_DOCUMENTS_PRESENTATION (g_object_new (GDATA_TYPE_DOCUMENTS_PRESENTATION, "id", id, NULL));
+
+ /* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
+ * setting it from parse_xml() to fail (duplicate element). */
+ _gdata_documents_entry_init_edited (GDATA_DOCUMENTS_ENTRY (presentation));
+
+ return presentation;
}
/**
diff --git a/gdata/services/documents/gdata-documents-spreadsheet.c b/gdata/services/documents/gdata-documents-spreadsheet.c
index b44434d..6458608 100644
--- a/gdata/services/documents/gdata-documents-spreadsheet.c
+++ b/gdata/services/documents/gdata-documents-spreadsheet.c
@@ -96,7 +96,13 @@ get_xml (GDataParsable *parsable, GString *xml_string)
GDataDocumentsSpreadsheet *
gdata_documents_spreadsheet_new (const gchar *id)
{
- return g_object_new (GDATA_TYPE_DOCUMENTS_SPREADSHEET, "id", id, NULL);
+ GDataDocumentsSpreadsheet *spreadsheet = GDATA_DOCUMENTS_SPREADSHEET (g_object_new (GDATA_TYPE_DOCUMENTS_SPREADSHEET, "id", id, NULL));
+
+ /* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
+ * setting it from parse_xml() to fail (duplicate element). */
+ _gdata_documents_entry_init_edited (GDATA_DOCUMENTS_ENTRY (spreadsheet));
+
+ return spreadsheet;
}
/**
diff --git a/gdata/services/documents/gdata-documents-text.c b/gdata/services/documents/gdata-documents-text.c
index da42d2f..1c82753 100644
--- a/gdata/services/documents/gdata-documents-text.c
+++ b/gdata/services/documents/gdata-documents-text.c
@@ -98,7 +98,13 @@ get_xml (GDataParsable *parsable, GString *xml_string)
GDataDocumentsText *
gdata_documents_text_new (const gchar *id)
{
- return g_object_new (GDATA_TYPE_DOCUMENTS_TEXT, "id", id, NULL);
+ GDataDocumentsText *text = GDATA_DOCUMENTS_TEXT (g_object_new (GDATA_TYPE_DOCUMENTS_TEXT, "id", id, NULL));
+
+ /* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
+ * setting it from parse_xml() to fail (duplicate element). */
+ _gdata_documents_entry_init_edited (GDATA_DOCUMENTS_ENTRY (text));
+
+ return text;
}
/**
diff --git a/gdata/services/picasaweb/gdata-picasaweb-album.c b/gdata/services/picasaweb/gdata-picasaweb-album.c
index 96341bf..a06d64f 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-album.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-album.c
@@ -407,10 +407,6 @@ gdata_picasaweb_album_init (GDataPicasaWebAlbum *self)
self->priv->georss_where = g_object_new (GDATA_TYPE_GEORSS_WHERE, NULL);
self->priv->visibility = GDATA_PICASAWEB_PRIVATE;
- /* Initialise the timestamp and edited properties to the current time (bgo#599140) */
- g_get_current_time (&(self->priv->timestamp));
- g_get_current_time (&(self->priv->edited));
-
/* Connect to the notify::title signal from GDataEntry so our media:group title can be kept in sync
* (the title of an album is duplicated in atom:title and media:group/media:title) */
g_signal_connect (GDATA_ENTRY (self), "notify::title", G_CALLBACK (notify_title_cb), NULL);
@@ -558,18 +554,9 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
&(self->priv->georss_where), &success, error) == TRUE ||
gdata_parser_string_from_element (node, "user", P_REQUIRED | P_NON_EMPTY, &(self->priv->user), &success, error) == TRUE ||
gdata_parser_string_from_element (node, "nickname", P_REQUIRED | P_NON_EMPTY, &(self->priv->nickname), &success, error) == TRUE ||
- gdata_parser_string_from_element (node, "location", P_NONE, &(self->priv->location), &success, error) == TRUE) {
+ gdata_parser_string_from_element (node, "location", P_NONE, &(self->priv->location), &success, error) == TRUE ||
+ gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
return success;
- } else if (xmlStrcmp (node->name, (xmlChar*) "edited") == 0) {
- /* app:edited */
- xmlChar *edited = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) edited, &(self->priv->edited)) == FALSE) {
- /* Error */
- gdata_parser_error_not_iso8601_format (node, (gchar*) edited, error);
- xmlFree (edited);
- return FALSE;
- }
- xmlFree (edited);
} else if (xmlStrcmp (node->name, (xmlChar*) "access") == 0) {
/* gphoto:access */
xmlChar *access = xmlNodeListGetString (doc, node->children, TRUE);
@@ -736,7 +723,14 @@ get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
GDataPicasaWebAlbum *
gdata_picasaweb_album_new (const gchar *id)
{
- return g_object_new (GDATA_TYPE_PICASAWEB_ALBUM, "id", id, NULL);
+ GDataPicasaWebAlbum *album = GDATA_PICASAWEB_ALBUM (g_object_new (GDATA_TYPE_PICASAWEB_ALBUM, "id", id, NULL));
+
+ /* Set the edited and timestamp properties to the current time (creation time). bgo#599140
+ * We don't do this in *_init() since that would cause setting it from parse_xml() to fail (duplicate element). */
+ g_get_current_time (&(album->priv->timestamp));
+ g_get_current_time (&(album->priv->edited));
+
+ return album;
}
/**
diff --git a/gdata/services/picasaweb/gdata-picasaweb-file.c b/gdata/services/picasaweb/gdata-picasaweb-file.c
index 9cea5a1..851551a 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-file.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-file.c
@@ -592,10 +592,6 @@ gdata_picasaweb_file_init (GDataPicasaWebFile *self)
self->priv->georss_where = g_object_new (GDATA_TYPE_GEORSS_WHERE, NULL);
self->priv->is_commenting_enabled = TRUE;
- /* Initialise the timestamp and edited properties to the current time (bgo#599140) */
- g_get_current_time (&(self->priv->timestamp));
- g_get_current_time (&(self->priv->edited));
-
/* We need to keep atom:title (the canonical title for the file) in sync with media:group/media:title */
g_signal_connect (self, "notify::title", G_CALLBACK (notify_title_cb), NULL);
/* atom:summary (the canonical summary/caption for the file) in sync with media:group/media:description */
@@ -808,18 +804,9 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
gdata_parser_string_from_element (node, "imageVersion", P_NONE, &(self->priv->version), &success, error) == TRUE ||
gdata_parser_string_from_element (node, "albumid", P_NONE, &(self->priv->album_id), &success, error) == TRUE ||
gdata_parser_string_from_element (node, "client", P_NONE, &(self->priv->client), &success, error) == TRUE ||
- gdata_parser_string_from_element (node, "checksum", P_NONE, &(self->priv->client), &success, error) == TRUE) {
+ gdata_parser_string_from_element (node, "checksum", P_NONE, &(self->priv->client), &success, error) == TRUE ||
+ gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
return success;
- } else if (xmlStrcmp (node->name, (xmlChar*) "edited") == 0) {
- /* app:edited */
- xmlChar *edited = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) edited, &(self->priv->edited)) == FALSE) {
- /* Error */
- gdata_parser_error_not_iso8601_format (node, (gchar*) edited, error);
- xmlFree (edited);
- return FALSE;
- }
- xmlFree (edited);
} else if (xmlStrcmp (node->name, (xmlChar*) "position") == 0) {
/* gphoto:position */
xmlChar *position_str = xmlNodeListGetString (doc, node->children, TRUE);
@@ -971,7 +958,14 @@ get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
GDataPicasaWebFile *
gdata_picasaweb_file_new (const gchar *id)
{
- return g_object_new (GDATA_TYPE_PICASAWEB_FILE, "id", id, NULL);
+ GDataPicasaWebFile *file = GDATA_PICASAWEB_FILE (g_object_new (GDATA_TYPE_PICASAWEB_FILE, "id", id, NULL));
+
+ /* Set the edited and timestamp properties to the current time (creation time). bgo#599140
+ * We don't do this in *_init() since that would cause setting it from parse_xml() to fail (duplicate element). */
+ g_get_current_time (&(file->priv->timestamp));
+ g_get_current_time (&(file->priv->edited));
+
+ return file;
}
/**
diff --git a/gdata/services/youtube/gdata-youtube-group.c b/gdata/services/youtube/gdata-youtube-group.c
index 208195a..1b431a7 100644
--- a/gdata/services/youtube/gdata-youtube-group.c
+++ b/gdata/services/youtube/gdata-youtube-group.c
@@ -95,7 +95,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
if (gdata_parser_object_from_element_setter (node, "content", P_REQUIRED, GDATA_TYPE_YOUTUBE_CONTENT,
_gdata_media_group_add_content, self, &success, error) == TRUE ||
- gdata_parser_string_from_element (node, "videoid", P_NO_DUPES, &(self->priv->video_id), &success, error) == TRUE) {
+ gdata_parser_string_from_element (node, "videoid", P_NO_DUPES, &(self->priv->video_id), &success, error) == TRUE ||
+ gdata_parser_time_val_from_element (node, "uploaded", P_REQUIRED | P_NO_DUPES, &(self->priv->uploaded), &success, error) == TRUE) {
return success;
} else if (xmlStrcmp (node->name, (xmlChar*) "credit") == 0) {
/* media:credit */
@@ -121,21 +122,6 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
} else if (xmlStrcmp (node->name, (xmlChar*) "private") == 0) {
/* yt:private */
gdata_youtube_group_set_is_private (self, TRUE);
- } else if (xmlStrcmp (node->name, (xmlChar*) "uploaded") == 0) {
- /* yt:uploaded */
- xmlChar *uploaded;
- GTimeVal uploaded_timeval;
-
- uploaded = xmlNodeListGetString (doc, node->children, TRUE);
- if (g_time_val_from_iso8601 ((gchar*) uploaded, &uploaded_timeval) == FALSE) {
- /* Error */
- gdata_parser_error_not_iso8601_format (node, (gchar*) uploaded, error);
- xmlFree (uploaded);
- return FALSE;
- }
- xmlFree (uploaded);
-
- self->priv->uploaded = uploaded_timeval;
} else if (xmlStrcmp (node->name, (xmlChar*) "aspectRatio") == 0) {
/* yt:aspectRatio */
xmlChar *aspect_ratio = xmlNodeGetContent (node);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]