Update jsonapi to current specs, refactor
authorMartin Schanzenbach <mschanzenbach@posteo.de>
Wed, 4 May 2016 17:18:02 +0000 (17:18 +0000)
committerMartin Schanzenbach <mschanzenbach@posteo.de>
Wed, 4 May 2016 17:18:02 +0000 (17:18 +0000)
15 files changed:
src/gns/plugin_rest_gns.c
src/identity-provider/gnunet-service-identity-provider.c
src/identity-provider/plugin_rest_identity_provider.c
src/identity/plugin_rest_identity.c
src/include/gnunet_jsonapi_lib.h
src/jsonapi/Makefile.am
src/jsonapi/jsonapi.c
src/jsonapi/jsonapi_document.c [new file with mode: 0644]
src/jsonapi/jsonapi_error.c [new file with mode: 0644]
src/jsonapi/jsonapi_objects.h [new file with mode: 0644]
src/jsonapi/jsonapi_relationship.c [new file with mode: 0644]
src/jsonapi/jsonapi_resource.c [new file with mode: 0644]
src/jsonapi/test_jsonapi.c
src/namestore/plugin_rest_namestore.c
src/rest/gnunet-rest-server.c

index 718a9b29bb74e06f3cbca6169a84df5e6a942c35..b2034c8cee9900cb8224f806baa1ab854e4f930a 100644 (file)
@@ -258,7 +258,7 @@ gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd)
                 (int) rd->record_type);
     return NULL;
   }
-  record_obj = json_object();
+  record_obj = json_object ();
   json_object_set_new (record_obj, "type", json_string (typename));
   json_object_set_new (record_obj, "value", json_string (string_val));
   GNUNET_free (string_val);
@@ -295,7 +295,7 @@ process_lookup_result (void *cls, uint32_t rd_count,
 {
   struct LookupHandle *handle = cls;
   struct MHD_Response *resp;
-  struct GNUNET_JSONAPI_Object *json_object;
+  struct GNUNET_JSONAPI_Document *json_document;
   struct GNUNET_JSONAPI_Resource *json_resource;
   uint32_t i;
   char *result;
@@ -303,7 +303,7 @@ process_lookup_result (void *cls, uint32_t rd_count,
   json_t *record_obj;
 
   result_array = json_array();
-  json_object = GNUNET_JSONAPI_object_new ();
+  json_document = GNUNET_JSONAPI_document_new ();
   json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_GNS_TYPEINFO, handle->name);
   handle->lookup_request = NULL;
   for (i=0; i<rd_count; i++)
@@ -318,11 +318,11 @@ process_lookup_result (void *cls, uint32_t rd_count,
   GNUNET_JSONAPI_resource_add_attr (json_resource,
                                          GNUNET_REST_JSONAPI_GNS_RECORD,
                                          result_array);
-  GNUNET_JSONAPI_object_resource_add (json_object, json_resource);
-  GNUNET_JSONAPI_data_serialize (json_object, &result);
+  GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
+  GNUNET_JSONAPI_document_serialize (json_document, &result);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
   json_decref (result_array);
-  GNUNET_JSONAPI_object_delete (json_object);
+  GNUNET_JSONAPI_document_delete (json_document);
   resp = GNUNET_REST_create_json_response (result);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result);
index 0bb400e07bfc58107e5e1bdc56257de1651b375d..0a690e2d3a2e05ec237b9d41cb7b852113156f66 100644 (file)
@@ -481,7 +481,6 @@ handle_token_update (void *cls)
                                           token_record,
                                           &store_token_cont,
                                           ego_entry);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, ">>> Updating Token w/ %s\n", new_token);
   token_destroy (new_token);
   token_destroy (token);
   GNUNET_free (new_ecdhe_privkey);
@@ -725,7 +724,7 @@ update_identities(void *cls)
     if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
       min_rel_exp = MIN_WAIT_TIME;
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                ">>> Finished. Rescheduling in %d\n",
+                ">>> Finished. Rescheduling in %lu\n",
                 min_rel_exp.rel_value_us);
     ns_it = NULL;
     //finished -> reschedule
index 1e1878cadc713a836a78994a1d2e4bb15f0f89a2..b039255b5f01cea7cbecba672b3cce64d8c7b18e 100644 (file)
@@ -279,7 +279,7 @@ struct RequestHandle
   /**
    * Response object
    */
-  struct GNUNET_JSONAPI_Object *resp_object;
+  struct GNUNET_JSONAPI_Document *resp_object;
 
 };
 
@@ -296,7 +296,7 @@ cleanup_handle (struct RequestHandle *handle)
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Cleaning up\n");
   if (NULL != handle->resp_object)
-    GNUNET_JSONAPI_object_delete (handle->resp_object);
+    GNUNET_JSONAPI_document_delete (handle->resp_object);
   if (NULL != handle->timeout_task)
     GNUNET_SCHEDULER_cancel (handle->timeout_task);
   if (NULL != handle->identity_handle)
@@ -403,7 +403,7 @@ token_creat_cont (void *cls,
     return;
   }
 
-  handle->resp_object = GNUNET_JSONAPI_object_new ();
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
   json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_PROVIDER_TICKET,
                                                     label);
   ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket);
@@ -420,9 +420,9 @@ token_creat_cont (void *cls,
   GNUNET_free (token_str);
   json_decref (ticket_json);
   json_decref (token_json);
-  GNUNET_JSONAPI_object_resource_add (handle->resp_object, json_resource);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
 
-  GNUNET_JSONAPI_data_serialize (handle->resp_object, &result_str);
+  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
   resp = GNUNET_REST_create_json_response (result_str);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
@@ -638,7 +638,7 @@ return_token_list (void *cls)
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
 
-  GNUNET_JSONAPI_data_serialize (handle->resp_object, &result_str);
+  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
   resp = GNUNET_REST_create_json_response (result_str);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
@@ -717,7 +717,7 @@ token_collect (void *cls,
                                              token);
       json_decref (token);
 
-      GNUNET_JSONAPI_object_resource_add (handle->resp_object, json_resource);
+      GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
       GNUNET_free (data);
     }
   }
@@ -776,7 +776,7 @@ list_token_cont (struct GNUNET_REST_RequestHandle *con_handle,
       GNUNET_free (ego_tmp);
     }
   }
-  handle->resp_object = GNUNET_JSONAPI_object_new ();
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
   if (NULL == handle->ego_head)
   {
     //Done
@@ -1045,7 +1045,7 @@ list_ego (void *cls,
     ego_entry->keystring =
       GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
     ego_entry->ego = ego;
-    GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
+    ego_entry->identifier = GNUNET_strdup (identifier);
     GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
   }
 
@@ -1076,7 +1076,7 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
   handle->conndata_handle = conndata_handle;
 
 
-  GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
+  handle->url = GNUNET_strdup (conndata_handle->url);
   if (handle->url[strlen (handle->url)-1] == '/')
     handle->url[strlen (handle->url)-1] = '\0';
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
index 4a2429a9ccc826c6d8811992bd7f42747d048868..50d13713a575a720611d73041682485e12ed22c3 100644 (file)
@@ -302,14 +302,14 @@ get_ego_for_subsys (void *cls,
                     const char *name)
 {
   struct RequestHandle *handle = cls;
-  struct GNUNET_JSONAPI_Object *json_object;
+  struct GNUNET_JSONAPI_Document *json_document;
   struct GNUNET_JSONAPI_Resource *json_resource;
   struct EgoEntry *ego_entry;
   struct MHD_Response *resp;
   json_t *name_json;
   char *result_str;
 
-  json_object = GNUNET_JSONAPI_object_new ();
+  json_document = GNUNET_JSONAPI_document_new ();
 
   for (ego_entry = handle->ego_head;
        NULL != ego_entry;
@@ -326,20 +326,20 @@ get_ego_for_subsys (void *cls,
                                            GNUNET_REST_JSONAPI_IDENTITY_NAME,
                                            name_json);
     json_decref (name_json);
-    GNUNET_JSONAPI_object_resource_add (json_object, json_resource);
+    GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
     break;
   }
-  if (0 == GNUNET_JSONAPI_object_resource_count (json_object))
+  if (0 == GNUNET_JSONAPI_document_resource_count (json_document))
   {
-    GNUNET_JSONAPI_object_delete (json_object);
+    GNUNET_JSONAPI_document_delete (json_document);
     handle->emsg = GNUNET_strdup("No identity matches results!");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  GNUNET_JSONAPI_data_serialize (json_object, &result_str);
+  GNUNET_JSONAPI_document_serialize (json_document, &result_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
   resp = GNUNET_REST_create_json_response (result_str);
-  GNUNET_JSONAPI_object_delete (json_object);
+  GNUNET_JSONAPI_document_delete (json_document);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result_str);
   cleanup_handle (handle);
@@ -365,7 +365,7 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con,
   struct EgoEntry *ego_entry;
   struct GNUNET_HashCode key;
   struct MHD_Response *resp;
-  struct GNUNET_JSONAPI_Object *json_object;
+  struct GNUNET_JSONAPI_Document *json_document;
   struct GNUNET_JSONAPI_Resource *json_resource;
   json_t *name_str;
 
@@ -415,7 +415,7 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con,
     }
   }
 
-  json_object = GNUNET_JSONAPI_object_new ();
+  json_document = GNUNET_JSONAPI_document_new ();
 
   //Return all egos
   for (ego_entry = handle->ego_head;
@@ -432,19 +432,19 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con,
                                            GNUNET_REST_JSONAPI_IDENTITY_NAME,
                                            name_str);
     json_decref (name_str);
-    GNUNET_JSONAPI_object_resource_add (json_object, json_resource);
+    GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
   }
-  if (0 == GNUNET_JSONAPI_object_resource_count (json_object))
+  if (0 == GNUNET_JSONAPI_document_resource_count (json_document))
   {
-    GNUNET_JSONAPI_object_delete (json_object);
+    GNUNET_JSONAPI_document_delete (json_document);
     handle->emsg = GNUNET_strdup ("No identities found!");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  GNUNET_JSONAPI_data_serialize (json_object, &result_str);
+  GNUNET_JSONAPI_document_serialize (json_document, &result_str);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
   resp = GNUNET_REST_create_json_response (result_str);
-  GNUNET_JSONAPI_object_delete (json_object);
+  GNUNET_JSONAPI_document_delete (json_document);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result_str);
   cleanup_handle (handle);
@@ -489,7 +489,7 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con,
   struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
   struct MHD_Response *resp;
-  struct GNUNET_JSONAPI_Object *json_obj;
+  struct GNUNET_JSONAPI_Document *json_obj;
   struct GNUNET_JSONAPI_Resource *json_res;
   json_t *egoname_json;
   const char* egoname;
@@ -509,24 +509,24 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con,
   }
   term_data[handle->data_size] = '\0';
   memcpy (term_data, handle->data, handle->data_size);
-  GNUNET_assert (GNUNET_OK == GNUNET_JSONAPI_object_parse (term_data,
+  GNUNET_assert (GNUNET_OK == GNUNET_JSONAPI_document_parse (term_data,
                                                            &json_obj));
   if (NULL == json_obj)
   {
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  if (1 != GNUNET_JSONAPI_object_resource_count (json_obj))
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
   {
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     handle->emsg = GNUNET_strdup ("Provided resource count invalid");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  json_res = GNUNET_JSONAPI_object_get_resource (json_obj, 0);
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
   if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO))
   {
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     resp = GNUNET_REST_create_json_response (NULL);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
     cleanup_handle (handle);
@@ -535,7 +535,7 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con,
   egoname_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_NAME);
   if (!json_is_string (egoname_json))
   {
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     handle->emsg = GNUNET_strdup ("No name provided");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
@@ -547,7 +547,7 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con,
   {
     if (0 == strcasecmp (egoname, ego_entry->identifier))
     {
-      GNUNET_JSONAPI_object_delete (json_obj);
+      GNUNET_JSONAPI_document_delete (json_obj);
       resp = GNUNET_REST_create_json_response (NULL);
       handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
       cleanup_handle (handle);
@@ -555,7 +555,7 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con,
     }
   }
   GNUNET_asprintf (&handle->name, "%s", egoname);
-  GNUNET_JSONAPI_object_delete (json_obj);
+  GNUNET_JSONAPI_document_delete (json_obj);
   handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
                                        handle->name,
                                        &do_finished,
@@ -575,7 +575,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con,
                const char *url,
                void *cls)
 {
-  struct GNUNET_JSONAPI_Object *json_obj;
+  struct GNUNET_JSONAPI_Document *json_obj;
   struct GNUNET_JSONAPI_Resource *json_res;
   struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
@@ -624,7 +624,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con,
 
   term_data[handle->data_size] = '\0';
   memcpy (term_data, handle->data, handle->data_size);
-  GNUNET_assert (GNUNET_OK == GNUNET_JSONAPI_object_parse (term_data,
+  GNUNET_assert (GNUNET_OK == GNUNET_JSONAPI_document_parse (term_data,
                                                            &json_obj));
 
   if (NULL == json_obj)
@@ -634,18 +634,18 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con,
     return;
   }
 
-  if (1 != GNUNET_JSONAPI_object_resource_count (json_obj))
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
   {
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     handle->emsg = GNUNET_strdup ("Resource amount invalid");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  json_res = GNUNET_JSONAPI_object_get_resource (json_obj, 0);
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
 
   if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO))
   {
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     handle->emsg = GNUNET_strdup ("Resource type invalid");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
@@ -665,7 +665,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con,
           0 != strcasecmp (keystring, ego_entry->keystring))
       {
         //Ego with same name not allowed
-        GNUNET_JSONAPI_object_delete (json_obj);
+        GNUNET_JSONAPI_document_delete (json_obj);
         resp = GNUNET_REST_create_json_response (NULL);
         handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
         cleanup_handle (handle);
@@ -677,7 +677,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con,
                                          newname,
                                          &do_finished,
                                          handle);
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     return;
   }
 
@@ -687,7 +687,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con,
   {
     subsys = json_string_value (subsys_json);
     GNUNET_asprintf (&handle->subsys, "%s", subsys);
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
                                       handle->subsys,
                                       ego_entry->ego,
@@ -695,7 +695,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con,
                                       handle);
     return;
   }
-  GNUNET_JSONAPI_object_delete (json_obj);
+  GNUNET_JSONAPI_document_delete (json_obj);
   handle->emsg = GNUNET_strdup ("Subsystem not provided");
   GNUNET_SCHEDULER_add_now (&do_error, handle);
 }
index d4556c17406361ecebf0c617a54076640e36b6a9..5535cb2aa88bdff3c840b3b33c708c7713d3e115 100644 (file)
 #include "gnunet_rest_lib.h"
 #include "gnunet_json_lib.h"
 
+#define GNUNET_JSONAPI_KEY_DATA "data"
+
+#define GNUNET_JSONAPI_KEY_ID "id"
+
+#define GNUNET_JSONAPI_KEY_TYPE "type"
+
+#define GNUNET_JSONAPI_KEY_META "meta"
+
+#define GNUNET_JSONAPI_KEY_ATTRIBUTES "attributes"
+
+#define GNUNET_JSONAPI_KEY_CODE "code"
+
+#define GNUNET_JSONAPI_KEY_TITLE "title"
+
+#define GNUNET_JSONAPI_KEY_DETAIL "detail"
+
+#define GNUNET_JSONAPI_KEY_SOURCE "source"
+
+#define GNUNET_JSONAPI_KEY_LINKS "links"
+
+#define GNUNET_JSONAPI_KEY_STATUS "status"
+
+#define GNUNET_JSONAPI_KEY_ERRORS "errors"
 
 /* ****************** JSONAPI parsing ******************* */
 
+struct GNUNET_JSONAPI_Relationship;
+
+struct GNUNET_JSONAPI_Error;
+
 struct GNUNET_JSONAPI_Resource;
 
-struct GNUNET_JSONAPI_Object;
+struct GNUNET_JSONAPI_Document;
+
+/**
+ * Specification for parsing a jsonapi relationship.
+ *
+ * @param jsonapi_obj where to store the jsonapi relationship
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_jsonapi_relationship (struct GNUNET_JSONAPI_Relationship **jsonapi_obj);
+
+/**
+ * Specification for parsing a jsonapi error.
+ *
+ * @param jsonapi_obj where to store the jsonapi error
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_jsonapi_error (struct GNUNET_JSONAPI_Error **jsonapi_obj);
+
+/**
+ * Specification for parsing a jsonapi resource.
+ *
+ * @param jsonapi_obj where to store the jsonapi resource
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_jsonapi_resource (struct GNUNET_JSONAPI_Resource **jsonapi_obj);
 
 /**
  * Specification for parsing a jsonapi object.
@@ -38,7 +89,58 @@ struct GNUNET_JSONAPI_Object;
  * @param jsonapi_obj where to store the jsonapi object
  */
 struct GNUNET_JSON_Specification
-GNUNET_JSON_spec_jsonapi (struct GNUNET_JSONAPI_Object **jsonapi_obj);
+GNUNET_JSON_spec_jsonapi_document (struct GNUNET_JSONAPI_Document **jsonapi_obj);
+
+/**
+ * Delete a JSON API relationship
+ *
+ * @param res the JSON resource
+ * @param result Pointer where the resource should be stored
+ */
+void
+GNUNET_JSONAPI_relationship_delete (struct GNUNET_JSONAPI_Relationship *rel);
+
+
+/**
+ * Add a JSON API error to document
+ *
+ * @param data The JSON API document to add to
+ * @param res the JSON API error to add
+ * @return the new number of resources
+ */
+void
+GNUNET_JSONAPI_document_error_add (struct GNUNET_JSONAPI_Document *doc,
+                                      struct GNUNET_JSONAPI_Error *err);
+
+/**
+ * String serialze jsonapi error to json
+ *
+ * @param data the JSON API error
+ * @param result where to store the result
+ * @return GNUNET_SYSERR on error else GNUNET_OK
+ */
+int
+GNUNET_JSONAPI_error_to_json (const struct GNUNET_JSONAPI_Error *err,
+                              json_t **result);
+
+/**
+ * Parse json to error object
+ *
+ * @param err_json JSON object
+ * @param[out] err error object
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_JSONAPI_json_to_error (json_t *err_json,
+                              struct GNUNET_JSONAPI_Error **err);
+
+/**
+ * Delete a JSON API error
+ *
+ * @param res the JSON error
+ */
+void
+GNUNET_JSONAPI_error_delete (struct GNUNET_JSONAPI_Error *error);
 
 /**
  * Create a JSON API resource
@@ -50,6 +152,29 @@ GNUNET_JSON_spec_jsonapi (struct GNUNET_JSONAPI_Object **jsonapi_obj);
 struct GNUNET_JSONAPI_Resource*
 GNUNET_JSONAPI_resource_new (const char *type, const char *id);
 
+
+/**
+ * String serialze jsonapi to json
+ *
+ * @param data the JSON API resource
+ * @param result where to store the result
+ * @return GNUNET_SYSERR on error else GNUNET_OK
+ */
+int
+GNUNET_JSONAPI_resource_to_json (const struct GNUNET_JSONAPI_Resource *res,
+                                 json_t **result);
+
+/**
+ * Parse json to resource object
+ *
+ * @param res_json JSON object
+ * @param[out] res resource object
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_JSONAPI_json_to_resource (json_t *res_json,
+                                 struct GNUNET_JSONAPI_Resource **res);
+
 /**
  * Delete a JSON API resource
  *
@@ -69,9 +194,9 @@ GNUNET_JSONAPI_resource_delete (struct GNUNET_JSONAPI_Resource *resource);
  *         #GNUNET_SYSERR if not
  */
 int
-GNUNET_JSONAPI_resource_add_attr (const struct GNUNET_JSONAPI_Resource *resource,
-                                       const char* key,
-                                       json_t *json);
+GNUNET_JSONAPI_resource_add_attr (struct GNUNET_JSONAPI_Resource *resource,
+                                  const char* key,
+                                  json_t *json);
 /**
  * Read a JSON API attribute
  *
@@ -81,7 +206,7 @@ GNUNET_JSONAPI_resource_add_attr (const struct GNUNET_JSONAPI_Resource *resource
  */
 json_t*
 GNUNET_JSONAPI_resource_read_attr (const struct GNUNET_JSONAPI_Resource *resource,
-                                       const char* key);
+                                   const char* key);
 
 
 /**
@@ -93,7 +218,7 @@ GNUNET_JSONAPI_resource_read_attr (const struct GNUNET_JSONAPI_Resource *resourc
  */
 int
 GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource,
-                                       const char* id);
+                                  const char* id);
 
 
 /**
@@ -105,7 +230,7 @@ GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource
  */
 int
 GNUNET_JSONAPI_resource_check_type (const struct GNUNET_JSONAPI_Resource *resource,
-                                         const char* type);
+                                    const char* type);
 
 
 /**
@@ -115,8 +240,8 @@ GNUNET_JSONAPI_resource_check_type (const struct GNUNET_JSONAPI_Resource *resour
  * @param id the JSON API resource id
  * @return a new JSON API resource or NULL on error.
  */
-struct GNUNET_JSONAPI_Object*
-GNUNET_JSONAPI_object_new ();
+struct GNUNET_JSONAPI_Document*
+GNUNET_JSONAPI_document_new ();
 
 
 /**
@@ -127,8 +252,8 @@ GNUNET_JSONAPI_object_new ();
  * @return GNUNET_OK on success
  */
 int
-GNUNET_JSONAPI_object_parse (const char* data,
-                             struct GNUNET_JSONAPI_Object** obj);
+GNUNET_JSONAPI_document_parse (const char* data,
+                               struct GNUNET_JSONAPI_Document** obj);
 
 
 /**
@@ -139,7 +264,7 @@ GNUNET_JSONAPI_object_parse (const char* data,
  * @return a new JSON API resource or NULL on error.
  */
 void
-GNUNET_JSONAPI_object_delete (struct GNUNET_JSONAPI_Object *resp);
+GNUNET_JSONAPI_document_delete (struct GNUNET_JSONAPI_Document *resp);
 
 /**
  * Add a JSON API resource to primary data
@@ -149,8 +274,8 @@ GNUNET_JSONAPI_object_delete (struct GNUNET_JSONAPI_Object *resp);
  * @return the new number of resources
  */
 void
-GNUNET_JSONAPI_object_resource_add (struct GNUNET_JSONAPI_Object *resp,
-                                           struct GNUNET_JSONAPI_Resource *res);
+GNUNET_JSONAPI_document_resource_add (struct GNUNET_JSONAPI_Document *resp,
+                                      struct GNUNET_JSONAPI_Resource *res);
 /**
  * Get a JSON API object resource count
  *
@@ -158,7 +283,7 @@ GNUNET_JSONAPI_object_resource_add (struct GNUNET_JSONAPI_Object *resp,
  * @return the number of resources
  */
 int
-GNUNET_JSONAPI_object_resource_count (struct GNUNET_JSONAPI_Object *resp);
+GNUNET_JSONAPI_document_resource_count (struct GNUNET_JSONAPI_Document *resp);
 
 /**
  * Get a JSON API object resource num
@@ -168,7 +293,7 @@ GNUNET_JSONAPI_object_resource_count (struct GNUNET_JSONAPI_Object *resp);
  * @return the resource
  */
 struct GNUNET_JSONAPI_Resource*
-GNUNET_JSONAPI_object_get_resource (struct GNUNET_JSONAPI_Object *resp, int num);
+GNUNET_JSONAPI_document_get_resource (struct GNUNET_JSONAPI_Document *resp, int num);
 
 
 /**
@@ -179,8 +304,8 @@ GNUNET_JSONAPI_object_get_resource (struct GNUNET_JSONAPI_Object *resp, int num)
  * @return the new number of resources
  */
 void
-GNUNET_JSONAPI_data_resource_remove (struct GNUNET_JSONAPI_Object *resp,
-                                          struct GNUNET_JSONAPI_Resource *res);
+GNUNET_JSONAPI_document_resource_remove (struct GNUNET_JSONAPI_Document *resp,
+                                         struct GNUNET_JSONAPI_Resource *res);
 
 /**
  * String serialze jsonapi primary data
@@ -190,8 +315,8 @@ GNUNET_JSONAPI_data_resource_remove (struct GNUNET_JSONAPI_Object *resp,
  * @return GNUNET_SYSERR on error else GNUNET_OK
  */
 int
-GNUNET_JSONAPI_data_serialize (const struct GNUNET_JSONAPI_Object *resp,
-                                    char **result);
+GNUNET_JSONAPI_document_serialize (const struct GNUNET_JSONAPI_Document *resp,
+                                   char **result);
 
 /**
  * Check a JSON API resource id
@@ -199,7 +324,7 @@ GNUNET_JSONAPI_data_serialize (const struct GNUNET_JSONAPI_Object *resp,
  * @param res the JSON resource
  * @return the resource id
  */
-json_t*
+char*
 GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource);
 
 
index bcd4172c6af53d129f42310aaade7aaaac41e7ef..7e881acbd13a391d95c22adbe652ed68fd851e41 100644 (file)
@@ -13,7 +13,11 @@ libgnunetjsonapi_la_LDFLAGS = \
   -version-info 0:0:0 \
   -no-undefined
 libgnunetjsonapi_la_SOURCES = \
-  jsonapi.c 
+  jsonapi.c \
+       jsonapi_document.c \
+       jsonapi_resource.c \
+       jsonapi_error.c \
+       jsonapi_relationship.c
 libgnunetjsonapi_la_LIBADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
        $(top_builddir)/src/json/libgnunetjson.la \
index b648590e55fdff3455b03c0124cb9ec25e3ff90d..53ff64694e386d4b0e4f6fd7c5712a5b7924b1b1 100644 (file)
 #include "gnunet_json_lib.h"
 #include "gnunet_rest_lib.h"
 
-#define GNUNET_JSONAPI_KEY_DATA "data"
-
-#define GNUNET_JSONAPI_KEY_ID "id"
-
-#define GNUNET_JSONAPI_KEY_TYPE "type"
-
-struct GNUNET_JSONAPI_Resource
-{
-  /**
-   * DLL
-   */
-  struct GNUNET_JSONAPI_Resource *next;
-
-  /**
-   * DLL
-   */
-  struct GNUNET_JSONAPI_Resource *prev;
-
-  /**
-   * Resource content
-   */
-  json_t *res_obj;
-};
-
-
-struct GNUNET_JSONAPI_Object
-{
-  /**
-   * DLL Resource
-   */
-  struct GNUNET_JSONAPI_Resource *res_list_head;
-
-  /**
-   * DLL Resource
-   */
-  struct GNUNET_JSONAPI_Resource *res_list_tail;
-
-  /**
-   * num resources
-   */
-  int res_count;
-};
-
-
 /**
- * JSON API
+ * TODO move this to jsonapi-utils
  */
 
-
-/**
- * Create a JSON API resource
- *
- * @param type the JSON API resource type
- * @param id the JSON API resource id
- * @return a new JSON API resource or NULL on error.
- */
-struct GNUNET_JSONAPI_Resource*
-GNUNET_JSONAPI_resource_new (const char *type, const char *id)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-
-  if ( (NULL == type) || (0 == strlen (type)) )
-    return NULL;
-  if ( (NULL == id) || (0 == strlen (id)) )
-    return NULL;
-
-  res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
-  res->prev = NULL;
-  res->next = NULL;
-
-  res->res_obj = json_object ();
-
-  json_object_set_new (res->res_obj, GNUNET_JSONAPI_KEY_ID, json_string (id));
-  json_object_set_new (res->res_obj, GNUNET_JSONAPI_KEY_TYPE, json_string (type));
-
-  return res;
-}
-
-
-
-/**
- * Add a JSON API attribute
- *
- * @param res the JSON resource
- * @param key the key for the attribute
- * @param json the json_t attribute to add
- * @return #GNUNET_OK if added successfully
- *         #GNUNET_SYSERR if not
- */
-int
-GNUNET_JSONAPI_resource_add_attr (const struct GNUNET_JSONAPI_Resource *resource,
-                                       const char* key,
-                                       json_t *json)
-{
-  if ( (NULL == resource) ||
-       (NULL == key) ||
-       (NULL == json) )
-    return GNUNET_SYSERR;
-  json_object_set (resource->res_obj, key, json);
-  return GNUNET_OK;
-}
-
-/**
- * Read a JSON API attribute
- *
- * @param res the JSON resource
- * @param key the key for the attribute
- * @return the json_t object
- */
-json_t*
-GNUNET_JSONAPI_resource_read_attr (const struct GNUNET_JSONAPI_Resource *resource,
-                                       const char* key)
-{
-  if ( (NULL == resource) ||
-       (NULL == key))
-    return NULL;
-  return json_object_get (resource->res_obj, key);
-}
-
-int
-check_resource_attr_str (const struct GNUNET_JSONAPI_Resource *resource,
-                         const char* key,
-                         const char* attr)
-{
-  json_t *value;
-  if ( (NULL == resource) ||
-       (NULL == key) ||
-       (NULL == attr))
-    return GNUNET_NO;
-  value = json_object_get (resource->res_obj, key);
-  if (NULL == value)
-    return GNUNET_NO;
-  if (!json_is_string (value) ||
-      (0 != strcmp (attr, json_string_value(value))))
-  {
-    return GNUNET_NO;
-  }
-  return GNUNET_YES;
-}
-
-/**
- * Check a JSON API resource id
- *
- * @param res the JSON resource
- * @param id the expected id
- * @return GNUNET_YES if id matches
- */
-int
-GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource,
-                                       const char* id)
-{
-  return check_resource_attr_str (resource, GNUNET_JSONAPI_KEY_ID, id);
-}
-
-/**
- * Check a JSON API resource id
- *
- * @param res the JSON resource
- * @return the resource id
- */
-json_t*
-GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource)
-{
-  return GNUNET_JSONAPI_resource_read_attr (resource, GNUNET_JSONAPI_KEY_ID);
-}
-
-/**
- * Check a JSON API resource type
- *
- * @param res the JSON resource
- * @param type the expected type
- * @return GNUNET_YES if id matches
- */
-int
-GNUNET_JSONAPI_resource_check_type (const struct GNUNET_JSONAPI_Resource *resource,
-                                         const char* type)
-{
-  return check_resource_attr_str (resource, GNUNET_JSONAPI_KEY_TYPE, type);
-}
-
-/**
- * Get a JSON API object resource count
- *
- * @param resp the JSON API object
- * @return the number of resources
- */
-int
-GNUNET_JSONAPI_object_resource_count (struct GNUNET_JSONAPI_Object *resp)
-{
-  return resp->res_count;
-}
-
-/**
- * Get a JSON API object resource by index
- *
- * @param resp the JSON API object
- * @param num the number of the resource
- * @return the resource
- */
-struct GNUNET_JSONAPI_Resource*
-GNUNET_JSONAPI_object_get_resource (struct GNUNET_JSONAPI_Object *resp,
-                                        int num)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-  int i;
-
-  if ((0 == resp->res_count) ||
-      (num >= resp->res_count))
-    return NULL;
-  res = resp->res_list_head;
-  for (i = 0; i < num; i++)
-  {
-    res = res->next;
-  }
-  return res;
-}
-
-/**
- * Delete a JSON API resource
- *
- * @param res the JSON resource
- * @param result Pointer where the resource should be stored
- */
-void
-GNUNET_JSONAPI_resource_delete (struct GNUNET_JSONAPI_Resource *resource)
-{
-  json_decref (resource->res_obj);
-  GNUNET_free (resource);
-  resource = NULL;
-}
-
-/**
- * Delete a JSON API primary data
- *
- * @param type the JSON API resource type
- * @param id the JSON API resource id
- * @return a new JSON API resource or NULL on error.
- */
-void
-GNUNET_JSONAPI_object_delete (struct GNUNET_JSONAPI_Object *resp)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-  struct GNUNET_JSONAPI_Resource *res_next;
-
-  for (res = resp->res_list_head;
-       res != NULL;)
-  {
-    res_next = res->next;
-    GNUNET_CONTAINER_DLL_remove (resp->res_list_head,
-                                 resp->res_list_tail,
-                                 res);
-    GNUNET_JSONAPI_resource_delete (res);
-    res = res_next;
-  }
-  GNUNET_free (resp);
-  resp = NULL;
-}
-
-/**
- * Create a JSON API primary data
- *
- * @return a new JSON API resource or NULL on error.
- */
-struct GNUNET_JSONAPI_Object*
-GNUNET_JSONAPI_object_new ()
-{
-  struct GNUNET_JSONAPI_Object *result;
-
-  result = GNUNET_new (struct GNUNET_JSONAPI_Object);
-  result->res_count = 0;
-  return result;
-}
-
-/**
- * Add a JSON API object to primary data
- *
- * @param data The JSON API data to add to
- * @param res the JSON API resource to add
- * @return the new number of resources
- */
-void
-GNUNET_JSONAPI_object_resource_add (struct GNUNET_JSONAPI_Object *resp,
-                                         struct GNUNET_JSONAPI_Resource *res)
-{
-  GNUNET_CONTAINER_DLL_insert (resp->res_list_head,
-                               resp->res_list_tail,
-                               res);
-
-  resp->res_count++;
-}
-
-static void
-add_json_resource (struct GNUNET_JSONAPI_Object *obj,
-                   const json_t *res_json)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-  const char *type_json;
-
-  struct GNUNET_JSON_Specification dspec[] = {
-    GNUNET_JSON_spec_string (GNUNET_JSONAPI_KEY_TYPE, &type_json),
-    GNUNET_JSON_spec_end()
-  };
-
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_JSON_parse (res_json, dspec,
-                                    NULL, NULL));
-  GNUNET_JSON_parse_free (dspec);
-  res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
-  res->next = NULL;
-  res->prev = NULL;
-  res->res_obj = json_deep_copy (res_json);
-  GNUNET_JSONAPI_object_resource_add (obj, res);
-}
-
-/**
- * Parse given JSON object to RSA public key.
- *
- * @param cls closure, NULL
- * @param root the json object representing data
- * @param[out] spec where to write the data
- * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
- */
-static int
-parse_jsonapiobject (void *cls,
-                     json_t *root,
-                     struct GNUNET_JSON_Specification *spec)
-{
-  struct GNUNET_JSONAPI_Object *result;
-  json_t *data_json;
-  int res_count = 0;
-  int i;
-
-  struct GNUNET_JSON_Specification jsonapispec[] = {
-    GNUNET_JSON_spec_json (GNUNET_JSONAPI_KEY_DATA, &data_json),
-    GNUNET_JSON_spec_end()
-  };
-  if (GNUNET_OK !=
-                 GNUNET_JSON_parse (root, jsonapispec,
-                                    NULL, NULL) || (NULL == data_json))
-  {
-    return GNUNET_SYSERR;
-  }
-
-  result = GNUNET_new (struct GNUNET_JSONAPI_Object);
-  result->res_count = 0;
-  if (json_is_object (data_json))
-    add_json_resource (result, data_json);
-  else if (json_is_array (data_json))
-  {
-    res_count = json_array_size (data_json);
-    for (i = 0; i < res_count; i++)
-      add_json_resource (result, json_array_get (data_json, i));
-  }
-  if (0 == result->res_count)
-  {
-    GNUNET_free (result);
-    GNUNET_JSON_parse_free (jsonapispec);
-    return GNUNET_SYSERR;
-  }
-  *(struct GNUNET_JSONAPI_Object **) spec->ptr = result;
-  GNUNET_JSON_parse_free (jsonapispec);
-  return GNUNET_OK;
-}
-
-
-/**
- * Cleanup data left from parsing RSA public key.
- *
- * @param cls closure, NULL
- * @param[out] spec where to free the data
- */
-static void
-clean_jsonapiobject (void *cls,
-                     struct GNUNET_JSON_Specification *spec)
-{
-  struct GNUNET_JSONAPI_Object **jsonapi_obj;
-  jsonapi_obj = (struct GNUNET_JSONAPI_Object **) spec->ptr;
-  if (NULL != *jsonapi_obj)
-  {
-    GNUNET_JSONAPI_object_delete (*jsonapi_obj);
-    *jsonapi_obj = NULL;
-  }
-}
-
-/**
- * Add a JSON API resource to primary data
- *
- * @param data The JSON API data to add to
- * @param res the JSON API resource to add
- * @return the new number of resources
- */
-void
-GNUNET_JSONAPI_data_resource_remove (struct GNUNET_JSONAPI_Object *resp,
-                                          struct GNUNET_JSONAPI_Resource *res)
-{
-  GNUNET_CONTAINER_DLL_remove (resp->res_list_head,
-                               resp->res_list_tail,
-                              res);
-  resp->res_count--;
-}
-
-/**
- * String serialze jsonapi primary data
- *
- * @param data the JSON API primary data
- * @param result where to store the result
- * @return GNUNET_SYSERR on error else GNUNET_OK
- */
-int
-GNUNET_JSONAPI_data_serialize (const struct GNUNET_JSONAPI_Object *resp,
-                                    char **result)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-  json_t *root_json;
-  json_t *res_arr;
-
-  if ((NULL == resp))
-    return GNUNET_SYSERR;
-
-  root_json = json_object ();
-  res_arr = json_array ();
-  for (res = resp->res_list_head;
-       res != NULL;
-       res = res->next)
-  {
-    json_array_append (res_arr, res->res_obj);
-  }
-  json_object_set (root_json, GNUNET_JSONAPI_KEY_DATA, res_arr);
-  *result = json_dumps (root_json, JSON_INDENT(2));
-  json_decref (root_json);
-  json_decref (res_arr);
-  return GNUNET_OK;
-}
-
-/**
- * JSON object.
- *
- * @param name name of the JSON field
- * @param[out] jsonp where to store the JSON found under @a name
- */
-struct GNUNET_JSON_Specification
-GNUNET_JSON_spec_jsonapi (struct GNUNET_JSONAPI_Object **jsonapi_object)
-{
-  struct GNUNET_JSON_Specification ret = {
-    .parser = &parse_jsonapiobject,
-    .cleaner = &clean_jsonapiobject,
-    .cls = NULL,
-    .field = NULL,
-    .ptr = jsonapi_object,
-    .ptr_size = 0,
-    .size_ptr = NULL
-  };
-  *jsonapi_object = NULL;
-  return ret;
-}
-
 /**
  * Check rest request for validity
  *
diff --git a/src/jsonapi/jsonapi_document.c b/src/jsonapi/jsonapi_document.c
new file mode 100644 (file)
index 0000000..4837ee2
--- /dev/null
@@ -0,0 +1,374 @@
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_json_lib.h"
+#include "jsonapi_objects.h"
+
+/**
+ * Get a JSON API object resource count
+ *
+ * @param resp the JSON API object
+ * @return the number of resources
+ */
+int
+GNUNET_JSONAPI_document_resource_count (struct GNUNET_JSONAPI_Document *doc)
+{
+  return doc->res_count;
+}
+
+/**
+ * Get a JSON API object resource by index
+ *
+ * @param resp the JSON API object
+ * @param idx index of the resource
+ * @return the resource
+ */
+struct GNUNET_JSONAPI_Resource*
+GNUNET_JSONAPI_document_get_resource (struct GNUNET_JSONAPI_Document *doc,
+                                      int idx)
+{
+  struct GNUNET_JSONAPI_Resource *res;
+  int i;
+
+  if ((0 == doc->res_count) ||
+      (idx >= doc->res_count))
+    return NULL;
+  res = doc->res_list_head;
+  for (i = 0; i < idx; i++)
+  {
+    res = res->next;
+  }
+  return res;
+}
+
+/**
+ * Delete a JSON API primary data
+ *
+ * @param type the JSON API resource type
+ * @param id the JSON API resource id
+ * @return a new JSON API resource or NULL on error.
+ */
+void
+GNUNET_JSONAPI_document_delete (struct GNUNET_JSONAPI_Document *doc)
+{
+  struct GNUNET_JSONAPI_Resource *res;
+  struct GNUNET_JSONAPI_Resource *res_next;
+  
+
+  for (res = doc->res_list_head;
+       res != NULL;)
+  {
+    res_next = res->next;
+    GNUNET_CONTAINER_DLL_remove (doc->res_list_head,
+                                 doc->res_list_tail,
+                                 res);
+    GNUNET_JSONAPI_resource_delete (res);
+    res = res_next;
+  }
+  GNUNET_free (doc);
+  doc = NULL;
+}
+
+/**
+ * Create a JSON API primary data
+ *
+ * @return a new JSON API resource or NULL on error.
+ */
+struct GNUNET_JSONAPI_Document*
+GNUNET_JSONAPI_document_new ()
+{
+  struct GNUNET_JSONAPI_Document *result;
+
+  result = GNUNET_new (struct GNUNET_JSONAPI_Document);
+  result->res_count = 0;
+  result->err_count = 0;
+  result->meta = 0;
+  return result;
+}
+
+/**
+ * Add a JSON API error to document
+ *
+ * @param data The JSON API document to add to
+ * @param res the JSON API error to add
+ * @return the new number of resources
+ */
+void
+GNUNET_JSONAPI_document_error_add (struct GNUNET_JSONAPI_Document *doc,
+                                      struct GNUNET_JSONAPI_Error *err)
+{
+  GNUNET_CONTAINER_DLL_insert (doc->err_list_head,
+                               doc->err_list_tail,
+                               err);
+
+  doc->err_count++;
+}
+
+/**
+ * Add a JSON API resource to primary data
+ *
+ * @param data The JSON API data to add to
+ * @param res the JSON API resource to add
+ * @return the new number of resources
+ */
+void
+GNUNET_JSONAPI_document_resource_add (struct GNUNET_JSONAPI_Document *doc,
+                                         struct GNUNET_JSONAPI_Resource *res)
+{
+  GNUNET_CONTAINER_DLL_insert (doc->res_list_head,
+                               doc->res_list_tail,
+                               res);
+
+  doc->res_count++;
+}
+
+
+/**
+ * Parse given JSON object to jsonapi document.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_jsonapiobject (void *cls,
+                     json_t *root,
+                     struct GNUNET_JSON_Specification *spec)
+{
+  struct GNUNET_JSONAPI_Document *result;
+  struct GNUNET_JSONAPI_Error *error;
+  struct GNUNET_JSONAPI_Resource *resource;
+  json_t *meta_json;
+  json_t *resource_json;
+  json_t *errors_json;
+  json_t *value;
+  size_t index;
+
+  struct GNUNET_JSON_Specification jsonapispecerrors[] = {
+    GNUNET_JSON_spec_json (GNUNET_JSONAPI_KEY_ERRORS, &errors_json),
+    GNUNET_JSON_spec_end()
+  };
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root, jsonapispecerrors,
+                         NULL, NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
+                "JSONAPI document does not contain error objects\n");
+  } else if (!json_is_array (errors_json))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error object is not array!\n");
+    GNUNET_JSON_parse_free (jsonapispecerrors);
+    return GNUNET_SYSERR;
+  }
+  struct GNUNET_JSON_Specification jsonapispecmeta[] = {
+    GNUNET_JSON_spec_json (GNUNET_JSONAPI_KEY_META, &meta_json),
+    GNUNET_JSON_spec_end()
+  };
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root, jsonapispecmeta,
+                         NULL, NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "JSONAPI document does not contain error objects\n");
+  }
+  struct GNUNET_JSON_Specification jsonapispecresource[] = {
+    GNUNET_JSON_spec_json (GNUNET_JSONAPI_KEY_DATA, &resource_json),
+    GNUNET_JSON_spec_end()
+  };
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root, jsonapispecresource,
+                         NULL, NULL))
+  {
+    if (NULL == errors_json)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "JSONAPI document contains neither error nor data!\n");
+      GNUNET_JSON_parse_free (jsonapispecerrors);
+      GNUNET_JSON_parse_free (jsonapispecmeta);
+      return GNUNET_SYSERR;
+    }
+  } else {
+    if (NULL != errors_json)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "JSONAPI document contains both error and data!\n");
+      GNUNET_JSON_parse_free (jsonapispecerrors);
+      GNUNET_JSON_parse_free (jsonapispecmeta);
+      GNUNET_JSON_parse_free (jsonapispecresource);
+      return GNUNET_SYSERR;
+    }
+  }
+
+  result = GNUNET_new (struct GNUNET_JSONAPI_Document);
+  result->res_count = 0;
+  result->err_count = 0;
+  if (NULL != meta_json)
+    result->meta = json_deep_copy (meta_json);
+  if (NULL != errors_json) {
+    json_array_foreach(errors_json, index, value) {
+      GNUNET_assert (GNUNET_OK == 
+                     GNUNET_JSONAPI_json_to_error (value,
+                                                   &error));
+      GNUNET_JSONAPI_document_error_add (result, error);
+    }
+  }
+  if (NULL != resource_json) {
+    if (0 != json_is_array (resource_json))
+    {
+      json_array_foreach(resource_json, index, value) {
+        GNUNET_assert (GNUNET_OK == 
+                       GNUNET_JSONAPI_json_to_resource (value,
+                                                        &resource));
+        GNUNET_JSONAPI_document_resource_add (result, resource);
+      }
+    } else {
+      GNUNET_assert (GNUNET_OK == 
+                     GNUNET_JSONAPI_json_to_resource (resource_json,
+                                                      &resource));
+      GNUNET_JSONAPI_document_resource_add (result, resource);
+    }
+  }
+  if (NULL != errors_json)
+    GNUNET_JSON_parse_free (jsonapispecerrors);
+  if (NULL != resource)
+    GNUNET_JSON_parse_free (jsonapispecresource);
+  if (NULL != meta_json)
+    GNUNET_JSON_parse_free (jsonapispecmeta);
+  *(struct GNUNET_JSONAPI_Document **) spec->ptr = result;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Cleanup data left from parsing RSA public key.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_jsonapiobject (void *cls,
+                     struct GNUNET_JSON_Specification *spec)
+{
+  struct GNUNET_JSONAPI_Document **jsonapi_obj;
+  jsonapi_obj = (struct GNUNET_JSONAPI_Document **) spec->ptr;
+  if (NULL != *jsonapi_obj)
+  {
+    GNUNET_JSONAPI_document_delete (*jsonapi_obj);
+    *jsonapi_obj = NULL;
+  }
+}
+
+/**
+ * Add a JSON API resource to primary data
+ *
+ * @param data The JSON API data to add to
+ * @param res the JSON API resource to add
+ * @return the new number of resources
+ */
+void
+GNUNET_JSONAPI_document_resource_remove (struct GNUNET_JSONAPI_Document *resp,
+                                         struct GNUNET_JSONAPI_Resource *res)
+{
+  GNUNET_CONTAINER_DLL_remove (resp->res_list_head,
+                               resp->res_list_tail,
+                               res);
+  resp->res_count--;
+}
+
+
+/**
+ * String serialze jsonapi primary data
+ *
+ * @param data the JSON API primary data
+ * @param result where to store the result
+ * @return GNUNET_SYSERR on error else GNUNET_OK
+ */
+int
+GNUNET_JSONAPI_document_serialize (const struct GNUNET_JSONAPI_Document *doc,
+                                   char **result)
+{
+  struct GNUNET_JSONAPI_Resource *res;
+  struct GNUNET_JSONAPI_Error *error;
+  json_t *root_json;
+  json_t *res_json;
+  json_t *res_json_tmp;
+
+  if ((NULL == doc))
+    return GNUNET_SYSERR;
+
+  root_json = json_object ();
+
+  //Check for errors first 
+  if (doc->err_count != 0)
+  {
+    res_json = json_array ();
+    for (error = doc->err_list_head;
+         error != NULL;
+         error = error->next)
+    {
+      GNUNET_assert (GNUNET_OK ==
+                     GNUNET_JSONAPI_error_to_json (error,
+                                                   &res_json_tmp));
+      json_array_append (res_json, res_json_tmp);
+    }
+    json_object_set (root_json, GNUNET_JSONAPI_KEY_ERRORS, res_json);
+  } else {
+    switch (doc->res_count)
+    {
+      case 0:
+        res_json = json_null();
+        break;
+      case 1:
+        GNUNET_assert (GNUNET_OK ==
+                       GNUNET_JSONAPI_resource_to_json (doc->res_list_head,
+                                                        &res_json));
+        break;
+      default:
+        res_json = json_array ();
+        for (res = doc->res_list_head;
+             res != NULL;
+             res = res->next)
+        {
+          GNUNET_assert (GNUNET_OK ==
+                         GNUNET_JSONAPI_resource_to_json (res,
+                                                          &res_json_tmp));
+          json_array_append (res_json, res_json_tmp);
+        }
+        break;
+    }
+    json_object_set (root_json, GNUNET_JSONAPI_KEY_DATA, res_json);
+  }
+
+  //Add meta
+  json_object_set (root_json, GNUNET_JSONAPI_KEY_META, doc->meta);
+  *result = json_dumps (root_json, JSON_INDENT(2));
+  json_decref (root_json);
+  json_decref (res_json);
+  return GNUNET_OK;
+}
+
+/**
+ * JSON object.
+ *
+ * @param name name of the JSON field
+ * @param[out] jsonp where to store the JSON found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_jsonapi_document (struct GNUNET_JSONAPI_Document **jsonapi_object)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_jsonapiobject,
+    .cleaner = &clean_jsonapiobject,
+    .cls = NULL,
+    .field = NULL,
+    .ptr = jsonapi_object,
+    .ptr_size = 0,
+    .size_ptr = NULL
+  };
+  *jsonapi_object = NULL;
+  return ret;
+}
+
+
diff --git a/src/jsonapi/jsonapi_error.c b/src/jsonapi/jsonapi_error.c
new file mode 100644 (file)
index 0000000..d91f0a6
--- /dev/null
@@ -0,0 +1,205 @@
+#include "platform.h"
+#include "gnunet_jsonapi_lib.h"
+#include "jsonapi_objects.h"
+
+/**
+ * Parse json to error object
+ *
+ * @param err_json JSON object
+ * @param[out] err error object
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_JSONAPI_json_to_error (json_t *err_json,
+                              struct GNUNET_JSONAPI_Error **err)
+{
+  struct GNUNET_JSON_Specification jsonapispecerror[] = {
+    GNUNET_JSON_spec_jsonapi_error (err),
+    GNUNET_JSON_spec_end()
+  };
+  return GNUNET_JSON_parse (err_json, jsonapispecerror,
+                            NULL, NULL);
+}
+
+/**
+ * Serialze jsonapi errors
+ *
+ * @param data the JSON API errors
+ * @param result where to store the result
+ * @return GNUNET_SYSERR on error else GNUNET_OK
+ */
+int
+GNUNET_JSONAPI_error_to_json (const struct GNUNET_JSONAPI_Error *err,
+                              json_t **result)
+{
+  *result = json_object ();
+
+  if ((NULL != err->id) &&
+      (0 != json_object_set_new (*result,
+                                 GNUNET_JSONAPI_KEY_ID,
+                                 json_string (err->id))))
+    return GNUNET_SYSERR;
+  if ((NULL != err->status) &&
+      (0 != json_object_set_new (*result,
+                                 GNUNET_JSONAPI_KEY_STATUS,
+                                 json_string (err->status))))
+    return GNUNET_SYSERR;
+  if ((NULL != err->code) &&
+      (0 != json_object_set_new (*result,
+                                 GNUNET_JSONAPI_KEY_CODE,
+                                 json_string (err->code))))
+    return GNUNET_SYSERR;
+
+  if ((NULL != err->title) &&
+      (0 != json_object_set_new (*result,
+                                 GNUNET_JSONAPI_KEY_TITLE,
+                                 json_string (err->title))))
+    return GNUNET_SYSERR;
+  if ((NULL != err->detail) &&
+      (0 != json_object_set_new (*result,
+                                 GNUNET_JSONAPI_KEY_DETAIL,
+                                 json_string (err->detail))))
+    return GNUNET_SYSERR;
+  if ((NULL != err->source) &&
+      (0 != json_object_set_new (*result,
+                                 GNUNET_JSONAPI_KEY_SOURCE,
+                                 err->source)))
+    return GNUNET_SYSERR;
+  if ((NULL != err->links) &&
+      (0 != json_object_set_new (*result,
+                                 GNUNET_JSONAPI_KEY_LINKS,
+                                 err->links)))
+    return GNUNET_SYSERR;
+  if ((NULL != err->meta) &&
+      (0 != json_object_set_new (*result,
+                                 GNUNET_JSONAPI_KEY_META,
+                                 err->meta)))
+    return GNUNET_SYSERR;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Parse given JSON object to jsonapi document.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_jsonapierror (void *cls,
+                     json_t *root,
+                     struct GNUNET_JSON_Specification *spec)
+{
+  struct GNUNET_JSONAPI_Error *result;
+  json_t *pos;
+  
+  GNUNET_assert (NULL != root);
+  result = GNUNET_new (struct GNUNET_JSONAPI_Error);
+  pos = json_object_get (root, GNUNET_JSONAPI_KEY_ID);
+  if (json_is_string (pos))
+    result->id = GNUNET_strdup (json_string_value (pos));
+  
+  pos = json_object_get (root, GNUNET_JSONAPI_KEY_LINKS);
+  if (json_is_object (pos))
+    result->links = json_deep_copy (pos);
+  
+  pos = json_object_get (root, GNUNET_JSONAPI_KEY_STATUS);
+  if (json_is_string (pos))
+    result->status = GNUNET_strdup (json_string_value (pos));
+
+  pos = json_object_get (root, GNUNET_JSONAPI_KEY_CODE);
+  if (json_is_string (pos))
+    result->code = GNUNET_strdup (json_string_value (pos));
+
+  pos = json_object_get (root, GNUNET_JSONAPI_KEY_TITLE);
+  if (json_is_string (pos))
+    result->title = GNUNET_strdup (json_string_value (pos));
+
+  pos = json_object_get (root, GNUNET_JSONAPI_KEY_DETAIL);
+  if (json_is_string (pos))
+    result->detail = GNUNET_strdup (json_string_value (pos));
+
+  pos = json_object_get (root, GNUNET_JSONAPI_KEY_SOURCE);
+  if (json_is_object (pos))
+    result->source = json_deep_copy (pos);
+  pos = json_object_get (root, GNUNET_JSONAPI_KEY_META);
+  if (json_is_object (pos))
+    result->meta = json_deep_copy (pos);
+  *(struct GNUNET_JSONAPI_Error **) spec->ptr = result;
+  return GNUNET_OK;
+}
+
+/**
+ * Delete a JSON API error
+ *
+ * @param res the JSON error
+ */
+void
+GNUNET_JSONAPI_error_delete (struct GNUNET_JSONAPI_Error *error)
+{
+  GNUNET_assert (NULL != error);
+
+  if (NULL != error->id)
+    GNUNET_free (error->id);
+  if (NULL != error->status)
+    GNUNET_free (error->status);
+  if (NULL != error->code)
+    GNUNET_free (error->code);
+  if (NULL != error->title)
+    GNUNET_free (error->title);
+  if (NULL != error->detail)
+    GNUNET_free (error->detail);
+  if (NULL != error->links)
+    json_decref (error->links);
+  if (NULL != error->source)
+    json_decref (error->source);
+  if (NULL != error->meta)
+    json_decref (error->meta);
+  GNUNET_free (error);
+}
+
+
+
+/**
+ * Cleanup data left from parsing RSA public key.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_jsonapierror (void *cls,
+                     struct GNUNET_JSON_Specification *spec)
+{
+  struct GNUNET_JSONAPI_Error **jsonapi_obj;
+  jsonapi_obj = (struct GNUNET_JSONAPI_Error **) spec->ptr;
+  if (NULL != *jsonapi_obj)
+  {
+    GNUNET_JSONAPI_error_delete (*jsonapi_obj);
+    *jsonapi_obj = NULL;
+  }
+}
+/**
+ * JSON object.
+ *
+ * @param name name of the JSON field
+ * @param[out] jsonp where to store the JSON found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_jsonapi_error (struct GNUNET_JSONAPI_Error **jsonapi_object)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_jsonapierror,
+    .cleaner = &clean_jsonapierror,
+    .cls = NULL,
+    .field = NULL,
+    .ptr = jsonapi_object,
+    .ptr_size = 0,
+    .size_ptr = NULL
+  };
+  *jsonapi_object = NULL;
+  return ret;
+}
+
+
diff --git a/src/jsonapi/jsonapi_objects.h b/src/jsonapi/jsonapi_objects.h
new file mode 100644 (file)
index 0000000..27c64ee
--- /dev/null
@@ -0,0 +1,162 @@
+#include "platform.h"
+#include "gnunet_jsonapi_lib.h"
+/**
+ * jsonapi error object
+ */
+struct GNUNET_JSONAPI_Error
+{
+  /**
+   * DLL
+   */
+  struct GNUNET_JSONAPI_Error *next;
+
+  /**
+   * DLL
+   */
+  struct GNUNET_JSONAPI_Error *prev;
+
+  /**
+   * Unique error id
+   */
+  char *id;
+
+  /**
+   * Links object
+   */
+  json_t *links;
+
+  /**
+   * HTTP status code for this error
+   */
+  char *status;
+
+  /**
+   * Application error code
+   */
+  char *code;
+
+  /**
+   * Error title
+   */
+  char *title;
+
+  /**
+   * Error details
+   */
+  char *detail;
+
+  /**
+   * Error source
+   */
+  json_t *source;
+
+  /**
+   * Meta info for the error
+   */
+  json_t *meta;
+};
+
+struct GNUNET_JSONAPI_Relationship
+{
+  /**
+   * Links object
+   */
+  struct GNUNET_JSONAPI_Link *links;
+
+  /**
+   * Resource linkage data
+   */
+  struct GNUNET_JSONAPI_Resource *res_list_head;
+
+  /**
+   * DLL
+   */
+  struct GNUNET_JSONAPI_Resource *res_list_tail;
+  
+  /**
+   * Number of resources in data section
+   */
+  int res_count;
+
+  /**
+   * Meta information
+   */
+  json_t *meta;
+};
+
+/**
+ * A jsonapi resource object
+ */
+struct GNUNET_JSONAPI_Resource
+{
+  /**
+   * DLL
+   */
+  struct GNUNET_JSONAPI_Resource *next;
+
+  /**
+   * DLL
+   */
+  struct GNUNET_JSONAPI_Resource *prev;
+
+  /**
+   * Resource type
+   */
+  char *type;
+
+  /**
+   * Resource ID
+   */
+  char *id;
+
+  /**
+   * Attributes object
+   */
+  json_t *attr_obj;
+
+  /**
+   * Relationship
+   */
+  struct GNUNET_JSONAPI_Relationship *relationship;
+};
+
+
+struct GNUNET_JSONAPI_Document
+{
+  /**
+   * DLL Resource
+   */
+  struct GNUNET_JSONAPI_Resource *res_list_head;
+
+  /**
+   * DLL Resource
+   */
+  struct GNUNET_JSONAPI_Resource *res_list_tail;
+
+  /**
+   * num resources
+   */
+  int res_count;
+
+  /**
+   * DLL Error
+   */
+  struct GNUNET_JSONAPI_Error *err_list_head;
+
+  /**
+   * DLL Error
+   */
+  struct GNUNET_JSONAPI_Error *err_list_tail;
+
+  /**
+   * num errors
+   */
+  int err_count;
+
+  /**
+   * Meta info
+   */
+  json_t *meta;
+};
+
+
diff --git a/src/jsonapi/jsonapi_relationship.c b/src/jsonapi/jsonapi_relationship.c
new file mode 100644 (file)
index 0000000..b88e74c
--- /dev/null
@@ -0,0 +1,17 @@
+#include "platform.h"
+#include "gnunet_jsonapi_lib.h"
+
+
+/**
+ * Delete a JSON API relationship TODO
+ *
+ * @param res the JSON relationship
+ */
+void
+GNUNET_JSONAPI_relationship_delete (struct GNUNET_JSONAPI_Relationship *relationship)
+{
+  GNUNET_assert (NULL != relationship);
+  GNUNET_free (relationship);
+}
+
+
diff --git a/src/jsonapi/jsonapi_resource.c b/src/jsonapi/jsonapi_resource.c
new file mode 100644 (file)
index 0000000..0921727
--- /dev/null
@@ -0,0 +1,367 @@
+#include "platform.h"
+#include "gnunet_jsonapi_lib.h"
+#include "jsonapi_objects.h"
+
+/**
+ * String serialze jsonapi resources
+ *
+ * @param data the JSON API resource
+ * @param result where to store the result
+ * @return GNUNET_SYSERR on error else GNUNET_OK
+ */
+int
+GNUNET_JSONAPI_resource_to_json (const struct GNUNET_JSONAPI_Resource *res,
+                                 json_t **result)
+{
+  struct GNUNET_JSONAPI_Resource *rel_res;
+  json_t *relationship;
+  json_t *res_json_tmp;
+  *result = json_object ();
+
+  if (0 != json_object_set_new (*result,
+                                GNUNET_JSONAPI_KEY_ID,
+                                json_string (res->id)))
+    return GNUNET_SYSERR;
+  if (0 != json_object_set_new (*result,
+                                GNUNET_JSONAPI_KEY_TYPE,
+                                json_string (res->type)))
+    return GNUNET_SYSERR;
+  if ((NULL != res->attr_obj) &&
+      (0 != json_object_set (*result,
+                             GNUNET_JSONAPI_KEY_ATTRIBUTES,
+                             res->attr_obj)))
+    return GNUNET_SYSERR;
+
+  //Relationships
+  if (NULL != res->relationship)
+  {
+    relationship = json_object ();
+    if (0 != res->relationship->res_count)
+    {
+      json_t *res_json;
+      switch (res->relationship->res_count)
+      {
+        case 0:
+          res_json = json_null();
+          break;
+        case 1:
+          GNUNET_assert (GNUNET_OK ==
+                         GNUNET_JSONAPI_resource_to_json (res->relationship->res_list_head,
+                                                          &res_json));
+          break;
+        default:
+          res_json = json_array ();
+          rel_res = NULL;
+          for (rel_res = rel_res->relationship->res_list_head;
+               rel_res != NULL;
+               rel_res = rel_res->next)
+          {
+            GNUNET_assert (GNUNET_OK ==
+                           GNUNET_JSONAPI_resource_to_json (rel_res,
+                                                            &res_json_tmp));
+            json_array_append_new (res_json, res_json_tmp);
+          }
+          break;
+      }
+      json_object_set_new (relationship,
+                           GNUNET_JSONAPI_KEY_DATA,
+                           res_json);
+    }
+    if ((NULL != res->relationship->meta) &&
+        (0 != json_object_set_new (relationship,
+                                   GNUNET_JSONAPI_KEY_META,
+                                   res->relationship->meta)))
+      return GNUNET_SYSERR;
+    //TODO link
+  }
+
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Create a JSON API resource
+ *
+ * @param type the JSON API resource type
+ * @param id the JSON API resource id
+ * @return a new JSON API resource or NULL on error.
+ */
+struct GNUNET_JSONAPI_Resource*
+GNUNET_JSONAPI_resource_new (const char *type, const char *id)
+{
+  struct GNUNET_JSONAPI_Resource *res;
+
+  if ( (NULL == type) || (0 == strlen (type)) )
+    return NULL;
+  if ( (NULL == id) || (0 == strlen (id)) )
+    return NULL;
+
+  res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
+  res->prev = NULL;
+  res->next = NULL;
+  res->attr_obj = NULL;
+  res->relationship = NULL;
+  res->id = GNUNET_strdup (id);
+  res->type = GNUNET_strdup (type);
+  return res;
+}
+
+/**
+ * Add a jsonapi relationship
+ * @param res the resource to add to
+ * @param rel the relationship to add
+ * @return #GNUNETOK if added successfully
+ */
+int
+GNUNET_JSONAPI_resource_set_relationship (struct GNUNET_JSONAPI_Resource *res,
+                                          struct GNUNET_JSONAPI_Relationship *rel)
+{
+  GNUNET_assert (NULL != res);
+  GNUNET_assert (NULL != rel);
+  if (NULL != res->relationship)
+    return GNUNET_SYSERR;
+  res->relationship = rel;
+  return GNUNET_OK;
+}
+
+/**
+ * Add a JSON API attribute
+ *
+ * @param res the JSON resource
+ * @param key the key for the attribute
+ * @param json the json_t attribute to add
+ * @return #GNUNET_OK if added successfully
+ *         #GNUNET_SYSERR if not
+ */
+int
+GNUNET_JSONAPI_resource_add_attr (struct GNUNET_JSONAPI_Resource *resource,
+                                  const char* key,
+                                  json_t *json)
+{
+  if ( (NULL == resource) ||
+       (NULL == key) ||
+       (NULL == json) )
+    return GNUNET_SYSERR;
+  if (NULL == resource->attr_obj)
+    resource->attr_obj = json_object ();
+  json_object_set (resource->attr_obj, key, json);
+  return GNUNET_OK;
+}
+
+/**
+ * Read a JSON API attribute
+ *
+ * @param res the JSON resource
+ * @param key the key for the attribute
+ * @return the json_t object
+ */
+json_t*
+GNUNET_JSONAPI_resource_read_attr (const struct GNUNET_JSONAPI_Resource *resource,
+                                   const char* key)
+{
+  if ( (NULL == resource) ||
+       (NULL == key) ||
+       (NULL == resource->attr_obj))
+    return NULL;
+  return json_object_get (resource->attr_obj, key);
+}
+
+int
+check_resource_attr_str (const struct GNUNET_JSONAPI_Resource *resource,
+                         const char* key,
+                         const char* attr)
+{
+  json_t *value;
+  if ( (NULL == resource) ||
+       (NULL == key) ||
+       (NULL == attr) ||
+       (NULL == resource->attr_obj))
+    return GNUNET_NO;
+  value = json_object_get (resource->attr_obj, key);
+  if (NULL == value)
+    return GNUNET_NO;
+  if (!json_is_string (value) ||
+      (0 != strcmp (attr, json_string_value(value))))
+  {
+    return GNUNET_NO;
+  }
+  return GNUNET_YES;
+}
+
+/**
+ * Check a JSON API resource type
+ *
+ * @param res the JSON resource
+ * @param type the expected type
+ * @return GNUNET_YES if id matches
+ */
+int
+GNUNET_JSONAPI_resource_check_type (const struct GNUNET_JSONAPI_Resource *resource,
+                                    const char* type)
+{
+  return (0 == memcmp (type, resource->type,
+                       strlen (resource->type))) ? GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
+ * Delete a JSON API resource
+ *
+ * @param res the JSON resource
+ * @param result Pointer where the resource should be stored
+ */
+void
+GNUNET_JSONAPI_resource_delete (struct GNUNET_JSONAPI_Resource *resource)
+{
+  GNUNET_free (resource->id);
+  GNUNET_free (resource->type);
+  if (NULL != resource->attr_obj)
+    json_decref (resource->attr_obj);
+  if (NULL != resource->relationship)
+    GNUNET_JSONAPI_relationship_delete (resource->relationship);
+  GNUNET_free (resource);
+  resource = NULL;
+}
+
+
+/**
+ * Check a JSON API resource id
+ *
+ * @param res the JSON resource
+ * @param id the expected id
+ * @return GNUNET_YES if id matches
+ */
+int
+GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource,
+                                  const char* id)
+{
+  return (0 == memcmp (resource->id, id, strlen (id))) ? GNUNET_YES : GNUNET_NO;
+}
+
+/**
+ * Check a JSON API resource id
+ *
+ * @param res the JSON resource
+ * @return the resource id
+ */
+char*
+GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource)
+{
+  return resource->id;
+}
+
+/**
+ * Parse json to resource object
+ *
+ * @param res_json JSON object
+ * @param[out] res resource object
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_JSONAPI_json_to_resource (json_t *res_json,
+                                 struct GNUNET_JSONAPI_Resource **res)
+{
+  struct GNUNET_JSON_Specification jsonapispecresource[] = {
+    GNUNET_JSON_spec_jsonapi_resource (res),
+    GNUNET_JSON_spec_end()
+  };
+  return GNUNET_JSON_parse (res_json, jsonapispecresource,
+                            NULL, NULL);
+}
+
+/**
+ * Parse given JSON object to jsonapi document.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_jsonapiresource (void *cls,
+                       json_t *root,
+                       struct GNUNET_JSON_Specification *spec)
+{
+  struct GNUNET_JSONAPI_Resource *res;
+  const char *type;
+  const char *id;
+  json_t *attrs;
+
+  struct GNUNET_JSON_Specification dspec[] = {
+    GNUNET_JSON_spec_string (GNUNET_JSONAPI_KEY_TYPE, &type),
+    GNUNET_JSON_spec_string (GNUNET_JSONAPI_KEY_ID, &id),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root, dspec,
+                         NULL, NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to parse resource\n");
+    return GNUNET_SYSERR;
+  }
+  res = GNUNET_JSONAPI_resource_new (type, id);
+  GNUNET_JSON_parse_free (dspec);
+
+  struct GNUNET_JSON_Specification attrspec[] = {
+    GNUNET_JSON_spec_json (GNUNET_JSONAPI_KEY_ATTRIBUTES, &attrs),
+    GNUNET_JSON_spec_end()
+  };
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root, attrspec,
+                         NULL, NULL))
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Resource does not contain attributes\n");
+  if (NULL != attrs)
+    res->attr_obj = json_deep_copy (attrs);
+
+  //TODO relationship
+  GNUNET_JSON_parse_free (attrspec);
+  *(struct GNUNET_JSONAPI_Resource **) spec->ptr = res;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Cleanup data left from parsing resource.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_jsonapiresource (void *cls,
+                       struct GNUNET_JSON_Specification *spec)
+{
+  struct GNUNET_JSONAPI_Resource **jsonapi_obj;
+  jsonapi_obj = (struct GNUNET_JSONAPI_Resource **) spec->ptr;
+  if (NULL != *jsonapi_obj)
+  {
+    GNUNET_JSONAPI_resource_delete (*jsonapi_obj);
+    *jsonapi_obj = NULL;
+  }
+}
+
+
+/**
+ * JSON object.
+ *
+ * @param name name of the JSON field
+ * @param[out] jsonp where to store the JSON found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_jsonapi_resource (struct GNUNET_JSONAPI_Resource **jsonapi_object)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_jsonapiresource,
+    .cleaner = &clean_jsonapiresource,
+    .cls = NULL,
+    .field = NULL,
+    .ptr = jsonapi_object,
+    .ptr_size = 0,
+    .size_ptr = NULL
+  };
+  *jsonapi_object = NULL;
+  return ret;
+}
+
+
index e9c85eaf6f8c6d564bfedf386774130ed7ca9128..8b0b13566425ce9cdfc1c2442cf2d1bd71b7d6d7 100644 (file)
 static int
 test_serialize ()
 {
-  struct GNUNET_JSONAPI_Object *obj;
-  char* data = "{\"data\":[{\"id\":\"1\", \"type\":\"test\"}]}";
+  struct GNUNET_JSONAPI_Document *obj;
+  char* data = "{\"data\":{\"id\":\"1\",\"type\":\"bar\", \"attributes\":{\"foo\":\"bar\"}}}";
   char* tmp_data;
   json_t* data_js;
   json_t* tmp_data_js;
   json_error_t err;
   struct GNUNET_JSON_Specification jsonapispec[] = {
-    GNUNET_JSON_spec_jsonapi (&obj),
+    GNUNET_JSON_spec_jsonapi_document (&obj),
     GNUNET_JSON_spec_end()
   };
   data_js = json_loads (data, JSON_DECODE_ANY, &err);
@@ -42,8 +42,8 @@ test_serialize ()
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_JSON_parse (data_js, jsonapispec,
                                     NULL, NULL));
-  GNUNET_assert (GNUNET_OK == GNUNET_JSONAPI_data_serialize (obj,
-                                                             &tmp_data));
+  GNUNET_assert (GNUNET_OK == GNUNET_JSONAPI_document_serialize (obj,
+                                                                 &tmp_data));
   GNUNET_JSON_parse_free (jsonapispec);
   tmp_data_js = json_loads (tmp_data, JSON_DECODE_ANY, &err);
   GNUNET_assert (NULL != tmp_data_js);
@@ -62,14 +62,14 @@ test_serialize ()
 static int
 test_spec_jsonapi ()
 {
-  struct GNUNET_JSONAPI_Object *obj;
+  struct GNUNET_JSONAPI_Document *obj;
   struct GNUNET_JSONAPI_Resource *res;
   const char* data = "{\"data\":{\"id\":\"1\", \"type\":\"test\"}}";
   json_t* data_js;
   json_error_t err;
 
   struct GNUNET_JSON_Specification jsonapispec[] = {
-    GNUNET_JSON_spec_jsonapi (&obj),
+    GNUNET_JSON_spec_jsonapi_document (&obj),
     GNUNET_JSON_spec_end()
   };
   data_js = json_loads (data, JSON_DECODE_ANY, &err);
@@ -78,10 +78,10 @@ test_spec_jsonapi ()
                  GNUNET_JSON_parse (data_js, jsonapispec,
                                     NULL, NULL));
   json_decref (data_js);
-  res = GNUNET_JSONAPI_object_get_resource (obj, 0);
+  res = GNUNET_JSONAPI_document_get_resource (obj, 0);
   GNUNET_assert (GNUNET_YES == GNUNET_JSONAPI_resource_check_id (res, "1"));
   GNUNET_assert (GNUNET_YES == GNUNET_JSONAPI_resource_check_type (res, "test"));
-  GNUNET_assert (1 == GNUNET_JSONAPI_object_resource_count (obj));
+  GNUNET_assert (1 == GNUNET_JSONAPI_document_resource_count (obj));
   GNUNET_JSON_parse_free (jsonapispec);
   return 0;
 }
index 76a1126a5a4db312f2441994c6c73f48b9eed4f0..c20ef8e8ac1062caaeecee27817fc12389d3899a 100644 (file)
@@ -106,7 +106,7 @@ struct RequestHandle
   /**
    * JSON response object
    */
-  struct GNUNET_JSONAPI_Object *resp_object;
+  struct GNUNET_JSONAPI_Document *resp_object;
 
   /**
    * Rest connection
@@ -251,7 +251,7 @@ cleanup_handle (struct RequestHandle *handle)
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Cleaning up\n");
   if (NULL != handle->resp_object)
-    GNUNET_JSONAPI_object_delete (handle->resp_object);
+    GNUNET_JSONAPI_document_delete (handle->resp_object);
   if (NULL != handle->name)
     GNUNET_free (handle->name);
   if (NULL != handle->timeout_task)
@@ -407,13 +407,13 @@ namestore_list_response (void *cls,
   char *result;
 
   if (NULL == handle->resp_object)
-    handle->resp_object = GNUNET_JSONAPI_object_new ();
+    handle->resp_object = GNUNET_JSONAPI_document_new ();
 
   if (NULL == rname)
   {
     handle->list_it = NULL;
     //Handle response
-    if (GNUNET_SYSERR == GNUNET_JSONAPI_data_serialize (handle->resp_object, &result))
+    if (GNUNET_SYSERR == GNUNET_JSONAPI_document_serialize (handle->resp_object, &result))
     {
       GNUNET_SCHEDULER_add_now (&do_error, handle);
       return;
@@ -456,7 +456,7 @@ namestore_list_response (void *cls,
     GNUNET_JSONAPI_resource_add_attr (json_resource,
                                            GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
                                            result_array);
-    GNUNET_JSONAPI_object_resource_add (handle->resp_object, json_resource);
+    GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
   }
 
   json_decref (result_array);
@@ -658,7 +658,7 @@ json_to_gnsrecord (const json_t *records_json,
                   "Value property is no string\n");
       return GNUNET_SYSERR;
     }
-    GNUNET_asprintf (&value, "%s", json_string_value (value_json));
+    value = GNUNET_strdup (json_string_value (value_json));
     if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type,
                                                        value,
                                                        &rdata,
@@ -719,9 +719,8 @@ namestore_create_cont (struct GNUNET_REST_RequestHandle *con,
 {
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
-  struct GNUNET_JSONAPI_Object *json_obj;
+  struct GNUNET_JSONAPI_Document *json_obj;
   struct GNUNET_JSONAPI_Resource *json_res;
-  json_t *name_json;
   json_t *records_json;
   char term_data[handle->rest_handle->data_size+1];
 
@@ -741,7 +740,7 @@ namestore_create_cont (struct GNUNET_REST_RequestHandle *con,
   memcpy (term_data,
           handle->rest_handle->data,
           handle->rest_handle->data_size);
-  GNUNET_assert (GNUNET_OK == GNUNET_JSONAPI_object_parse (term_data,
+  GNUNET_assert (GNUNET_OK == GNUNET_JSONAPI_document_parse (term_data,
                                                            &json_obj));
   if (NULL == json_obj)
   {
@@ -751,54 +750,45 @@ namestore_create_cont (struct GNUNET_REST_RequestHandle *con,
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  if (1 != GNUNET_JSONAPI_object_resource_count (json_obj))
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Cannot create more than 1 resource! (Got %d)\n",
-                GNUNET_JSONAPI_object_resource_count (json_obj));
-    GNUNET_JSONAPI_object_delete (json_obj);
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  json_res = GNUNET_JSONAPI_object_get_resource (json_obj, 0);
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
   if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
                                                             GNUNET_REST_JSONAPI_NAMESTORE_RECORD))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unsupported JSON data type\n");
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     resp = GNUNET_REST_create_json_response (NULL);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
     cleanup_handle (handle);
     return;
   }
-  name_json = GNUNET_JSONAPI_resource_get_id (json_res);
-  if (!json_is_string (name_json))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Name property is no string\n");
-    GNUNET_JSONAPI_object_delete (json_obj);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  GNUNET_asprintf (&handle->name, "%s", json_string_value (name_json));
+  handle->name = GNUNET_strdup (GNUNET_JSONAPI_resource_get_id (json_res));
   records_json = GNUNET_JSONAPI_resource_read_attr (json_res,
                                                          GNUNET_REST_JSONAPI_NAMESTORE_RECORD);
   if (NULL == records_json)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "No records given\n");
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   if (GNUNET_SYSERR == json_to_gnsrecord (records_json, &handle->rd, &handle->rd_count))
   {
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  GNUNET_JSONAPI_object_delete (json_obj);
+  GNUNET_JSONAPI_document_delete (json_obj);
 
   handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
                                                     &handle->zone_pkey,
@@ -815,13 +805,13 @@ namestore_zkey_response (void *cls,
 {
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
-  struct GNUNET_JSONAPI_Object *json_obj;
+  struct GNUNET_JSONAPI_Document *json_obj;
   struct GNUNET_JSONAPI_Resource *json_res;
   json_t *name_json;
   char* result;
 
   handle->reverse_qe = NULL;
-  json_obj = GNUNET_JSONAPI_object_new ();
+  json_obj = GNUNET_JSONAPI_document_new ();
   if (NULL != label)
   {
     name_json = json_string (label);
@@ -830,19 +820,19 @@ namestore_zkey_response (void *cls,
     GNUNET_JSONAPI_resource_add_attr (json_res,
                                            GNUNET_REST_JSONAPI_NAMESTORE_NAME,
                                            name_json);
-    GNUNET_JSONAPI_object_resource_add (json_obj, json_res);
+    GNUNET_JSONAPI_document_resource_add (json_obj, json_res);
     json_decref (name_json);
   }
   //Handle response
-  if (GNUNET_SYSERR == GNUNET_JSONAPI_data_serialize (json_obj, &result))
+  if (GNUNET_SYSERR == GNUNET_JSONAPI_document_serialize (json_obj, &result))
   {
-    GNUNET_JSONAPI_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   resp = GNUNET_REST_create_json_response (result);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_JSONAPI_object_delete (json_obj);
+  GNUNET_JSONAPI_document_delete (json_obj);
   GNUNET_free (result);
   GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
   return;
@@ -1105,9 +1095,9 @@ testservice_id_task (void *cls, int result)
   }
   name = get_name_from_url (handle->url);
   if (NULL != ego)
-    GNUNET_asprintf (&handle->ego_name, "%s", ego);
+    handle->ego_name = GNUNET_strdup (ego);
   if (NULL != name)
-    GNUNET_asprintf (&handle->name, "%s", name);
+    handle->name = GNUNET_strdup (name);
   if (NULL == handle->ego_name)
   {
     handle->identity_handle = GNUNET_IDENTITY_connect (handle->cfg, &id_connect_cb, handle);
@@ -1148,7 +1138,7 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
   handle->proc_cls = proc_cls;
   handle->proc = proc;
   handle->rest_handle = rest_handle;
-  GNUNET_asprintf (&handle->url, "%s", rest_handle->url);
+  handle->url = GNUNET_strdup (rest_handle->url);
   if (handle->url[strlen (handle->url)-1] == '/')
     handle->url[strlen (handle->url)-1] = '\0';
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
index 92bef10949a49f7109f66c9eace8edb3a69c67e1..92d4784429158ace729994a3613907d5df56a618 100644 (file)
@@ -757,7 +757,7 @@ run (void *cls,
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Service listens on port %u\n",
+              "Service listens on port %lu\n",
               port);
   httpd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET,
                             0,