@igea/oac_backend 1.0.39 → 1.0.40
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 +1 -1
- package/src/controllers/fuseki.js +115 -1
- package/src/controllers/ontology.js +15 -1
- package/src/models/fuseki.js +22 -0
- package/src/ontology/schema_v2.shacl.ttl +24 -50
package/package.json
CHANGED
|
@@ -116,6 +116,121 @@ router.post('/upload/vocabularies', upload.array('files'), (req, res) => {
|
|
|
116
116
|
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
+
//---------------------------------------------------------------
|
|
120
|
+
router.get('/get-vocabolary-terms/:key', (req, res) => {
|
|
121
|
+
const key = req.params.key;
|
|
122
|
+
const rootIRI = `<http://diagnostica/vocabularies/${key}>`;
|
|
123
|
+
|
|
124
|
+
let _query = `PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
|
|
125
|
+
CONSTRUCT {
|
|
126
|
+
?concept ?p ?o .
|
|
127
|
+
}
|
|
128
|
+
WHERE {
|
|
129
|
+
?concept (crm:P127_has_broader_term*) ${rootIRI} .
|
|
130
|
+
?concept ?p ?o .
|
|
131
|
+
}`;
|
|
132
|
+
|
|
133
|
+
let query = `PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
|
|
134
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
135
|
+
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
|
|
136
|
+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
|
|
137
|
+
|
|
138
|
+
CONSTRUCT {
|
|
139
|
+
|
|
140
|
+
?concept a owl:Class ;
|
|
141
|
+
rdfs:subClassOf ?parent ;
|
|
142
|
+
skos:prefLabel ?label ;
|
|
143
|
+
skos:closeMatch ?mappedConcept .
|
|
144
|
+
|
|
145
|
+
}
|
|
146
|
+
WHERE {
|
|
147
|
+
|
|
148
|
+
# Trovo tutti i concetti del vocabolario
|
|
149
|
+
?concept (crm:P127_has_broader_term*) ${rootIRI} .
|
|
150
|
+
|
|
151
|
+
# Recupero l'etichetta
|
|
152
|
+
OPTIONAL { ?concept rdfs:label ?label . }
|
|
153
|
+
|
|
154
|
+
# Prelevo il parent da broader term
|
|
155
|
+
OPTIONAL {
|
|
156
|
+
?concept crm:P127_has_broader_term ?parent .
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Genero un mapping verso un URI esterno
|
|
160
|
+
BIND(
|
|
161
|
+
IRI(CONCAT("${rootIRI}", REPLACE(STR(?concept), "^.*[/#]", "")))
|
|
162
|
+
AS ?mappedConcept
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
ORDER BY ?label`
|
|
167
|
+
|
|
168
|
+
axios.post(fusekiUrl, `query=${encodeURIComponent(query)}`,{
|
|
169
|
+
headers: {
|
|
170
|
+
'Accept': `text/turtle`,
|
|
171
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
172
|
+
},
|
|
173
|
+
responseType: 'stream'
|
|
174
|
+
}).then(response => {
|
|
175
|
+
res.setHeader('Content-Type', response.headers['content-type']);
|
|
176
|
+
response.data.pipe(res);
|
|
177
|
+
}).catch(err => {
|
|
178
|
+
res.status(500).json({
|
|
179
|
+
success: false,
|
|
180
|
+
data: null,
|
|
181
|
+
message: `Error: ${err}`
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
})
|
|
185
|
+
//---------------------------------------------------------------
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
|
189
|
+
|
|
190
|
+
SELECT ?obj
|
|
191
|
+
WHERE {
|
|
192
|
+
?obj rdf:type <http://www.cidoc-crm.org/cidoc-crm/E55_Type> .
|
|
193
|
+
}
|
|
194
|
+
ORDER BY ?obj
|
|
195
|
+
LIMIT 10
|
|
196
|
+
OFFSET 50
|
|
197
|
+
*/
|
|
198
|
+
//---------------------------------------------------------------
|
|
199
|
+
router.post('/search/by-prefix', (req, res) => {
|
|
200
|
+
const query = Fuseki.getQuerySearchByPrefix(
|
|
201
|
+
req.body.prefix || "",
|
|
202
|
+
parseInt(req.body.limit) || 50,
|
|
203
|
+
parseInt(req.body.offset) || 0
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
axios.post(fusekiUrl, `query=${encodeURIComponent(query)}`, {
|
|
207
|
+
headers: {
|
|
208
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
209
|
+
'Accept': 'application/sparql-results+json'
|
|
210
|
+
}
|
|
211
|
+
}).then(response => {
|
|
212
|
+
const bindings = response.data.results.bindings;
|
|
213
|
+
let results = []
|
|
214
|
+
bindings.forEach(result => {
|
|
215
|
+
results.push({
|
|
216
|
+
instance: result.instance.value,
|
|
217
|
+
label: result.label.value,
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
res.json({
|
|
221
|
+
success: true,
|
|
222
|
+
data: results,
|
|
223
|
+
message: null
|
|
224
|
+
});
|
|
225
|
+
}).catch(err => {
|
|
226
|
+
res.status(500).json({
|
|
227
|
+
success: false,
|
|
228
|
+
data: null,
|
|
229
|
+
message: `Error: ${err}`
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
});
|
|
119
234
|
//---------------------------------------------------------------
|
|
120
235
|
router.get('/count/entities', (req, res) => {
|
|
121
236
|
const query = `
|
|
@@ -154,7 +269,6 @@ router.get('/count/entities', (req, res) => {
|
|
|
154
269
|
message: `Error: ${err}`
|
|
155
270
|
});
|
|
156
271
|
});
|
|
157
|
-
|
|
158
272
|
});
|
|
159
273
|
|
|
160
274
|
router.get('/export/:format/:entity/:id', (req, res) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const express = require('express');
|
|
2
2
|
const router = express.Router();
|
|
3
3
|
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
4
5
|
const ONTO_FOLDER = path.join(__dirname, '..', 'ontology');
|
|
5
6
|
const Converter = require('../models/converter');
|
|
6
7
|
const tmp = require('tmp');
|
|
@@ -35,7 +36,20 @@ router.get('/schema/:format', (req, res) => {
|
|
|
35
36
|
});
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
+
|
|
40
|
+
let fileContent = fs.readFileSync(path.join(ONTO_FOLDER, filePath), 'utf8');
|
|
41
|
+
let protocol = process.env.OAC_EXPOSED_PROTOCOL || 'http';
|
|
42
|
+
let host = process.env.OAC_EXPOSED_HOST || '127.0.0.1';
|
|
43
|
+
if(host=="localhost") host="127.0.0.1";
|
|
44
|
+
let port = process.env.OAC_EXPOSED_PORT || '4000';
|
|
45
|
+
fileContent = fileContent.replace(/OAC_EXPOSED_PROTOCOL/g, protocol);
|
|
46
|
+
fileContent = fileContent.replace(/OAC_EXPOSED_HOST/g, host);
|
|
47
|
+
fileContent = fileContent.replace(/OAC_EXPOSED_PORT/g, port);
|
|
48
|
+
|
|
49
|
+
const tempFile = tmp.fileSync({ postfix: filePath });
|
|
50
|
+
fs.writeFileSync(tempFile.name, fileContent);
|
|
51
|
+
|
|
52
|
+
res.sendFile(tempFile.name, (err) => {
|
|
39
53
|
if (err) {
|
|
40
54
|
res.status(500).json({
|
|
41
55
|
success: false,
|
package/src/models/fuseki.js
CHANGED
|
@@ -84,6 +84,28 @@ class Fuseki {
|
|
|
84
84
|
}`;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
static getQuerySearchByPrefix(prefix, limit, offset){
|
|
88
|
+
limit = limit || 50;
|
|
89
|
+
offset = offset || 0;
|
|
90
|
+
if(limit < 1) limit = 50;
|
|
91
|
+
return `
|
|
92
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
93
|
+
SELECT DISTINCT ?instance ?label
|
|
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 . }
|
|
103
|
+
}
|
|
104
|
+
ORDER BY ?label
|
|
105
|
+
LIMIT ${limit}
|
|
106
|
+
OFFSET ${offset}`
|
|
107
|
+
}
|
|
108
|
+
|
|
87
109
|
}
|
|
88
110
|
|
|
89
111
|
module.exports = Fuseki;
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
4
4
|
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
5
5
|
@prefix crm: <http://www.cidoc-crm.org/cidoc-crm/> .
|
|
6
|
+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
7
|
+
@prefix dcterms: <http://purl.org/dc/terms/> .
|
|
6
8
|
|
|
7
9
|
ex:E7ActivityShape
|
|
8
10
|
a sh:NodeShape ;
|
|
@@ -57,7 +59,8 @@ ex:E42IdentifierShape
|
|
|
57
59
|
sh:path ex:P48_has_preferred_identifier ;
|
|
58
60
|
sh:datatype xsd:string ;
|
|
59
61
|
sh:name "ID" ;
|
|
60
|
-
|
|
62
|
+
sh:nodeKind sh:IRI;
|
|
63
|
+
sh:description "http://diagnostica/indagine/$UUID$" ;
|
|
61
64
|
sh:maxCount 1 ;
|
|
62
65
|
sh:minCount 1 ;
|
|
63
66
|
] .
|
|
@@ -66,24 +69,14 @@ ex:E55Type01Shape
|
|
|
66
69
|
a sh:NodeShape ;
|
|
67
70
|
sh:targetClass crm:E55_Type ;
|
|
68
71
|
sh:property [
|
|
69
|
-
sh:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
sh:in ( "Tipo indagine A" "Tipo indagine B" ) ;
|
|
73
|
-
#owl:imports
|
|
72
|
+
sh:class owl:Class ;
|
|
73
|
+
sh:path crm:P127_has_broader_term ;
|
|
74
|
+
owl:imports <OAC_EXPOSED_PROTOCOL://OAC_EXPOSED_HOST:OAC_EXPOSED_PORT/backend/fuseki/get-vocabolary-terms/fase-di-analisi> ;
|
|
74
75
|
sh:name "Tipo" ;
|
|
75
76
|
sh:maxCount 1 ;
|
|
76
77
|
sh:minCount 1 ;
|
|
77
78
|
] .
|
|
78
79
|
|
|
79
|
-
# Vocabolario E55Type01 (Tipo indagine)
|
|
80
|
-
#ex:TipoIndagineA
|
|
81
|
-
# a crm:E55_Type ;
|
|
82
|
-
# rdfs:label "Tipo indagine A" .
|
|
83
|
-
#ex:TipoIndagineB
|
|
84
|
-
# a crm:E55_Type ;
|
|
85
|
-
# rdfs:label "Tipo indagine B" .
|
|
86
|
-
|
|
87
80
|
ex:I12AdoptedBeliefShape
|
|
88
81
|
a sh:NodeShape ;
|
|
89
82
|
sh:targetClass crm:I12_Adopted_Belief ;
|
|
@@ -99,13 +92,18 @@ ex:E55Type02Shape
|
|
|
99
92
|
a sh:NodeShape ;
|
|
100
93
|
sh:targetClass crm:E55_Type ;
|
|
101
94
|
sh:property [
|
|
102
|
-
sh:path ex:P2hastype2 ;
|
|
103
|
-
#sh:class ex:E55Type02 ;
|
|
104
|
-
#sh:in ( ex:TipoQuesitoDiagnostico1 ex:TipoQuesitoDiagnostico2 ex:TipoQuesitoDiagnostico3 ) ;
|
|
105
|
-
sh:in ( "Tipo quesito diagnistico 1" "Tipo quesito diagnistico 2" "Tipo quesito diagnistico 3" ) ;
|
|
106
95
|
sh:name "Tipo" ;
|
|
107
96
|
sh:maxCount 1 ;
|
|
108
97
|
sh:minCount 1 ;
|
|
98
|
+
#sh:class crm:E55_Type ;
|
|
99
|
+
sh:class owl:Class ;
|
|
100
|
+
sh:path crm:P127_has_broader_term ;
|
|
101
|
+
owl:imports <OAC_EXPOSED_PROTOCOL://OAC_EXPOSED_HOST:OAC_EXPOSED_PORT/backend/fuseki/get-vocabolary-terms/quesito-diagnostico> ;
|
|
102
|
+
|
|
103
|
+
#sh:class owl:Class ;
|
|
104
|
+
#sh:path dcterms:subject ;
|
|
105
|
+
#owl:imports <https://raw.githubusercontent.com/tibonto/DFG-Fachsystematik-Ontology/refs/heads/main/dfgfo.ttl> ;
|
|
106
|
+
|
|
109
107
|
] ;
|
|
110
108
|
sh:property [
|
|
111
109
|
sh:path crm:P3_has_note ;
|
|
@@ -114,25 +112,20 @@ ex:E55Type02Shape
|
|
|
114
112
|
sh:maxCount 1 ;
|
|
115
113
|
] .
|
|
116
114
|
|
|
117
|
-
# Vocabolario E55Type02 (Tipo quesito diagnostico)
|
|
118
|
-
#ex:TipoQuesitoDiagnostico1
|
|
119
|
-
# a crm:E55_Type ;
|
|
120
|
-
# rdfs:label "Tipo quesito diagnistico 1" .
|
|
121
|
-
#ex:TipoQuesitoDiagnostico2
|
|
122
|
-
# a crm:E55_Type ;
|
|
123
|
-
# rdfs:label "Tipo quesito diagnistico 2" .
|
|
124
|
-
#ex:TipoQuesitoDiagnostico3
|
|
125
|
-
# a crm:E55_Type ;
|
|
126
|
-
# rdfs:label "Tipo quesito diagnistico 3" .
|
|
127
|
-
|
|
128
115
|
ex:E29ActorShape
|
|
129
116
|
a sh:NodeShape ;
|
|
130
117
|
sh:targetClass crm:E29_Actor ;
|
|
131
118
|
sh:property [
|
|
132
119
|
sh:path ex:ente_richiedente ;
|
|
133
120
|
sh:datatype xsd:string ;
|
|
134
|
-
|
|
135
|
-
sh:
|
|
121
|
+
|
|
122
|
+
#sh:name "Ente richiedente" ;
|
|
123
|
+
#sh:maxCount 1 ;
|
|
124
|
+
|
|
125
|
+
sh:name "ID" ;
|
|
126
|
+
sh:nodeKind sh:IRI;
|
|
127
|
+
sh:description "http://diagnostica/actor/$UUID$" ;
|
|
128
|
+
|
|
136
129
|
] ;
|
|
137
130
|
sh:property [
|
|
138
131
|
sh:path ex:schedatore ;
|
|
@@ -141,22 +134,3 @@ ex:E29ActorShape
|
|
|
141
134
|
sh:maxCount 1 ;
|
|
142
135
|
sh:minCount 1 ;
|
|
143
136
|
] .
|
|
144
|
-
|
|
145
|
-
#Vocabolario E55Type03a (con unico termine "Ente_richiedente") ???
|
|
146
|
-
#Vocabolario E55Type03b (con unico termine "Ente_schedatore") ???
|
|
147
|
-
#ex:TipoAttore1
|
|
148
|
-
# a crm:E55_Type ;
|
|
149
|
-
# rdfs:label "Ente richiedente" .
|
|
150
|
-
#ex:TipoAttore2
|
|
151
|
-
# a crm:E55_Type ;
|
|
152
|
-
# rdfs:label "Schedatore" .
|
|
153
|
-
|
|
154
|
-
#ex:E55Type03Shape
|
|
155
|
-
# a sh:NodeShape ;
|
|
156
|
-
# sh:targetClass crm:E55_Type ;
|
|
157
|
-
# sh:property [
|
|
158
|
-
# sh:path crm:P1_is_defined_by ;
|
|
159
|
-
# sh:node ex:E41AppellationShape ;
|
|
160
|
-
# sh:name "Attore" ;
|
|
161
|
-
# sh:maxCount 1 ;
|
|
162
|
-
# ] .
|