123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- #include "desc.h"
- LSUP_rc
- LSR_desc_new_multi (LSUP_Graph *const *data, LSR_Desc **rsrc_p)
- {
- LSUP_rc rc = LSUP_OK;
- LSR_Desc *rsrc;
- MALLOC_GUARD (rsrc, LSUP_MEM_ERR);
- uuid_generate_random (rsrc->id);
- // Default context graph.
- rsrc->main_data = LSUP_graph_new (
- LSUP_default_ctx, LSUP_STORE_HTABLE, NULL, NULL, 0);
- LSUP_GraphIterator *lu_it, *add_it, *admin_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 *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_term_copy (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 (
- gr_uri, LSUP_STORE_HTABLE, NULL, NULL, 0);
- 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_PFX), 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_PFX));
- rc = LSUP_VALUE_ERR;
- goto finally;
- }
- }
- // Check object.
- if (LSR_IS_RSRC_IRI (dest_o)) {
- uuid_parse (dest_o->data + strlen (LSR_RSRC_PFX), 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_PFX));
- 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");
- rsrc->admin_data = LSUP_graph_new (
- gr_uri, LSUP_STORE_HTABLE, NULL, NULL, 0);
- admin_add_it = LSUP_graph_add_init (rsrc->admin_data);
- dest_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;
- 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);
- 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);
- // Timestamps. For now, second precision is fine.
- time_t now;
- time (&now);
- 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 (
- 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);
- /* 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;
- 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: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);
- // 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_add_done (admin_add_it);
- admin_add_it = NULL;
- /* END adding graph metadata. */
- finally:
- LSUP_term_free (rsrc_uri);
- LSUP_term_free (rdf_t);
- if (rc < 0) goto fail;
- rsrc->flags |= LSR_RS_DIRTY;
- *rsrc_p = rsrc;
- 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)
- {
- // TODO Make atomic. Needs to implement transactions in backend.
- LSR_Desc *old_rsrc;
- LSUP_rc rc = LSR_desc_get (rsrc->id, &old_rsrc);
- if (UNLIKELY (rc < 0)) return rc;
- // Remove all existing user graphs.
- if (old_rsrc) {
- LSUP_Term *main_data_urn = LSUP_graph_uri (old_rsrc->main_data);
- // TODO Handle managed preds and types.
- // TODO Handle conflict between disjoint managed types.
- // TODO Retain created and created_by.
- for (size_t i = 0; old_rsrc->user_data[i] != NULL; i++) {
- LSUP_Term *gr_uri = LSUP_graph_uri (old_rsrc->user_data[i]);
- size_t ct;
- // Remove triples from user graph.
- LSUP_graph_remove (old_rsrc->user_data[i], NULL, NULL, NULL, &ct);
- log_debug ( "Removed %lu triples from graph %s", ct, gr_uri->data);
- // Remove user graph metadata.
- LSUP_graph_remove (old_rsrc->main_data, gr_uri, NULL, NULL, NULL);
- LSUP_graph_remove (old_rsrc->main_data, NULL, NULL, gr_uri, NULL);
- }
- }
- // Add new triples.
- for (size_t i = 0; rsrc->user_data[i] != NULL; i++) {
- LSUP_Term *gr_uri = LSUP_graph_uri (rsrc->user_data[i]);
- LSUP_graph_store (rsrc->user_data[i], NULL, NULL);
- }
- // Update admin data.
- LSUP_graph_store (rsrc->admin_data, NULL, NULL);
- // Update graph metadata.
- LSUP_graph_store (rsrc->main_data, NULL, NULL);
- }
- LSUP_rc
- LSUP_desc_update (LSR_id id, LSUP_Term **remove, LSUP_Triple *add)
- {
- }
- LSUP_rc
- LSR_desc_get (const uuid_t id, LSR_Desc **rsrc_p)
- {
- LSUP_rc rc = LSUP_OK;
- LSUP_Graph *main_gr = LSUP_graph_new (
- LSUP_default_ctx, LSR_DEFAULT_BACKEND, NULL, NULL, 0);
- LSUP_Term
- *s = LSR_id_to_urn (id, NULL),
- *p = LSUP_iriref_new ("rdf:type", LSUP_default_nsm),
- *o = LSUP_iriref_new ("lsup:Resource", LSUP_default_nsm);
- LSUP_Triple *spo = LSUP_triple_new (s, p, o);
- LSUP_triple_free (spo);
- if (!LSUP_graph_contains (main_gr, spo)) {
- rc = LSUP_NORESULT;
- goto finally;
- }
- LSUP_term_free (o);
- o = LSUP_iriref_new ("lsup:DescriptiveResource", LSUP_default_nsm);
- spo = LSUP_triple_new (s, p, o);
- if (!LSUP_graph_contains (main_gr, spo)) {
- log_error ("%s is not a descriptive resource.", o->data);
- rc = LSUP_NORESULT;
- goto finally;
- }
- LSUP_term_free (p);
- p = LSUP_iriref_new ("foaf:primaryTopic", LSUP_default_nsm);
- size_t ct = 0, i = 0;
- // Find all graphs making up the resource.
- LSUP_GraphIterator *it = LSUP_graph_lookup (main_gr, NULL, p, s, &ct);
- LSUP_Graph **data = calloc (sizeof (*data), ct + 1);
- while (LSUP_graph_iter_next (it, &spo)) {
- data[i] = LSUP_graph_new (spo->s, LSR_DEFAULT_BACKEND, NULL, NULL, 0);
- if (! data[i++]) break; // Last slot remains NULL (sentinel).
- }
- LSUP_graph_iter_free (it);
- rc = LSR_desc_new_multi (data, rsrc_p);
- i = 0;
- while (i < ct) LSUP_graph_free (data[i++]);
- free (data);
- finally:
- LSUP_triple_free (spo);
- LSUP_term_free (s);
- LSUP_term_free (p);
- LSUP_term_free (o);
- LSUP_graph_free (main_gr);
- return rc;
- }
- LSUP_Graph *
- LSR_desc_metadata (const LSR_Desc *rsrc)
- {
- uuid_t uuid;
- char
- *rsrc_uri_str = LSUP_graph_uri (rsrc->admin_data)->data,
- *frag = "#metadata-",
- uuid_str [UUID_STR_LEN],
- id_str [8],
- *uri_str = malloc (
- strlen (frag) + strlen (rsrc_uri_str) + sizeof (id_str));
- if (UNLIKELY (!uri_str)) return NULL;
- uuid_generate_random (uuid);
- uuid_unparse_lower (uuid, uuid_str);
- strncpy (id_str, uuid_str, sizeof (id_str) - 1);
- sprintf (uri_str, "%s%s%s", rsrc_uri_str, frag, id_str);
- LSUP_Graph *res = LSUP_graph_copy (rsrc->admin_data);
- if (LIKELY (res))
- LSUP_graph_set_uri (res, LSUP_iriref_new (uri_str, NULL));
- free (uri_str);
- free (rsrc_uri_str);
- free (uuid);
- return res;
- }
- LSUP_Graph **
- LSR_desc_user_data (const LSR_Desc *rsrc)
- {
- uuid_t uuid;
- char
- *rsrc_uri_str = LSUP_graph_uri (rsrc->admin_data)->data,
- *frag = "#metadata-",
- uuid_str [UUID_STR_LEN],
- id_str [8],
- *uri_str = malloc (
- strlen (frag) + strlen (rsrc_uri_str) + sizeof (id_str));
- if (UNLIKELY (!uri_str)) return NULL;
- size_t ct = 0;
- while (rsrc->user_data[ct]) ct ++;
- LSUP_Graph **res = malloc (sizeof *res * (ct + 1));
- if (UNLIKELY (!res)) return NULL;
- for (size_t i = 0; i < ct; i++) {
- uuid_generate_random (uuid);
- uuid_unparse_lower (uuid, uuid_str);
- strncpy (id_str, uuid_str, sizeof (id_str) - 1);
- sprintf (uri_str, "%s%s%s", rsrc_uri_str, frag, id_str);
- res[i] = LSUP_graph_copy (rsrc->user_data[i]);
- if (LIKELY (res))
- LSUP_graph_set_uri (res[i], LSUP_iriref_new (uri_str, NULL));
- }
- res[ct] = NULL;
- free (uri_str);
- free (rsrc_uri_str);
- free (uuid);
- return res;
- }
- void LSR_desc_free (LSR_Desc *rsrc)
- {
- size_t i = 0;
- while (rsrc->user_data[i])
- LSUP_graph_free (rsrc->user_data[i++]);
- free (rsrc->user_data);
- LSUP_graph_free (rsrc->admin_data);
- LSUP_graph_free (rsrc->main_data);
- free (rsrc);
- }
- LSUP_rc
- LSR_desc_store (const LSR_Desc *rsrc)
- {
- // TODO Make atomic. Needs to implement transactions in backend.
- LSR_Desc *old_rsrc;
- LSUP_rc rc = LSR_desc_get (rsrc->id, &old_rsrc);
- if (UNLIKELY (rc < 0)) return rc;
- // Remove all existing user graphs.
- if (rc == LSUP_OK) {
- //LSUP_Term *main_data_urn = LSUP_graph_uri (old_rsrc->main_data);
- for (size_t i = 0; old_rsrc->user_data[i] != NULL; i++) {
- LSUP_Term *gr_uri = LSUP_graph_uri (old_rsrc->user_data[i]);
- size_t ct;
- // Remove triples from user graph.
- LSUP_graph_remove (old_rsrc->user_data[i], NULL, NULL, NULL, &ct);
- log_debug ( "Removed %lu triples from graph %s", ct, gr_uri->data);
- // Remove user graph metadata.
- LSUP_graph_remove (old_rsrc->main_data, gr_uri, NULL, NULL, NULL);
- LSUP_graph_remove (old_rsrc->main_data, NULL, NULL, gr_uri, NULL);
- }
- } else rc = LSUP_OK;
- // Add new triples.
- for (size_t i = 0; rsrc->user_data[i] != NULL; i++) {
- //LSUP_Term *gr_uri = LSUP_graph_uri (rsrc->user_data[i]);
- log_trace ("Storing data graph #%lu", i);
- LSUP_graph_store (rsrc->user_data[i], NULL, NULL);
- }
- // Update admin data.
- LSUP_graph_store (rsrc->admin_data, NULL, NULL);
- // Update graph metadata.
- LSUP_graph_store (rsrc->main_data, NULL, NULL);
- return rc;
- }
- LSUP_rc
- LSUP_desc_update (LSR_id id, LSUP_Term **remove, LSUP_Triple *add)
- {
- LSUP_rc rc = LSUP_OK;
- return rc;
- }
|