From 79747838cf9ea301bcd838a1f98a530e2d2cb68d Mon Sep 17 00:00:00 2001 From: Stephan Heunis Date: Fri, 14 Feb 2025 14:37:58 +0100 Subject: [PATCH] Allow recursive blank node resolution for submission This has been a long time coming. In the end it needed a simple adjustment to the utils/getSubjectTriples function to allow recursion. This was after much time went into the design, with thoughts written in https://hub.datalad.org/datalink/annotate-trr379-demo/issues/45 --- src/components/SubmitComp.vue | 3 ++- src/composables/formdata.js | 25 ++++++++++++++++++------- src/modules/io.js | 4 ---- src/modules/utils.js | 13 +++++++++++-- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/components/SubmitComp.vue b/src/components/SubmitComp.vue index 76d5031..4d1b865 100644 --- a/src/components/SubmitComp.vue +++ b/src/components/SubmitComp.vue @@ -61,6 +61,7 @@ const submitDialog = inject('submitDialog') const tokenExists = ref(false) const nodeShapes = inject('nodeShapes') + const graphData = inject('graphData') const ID_IRI = inject('ID_IRI') const config = inject('config') const allPrefixes = inject('allPrefixes'); @@ -88,7 +89,7 @@ setToken(tokenval.value) } awaitingResponse.value = true - var submit_result = await submitFormData(nodeShapes.value, ID_IRI.value, allPrefixes, config) + var submit_result = await submitFormData(nodeShapes.value, ID_IRI.value, allPrefixes, config, graphData) console.log("submit_result") console.log(submit_result) diff --git a/src/composables/formdata.js b/src/composables/formdata.js index 35a860b..9544823 100644 --- a/src/composables/formdata.js +++ b/src/composables/formdata.js @@ -191,7 +191,7 @@ export function useFormData() { } } - async function submitFormData(nodeShapes, id_iri, prefixes, config) { + async function submitFormData(nodeShapes, id_iri, prefixes, config, graphData) { console.log("inside submitFormData function") console.log(toRaw(formData)) if (Object.keys(formData).length == 0) { @@ -210,16 +210,12 @@ export function useFormData() { return } const { token } = useToken(); - // Send a POST to a service for every record in formData - // Some exploration: - // - we need to send a POST request for every NAMED NODE record, - // with blank nodes resolved + var headers = {} if (token.value !== null && token.value !== "null") { headers['X-DumpThings-Token'] = token.value; } - try { // collect all POST requests as Promises let postPromises = []; @@ -228,10 +224,25 @@ export function useFormData() { // Get shapes for reference var nodeShape = nodeShapes[class_uri] var propertyShapes = nodeShape.properties + // if the nodeshape does NOT have a propertyshape with sh:path being equal to ID_IRI, + // it means the class's records will be blank nodes and we can skip the whole class + var ps = propertyShapes.find((prop) => prop[SHACL.path.value] == id_iri) + if(!ps) { + console.log(`Class '${class_uri}' shape does not have an id field, i.e. it will have blank node records, i.e. skipping.`) + continue; + } for (var record_id of Object.keys(formData[class_uri])) { + console.log(`formData for node: ${record_id}`) + console.log(toRaw(formData[class_uri][record_id])) // Turn the record/node into quads - // var quads = formNodeToQuads(class_uri, record_id, nodeShapes, propertyShapes, id_iri, prefixes) + // Ne need to resolve blank nodes recursively, and add all to the dataset + quads.forEach(quad => { + if (quad.object.termType === "BlankNode") { + var moreQuads = getSubjectTriples(graphData, quad.object, true) + quads = quads.concat(Array.from(moreQuads)) + } + }); // Create an rdf dataset per record var ds = rdf.dataset() quads.forEach(quad => { diff --git a/src/modules/io.js b/src/modules/io.js index 6f3c7e0..7f48833 100644 --- a/src/modules/io.js +++ b/src/modules/io.js @@ -121,7 +121,3 @@ export async function postRDF(endpoint, dataset, format = 'text/turtle', headers throw error; } } - - - - diff --git a/src/modules/utils.js b/src/modules/utils.js index 62e7219..939bc56 100644 --- a/src/modules/utils.js +++ b/src/modules/utils.js @@ -235,13 +235,22 @@ export function getLiteralAndNamedNodes(graphData, predicate, propertyClass, pre } -export function getSubjectTriples(graphData, someTerm) { +export function getSubjectTriples(graphData, someTerm, blankNodesResolved=false) { // console.log(`Getting all triples with subject: ${someTerm.value}`) const quads = rdf.grapoi({ dataset: graphData, term: someTerm }).out().quads(); // Array.from(quads).forEach(quad => { // console.log(`\t${quad.subject.value} - ${quad.predicate.value} - ${quad.object.value}`) // }) - return Array.from(quads) + var quadArray = Array.from(quads) + if (blankNodesResolved) { + quads.forEach(q => { + if (q.object.termType === "BlankNode") { + var moreQuads = getSubjectTriples(graphData, q, true) + quadArray = quadArray.concat(Array.from(moreQuads)) + } + }) + } + return quadArray }