@igea/oac_backend 1.0.49 → 1.0.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@igea/oac_backend",
3
- "version": "1.0.49",
3
+ "version": "1.0.51",
4
4
  "description": "Backend service for the OAC project",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -24,22 +24,27 @@
24
24
  "homepage": "https://github.com/chpigea/oac_backend#readme",
25
25
  "dependencies": {
26
26
  "@igea/oac_jwt_helpers": "1.0.10",
27
+ "@rdfjs/data-model": "1.1.2",
28
+ "@rdfjs/types": "1.1.0",
27
29
  "axios": "1.10.0",
28
30
  "cookie-parser": "1.4.7",
29
31
  "crypto": "1.0.1",
30
32
  "express": "5.1.0",
31
33
  "express-rate-limit": "8.1.0",
32
- "fast-xml-parser": "^5.3.3",
34
+ "fast-xml-parser": "5.3.3",
33
35
  "get-port": "7.1.0",
34
36
  "knex": "3.1.0",
35
37
  "libxmljs2": "0.37.0",
36
38
  "multer": "2.0.2",
37
- "n3": "1.26.0",
39
+ "n3": "1.17.2",
38
40
  "nodemailer": "7.0.6",
39
41
  "pg": "8.16.3",
42
+ "rdf-data-factory": "2.0.2",
43
+ "rdf-ext": "1.3.0",
40
44
  "rdf-validate-shacl": "0.6.5",
41
45
  "strip-bom": "5.0.0",
42
- "tmp": "0.2.5"
46
+ "tmp": "0.2.5",
47
+ "xmlbuilder2": "4.0.3"
43
48
  },
44
49
  "devDependencies": {
45
50
  "chai": "5.2.1",
@@ -239,10 +239,13 @@ router.post('/search/by-prefix', (req, res) => {
239
239
  const bindings = response.data.results.bindings;
240
240
  let results = []
241
241
  bindings.forEach(result => {
242
- results.push({
243
- instance: result.instance.value,
244
- label: result.label.value,
245
- });
242
+ if(result.node){
243
+ var label = result.label ? result.label.value : "";
244
+ results.push({
245
+ instance: result.node.value,
246
+ label
247
+ });
248
+ }
246
249
  });
247
250
  res.json({
248
251
  success: true,
@@ -250,6 +253,7 @@ router.post('/search/by-prefix', (req, res) => {
250
253
  message: null
251
254
  });
252
255
  }).catch(err => {
256
+ console.log(err)
253
257
  res.status(500).json({
254
258
  success: false,
255
259
  data: null,
@@ -228,7 +228,7 @@ router.post('/convert/:from/:to', (req, res) => {
228
228
  console.log(`Requesting conversion from ${from} to ${to}`);
229
229
  let conversionFunction = null
230
230
  if(from === 'ttl' && to === 'xml'){
231
- conversionFunction = Converter.turtle2RdfXml
231
+ conversionFunction = Converter.turtle2RdfXmlCustom
232
232
  }else if(from === 'xml' && to === 'ttl'){
233
233
  conversionFunction = Converter.rdfXml2Turtle
234
234
  }else if(from === to){
@@ -1,7 +1,9 @@
1
1
  const fs = require('fs');
2
- const { Parser } = require('n3');
3
- const { DataFactory, Store } = require('n3');
2
+
3
+ const { Parser, DataFactory, Store } = require('n3');
4
4
  const { exec } = require('child_process');
5
+ const { create } = require('xmlbuilder2');
6
+ const rdf = require('rdf-ext')
5
7
 
6
8
  class Converter {
7
9
 
@@ -94,6 +96,95 @@ class Converter {
94
96
 
95
97
  }
96
98
 
99
+ //------------------------------------------------------------------------------------
100
+ // Helper per estrarre QName/localName
101
+
102
+ static qnameLocal(uriObj) {
103
+ let uri = (typeof uriObj === 'string') ? uriObj : uriObj.value
104
+ if (uri.includes('#'))
105
+ return uri.split('#')[1];
106
+ return uri.split('/').pop();
107
+ }
108
+
109
+ // Generatore XML ricorsivo
110
+ static buildNode(dataset, subject, parent, visited) {
111
+ if (visited.has(subject.value)) {
112
+ parent.ele('Reference').att('rdf:resource', subject.value);
113
+ return;
114
+ }
115
+ visited.add(subject.value);
116
+
117
+ // Determina tag principale dall'rdf:type
118
+ const types = [...dataset.match(subject, rdf.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'))];
119
+ const tagUri = types.length ? types[0].object.value : subject.value;
120
+ const tagName = Converter.qnameLocal(tagUri);
121
+
122
+ const elem = parent.ele(tagName).att('rdf:about', subject.value);
123
+
124
+ // Itera predicati
125
+ const preds = new Set(dataset.match(subject).map(q => q.predicate.value));
126
+ for (let p of Array.from(preds).sort()) {
127
+ const predName = Converter.qnameLocal(p);
128
+ console.log("predName: " + predName)
129
+ const objects = dataset.match(subject, rdf.namedNode(p)).map(q => q.object);
130
+
131
+ for (let obj of objects) {
132
+ const child = elem.ele(predName);
133
+
134
+ if (obj.termType === 'Literal') {
135
+ const lit = child.ele('rdfs:Literal').att('rdf:about', obj.value);
136
+ lit.ele('rdfs:label').txt(obj.value);
137
+ } else if (obj.termType === 'NamedNode' || obj.termType === 'BlankNode') {
138
+ Converter.buildNode(dataset, obj, child, visited);
139
+ } else {
140
+ child.txt(obj.value);
141
+ }
142
+ }
143
+ }
144
+
145
+ return elem;
146
+ }
147
+
148
+ static turtle2RdfXmlCustom(turtle, outRdfXmlPath=null) {
149
+
150
+ return new Promise((resolve, reject) => {
151
+ const parser = new Parser();
152
+ const quads = parser.parse(turtle);
153
+
154
+ const dataset = rdf.dataset();
155
+ for (const quad of quads) {
156
+ dataset.add(quad);
157
+ }
158
+
159
+ const root = create({ version: '1.0', encoding: 'UTF-8' })
160
+ .ele('rdf:RDF', {
161
+ 'xmlns:rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
162
+ 'xmlns:rdfs': 'http://www.w3.org/2000/01/rdf-schema#'
163
+ });
164
+
165
+ const visited = new Set();
166
+ const subjects = Array.from(new Set(dataset.map(q => q.subject.value)))
167
+ .map(uri => rdf.namedNode(uri))
168
+ .sort((a, b) => a.value.localeCompare(b.value));
169
+
170
+ console.log(subjects)
171
+ for (let s of subjects) {
172
+ Converter.buildNode(dataset, s, root, visited);
173
+ }
174
+
175
+ const xml = root.end({ prettyPrint: true });
176
+
177
+ if(outRdfXmlPath){
178
+ fs.writeFileSync(outRdfXmlPath, xml, 'utf8');
179
+ }
180
+
181
+ resolve(xml)
182
+ })
183
+
184
+ }
185
+
186
+ //------------------------------------------------------------------------------------
187
+
97
188
  static async turtle2RdfXml(inTurtlePath, outRdfXmlPath) {
98
189
  return new Promise((resolve, reject) => {
99
190
  const command = `rapper -i turtle -o rdfxml "${inTurtlePath}" > "${outRdfXmlPath}"`;
@@ -90,20 +90,22 @@ class Fuseki {
90
90
  if(limit < 1) limit = 50;
91
91
  return `
92
92
  PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
93
- SELECT DISTINCT ?instance ?label
93
+ SELECT ?node ?label
94
94
  WHERE {
95
- # tutte le istanze con qualsiasi proprietà
96
- ?instance ?p ?o .
97
- # filtro per IRI che inizia con il prefisso specifico
98
- FILTER(STRSTARTS(STR(?instance), "${prefix}"))
99
- # filtro per IRI che termina con UUID
100
- #FILTER(REGEX(STR(?instance), "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"))
101
- # label opzionale
102
- OPTIONAL { ?instance rdfs:label ?label . }
95
+ {
96
+ ?s ?p ?node .
97
+ FILTER (isIRI(?node) && STRSTARTS(STR(?node), "${prefix}"))
98
+ }
99
+ UNION
100
+ {
101
+ ?node ?p ?o.
102
+ FILTER (isIRI(?node) && STRSTARTS(STR(?node), "${prefix}"))
103
+ }
104
+ OPTIONAL { ?node rdfs:label ?label . }
103
105
  }
104
106
  ORDER BY ?label
105
107
  LIMIT ${limit}
106
- OFFSET ${offset}`
108
+ OFFSET ${offset}`
107
109
  }
108
110
 
109
111
  static getQuerySearchInvestigation(id, prefix='http://indagine/') {
@@ -96,7 +96,7 @@ class Parser{
96
96
  resolve(queries);
97
97
  }
98
98
  let checkCompleted = function(index, query, status, message){
99
- console.log(`Completed ${index+1}/${files.length}`);
99
+ //console.log(`Completed ${index+1}/${files.length}`);
100
100
  files[index].status = status;
101
101
  files[index].message = message;
102
102
  if(status) queries[index]=query;
@@ -12,6 +12,12 @@
12
12
  #@prefix skos: <http://www.w3.org/2004/02/skos/core> .
13
13
  #@prefix pref: <http://indagine/> .
14
14
 
15
+ @prefix core: <http://data.sparna.fr/ontologies/sparnatural-config-core#> .
16
+ @prefix dash: <http://datashapes.org/dash#> .
17
+ @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
18
+ @prefix skosxl: <http://www.w3.org/2008/05/skos-xl#> .
19
+ @prefix volipi: <http://data.sparna.fr/ontologies/volipi#> .
20
+
15
21
 
16
22
  ex:E7ActivityShape # INDAGINE
17
23
  a sh:NodeShape, rdfs:Class ;
@@ -136,11 +142,13 @@ ex:E41Appellation02Shape # DENOMINAZIONE BENE
136
142
  ex:E55Type02Shape # TIPO QUESITO DIAGNOSTICO
137
143
  a sh:NodeShape, rdfs:Class ;
138
144
  sh:targetClass crm:E55_Type ;
145
+ volipi:iconName "fa-solid fa-car" ;
139
146
  sh:property [
140
147
  sh:path ex:P2hastype02 ;
141
- sh:class owl:Class ; # vocabolario QUESITO DIAGNOSTICO (8) id="quesito-diagnostico"
148
+ #dash:searchWidget core:TreeProperty ;
149
+ sh:class owl:Class ; # vocabolario QUESITO DIAGNOSTICO (8) id="quesito-diagnostico"
142
150
  owl:imports <OAC_EXPOSED_PROTOCOL://OAC_EXPOSED_HOST:OAC_EXPOSED_PORT/backend/fuseki/get-vocabolary-terms/quesito-diagnostico> ;
143
- sh:name "Tipo" ;
151
+ sh:name "Tipo" ;
144
152
  sh:maxCount 1 ;
145
153
  sh:minCount 1 ;
146
154
  ] ;
@@ -27,13 +27,23 @@ describe('Converter', () => {
27
27
  });
28
28
  });
29
29
 
30
- it('should convert a turtle string to sparql UPSERT', (done) => {
30
+ it('should convert a turtle string to sparql UPSERT', (done) => {
31
31
  let inputTurtle = fs.readFileSync(__dirname + '/example-investigation-01.ttl', 'utf8');
32
32
  let sparql = converter.turtle2Sparql(inputTurtle)
33
33
  expect(sparql).to.be.a('string');
34
34
  expect(sparql.length).to.be.greaterThan(0);
35
- console.log(sparql);
35
+ //console.log(sparql);
36
36
  done();
37
37
  });
38
38
 
39
+ it('should convert a turtle string to Custom RDF/Xml', (done) => {
40
+ let inputTurtle = fs.readFileSync(__dirname + '/example-investigation-02.ttl', 'utf8');
41
+ converter.turtle2RdfXmlCustom(inputTurtle).then((sparql) => {
42
+ expect(sparql).to.be.a('string');
43
+ expect(sparql.length).to.be.greaterThan(0);
44
+ console.log(sparql);
45
+ done();
46
+ })
47
+ });
48
+
39
49
  })
@@ -0,0 +1,32 @@
1
+ @prefix sh: <http://www.w3.org/ns/shacl#>.
2
+ @prefix ex: <http://example.org/shapes/>.
3
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
4
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
5
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
6
+ @prefix owl: <http://www.w3.org/2002/07/owl#>.
7
+ @prefix crm: <http://www.cidoc-crm.org/cidoc-crm/>.
8
+ @prefix basecpm: <http://ontome.net/ns/cpm/>.
9
+ @prefix base: <http://www.ics.forth.gr/isl/CRMinf/>.
10
+ @prefix cpm: <http://ontome.net/ns/cpm/>.
11
+ @prefix crmsci: <http://www.cidoc-crm.org/extensions/crmsci/>.
12
+ @prefix pref: <http://diagnostica/>.
13
+ @prefix skos: <http://www.w3.org/2004/02/skos/core#>.
14
+
15
+ pref:3cc24c8c-ce06-40ef-bdce-9da2c4c5394b ex:P48haspreferredidentifier01 <http://indagine/3>;
16
+ a crm:E42_Identifier.
17
+ pref:1adba9d5-c83b-41a8-b97f-c6e5b168658a a crm:E7_Activity;
18
+ crm:P48_has_preferred_identifier pref:3cc24c8c-ce06-40ef-bdce-9da2c4c5394b;
19
+ crm:P17_was_motivated_by pref:f30ead0e-edcc-4f6f-868e-8bc6f9d13813;
20
+ crm:P14_carried_out_by pref:57701c6c-ece4-472b-bc24-b75c1c254568;
21
+ <http://purl.org/dc/terms/conformsTo> ex:E7ActivityShape.
22
+ pref:40a75ae6-daa4-4ae1-bd41-2e07175f6f75 a crm:E55_Type;
23
+ ex:P2hastype02 <http://diagnostica/vocabularies/quesito-diagnostico/tecnologia-di-produzione>.
24
+ pref:f30ead0e-edcc-4f6f-868e-8bc6f9d13813 a base:I12_Adopted_Belief;
25
+ crm:P2_has_type pref:40a75ae6-daa4-4ae1-bd41-2e07175f6f75.
26
+ pref:95e957ad-55b5-45d3-bf62-6a292959c4f9 a crm:E41_Appellation;
27
+ ex:ente_richiedente "Università";
28
+ ex:schedatore "Christian".
29
+ pref:956f0c5a-6fc5-4a79-b399-6c6288fb000f a crm:E55_Type;
30
+ crm:P1_is_defined_by pref:95e957ad-55b5-45d3-bf62-6a292959c4f9.
31
+ pref:57701c6c-ece4-472b-bc24-b75c1c254568 a crm:E29_Actor;
32
+ crm:P2_has_type pref:956f0c5a-6fc5-4a79-b399-6c6288fb000f.