[libgdata] core: Add get_content_type virtual function to GDataParsable
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgdata] core: Add get_content_type virtual function to GDataParsable
- Date: Sat, 28 Sep 2013 14:50:53 +0000 (UTC)
commit da3aa429b5fba38b57aec40ecb37ab340cce90a5
Author: Peteris Krisjanis <pecisk gmail com>
Date: Sat Sep 28 16:53:49 2013 +0300
core: Add get_content_type virtual function to GDataParsable
Adding get_content_type virtual function to GDataParsable to allow
insert/update/delete_entry functions in GDataService to distinguish between
JSON and XML based GDataParsables. GDataParsable subclass who uses JSON
format data define their virtual function and return const gchar* string
application/json. Otherwise GDataParsable own defined virtual function will
return application/atom+xml. For insert/update_entry it allows to choose
between two different calls to build xml or json message, and also in return
parse returned data from online service correctly. For delete_entry it
allows to choose different link from links list, as for json it is stored in
different place.
Helps: https://bugzilla.gnome.org/show_bug.cgi?id=657539
gdata/gdata-parsable.c | 7 ++++
gdata/gdata-parsable.h | 3 ++
gdata/gdata-service.c | 95 +++++++++++++++++++++++++++++++++---------------
3 files changed, 75 insertions(+), 30 deletions(-)
---
diff --git a/gdata/gdata-parsable.c b/gdata/gdata-parsable.c
index f9e1dfb..2472c76 100644
--- a/gdata/gdata-parsable.c
+++ b/gdata/gdata-parsable.c
@@ -53,6 +53,7 @@ static void gdata_parsable_set_property (GObject *object, guint property_id, con
static void gdata_parsable_finalize (GObject *object);
static gboolean real_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data,
GError **error);
static gboolean real_parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, GError
**error);
+static const gchar *get_content_type (void);
struct _GDataParsablePrivate {
/* XML stuff. */
@@ -83,6 +84,7 @@ gdata_parsable_class_init (GDataParsableClass *klass)
gobject_class->finalize = gdata_parsable_finalize;
klass->parse_xml = real_parse_xml;
klass->parse_json = real_parse_json;
+ klass->get_content_type = get_content_type;
/**
* GDataParsable:constructed-from-xml:
@@ -275,6 +277,11 @@ real_parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data
return TRUE;
}
+static const gchar *
+get_content_type (void) {
+ return "application/atom+xml";
+}
+
/**
* gdata_parsable_new_from_xml:
* @parsable_type: the type of the class represented by the XML
diff --git a/gdata/gdata-parsable.h b/gdata/gdata-parsable.h
index 2f13c25..ec332db 100644
--- a/gdata/gdata-parsable.h
+++ b/gdata/gdata-parsable.h
@@ -77,6 +77,7 @@ typedef struct {
* @parse_json: a function to parse a JSON representation of the #GDataParsable to set the properties of the
@parsable
* @post_parse_json: a function called after parsing a JSON object, to allow the @parsable to validate the
parsed properties
* @get_json: a function to build a JSON representation of the #GDataParsable in its current state,
appending it to the provided #JsonBuilder
+ * @get_content_type: a function which returns content type upon which is #GDataParsable built
* @element_name: the name of the XML element which represents this parsable
* @element_namespace: the prefix of the XML namespace used for the parsable
*
@@ -100,6 +101,8 @@ typedef struct {
gboolean (*post_parse_json) (GDataParsable *parsable, gpointer user_data, GError **error);
void (*get_json) (GDataParsable *parsable, JsonBuilder *builder);
+ const gchar *(*get_content_type) (void);
+
const gchar *element_name;
const gchar *element_namespace;
} GDataParsableClass;
diff --git a/gdata/gdata-service.c b/gdata/gdata-service.c
index 9d446c9..28a5460 100644
--- a/gdata/gdata-service.c
+++ b/gdata/gdata-service.c
@@ -1350,6 +1350,7 @@ gdata_service_insert_entry (GDataService *self, GDataAuthorizationDomain *domain
SoupMessage *message;
gchar *upload_data;
guint status;
+ GDataParsableClass *klass;
g_return_val_if_fail (GDATA_IS_SERVICE (self), NULL);
g_return_val_if_fail (domain == NULL || GDATA_IS_AUTHORIZATION_DOMAIN (domain), NULL);
@@ -1367,8 +1368,15 @@ gdata_service_insert_entry (GDataService *self, GDataAuthorizationDomain *domain
message = _gdata_service_build_message (self, domain, SOUP_METHOD_POST, upload_uri, NULL, FALSE);
/* Append the data */
- upload_data = gdata_parsable_get_xml (GDATA_PARSABLE (entry));
- soup_message_set_request (message, "application/atom+xml", SOUP_MEMORY_TAKE, upload_data, strlen
(upload_data));
+ klass = GDATA_PARSABLE_GET_CLASS (entry);
+ g_assert (klass->get_content_type != NULL);
+ if (g_strcmp0 (klass->get_content_type (), "application/json") == 0) {
+ upload_data = gdata_parsable_get_json (GDATA_PARSABLE (entry));
+ soup_message_set_request (message, "application/json", SOUP_MEMORY_TAKE, upload_data, strlen
(upload_data));
+ } else {
+ upload_data = gdata_parsable_get_xml (GDATA_PARSABLE (entry));
+ soup_message_set_request (message, "application/atom+xml", SOUP_MEMORY_TAKE, upload_data,
strlen (upload_data));
+ }
/* Send the message */
status = _gdata_service_send_message (self, message, cancellable, error);
@@ -1377,20 +1385,25 @@ gdata_service_insert_entry (GDataService *self, GDataAuthorizationDomain *domain
/* Redirect error or cancelled */
g_object_unref (message);
return NULL;
- } else if (status != SOUP_STATUS_CREATED) {
- /* Error */
- GDataServiceClass *klass = GDATA_SERVICE_GET_CLASS (self);
- g_assert (klass->parse_error_response != NULL);
- klass->parse_error_response (self, GDATA_OPERATION_INSERTION, status, message->reason_phrase,
message->response_body->data,
- message->response_body->length, error);
+ } else if (status != SOUP_STATUS_CREATED && status != SOUP_STATUS_OK) {
+ /* Error: for XML APIs Google returns CREATED and for JSON it returns OK. */
+ GDataServiceClass *service_klass = GDATA_SERVICE_GET_CLASS (self);
+ g_assert (service_klass->parse_error_response != NULL);
+ service_klass->parse_error_response (self, GDATA_OPERATION_INSERTION, status,
message->reason_phrase, message->response_body->data,
+ message->response_body->length, error);
g_object_unref (message);
return NULL;
}
- /* Parse the XML; create and return a new GDataEntry of the same type as @entry */
+ /* Parse the XML or JSON according to GDataEntry type; create and return a new GDataEntry of the same
type as @entry */
g_assert (message->response_body->data != NULL);
- updated_entry = GDATA_ENTRY (gdata_parsable_new_from_xml (G_OBJECT_TYPE (entry),
message->response_body->data, message->response_body->length,
- error));
+ if (g_strcmp0 (klass->get_content_type (), "application/json") == 0) {
+ updated_entry = GDATA_ENTRY (gdata_parsable_new_from_json (G_OBJECT_TYPE (entry),
message->response_body->data,
+ message->response_body->length, error));
+ } else {
+ updated_entry = GDATA_ENTRY (gdata_parsable_new_from_xml (G_OBJECT_TYPE (entry),
message->response_body->data,
+ message->response_body->length, error));
+ }
g_object_unref (message);
return updated_entry;
@@ -1541,6 +1554,7 @@ gdata_service_update_entry (GDataService *self, GDataAuthorizationDomain *domain
SoupMessage *message;
gchar *upload_data;
guint status;
+ GDataParsableClass *klass;
g_return_val_if_fail (GDATA_IS_SERVICE (self), NULL);
g_return_val_if_fail (domain == NULL || GDATA_IS_AUTHORIZATION_DOMAIN (domain), NULL);
@@ -1548,14 +1562,24 @@ gdata_service_update_entry (GDataService *self, GDataAuthorizationDomain *domain
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- /* Get the edit URI */
- _link = gdata_entry_look_up_link (entry, GDATA_LINK_EDIT);
- g_assert (_link != NULL);
- message = _gdata_service_build_message (self, domain, SOUP_METHOD_PUT, gdata_link_get_uri (_link),
gdata_entry_get_etag (entry), TRUE);
-
/* Append the data */
- upload_data = gdata_parsable_get_xml (GDATA_PARSABLE (entry));
- soup_message_set_request (message, "application/atom+xml", SOUP_MEMORY_TAKE, upload_data, strlen
(upload_data));
+ klass = GDATA_PARSABLE_GET_CLASS (entry);
+ g_assert (klass->get_content_type != NULL);
+ if (g_strcmp0 (klass->get_content_type (), "application/json") == 0) {
+ /* Get the edit URI */
+ _link = gdata_entry_look_up_link (entry, GDATA_LINK_SELF);
+ g_assert (_link != NULL);
+ message = _gdata_service_build_message (self, domain, SOUP_METHOD_PUT, gdata_link_get_uri
(_link), gdata_entry_get_etag (entry), TRUE);
+ upload_data = gdata_parsable_get_json (GDATA_PARSABLE (entry));
+ soup_message_set_request (message, "application/json", SOUP_MEMORY_TAKE, upload_data, strlen
(upload_data));
+ } else {
+ /* Get the edit URI */
+ _link = gdata_entry_look_up_link (entry, GDATA_LINK_EDIT);
+ g_assert (_link != NULL);
+ message = _gdata_service_build_message (self, domain, SOUP_METHOD_PUT, gdata_link_get_uri
(_link), gdata_entry_get_etag (entry), TRUE);
+ upload_data = gdata_parsable_get_xml (GDATA_PARSABLE (entry));
+ soup_message_set_request (message, "application/atom+xml", SOUP_MEMORY_TAKE, upload_data,
strlen (upload_data));
+ }
/* Send the message */
status = _gdata_service_send_message (self, message, cancellable, error);
@@ -1566,18 +1590,22 @@ gdata_service_update_entry (GDataService *self, GDataAuthorizationDomain *domain
return NULL;
} else if (status != SOUP_STATUS_OK) {
/* Error */
- GDataServiceClass *klass = GDATA_SERVICE_GET_CLASS (self);
- g_assert (klass->parse_error_response != NULL);
- klass->parse_error_response (self, GDATA_OPERATION_UPDATE, status, message->reason_phrase,
message->response_body->data,
- message->response_body->length, error);
+ GDataServiceClass *service_klass = GDATA_SERVICE_GET_CLASS (self);
+ g_assert (service_klass->parse_error_response != NULL);
+ service_klass->parse_error_response (self, GDATA_OPERATION_UPDATE, status,
message->reason_phrase, message->response_body->data,
+ message->response_body->length, error);
g_object_unref (message);
return NULL;
}
/* Parse the XML; create and return a new GDataEntry of the same type as @entry */
- g_assert (message->response_body->data != NULL);
- updated_entry = GDATA_ENTRY (gdata_parsable_new_from_xml (G_OBJECT_TYPE (entry),
message->response_body->data, message->response_body->length,
- error));
+ if (g_strcmp0 (klass->get_content_type (), "application/json") == 0) {
+ updated_entry = GDATA_ENTRY (gdata_parsable_new_from_json (G_OBJECT_TYPE (entry),
message->response_body->data,
+ message->response_body->length, error));
+ } else {
+ updated_entry = GDATA_ENTRY (gdata_parsable_new_from_xml (G_OBJECT_TYPE (entry),
message->response_body->data,
+ message->response_body->length, error));
+ }
g_object_unref (message);
return updated_entry;
@@ -1721,6 +1749,7 @@ gdata_service_delete_entry (GDataService *self, GDataAuthorizationDomain *domain
SoupMessage *message;
guint status;
gchar *fixed_uri;
+ GDataParsableClass *klass;
g_return_val_if_fail (GDATA_IS_SERVICE (self), FALSE);
g_return_val_if_fail (domain == NULL || GDATA_IS_AUTHORIZATION_DOMAIN (domain), FALSE);
@@ -1729,7 +1758,13 @@ gdata_service_delete_entry (GDataService *self, GDataAuthorizationDomain *domain
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* Get the edit URI. We have to fix it to always use HTTPS as YouTube videos appear to incorrectly
return a HTTP URI as their edit URI. */
- _link = gdata_entry_look_up_link (entry, GDATA_LINK_EDIT);
+ klass = GDATA_PARSABLE_GET_CLASS (entry);
+ g_assert (klass->get_content_type != NULL);
+ if (g_strcmp0 (klass->get_content_type (), "application/json") == 0) {
+ _link = gdata_entry_look_up_link (entry, GDATA_LINK_SELF);
+ } else {
+ _link = gdata_entry_look_up_link (entry, GDATA_LINK_EDIT);
+ }
g_assert (_link != NULL);
fixed_uri = _gdata_service_fix_uri_scheme (gdata_link_get_uri (_link));
@@ -1745,10 +1780,10 @@ gdata_service_delete_entry (GDataService *self, GDataAuthorizationDomain *domain
return FALSE;
} else if (status != SOUP_STATUS_OK) {
/* Error */
- GDataServiceClass *klass = GDATA_SERVICE_GET_CLASS (self);
- g_assert (klass->parse_error_response != NULL);
- klass->parse_error_response (self, GDATA_OPERATION_DELETION, status, message->reason_phrase,
message->response_body->data,
- message->response_body->length, error);
+ GDataServiceClass *service_klass = GDATA_SERVICE_GET_CLASS (self);
+ g_assert (service_klass->parse_error_response != NULL);
+ service_klass->parse_error_response (self, GDATA_OPERATION_DELETION, status,
message->reason_phrase, message->response_body->data,
+ message->response_body->length, error);
g_object_unref (message);
return FALSE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]