@igea/oac_backend 1.0.50 → 1.0.52

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.50",
3
+ "version": "1.0.52",
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",
@@ -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,124 @@ 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
+ let tagName = Converter.qnameLocal(tagUri);
121
+
122
+ const tagIsNumber = (typeof tagName === 'string' && tagName.trim() !== '' && !isNaN(tagName))
123
+ if(tagIsNumber) tagName = "_" + tagName; // Prefix numerici per XML
124
+
125
+ //console.log("Building node: " + tagName + " for subject: " + subject.value)
126
+
127
+ const elem = parent.ele(tagName).att('rdf:about', subject.value);
128
+
129
+ // Itera predicati
130
+ const preds = new Set(dataset.match(subject).toArray().map(q => q.predicate.value));
131
+ for (let p of Array.from(preds).sort()) {
132
+ const predName = Converter.qnameLocal(p);
133
+ //console.log(">>> predName: " + predName)
134
+ const objects = dataset.match(subject, rdf.namedNode(p)).toArray().map(q => q.object);
135
+
136
+ for (let obj of objects) {
137
+ // Skip rdf:type as it's used for the tag name
138
+ if(predName === "type") continue;
139
+
140
+ const child = elem.ele(predName);
141
+
142
+ if (obj.termType === 'Literal') {
143
+ const lit = child.ele('rdfs:Literal').att('rdf:about', obj.value);
144
+ lit.ele('rdfs:label').txt(obj.value);
145
+ } else if (obj.termType === 'NamedNode' || obj.termType === 'BlankNode') {
146
+
147
+ Converter.buildNode(dataset, obj, child, visited);
148
+
149
+ } else {
150
+ child.txt(obj.value);
151
+ }
152
+ }
153
+ }
154
+
155
+ return elem;
156
+ }
157
+
158
+ static turtle2RdfXmlCustom(turtle, outRdfXmlPath=null) {
159
+
160
+ return new Promise((resolve, reject) => {
161
+ const parser = new Parser();
162
+ const quads = parser.parse(turtle);
163
+
164
+ const dataset = rdf.dataset();
165
+ for (const quad of quads) {
166
+ dataset.add(quad);
167
+ }
168
+
169
+ const root = create({ version: '1.0', encoding: 'UTF-8' })
170
+ .ele('rdf:RDF', {
171
+ 'xmlns:rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
172
+ 'xmlns:rdfs': 'http://www.w3.org/2000/01/rdf-schema#'
173
+ });
174
+
175
+ const visited = new Set();
176
+
177
+ const subjects = Array.from(
178
+ new Set(
179
+ dataset.toArray().map(q => q.subject.value)
180
+ )
181
+ ).map(uri => rdf.namedNode(uri))
182
+ .sort((a, b) => a.value.localeCompare(b.value));
183
+
184
+ const objects = Array.from(
185
+ new Set(
186
+ dataset.toArray().map(q => q.object.value)
187
+ )
188
+ ).map(uri => rdf.namedNode(uri))
189
+ .sort((a, b) => a.value.localeCompare(b.value));
190
+
191
+ for (let s of subjects) {
192
+ s["_isRoot"] = false;
193
+ if (objects.findIndex(o => o.value === s.value) == -1) {
194
+ s["_isRoot"] = true;
195
+ //console.log("Root subject: " + s.value);
196
+ }
197
+ }
198
+
199
+ for (let s of subjects) {
200
+ if(s["_isRoot"])
201
+ Converter.buildNode(dataset, s, root, visited);
202
+ }
203
+
204
+ const xml = root.end({ prettyPrint: true });
205
+
206
+ if(outRdfXmlPath){
207
+ fs.writeFileSync(outRdfXmlPath, xml, 'utf8');
208
+ }
209
+
210
+ resolve(xml)
211
+ })
212
+
213
+ }
214
+
215
+ //------------------------------------------------------------------------------------
216
+
97
217
  static async turtle2RdfXml(inTurtlePath, outRdfXmlPath) {
98
218
  return new Promise((resolve, reject) => {
99
219
  const command = `rapper -i turtle -o rdfxml "${inTurtlePath}" > "${outRdfXmlPath}"`;
@@ -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.