desc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. #include "desc.h"
  2. LSUP_rc
  3. LSR_desc_new_multi (LSUP_Graph *const *data, LSR_Desc **rsrc_p)
  4. {
  5. LSUP_rc rc = LSUP_OK;
  6. LSR_Desc *rsrc;
  7. MALLOC_GUARD (rsrc, LSUP_MEM_ERR);
  8. uuid_generate_random (rsrc->id);
  9. // Default context graph.
  10. rsrc->main_data = LSUP_graph_new (LSUP_term_new_from_buffer (
  11. LSUP_default_env->default_ctx), LSUP_STORE_MEM);
  12. LSUP_GraphIterator *lu_it, *add_it, *admin_add_it = NULL;
  13. LSUP_Term *dest_s, *dest_p, *dest_o;
  14. LSUP_Triple src_spo_s, dest_spo_s;
  15. LSUP_Triple
  16. *src_spo = &src_spo_s,
  17. *dest_spo = &dest_spo_s;
  18. LSUP_Term *rsrc_uri = LSR_id_to_urn (rsrc->id, NULL);
  19. LSUP_Term *rdf_t = LSUP_iriref_new ("rdf:type", LSUP_DEF_NSM);
  20. // Count graphs inserted.
  21. size_t ct = 0;
  22. while (data[ct]) ct++;
  23. rsrc->user_data = calloc (sizeof (*rsrc->user_data), ct + 1);
  24. if (UNLIKELY (! rsrc->user_data)) return LSUP_MEM_ERR;
  25. /* BEGIN adding user data. */
  26. // Loop over input graphs.
  27. for (size_t i = 0; i < ct; i++) {
  28. LSUP_Term *gr_uri = LSUP_term_copy (LSUP_graph_uri (data[i]));
  29. LSUP_Term *rel_uri = LSUP_iriref_relative (rsrc_uri, gr_uri);
  30. if (strstr (rel_uri->data, "#__") == rel_uri->data) {
  31. log_error ("Fragment URI cannot start with double underscore.");
  32. rc = LSUP_VALUE_ERR;
  33. }
  34. LSUP_term_free (rel_uri);
  35. if (rc < 0) goto finally;
  36. rsrc->user_data[i] = LSUP_graph_new (gr_uri, LSUP_STORE_MEM);
  37. add_it = LSUP_graph_add_init (rsrc->user_data[i]);
  38. lu_it = LSUP_graph_lookup (rsrc->user_data[i], NULL, NULL, NULL, NULL);
  39. // Loop over graph triples.
  40. while (LSUP_graph_iter_next (lu_it, src_spo) == LSUP_OK) {
  41. dest_s = LSUP_IS_IRI (src_spo->s) ?
  42. LSUP_iriref_relative (rsrc_uri, src_spo->s) : src_spo->s;
  43. dest_p = LSUP_term_copy (src_spo->p);
  44. dest_o = LSUP_IS_IRI (src_spo->s) ?
  45. LSUP_iriref_relative (rsrc_uri, src_spo->s) : src_spo->s;
  46. LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
  47. // if the pred is managed, ignore the triple and send a warning.
  48. LSR_TermMap *tmp;
  49. LSUP_Key pk = LSUP_term_hash (dest_spo->p);
  50. HASH_FIND (hh, LSR_managed_preds, &pk, sizeof (pk), tmp);
  51. if (tmp) {
  52. log_warn (
  53. "Predicate %s is managed. Skipping triple.",
  54. dest_s->data);
  55. free (tmp);
  56. goto loop_end;
  57. }
  58. /*
  59. * If the subject or object is a resource, check if it exists; if
  60. * it does, add triple to user_data; if not, return an error.
  61. */
  62. uuid_t id_tmp;
  63. LSUP_rc tmp_rc;
  64. if (LSR_IS_RSRC_IRI (dest_s)) {
  65. uuid_parse (dest_s->data + strlen (LSR_RSRC_PFX), id_tmp);
  66. tmp_rc = LSR_desc_get (id_tmp, NULL);
  67. if (tmp_rc != LSUP_OK) {
  68. log_error (
  69. "Referenced subject does not exist: %s",
  70. dest_s->data + strlen (LSR_RSRC_PFX));
  71. rc = LSUP_VALUE_ERR;
  72. goto finally;
  73. }
  74. }
  75. if (LSR_IS_RSRC_IRI (dest_o)) {
  76. uuid_parse (dest_o->data + strlen (LSR_RSRC_PFX), id_tmp);
  77. tmp_rc = LSR_desc_get (id_tmp, NULL);
  78. if (tmp_rc != LSUP_OK) {
  79. log_error (
  80. "Referenced object does not exist: %s",
  81. dest_o->data + strlen (LSR_RSRC_PFX));
  82. rc = LSUP_VALUE_ERR;
  83. goto finally;
  84. }
  85. }
  86. // RDF type check.
  87. if (
  88. LSUP_term_equals (
  89. gr_uri, LSUP_iriref_absolute (rsrc_uri, dest_spo->p))
  90. && LSUP_term_equals (rdf_t, dest_spo->p)
  91. ) {
  92. // If the resource is a special type, handle specific workflow.
  93. // TODO
  94. }
  95. // Add triple to user_data.
  96. LSUP_graph_add_iter (add_it, dest_spo);
  97. loop_end:
  98. if (dest_s != src_spo->s) LSUP_term_free (dest_s);
  99. if (dest_o != src_spo->o) LSUP_term_free (dest_o);
  100. }
  101. // Add user graph metadata to default graph.
  102. admin_add_it = LSUP_graph_add_init (rsrc->main_data);
  103. dest_s = gr_uri;
  104. dest_p = LSUP_iriref_new ("rdf:type", LSUP_DEF_NSM);
  105. dest_o = LSUP_iriref_new ("lsup:Metadata", LSUP_DEF_NSM);
  106. LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
  107. LSUP_graph_add_iter (admin_add_it, dest_spo);
  108. LSUP_term_free (dest_o);
  109. dest_o = LSUP_iriref_new ("lsup:UserMetadata", LSUP_DEF_NSM);
  110. LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
  111. LSUP_graph_add_iter (admin_add_it, dest_spo);
  112. LSUP_term_free (dest_o);
  113. LSUP_term_free (dest_p);
  114. // Relationship between data graph and resource.
  115. dest_p = LSUP_iriref_new ("foaf:primaryTopic", LSUP_DEF_NSM);
  116. dest_o = rsrc_uri;
  117. LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
  118. LSUP_graph_add_iter (admin_add_it, dest_spo);
  119. LSUP_term_free (dest_p);
  120. LSUP_graph_iter_free (lu_it);
  121. LSUP_graph_add_done (add_it);
  122. LSUP_graph_add_done (admin_add_it);
  123. lu_it = add_it = admin_add_it = NULL;
  124. }
  125. /* END adding user data. */
  126. /* BEGIN adding managed (admin) data. */
  127. LSUP_Term *gr_uri = LSR_id_to_urn (rsrc->id, "__admin");
  128. rsrc->admin_data = LSUP_graph_new (gr_uri, LSUP_STORE_MEM);
  129. admin_add_it = LSUP_graph_add_init (rsrc->admin_data);
  130. dest_s = LSUP_iriref_new("", NULL); // Relative to resource URI.
  131. LSUP_Triple admin_spo_s;
  132. LSUP_Triple *admin_spo = &admin_spo_s;
  133. // RDF types.
  134. dest_p = rdf_t;
  135. dest_o = LSUP_iriref_new ("lsup:Resource", LSUP_DEF_NSM);
  136. LSUP_triple_init (admin_spo, dest_s, dest_p, dest_o);
  137. LSUP_graph_add_iter (admin_add_it, admin_spo);
  138. LSUP_term_free (dest_o);
  139. dest_o = LSUP_iriref_new ("lsup:DescriptiveResource", LSUP_DEF_NSM);
  140. LSUP_triple_init (admin_spo, dest_s, dest_p, dest_o);
  141. LSUP_graph_add_iter (admin_add_it, admin_spo);
  142. LSUP_term_free (dest_o);
  143. // Timestamps. For now, second precision is fine.
  144. time_t now;
  145. time (&now);
  146. char buf [sizeof ("0000-00-00T00:00:00Z")];
  147. strftime (buf, sizeof (buf), "%FT%TZ", gmtime (&now));
  148. dest_p = LSUP_iriref_new ("lsup:created", LSUP_DEF_NSM);
  149. dest_o = LSUP_literal_new (
  150. buf, LSUP_iriref_new ("xsd:dateTime", LSUP_DEF_NSM));
  151. LSUP_triple_init (admin_spo, dest_s, dest_p, dest_o);
  152. LSUP_graph_add_iter (admin_add_it, admin_spo);
  153. LSUP_term_free (dest_p);
  154. dest_p = LSUP_iriref_new ("lsup:lastModified", LSUP_DEF_NSM);
  155. LSUP_triple_init (admin_spo, dest_s, dest_p, dest_o);
  156. LSUP_graph_add_iter (admin_add_it, admin_spo);
  157. LSUP_term_free (dest_p);
  158. LSUP_term_free (dest_o);
  159. LSUP_graph_add_done (admin_add_it);
  160. // Add admin graph metadata to default graph.
  161. admin_add_it = LSUP_graph_add_init (rsrc->main_data);
  162. LSUP_term_free (dest_s);
  163. dest_s = gr_uri;
  164. dest_p = rdf_t;
  165. dest_o = LSUP_iriref_new ("lsup:Metadata", LSUP_DEF_NSM);
  166. LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
  167. LSUP_graph_add_iter (admin_add_it, dest_spo);
  168. LSUP_term_free (dest_o);
  169. dest_o = LSUP_iriref_new ("lsup:AdminMetadata", LSUP_DEF_NSM);
  170. LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
  171. LSUP_graph_add_iter (admin_add_it, dest_spo);
  172. LSUP_term_free (dest_o);
  173. // Relationship between data graph and resource.
  174. dest_p = LSUP_iriref_new ("foaf:primaryTopic", LSUP_DEF_NSM);
  175. dest_o = rsrc_uri;
  176. LSUP_triple_init (dest_spo, dest_s, dest_p, dest_o);
  177. LSUP_graph_add_iter (admin_add_it, dest_spo);
  178. LSUP_term_free (dest_p);
  179. LSUP_graph_add_done (admin_add_it);
  180. admin_add_it = NULL;
  181. /* END adding admin data. */
  182. finally:
  183. LSUP_term_free (rsrc_uri);
  184. LSUP_term_free (rdf_t);
  185. if (rc < 0) goto fail;
  186. rsrc->flags |= LSR_RS_DIRTY;
  187. *rsrc_p = rsrc;
  188. return rc;
  189. fail:
  190. LSUP_graph_iter_free (lu_it);
  191. LSUP_graph_add_done (add_it);
  192. LSUP_graph_add_done (admin_add_it);
  193. LSR_desc_free (rsrc);
  194. *rsrc_p = NULL;
  195. return rc;
  196. }
  197. LSUP_rc
  198. LSR_desc_store (const LSR_Desc *rsrc)
  199. {
  200. // TODO Make atomic. Needs to implement transactions in backend.
  201. LSR_Desc *old_rsrc;
  202. LSUP_rc rc = LSR_desc_get (rsrc->id, &old_rsrc);
  203. if (UNLIKELY (rc < 0)) return rc;
  204. // Remove all existing user graphs.
  205. if (rc == LSUP_OK) {
  206. //LSUP_Term *main_data_urn = LSUP_graph_uri (old_rsrc->main_data);
  207. for (size_t i = 0; old_rsrc->user_data[i] != NULL; i++) {
  208. LSUP_Term *gr_uri = LSUP_graph_uri (old_rsrc->user_data[i]);
  209. size_t ct;
  210. // Remove triples from user graph.
  211. LSUP_graph_remove (old_rsrc->user_data[i], NULL, NULL, NULL, &ct);
  212. log_debug ( "Removed %lu triples from graph %s", ct, gr_uri->data);
  213. // Remove user graph metadata.
  214. LSUP_graph_remove (old_rsrc->main_data, gr_uri, NULL, NULL, NULL);
  215. LSUP_graph_remove (old_rsrc->main_data, NULL, NULL, gr_uri, NULL);
  216. }
  217. } else rc = LSUP_OK;
  218. // Add new triples.
  219. for (size_t i = 0; rsrc->user_data[i] != NULL; i++) {
  220. //LSUP_Term *gr_uri = LSUP_graph_uri (rsrc->user_data[i]);
  221. log_trace ("Storing data graph #%lu", i);
  222. LSUP_graph_store (rsrc->user_data[i], NULL, NULL);
  223. }
  224. // Update admin data.
  225. LSUP_graph_store (rsrc->admin_data, NULL, NULL);
  226. // Update graph metadata.
  227. LSUP_graph_store (rsrc->main_data, NULL, NULL);
  228. return rc;
  229. }
  230. LSUP_rc
  231. LSUP_desc_update (LSR_id id, LSUP_Term **remove, LSUP_Triple *add)
  232. {
  233. LSUP_rc rc = LSUP_OK;
  234. return rc;
  235. }
  236. LSUP_rc
  237. LSR_desc_get (const uuid_t id, LSR_Desc **rsrc_p)
  238. {
  239. LSUP_rc rc = LSUP_OK;
  240. LSUP_Term *default_gr_uri = LSUP_term_new_from_buffer (
  241. LSUP_default_env->default_ctx);
  242. LSUP_Graph *main_gr = LSUP_graph_new (default_gr_uri, LSUP_STORE_MDB);
  243. LSUP_Term
  244. *s = LSR_id_to_urn (id, NULL),
  245. *p = LSUP_iriref_new ("rdf:type", LSUP_DEF_NSM),
  246. *o = LSUP_iriref_new ("lsup:Resource", LSUP_DEF_NSM);
  247. LSUP_Triple *spo = LSUP_triple_new (s, p, o);
  248. if (!LSUP_graph_contains (main_gr, spo)) rc = LSUP_NORESULT;
  249. LSUP_term_free (p);
  250. LSUP_term_free (o);
  251. if (rsrc_p)
  252. if(rc == LSUP_OK) {
  253. p = LSUP_iriref_new ("foaf:primaryTopic", LSUP_DEF_NSM);
  254. size_t ct = 0, i = 0;
  255. // Find all graphs making up the resource.
  256. LSUP_GraphIterator *it = LSUP_graph_lookup (main_gr, NULL, p, s, &ct);
  257. LSUP_Graph **data = calloc (sizeof (*data), ct + 1);
  258. while (LSUP_graph_iter_next (it, spo)) {
  259. data[i] = LSUP_graph_new (spo->s, LSUP_STORE_MDB);
  260. if (! data[i++]) break;
  261. }
  262. LSUP_graph_iter_free (it);
  263. rc = LSR_desc_new_multi (data, rsrc_p);
  264. i = 0;
  265. while (i < ct) LSUP_graph_free (data[i++]);
  266. free (data);
  267. LSUP_term_free (s);
  268. LSUP_term_free (p);
  269. }
  270. LSUP_graph_free (main_gr);
  271. return rc;
  272. }
  273. void LSR_desc_free (LSR_Desc *rsrc)
  274. {
  275. size_t i = 0;
  276. while (rsrc->user_data[i])
  277. LSUP_graph_free (rsrc->user_data[i++]);
  278. free (rsrc->user_data);
  279. LSUP_graph_free (rsrc->admin_data);
  280. LSUP_graph_free (rsrc->main_data);
  281. free (rsrc);
  282. }