/**
 * gdata_contacts_service_insert_group:
 * @self: a #GDataContactsService
 * @group: a #GDataContactsGroup to create on the server
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 * @error: a #GError, or %NULL
 *
 * Inserts a new contact group described by @group. The user must be authenticated to use this function.
 *
 * Return value: (transfer full): the inserted #GDataContactsGroup; unref with g_object_unref()
 *
 * Since: 0.7.0
 **/
GDataContactsGroup *
gdata_contacts_service_insert_group (GDataContactsService *self, GDataContactsGroup *group, GCancellable *cancellable, GError **error)
{
	gchar *request_uri;
	GDataEntry *new_group;

	g_return_val_if_fail (GDATA_IS_CONTACTS_SERVICE (self), NULL);
	g_return_val_if_fail (GDATA_IS_CONTACTS_GROUP (group), NULL);
	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
	g_return_val_if_fail (error == NULL || *error == NULL, NULL);

	if (gdata_entry_is_inserted (GDATA_ENTRY (group)) == TRUE) {
		g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED,
		                     _("The group has already been inserted."));
		return NULL;
	}

	if (gdata_authorizer_is_authorized_for_domain (gdata_service_get_authorizer (GDATA_SERVICE (self)),
	                                               get_contacts_authorization_domain ()) == FALSE) {
		g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED,
		                     _("You must be authenticated to insert a group."));
		return NULL;
	}

	request_uri = g_strconcat (_gdata_service_get_scheme (), "://www.google.com/m8/feeds/groups/default/full", NULL);
	new_group = gdata_service_insert_entry (GDATA_SERVICE (self), get_contacts_authorization_domain (), request_uri, GDATA_ENTRY (group),
	                                        cancellable, error);
	g_free (request_uri);

	return GDATA_CONTACTS_GROUP (new_group);
}
/**
 * gdata_access_handler_insert_rule:
 * @self: a #GDataAccessHandler
 * @service: a #GDataService
 * @rule: the #GDataAccessRule to insert
 * @cancellable: optional #GCancellable object, or %NULL
 * @error: a #GError, or %NULL
 *
 * Inserts @rule in the access control list of the #GDataAccessHandler.
 *
 * The service will return an updated version of the rule, which is the return value of this function on success.
 *
 * If @cancellable is not %NULL, then the operation can be cancelled by triggering the @cancellable object from another thread.
 * If the operation was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
 *
 * If the rule is marked as already having been inserted a %GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED error will be returned immediately
 * (there will be no network requests).
 *
 * If there is an error inserting the rule, a %GDATA_SERVICE_ERROR_WITH_INSERTION error will be returned.
 *
 * Return value: an updated #GDataAccessRule, or %NULL
 *
 * Since: 0.3.0
 **/
GDataAccessRule *
gdata_access_handler_insert_rule (GDataAccessHandler *self, GDataService *service, GDataAccessRule *rule, GCancellable *cancellable, GError **error)
{
	GDataServiceClass *klass;
	GDataAccessRule *updated_rule;
	GDataLink *link;
	SoupMessage *message;
	gchar *upload_data;
	guint status;

	g_return_val_if_fail (GDATA_IS_ENTRY (self), NULL);
	g_return_val_if_fail (GDATA_IS_SERVICE (service), NULL);
	g_return_val_if_fail (GDATA_IS_ACCESS_RULE (rule), NULL);

	if (gdata_entry_is_inserted (GDATA_ENTRY (rule)) == TRUE) {
		g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED,
				     _("The rule has already been inserted."));
		return NULL;
	}

	/* Get the ACL URI */
	link = gdata_entry_look_up_link (GDATA_ENTRY (self), "http://schemas.google.com/acl/2007#accessControlList");
	g_assert (link != NULL);
	message = soup_message_new (SOUP_METHOD_POST, link->href);

	/* Make sure subclasses set their headers */
	klass = GDATA_SERVICE_GET_CLASS (service);
	if (klass->append_query_headers != NULL)
		klass->append_query_headers (service, message);

	/* Append the data */
	upload_data = gdata_entry_get_xml (GDATA_ENTRY (rule));
	soup_message_set_request (message, "application/atom+xml", SOUP_MEMORY_TAKE, upload_data, strlen (upload_data));

	/* Send the message */
	status = _gdata_service_send_message (service, message, error);
	if (status == SOUP_STATUS_NONE) {
		g_object_unref (message);
		return NULL;
	}

	/* Check for cancellation */
	if (g_cancellable_set_error_if_cancelled (cancellable, error) == TRUE) {
		g_object_unref (message);
		return NULL;
	}

	if (status != 201) {
		/* Error */
		g_assert (klass->parse_error_response != NULL);
		klass->parse_error_response (service, GDATA_SERVICE_ERROR_WITH_INSERTION, status, message->reason_phrase, message->response_body->data,
					     message->response_body->length, error);
		g_object_unref (message);
		return NULL;
	}

	/* Build the updated entry */
	g_assert (message->response_body->data != NULL);

	/* Parse the XML; create and return a new GDataEntry of the same type as @entry */
	updated_rule = GDATA_ACCESS_RULE (_gdata_entry_new_from_xml (G_OBJECT_TYPE (rule), message->response_body->data,
					  message->response_body->length, error));
	g_object_unref (message);

	return updated_rule;
}