scossu 1 year ago
parent
commit
5765a1e558
2 changed files with 250 additions and 183 deletions
  1. 21 0
      include/desc.h
  2. 229 183
      src/desc.c

+ 21 - 0
include/desc.h

@@ -119,6 +119,27 @@ LSUP_rc
 LSR_desc_get (const uuid_t id, LSR_Desc **rsrc);
 
 
+
+/** @brief Update an existing resource.
+ *
+ * @param[in] rsrc Resource handle.
+ *
+ * @param[in] rm_data Array of graph handles. Each graph contains triples to be
+ * removed from graphs with a matching URI in the resource. If no matching
+ * graph is found, that graph has no effect.
+ *
+ * @param[in] add_data Array of graph handles to add. If the resource has
+ * already a matching graph for a graph being added, the triples are added to
+ * the existing graph.
+ *
+ * @return LSUP_OK on successful update; TODO
+ */
+static LSUP_rc
+LSR_desc_update (
+        LSR_Desc *rsrc, LSUP_Graph *const *rm_data,
+        LSUP_Graph *const *add_data);
+
+
 /** @brief Free a DESC-R.
  */
 void

+ 229 - 183
src/desc.c

@@ -1,5 +1,11 @@
 #include "desc.h"
 
+static LSUP_rc
+desc_update (
+        LSR_Desc *rsrc, LSUP_Graph *const *rm_data,
+        LSUP_Graph *const *add_data, bool _new);
+
+
 LSUP_rc
 LSR_desc_new_multi (LSUP_Graph *const *data, LSR_Desc **rsrc_p)
 {
@@ -10,153 +16,26 @@ LSR_desc_new_multi (LSUP_Graph *const *data, LSR_Desc **rsrc_p)
 
     uuid_generate_random (rsrc->id);
 
+    LSUP_Graph *const *rm_data = {NULL};
+    PCHECK (desc_update (rsrc, rm_data, data, true), finally);
+
     // Default context graph.
-    rsrc->main_data = LSUP_graph_new (NULL, LSUP_default_ctx, NULL);
+    LSUP_Term *main_data_urn = LSR_id_to_urn (rsrc->id, "__main");
+    rsrc->main_data = LSUP_graph_new (NULL, main_data_urn, LSUP_default_nsm);
+    LSUP_term_free (main_data_urn);
     log_debug (
             "Main data graph: %s",
             LSUP_graph_uri(rsrc->main_data)->data);
 
-    LSUP_GraphIterator
-        *lu_it,                 // Lookup iterator.
-        *add_it,                // Main graph add iterator.
-        *admin_add_it = NULL;   // Admin graph add iterator.
+    LSUP_GraphIterator *add_it = NULL;
 
-    LSUP_Term *dest_s, *dest_p, *dest_o;
-    LSUP_Triple src_spo_s, dest_spo_s;
-    LSUP_Triple
-        *src_spo = &src_spo_s,
-        *dest_spo = &dest_spo_s;
+    LSUP_Term *s, *p, *o;
+    LSUP_Triple dest_spo_s;
+    LSUP_Triple *dest_spo = &dest_spo_s;
 
     LSUP_Term *rsrc_uri = LSR_id_to_urn (rsrc->id, NULL);
     LSUP_Term *rdf_t = LSUP_iriref_new ("rdf:type", LSUP_default_nsm);
 
-    // Count graphs inserted and allocate space.
-    size_t ct = 0;
-    while (data[ct]) ct++;
-    rsrc->user_data = calloc (sizeof (*rsrc->user_data), ct + 1);
-    if (UNLIKELY (! rsrc->user_data)) return LSUP_MEM_ERR;
-
-    /* BEGIN adding user data. */
-
-    // Loop over input graphs.
-    for (size_t i = 0; i < ct; i++) {
-        LSUP_Term *gr_uri = LSUP_graph_uri (data[i]);
-
-        LSUP_Term *rel_uri = LSUP_iriref_relative (rsrc_uri, gr_uri);
-        if (strstr (rel_uri->data, "#__") == rel_uri->data) {
-            log_error ("Fragment URI cannot start with double underscore.");
-            rc = LSUP_VALUE_ERR;
-        }
-        LSUP_term_free (rel_uri);
-        if (rc < 0) goto finally;
-
-        rsrc->user_data[i] = LSUP_graph_new (NULL, gr_uri, NULL);
-        log_debug (
-                "User data graph (@%p): %s",
-                LSUP_graph_uri(rsrc->user_data[i]),
-                LSUP_graph_uri(rsrc->user_data[i])->data);
-
-        add_it = LSUP_graph_add_init (rsrc->user_data[i]);
-        lu_it = LSUP_graph_lookup (rsrc->user_data[i], NULL, NULL, NULL, NULL);
-
-        // Loop over graph triples.
-        while (LSUP_graph_iter_next (lu_it, &src_spo) == LSUP_OK) {
-            dest_s = LSUP_IS_IRI (src_spo->s) ?
-                    LSUP_iriref_relative (rsrc_uri, src_spo->s) : src_spo->s;
-            dest_p = LSUP_term_copy (src_spo->p);
-            dest_o = LSUP_IS_IRI (src_spo->s) ?
-                    LSUP_iriref_relative (rsrc_uri, src_spo->s) : src_spo->s;
-            LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
-
-            // if the pred is managed, ignore the triple and send a warning.
-            if (hashmap_get(LSR_managed_preds, dest_spo->p)) {
-                log_warn (
-                        "Predicate %s is managed. Skipping triple.",
-                        dest_p->data);
-                goto loop_end;
-            }
-
-            /*
-             * If the subject or object is a resource, check if it exists; if
-             * it does, add triple to user_data; if not, return an error.
-             */
-            uuid_t id_tmp;
-            LSUP_rc tmp_rc;
-            // Check subject.
-            if (LSR_IS_RSRC_IRI (dest_s)) {
-                uuid_parse (dest_s->data + strlen (LSR_RSRC_NS), id_tmp);
-                tmp_rc = LSR_desc_get (id_tmp, NULL);
-                if (tmp_rc != LSUP_OK) {
-                    log_error (
-                            "Referenced subject does not exist: %s",
-                            dest_s->data + strlen (LSR_RSRC_NS));
-                    rc = LSUP_VALUE_ERR;
-                    goto finally;
-                }
-            }
-            // Check object.
-            if (LSR_IS_RSRC_IRI (dest_o)) {
-                uuid_parse (dest_o->data + strlen (LSR_RSRC_NS), id_tmp);
-                tmp_rc = LSR_desc_get (id_tmp, NULL);
-                if (tmp_rc != LSUP_OK) {
-                    log_error (
-                            "Referenced object does not exist: %s",
-                            dest_o->data + strlen (LSR_RSRC_NS));
-                    rc = LSUP_VALUE_ERR;
-                    goto finally;
-                }
-            }
-
-            // RDF type check.
-            if (
-                LSUP_term_equals (
-                    gr_uri, LSUP_iriref_absolute (rsrc_uri, dest_spo->s))
-                && LSUP_term_equals (rdf_t, dest_spo->p)
-            ) {
-                // If the resource is a special type, handle specific workflow.
-                // TODO
-                if (hashmap_get (LSR_managed_types, dest_spo->o)) {
-                }
-            }
-
-            // Add triple to user_data.
-            LSUP_graph_add_iter (add_it, dest_spo);
-loop_end:
-            if (dest_s != src_spo->s) LSUP_term_free (dest_s);
-            if (dest_o != src_spo->o) LSUP_term_free (dest_o);
-        }
-
-        // Add user graph metadata to default graph.
-        admin_add_it = LSUP_graph_add_init (rsrc->main_data);
-        dest_s = gr_uri;
-        dest_p = LSUP_iriref_new ("rdf:type", LSUP_default_nsm);
-
-        dest_o = LSUP_iriref_new ("lsup:Metadata", LSUP_default_nsm);
-        LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
-        LSUP_graph_add_iter (admin_add_it, dest_spo);
-        LSUP_term_free (dest_o);
-
-        dest_o = LSUP_iriref_new ("lsup:UserMetadata", LSUP_default_nsm);
-        LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
-        LSUP_graph_add_iter (admin_add_it, dest_spo);
-        LSUP_term_free (dest_o);
-        LSUP_term_free (dest_p);
-
-        // Relationship between data graph and resource.
-        dest_p = LSUP_iriref_new ("foaf:primaryTopic", LSUP_default_nsm);
-        dest_o = rsrc_uri;
-        LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
-        LSUP_graph_add_iter (admin_add_it, dest_spo);
-        LSUP_term_free (dest_p);
-
-        LSUP_graph_iter_free (lu_it);
-        LSUP_graph_add_done (add_it);
-        LSUP_graph_add_done (admin_add_it);
-        lu_it = add_it = admin_add_it = NULL;
-    }
-
-    /* END adding user data. */
-
     /* BEGIN adding managed (admin) data. */
 
     LSUP_Term *gr_uri = LSR_id_to_urn (rsrc->id, "__admin");
@@ -166,23 +45,23 @@ loop_end:
             LSUP_graph_uri(rsrc->admin_data),
             LSUP_graph_uri(rsrc->admin_data)->data);
 
-    admin_add_it = LSUP_graph_add_init (rsrc->admin_data);
-    dest_s = LSUP_iriref_new("", NULL); // Relative to resource URI.
+    add_it = LSUP_graph_add_init (rsrc->admin_data);
+    s = LSUP_iriref_new("", NULL); // Relative to resource URI.
     LSUP_Triple admin_spo_s;
     LSUP_Triple *admin_spo = &admin_spo_s;
 
     // RDF types.
-    dest_p = rdf_t;
+    p = rdf_t;
 
-    dest_o = LSUP_iriref_new ("lsup:Resource", LSUP_default_nsm);
-    LSUP_triple_init (admin_spo, dest_s, dest_p, dest_o);
-    LSUP_graph_add_iter (admin_add_it, admin_spo);
-    LSUP_term_free (dest_o);
+    o = LSUP_iriref_new ("lsup:Resource", LSUP_default_nsm);
+    LSUP_triple_init (admin_spo, s, p, o);
+    LSUP_graph_add_iter (add_it, admin_spo);
+    LSUP_term_free (o);
 
-    dest_o = LSUP_iriref_new ("lsup:DescriptiveResource", LSUP_default_nsm);
-    LSUP_triple_init (admin_spo, dest_s, dest_p, dest_o);
-    LSUP_graph_add_iter (admin_add_it, admin_spo);
-    LSUP_term_free (dest_o);
+    o = LSUP_iriref_new ("lsup:DescriptiveResource", LSUP_default_nsm);
+    LSUP_triple_init (admin_spo, s, p, o);
+    LSUP_graph_add_iter (add_it, admin_spo);
+    LSUP_term_free (o);
 
     // Timestamps. For now, second precision is fine.
     time_t now;
@@ -190,49 +69,49 @@ loop_end:
     char buf [sizeof ("0000-00-00T00:00:00Z")];
     strftime (buf, sizeof (buf), "%FT%TZ", gmtime (&now));
 
-    dest_p = LSUP_iriref_new ("lsup:created", LSUP_default_nsm);
-    dest_o = LSUP_literal_new (
+    p = LSUP_iriref_new ("lsup:created", LSUP_default_nsm);
+    o = LSUP_literal_new (
             buf, LSUP_iriref_new ("xsd:dateTime", LSUP_default_nsm));
-    LSUP_triple_init (admin_spo, dest_s, dest_p, dest_o);
-    LSUP_graph_add_iter (admin_add_it, admin_spo);
-    LSUP_term_free (dest_p);
-
-    dest_p = LSUP_iriref_new ("lsup:lastModified", LSUP_default_nsm);
-    LSUP_triple_init (admin_spo, dest_s, dest_p, dest_o);
-    LSUP_graph_add_iter (admin_add_it, admin_spo);
-    LSUP_term_free (dest_p);
-    LSUP_term_free (dest_o);
-    LSUP_graph_add_done (admin_add_it);
+    LSUP_triple_init (admin_spo, s, p, o);
+    LSUP_graph_add_iter (add_it, admin_spo);
+    LSUP_term_free (p);
+
+    p = LSUP_iriref_new ("lsup:lastModified", LSUP_default_nsm);
+    LSUP_triple_init (admin_spo, s, p, o);
+    LSUP_graph_add_iter (add_it, admin_spo);
+    LSUP_term_free (p);
+    LSUP_term_free (o);
+    LSUP_graph_add_done (add_it);
 
     /* END adding admin data. */
 
     /* BEGIN adding graph metadata (main). */
 
-    admin_add_it = LSUP_graph_add_init (rsrc->main_data);
-    LSUP_term_free (dest_s);
-    dest_s = gr_uri;
-    dest_p = rdf_t;
+    add_it = LSUP_graph_add_init (rsrc->main_data);
+    LSUP_term_free (s);
+    s = gr_uri;
+    p = rdf_t;
 
-    dest_o = LSUP_iriref_new ("lsup:Metadata", LSUP_default_nsm);
-    LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
-    LSUP_graph_add_iter (admin_add_it, dest_spo);
-    LSUP_term_free (dest_o);
+    o = LSUP_iriref_new ("lsup:Metadata", LSUP_default_nsm);
+    LSUP_triple_init (dest_spo, s, p, o);
+    LSUP_graph_add_iter (add_it, dest_spo);
+    LSUP_term_free (o);
 
-    dest_o = LSUP_iriref_new ("lsup:AdminMetadata", LSUP_default_nsm);
-    LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
-    LSUP_graph_add_iter (admin_add_it, dest_spo);
-    LSUP_term_free (dest_o);
+    o = LSUP_iriref_new ("lsup:AdminMetadata", LSUP_default_nsm);
+    LSUP_triple_init (dest_spo, s, p, o);
+    LSUP_graph_add_iter (add_it, dest_spo);
+    LSUP_term_free (o);
 
     // Relationship between data graph and resource.
-    dest_p = LSUP_iriref_new ("foaf:primaryTopic", LSUP_default_nsm);
-    dest_o = rsrc_uri;
-    LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
-    LSUP_graph_add_iter (admin_add_it, dest_spo);
-    LSUP_term_free (dest_p);
-    LSUP_term_free (dest_s); // === gr_uri
+    p = LSUP_iriref_new ("foaf:primaryTopic", LSUP_default_nsm);
+    o = rsrc_uri;
+    LSUP_triple_init (dest_spo, s, p, o);
+    LSUP_graph_add_iter (add_it, dest_spo);
+    LSUP_term_free (p);
+    LSUP_term_free (s); // === gr_uri
 
-    LSUP_graph_add_done (admin_add_it);
-    admin_add_it = NULL;
+    LSUP_graph_add_done (add_it);
+    add_it = NULL;
 
     /* END adding graph metadata. */
 
@@ -249,16 +128,13 @@ finally:
     return rc;
 
 fail:
-    LSUP_graph_iter_free (lu_it);
     LSUP_graph_add_done (add_it);
-    LSUP_graph_add_done (admin_add_it);
     LSR_desc_free (rsrc);
     *rsrc_p = NULL;
 
     return rc;
 }
 
-
 LSUP_rc
 LSR_desc_store (const LSR_Desc *rsrc)
 {
@@ -439,6 +315,12 @@ LSR_desc_user_data (const LSR_Desc *rsrc)
 }
 
 
+LSUP_Graph *
+LSR_desc_update (
+        LSR_Desc *rsrc, LSUP_Graph *const *remove, LSUP_Graph *const *add)
+{ return desc_update (rsrc, remove, add, false); }
+
+
 void LSR_desc_free (LSR_Desc *rsrc)
 {
     size_t i = 0;
@@ -452,3 +334,167 @@ void LSR_desc_free (LSR_Desc *rsrc)
 }
 
 
+/** @brief Update a resource's user data.
+ *
+ * This is exposed externally by #LSR_desc_update(), in which it only differs
+ * from the additional "new" parameter, which is used by #LSR_desc_new_multi()
+ * to indicate that the resource being updated has just been created.
+ */
+static LSUP_rc
+desc_update (
+        LSR_Desc *rsrc, LSUP_Graph *const *rm_data,
+        LSUP_Graph *const *add_data, bool _new)
+{
+    LSUP_rc rc = LSUP_NOACTION;
+    LSUP_Term *rsrc_uri = LSR_id_to_urn (rsrc->id, NULL);
+
+    // Count graphs inserted and allocate space.
+    size_t ct = 0;
+    while (add_data[ct]) ct++;
+    rsrc->user_data = calloc (sizeof (*rsrc->user_data), ct + 1);
+    if (UNLIKELY (! rsrc->user_data)) return NULL;
+
+    LSUP_Triple spo_s;
+    LSUP_Triple *spo = &spo_s;
+    LSUP_GraphIterator
+        *lu_it,                 // Lookup iterator.
+        *add_it;                // Main graph add iterator.
+
+    // Loop over input graphs.
+    for (size_t i = 0; i < ct; i++) {
+        LSUP_Term *gr_uri = LSUP_graph_uri (add_data[i]);
+
+        LSUP_Term *rel_uri = LSUP_iriref_relative (rsrc_uri, gr_uri);
+        if (strstr (rel_uri->data, "#__") == rel_uri->data) {
+            log_error ("Fragment URI cannot start with double underscore.");
+            rc = LSUP_VALUE_ERR;
+        }
+        LSUP_term_free (rel_uri);
+        if (rc < 0) goto finally;
+
+        rsrc->user_data[i] = LSUP_graph_new (NULL, gr_uri, NULL);
+        log_debug (
+                "User data graph (@%p): %s",
+                LSUP_graph_uri(rsrc->user_data[i]),
+                LSUP_graph_uri(rsrc->user_data[i])->data);
+
+        add_it = LSUP_graph_add_init (rsrc->user_data[i]);
+        lu_it = LSUP_graph_lookup (rsrc->user_data[i], NULL, NULL, NULL, NULL);
+
+        // Loop over graph triples.
+        LSUP_Term *dest_s, *dest_p, *dest_o;
+        while (LSUP_graph_iter_next (lu_it, &src_spo) == LSUP_OK) {
+            dest_s = LSUP_IS_IRI (src_spo->s) ?
+                    LSUP_iriref_relative (rsrc_uri, src_spo->s) : src_spo->s;
+            dest_p = LSUP_term_copy (src_spo->p);
+            dest_o = LSUP_IS_IRI (src_spo->s) ?
+                    LSUP_iriref_relative (rsrc_uri, src_spo->s) : src_spo->s;
+            LSUP_triple_init (spo, dest_s, dest_p, dest_o);
+
+            // if the pred is managed, ignore the triple and send a warning.
+            if (hashmap_get(LSR_managed_preds, spo->p)) {
+                log_warn (
+                        "Predicate %s is managed. Skipping triple.",
+                        dest_p->data);
+                goto loop_end;
+            }
+
+            /*
+             * If the subject or object is a resource, check if it exists; if
+             * it does, add triple to user_data; if not, return an error.
+             */
+            uuid_t id_tmp;
+            LSUP_rc tmp_rc;
+            // Check subject.
+            if (LSR_IS_RSRC_IRI (dest_s)) {
+                uuid_parse (dest_s->data + strlen (LSR_RSRC_NS), id_tmp);
+                tmp_rc = LSR_desc_get (id_tmp, NULL);
+                if (tmp_rc != LSUP_OK) {
+                    log_error (
+                            "Referenced subject does not exist: %s",
+                            dest_s->data + strlen (LSR_RSRC_NS));
+                    rc = LSUP_VALUE_ERR;
+                    goto finally;
+                }
+            }
+            // Check object.
+            if (LSR_IS_RSRC_IRI (dest_o)) {
+                uuid_parse (dest_o->data + strlen (LSR_RSRC_NS), id_tmp);
+                tmp_rc = LSR_desc_get (id_tmp, NULL);
+                if (tmp_rc != LSUP_OK) {
+                    log_error (
+                            "Referenced object does not exist: %s",
+                            dest_o->data + strlen (LSR_RSRC_NS));
+                    rc = LSUP_VALUE_ERR;
+                    goto finally;
+                }
+            }
+
+            // RDF type check.
+            if (
+                LSUP_term_equals (
+                    gr_uri, LSUP_iriref_absolute (rsrc_uri, spo->s))
+                && LSUP_term_equals (rdf_t, spo->p)
+            ) {
+                // If the resource is a special type, handle specific workflow.
+                if (hashmap_get (LSR_managed_types, spo->o)) {
+                    if (
+                            strcmp (spo->o->data, "lsup:List") == 0 ||
+                            strcmp (spo->o->data, "lsup:ListItem") == 0 ||
+                            strcmp (spo->o->data, "lsup:Set") == 0 ||
+                            strcmp (spo->o->data, "lsup:Proxy") == 0) {
+                        // TODO
+                    } else {
+                        log_error (
+                                "%s is a managed predicate and cannot "
+                                "be used on creation.", spo->o->data);
+                        rc = LSUP_VALUE_ERR;
+                        goto finally;
+                    }
+                }
+            }
+
+            // Add triple to user_data.
+            LSUP_graph_add_iter (add_it, spo);
+loop_end:
+            if (dest_s != src_spo->s) LSUP_term_free (dest_s);
+            if (dest_o != src_spo->o) LSUP_term_free (dest_o);
+        }
+
+        // Add user graph metadata to default graph.
+        admin_add_it = LSUP_graph_add_init (rsrc->main_data);
+        dest_s = gr_uri;
+        dest_p = LSUP_iriref_new ("rdf:type", LSUP_default_nsm);
+
+        dest_o = LSUP_iriref_new ("lsup:Metadata", LSUP_default_nsm);
+        LSUP_triple_init (spo, dest_s, dest_p, dest_o);
+        LSUP_graph_add_iter (admin_add_it, spo);
+        LSUP_term_free (dest_o);
+
+        dest_o = LSUP_iriref_new ("lsup:UserMetadata", LSUP_default_nsm);
+        LSUP_triple_init (spo, dest_s, dest_p, dest_o);
+        LSUP_graph_add_iter (admin_add_it, spo);
+        LSUP_term_free (dest_o);
+        LSUP_term_free (dest_p);
+
+        // Relationship between data graph and resource.
+        dest_p = LSUP_iriref_new ("foaf:primaryTopic", LSUP_default_nsm);
+        dest_o = rsrc_uri;
+        LSUP_triple_init (spo, dest_s, dest_p, dest_o);
+        LSUP_graph_add_iter (admin_add_it, spo);
+        LSUP_term_free (dest_p);
+
+        LSUP_graph_iter_free (lu_it);
+        LSUP_graph_add_done (add_it);
+        LSUP_graph_add_done (admin_add_it);
+        lu_it = add_it = admin_add_it = NULL;
+    }
+
+finally:
+    LSUP_term_free (rsrc_uri);
+    LSUP_graph_iter_free (lu_it);
+    LSUP_graph_add_done (add_it);
+
+}
+
+