@igea/oac_backend 1.0.45 → 1.0.47
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 +2 -1
- package/src/controllers/fuseki.js +57 -24
- package/src/models/vocabolaries/parser +63 -35
- package/src/models/vocabolaries/splitter.js +69 -0
- package/src/models/vocabolaries/vocabolaries.xsd +8 -1
- package/src/models/vocabolaries/vocabolaries.xslt +3 -3
- package/src/ontology/form/01/shacl.ttl +175 -0
- package/src/ontology/schema_v2.shacl copy.ttl +136 -0
- package/src/ontology/schema_v2.shacl.ttl +109 -70
- package/test/models/vocabolaries/parser.test.js +4 -1
- package/test/models/vocabolaries/splitter.test.js +36 -0
- package/test/models/vocabolaries/vocabolaries.xml +1 -1
- package/test/models/vocabolaries/vocabolaries_2.xml +4508 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@igea/oac_backend",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.47",
|
|
4
4
|
"description": "Backend service for the OAC project",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"crypto": "1.0.1",
|
|
30
30
|
"express": "5.1.0",
|
|
31
31
|
"express-rate-limit": "8.1.0",
|
|
32
|
+
"fast-xml-parser": "^5.3.3",
|
|
32
33
|
"get-port": "7.1.0",
|
|
33
34
|
"knex": "3.1.0",
|
|
34
35
|
"libxmljs2": "0.37.0",
|
|
@@ -71,32 +71,65 @@ router.post('/upload/vocabularies', upload.array('files'), (req, res) => {
|
|
|
71
71
|
|
|
72
72
|
if(xmlFiles.length == 1) {
|
|
73
73
|
let xmlFile = uploadedFiles[0];
|
|
74
|
-
|
|
75
|
-
console.log("Query to insert vocabularies: ", query);
|
|
76
|
-
|
|
74
|
+
if(!xmlFile.valid){
|
|
77
75
|
deleteFiles(uploadedFiles)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
return res.status(400).json({ message: 'Uploaded XML file is not valid' });
|
|
77
|
+
}
|
|
78
|
+
VocabParser.insertQuery(xmlFile.path).then(queries => {
|
|
79
|
+
//console.log("Query to insert vocabularies: ", query);
|
|
80
|
+
let results = Array(queries.length, null);
|
|
81
|
+
let checkCompleted = function(){
|
|
82
|
+
console.log(results)
|
|
83
|
+
deleteFiles(uploadedFiles)
|
|
84
|
+
let failed = results.filter(r => r.status === false);
|
|
85
|
+
console.log(failed);
|
|
86
|
+
if(failed.length > 0){
|
|
87
|
+
let message = `Error inserting vocabularies in ${failed.length} files.`;
|
|
88
|
+
return res.status(500).json({
|
|
89
|
+
message,
|
|
90
|
+
files: uploadedFiles,
|
|
91
|
+
results
|
|
92
|
+
});
|
|
93
|
+
}else{
|
|
94
|
+
res.json({
|
|
95
|
+
message: 'File correctly uploaded and vocabularies updated in the triple store',
|
|
96
|
+
files: uploadedFiles
|
|
97
|
+
});
|
|
84
98
|
}
|
|
99
|
+
}
|
|
100
|
+
let fusekiCall = function(index){
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
let query = queries[index];
|
|
103
|
+
try{
|
|
104
|
+
axios.post(fusekiUrlUpdate, query, {
|
|
105
|
+
headers: {
|
|
106
|
+
'Content-Type': 'application/sparql-update',
|
|
107
|
+
'Accept': 'application/sparql-results+json'
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
.then(() => {
|
|
111
|
+
resolve({
|
|
112
|
+
index, success: true, message: 'Vocabulary inserted correctly'
|
|
113
|
+
});
|
|
114
|
+
}).catch(error => {
|
|
115
|
+
let msg = (error.response?.status + error.response?.data) || error.message
|
|
116
|
+
resolve({
|
|
117
|
+
index, success: false, message: `Error from SPARQL end-point: ${msg}`
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
}catch(e){
|
|
121
|
+
resolve({
|
|
122
|
+
index, success: false, message: `Error: ${e}`
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
setTimeout(async ()=>{
|
|
128
|
+
for(let index=0; index<queries.length; index++){
|
|
129
|
+
results[index] = await fusekiCall(index);
|
|
130
|
+
}
|
|
131
|
+
checkCompleted();
|
|
85
132
|
})
|
|
86
|
-
.then(response => {
|
|
87
|
-
res.json({
|
|
88
|
-
message: 'File correctly uploaded and vocabularies updated: ' + response.data,
|
|
89
|
-
files: uploadedFiles
|
|
90
|
-
});
|
|
91
|
-
}).catch(error => {
|
|
92
|
-
let message = (error.response?.status + error.response?.data) || error.message
|
|
93
|
-
res.status(500).json({
|
|
94
|
-
message: 'Error from SPARQL end-point: ' + message,
|
|
95
|
-
files: uploadedFiles,
|
|
96
|
-
query
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
133
|
}).catch(err => {
|
|
101
134
|
deleteFiles(uploadedFiles)
|
|
102
135
|
console.error('Error transforming XML:', err);
|
|
@@ -108,7 +141,7 @@ router.post('/upload/vocabularies', upload.array('files'), (req, res) => {
|
|
|
108
141
|
|
|
109
142
|
}else{
|
|
110
143
|
deleteFiles(uploadedFiles);
|
|
111
|
-
let message = 'Multiple XML files
|
|
144
|
+
let message = 'Multiple XML files are not supported';
|
|
112
145
|
if(xmlFiles.length == 0)
|
|
113
146
|
message = 'No XML files uploaded';
|
|
114
147
|
return res.status(400).json({ message });
|
|
@@ -5,7 +5,7 @@ const { exec } = require('child_process');
|
|
|
5
5
|
const stripBom = require('strip-bom').default;
|
|
6
6
|
const config = require('../../config');
|
|
7
7
|
const VocabPrefix = config.fuseki.vocabularies.prefix || 'diagnostica';
|
|
8
|
-
|
|
8
|
+
const Splitter = require('./splitter');
|
|
9
9
|
|
|
10
10
|
const transformMode = {
|
|
11
11
|
default: 'default',
|
|
@@ -63,7 +63,7 @@ class Parser{
|
|
|
63
63
|
let xsltPath = this.xsltPath[using] || this.xsltPath.default;
|
|
64
64
|
try{
|
|
65
65
|
let command = 'xsltproc --stringparam prefix ' + VocabPrefix + ' ';
|
|
66
|
-
command += xsltPath + ' ' + xmlPath
|
|
66
|
+
command += xsltPath + ' "' + xmlPath + '"';
|
|
67
67
|
exec(command, (err, stdout, stderr) => {
|
|
68
68
|
if (err) {
|
|
69
69
|
reject(err)
|
|
@@ -75,45 +75,73 @@ class Parser{
|
|
|
75
75
|
}catch(e){
|
|
76
76
|
reject(e)
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
/*
|
|
80
|
-
let xmlData = this._getXmlData(xmlPath);
|
|
81
|
-
const xml = xmlParser.xmlParse(xmlData);
|
|
82
|
-
xslt.xsltProcess(xml, this.xslt)
|
|
83
|
-
.then(result => {
|
|
84
|
-
var terms = result.split(' ')
|
|
85
|
-
resolve(terms.map(line => line.trim()).filter(line => line.length > 0));
|
|
86
|
-
}).catch(err => {
|
|
87
|
-
reject(err)
|
|
88
|
-
});
|
|
89
|
-
*/
|
|
90
78
|
});
|
|
91
79
|
}
|
|
92
80
|
|
|
93
|
-
insertQuery(xmlPath){
|
|
81
|
+
insertQuery(xmlPath, className='crm:E55_Type'){
|
|
94
82
|
return new Promise((resolve, reject) => {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
83
|
+
const xmlFolder = path.dirname(xmlPath);
|
|
84
|
+
const xmlFile = path.basename(xmlPath);
|
|
85
|
+
const splitter = new Splitter(xmlFolder, xmlFile);
|
|
86
|
+
const files = splitter.splitFiles();
|
|
87
|
+
let queries = new Array(files.length);
|
|
88
|
+
let cleanTempFiles = function(queries){
|
|
89
|
+
for(let file of files){
|
|
90
|
+
try{
|
|
91
|
+
fs.unlinkSync(file.path);
|
|
92
|
+
}catch(e){
|
|
93
|
+
//console.log(`Error deleting temp file ${file.path}: ${e.message}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
resolve(queries);
|
|
97
|
+
}
|
|
98
|
+
let checkCompleted = function(index, query, status, message){
|
|
99
|
+
console.log(`Completed ${index+1}/${files.length}`);
|
|
100
|
+
files[index].status = status;
|
|
101
|
+
files[index].message = message;
|
|
102
|
+
if(status) queries[index]=query;
|
|
103
|
+
let allDone = files.every(f => f.status !== null);
|
|
104
|
+
if(allDone){
|
|
105
|
+
cleanTempFiles(queries);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
let transformFn = function(instance, index, className, xmlPath){
|
|
109
|
+
return function(){
|
|
110
|
+
instance.transform(xmlPath, transformMode.forInsert).then(terms => {
|
|
111
|
+
let query = `
|
|
112
|
+
PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
|
|
113
|
+
PREFIX basecpm: <http://ontome.net/ns/cpm/>
|
|
114
|
+
PREFIX j.0: <http://www.cidoc-crm.org/extensions/crmsci/>
|
|
115
|
+
PREFIX crmsci: <http://www.ics.forth.gr/isl/CRMsci>
|
|
116
|
+
PREFIX base: <http://www.ics.forth.gr/isl/CRMinf/>
|
|
117
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
99
118
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
119
|
+
INSERT {
|
|
120
|
+
?term a ${className} ;
|
|
121
|
+
rdfs:label ?label ;
|
|
122
|
+
crm:P127_has_broader_term ?broader .
|
|
123
|
+
}
|
|
124
|
+
WHERE {
|
|
125
|
+
VALUES (?term ?label ?broader) {
|
|
126
|
+
${terms.join(' \n')}
|
|
127
|
+
}
|
|
128
|
+
FILTER NOT EXISTS {
|
|
129
|
+
?term rdfs:label ?label .
|
|
130
|
+
}
|
|
131
|
+
}`
|
|
132
|
+
checkCompleted(index, query, true, null);
|
|
133
|
+
}).catch(err => {
|
|
134
|
+
console.log(err);
|
|
135
|
+
checkCompleted(index, null, false, `${err}`);
|
|
136
|
+
});
|
|
104
137
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}`
|
|
113
|
-
resolve(query);
|
|
114
|
-
}).catch(err => {
|
|
115
|
-
reject(err);
|
|
116
|
-
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for(let index=0; index<files.length; index++){
|
|
141
|
+
let fn = transformFn(this, index, files[index].class, files[index].path);
|
|
142
|
+
fn();
|
|
143
|
+
}
|
|
144
|
+
|
|
117
145
|
})
|
|
118
146
|
}
|
|
119
147
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { XMLParser, XMLBuilder } = require('fast-xml-parser');
|
|
4
|
+
|
|
5
|
+
class Splitter {
|
|
6
|
+
|
|
7
|
+
constructor(xmlFolder, xmlName, skipWrite=false) {
|
|
8
|
+
this.xmlFolder = xmlFolder;
|
|
9
|
+
this.xmlName = xmlName;
|
|
10
|
+
this.skipWrite = skipWrite;
|
|
11
|
+
const xmlPath = path.join(this.xmlFolder, this.xmlName);
|
|
12
|
+
this.xml = fs.readFileSync(xmlPath, 'utf8');
|
|
13
|
+
// Parser
|
|
14
|
+
this.parser = new XMLParser({
|
|
15
|
+
ignoreAttributes: false,
|
|
16
|
+
attributeNamePrefix: '@_'
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
splitByClass() {
|
|
21
|
+
const data = this.parser.parse(this.xml);
|
|
22
|
+
const vocabularies = data.vocabularies.vocabulary;
|
|
23
|
+
|
|
24
|
+
// Normalizza a array
|
|
25
|
+
const vocabArray = Array.isArray(vocabularies)
|
|
26
|
+
? vocabularies
|
|
27
|
+
: [vocabularies];
|
|
28
|
+
|
|
29
|
+
// Raggruppa per class
|
|
30
|
+
const grouped = {};
|
|
31
|
+
for (const vocab of vocabArray) {
|
|
32
|
+
const cls = vocab['@_class'] || 'NO_CLASS';
|
|
33
|
+
if (!grouped[cls]) grouped[cls] = [];
|
|
34
|
+
grouped[cls].push(vocab);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return grouped;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
splitFiles() {
|
|
41
|
+
const grouped = this.splitByClass();
|
|
42
|
+
const builder = new XMLBuilder({
|
|
43
|
+
ignoreAttributes: false,
|
|
44
|
+
attributeNamePrefix: '@_',
|
|
45
|
+
format: true,
|
|
46
|
+
indentBy: ' '
|
|
47
|
+
});
|
|
48
|
+
let index = 0
|
|
49
|
+
let results = [];
|
|
50
|
+
for (const cls in grouped) {
|
|
51
|
+
const outObj = {
|
|
52
|
+
vocabularies: {
|
|
53
|
+
vocabulary: grouped[cls]
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
index++;
|
|
57
|
+
const xmlOut = builder.build(outObj);
|
|
58
|
+
const xmlOutPath = path.join(this.xmlFolder, `${this.xmlName}_split_${index}.xml`);
|
|
59
|
+
if(!this.skipWrite)
|
|
60
|
+
fs.writeFileSync(xmlOutPath, xmlOut, 'utf8');
|
|
61
|
+
results.push({ class: cls, path: xmlOutPath, status:null, message:null });
|
|
62
|
+
}
|
|
63
|
+
return results.sort((a, b) => a.class.localeCompare(b.class));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
module.exports = Splitter;
|
|
@@ -52,7 +52,14 @@
|
|
|
52
52
|
</xs:element>
|
|
53
53
|
</xs:sequence>
|
|
54
54
|
|
|
55
|
-
<xs:attribute name="id"
|
|
55
|
+
<xs:attribute name="id" use="required">
|
|
56
|
+
<xs:simpleType>
|
|
57
|
+
<xs:restriction base="xs:string">
|
|
58
|
+
<xs:pattern value="[A-Za-z0-9_\-]+"/>
|
|
59
|
+
</xs:restriction>
|
|
60
|
+
</xs:simpleType>
|
|
61
|
+
</xs:attribute>
|
|
62
|
+
|
|
56
63
|
</xs:complexType>
|
|
57
64
|
|
|
58
65
|
</xs:schema>
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
</xsl:if>
|
|
44
44
|
</xsl:variable>
|
|
45
45
|
|
|
46
|
-
<xsl:variable name="vocab-id" select="normalize-space(@id)"/>
|
|
46
|
+
<xsl:variable name="vocab-id" select="translate(normalize-space(@id), ' ', '_')"/>
|
|
47
47
|
<xsl:apply-templates select="term">
|
|
48
48
|
<xsl:with-param name="path" select="concat('http://', $prefix, $vocab-id)"/>
|
|
49
49
|
<xsl:with-param name="type" select="concat($type, ' ')"/>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
<xsl:template match="term">
|
|
55
55
|
<xsl:param name="path"/>
|
|
56
56
|
<xsl:param name="type"/>
|
|
57
|
-
<xsl:variable name="current-id" select="normalize-space(@id)"/>
|
|
57
|
+
<xsl:variable name="current-id" select="translate(normalize-space(@id), ' ', '_')"/>
|
|
58
58
|
<xsl:variable name="new-path" select="concat($path, '/', $current-id)"/>
|
|
59
59
|
<xsl:variable name="new-type" select="concat($type, ' ')"/>
|
|
60
60
|
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
</xsl:when>
|
|
77
77
|
<xsl:otherwise>
|
|
78
78
|
|
|
79
|
-
<xsl:variable name="cid" select="normalize-space(@id)"/>
|
|
79
|
+
<xsl:variable name="cid" select="translate(normalize-space(@id), ' ', '_')"/>
|
|
80
80
|
<xsl:variable name="npath" select="concat($path, '/', $current-id)"/>
|
|
81
81
|
|
|
82
82
|
<xsl:for-each select="name">
|
|
@@ -0,0 +1,175 @@
|
|
|
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 j.0: <http://www.cidoc-crm.org/extensions/crmsci/> .
|
|
10
|
+
#@prefix crmsci: <http://www.ics.forth.gr/isl/CRMsci> .
|
|
11
|
+
@prefix base: <http://www.ics.forth.gr/isl/CRMinf/> .
|
|
12
|
+
#@prefix skos: <http://www.w3.org/2004/02/skos/core> .
|
|
13
|
+
#@prefix pref: <http://indagine/> .
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
ex:E7ActivityShape # INDAGINE
|
|
17
|
+
a sh:NodeShape, rdfs:Class ;
|
|
18
|
+
sh:targetClass crm:E7_Activity ;
|
|
19
|
+
sh:property [
|
|
20
|
+
sh:path crm:P48_has_preferred_identifier ;
|
|
21
|
+
sh:node ex:E42Identifier01Shape ;
|
|
22
|
+
sh:name "ID indagine" ;
|
|
23
|
+
sh:maxCount 1 ;
|
|
24
|
+
sh:minCount 1 ;
|
|
25
|
+
] ;
|
|
26
|
+
sh:property [
|
|
27
|
+
sh:path crm:P17_was_motivated_by ;
|
|
28
|
+
sh:node ex:I12AdoptedBeliefShape ;
|
|
29
|
+
sh:name "Quesito diagnostico" ;
|
|
30
|
+
sh:maxCount 1 ;
|
|
31
|
+
sh:minCount 1 ;
|
|
32
|
+
] ;
|
|
33
|
+
sh:property [
|
|
34
|
+
sh:path crm:P14_carried_out_by ;
|
|
35
|
+
sh:node ex:E29ActorShape ;
|
|
36
|
+
sh:name "Attori" ;
|
|
37
|
+
sh:maxCount 1 ;
|
|
38
|
+
] ;
|
|
39
|
+
sh:property [
|
|
40
|
+
sh:path crm:P16_used_specific_object ;
|
|
41
|
+
sh:node ex:S13SampleShape ;
|
|
42
|
+
sh:name "Campione" ;
|
|
43
|
+
sh:maxCount 1 ;
|
|
44
|
+
] .
|
|
45
|
+
|
|
46
|
+
ex:E29ActorShape # ATTORI
|
|
47
|
+
a sh:NodeShape, rdfs:Class ;
|
|
48
|
+
sh:targetClass crm:E29_Actor ;
|
|
49
|
+
sh:property [
|
|
50
|
+
sh:path crm:P2_has_type ;
|
|
51
|
+
sh:node ex:E55Type03Shape ;
|
|
52
|
+
sh:name "Attori coinvolti" ;
|
|
53
|
+
sh:maxCount 1 ;
|
|
54
|
+
] .
|
|
55
|
+
|
|
56
|
+
ex:S13SampleShape # CAMPIONE
|
|
57
|
+
a sh:NodeShape, rdfs:Class ;
|
|
58
|
+
sh:targetClass crm:S13_Sample ;
|
|
59
|
+
sh:property [
|
|
60
|
+
sh:path crm:P2_has_type ;
|
|
61
|
+
sh:node ex:E55Type05Shape ;
|
|
62
|
+
sh:name "Tipo campione" ;
|
|
63
|
+
sh:maxCount 1 ;
|
|
64
|
+
sh:minCount 1 ;
|
|
65
|
+
] ;
|
|
66
|
+
sh:property [
|
|
67
|
+
sh:path basecpm:Pc43i_uses ;
|
|
68
|
+
sh:node ex:CP2ArchitectureWorkShape ;
|
|
69
|
+
sh:name "Bene di riferimento" ;
|
|
70
|
+
sh:maxCount 1 ;
|
|
71
|
+
] .
|
|
72
|
+
|
|
73
|
+
ex:CP2ArchitectureWorkShape # BENE DI RIFERIMENTO
|
|
74
|
+
a sh:NodeShape, rdfs:Class ;
|
|
75
|
+
sh:targetClass basecpm:CP2_Architecture_Work ;
|
|
76
|
+
sh:property [
|
|
77
|
+
sh:path crm:P1_is_identified_by ;
|
|
78
|
+
sh:node ex:E41Appellation02Shape ;
|
|
79
|
+
sh:name "Denominazione bene" ;
|
|
80
|
+
sh:maxCount 1 ;
|
|
81
|
+
sh:minCount 1 ;
|
|
82
|
+
] .
|
|
83
|
+
|
|
84
|
+
ex:E42Identifier01Shape #ID INDAGINE
|
|
85
|
+
a sh:NodeShape, rdfs:Class ;
|
|
86
|
+
sh:targetClass crm:E42_Identifier ;
|
|
87
|
+
sh:property [
|
|
88
|
+
sh:path ex:P48haspreferredidentifier01 ;
|
|
89
|
+
#sh:datatype xsd:string ;
|
|
90
|
+
sh:name "ID" ;
|
|
91
|
+
sh:description "http://indagine/$SEQ1$" ;
|
|
92
|
+
sh:nodeKind sh:IRI ;
|
|
93
|
+
sh:maxCount 1 ;
|
|
94
|
+
sh:minCount 1 ;
|
|
95
|
+
] .
|
|
96
|
+
|
|
97
|
+
ex:I12AdoptedBeliefShape # QUESITO DIAGNOSTICO
|
|
98
|
+
a sh:NodeShape, rdfs:Class ;
|
|
99
|
+
sh:targetClass base:I12_Adopted_Belief ;
|
|
100
|
+
sh:property [
|
|
101
|
+
sh:path crm:P2_has_type ;
|
|
102
|
+
sh:node ex:E55Type02Shape ;
|
|
103
|
+
sh:name "Tipo quesito diagnostico" ;
|
|
104
|
+
sh:maxCount 1 ;
|
|
105
|
+
sh:minCount 1 ;
|
|
106
|
+
] .
|
|
107
|
+
|
|
108
|
+
ex:E41Appellation01Shape # ENTE E SCHEDATORE
|
|
109
|
+
a sh:NodeShape, rdfs:Class ;
|
|
110
|
+
sh:targetClass crm:E41_Appellation ;
|
|
111
|
+
sh:property [
|
|
112
|
+
sh:path ex:ente_richiedente ;
|
|
113
|
+
sh:datatype xsd:string ;
|
|
114
|
+
sh:name "Ente richiedente" ;
|
|
115
|
+
sh:maxCount 1 ;
|
|
116
|
+
] ;
|
|
117
|
+
sh:property [
|
|
118
|
+
sh:path ex:schedatore ;
|
|
119
|
+
sh:datatype xsd:string ;
|
|
120
|
+
sh:name "Schedatore" ;
|
|
121
|
+
sh:maxCount 1 ;
|
|
122
|
+
sh:minCount 1 ;
|
|
123
|
+
] .
|
|
124
|
+
|
|
125
|
+
ex:E41Appellation02Shape # DENOMINAZIONE BENE
|
|
126
|
+
a sh:NodeShape, rdfs:Class ;
|
|
127
|
+
sh:targetClass crm:E41_Appellation ;
|
|
128
|
+
sh:property [
|
|
129
|
+
sh:path ex:P1isidentifiedby ;
|
|
130
|
+
sh:datatype xsd:string ;
|
|
131
|
+
sh:name "Denominazione" ;
|
|
132
|
+
sh:maxCount 1 ;
|
|
133
|
+
sh:minCount 1 ;
|
|
134
|
+
] .
|
|
135
|
+
|
|
136
|
+
ex:E55Type02Shape # TIPO QUESITO DIAGNOSTICO
|
|
137
|
+
a sh:NodeShape, rdfs:Class ;
|
|
138
|
+
sh:targetClass crm:E55_Type ;
|
|
139
|
+
sh:property [
|
|
140
|
+
sh:path ex:P2hastype02 ;
|
|
141
|
+
sh:class owl:Class ; # vocabolario QUESITO DIAGNOSTICO (8) id="quesito-diagnostico"
|
|
142
|
+
owl:imports <OAC_EXPOSED_PROTOCOL://OAC_EXPOSED_HOST:OAC_EXPOSED_PORT/backend/fuseki/get-vocabolary-terms/quesito-diagnostico> ;
|
|
143
|
+
sh:name "Tipo" ;
|
|
144
|
+
sh:maxCount 1 ;
|
|
145
|
+
sh:minCount 1 ;
|
|
146
|
+
] ;
|
|
147
|
+
sh:property [
|
|
148
|
+
sh:path crm:P3_has_note ;
|
|
149
|
+
sh:datatype xsd:string ;
|
|
150
|
+
sh:name "Altro" ;
|
|
151
|
+
sh:maxCount 1 ;
|
|
152
|
+
] .
|
|
153
|
+
|
|
154
|
+
ex:E55Type03Shape # TIPOLOGIA ATTORI COINVOLTI
|
|
155
|
+
a sh:NodeShape, rdfs:Class ;
|
|
156
|
+
sh:targetClass crm:E55_Type ;
|
|
157
|
+
sh:property [
|
|
158
|
+
sh:path crm:P1_is_defined_by ;
|
|
159
|
+
sh:node ex:E41Appellation01Shape ;
|
|
160
|
+
sh:name "Tipologia attori" ;
|
|
161
|
+
#sh:maxCount 1 ;
|
|
162
|
+
] .
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
ex:E55Type05Shape # TIPO CAMPIONE
|
|
166
|
+
a sh:NodeShape, rdfs:Class ;
|
|
167
|
+
sh:targetClass crm:E55_Type ;
|
|
168
|
+
sh:property [
|
|
169
|
+
sh:path ex:P2hastype05 ;
|
|
170
|
+
sh:class owl:Class ; # vocabolario TIPO CAMPIONE (21) id="tipo-campione
|
|
171
|
+
owl:imports <OAC_EXPOSED_PROTOCOL://OAC_EXPOSED_HOST:OAC_EXPOSED_PORT/backend/fuseki/get-vocabolary-terms/tipo-campione> ;
|
|
172
|
+
sh:name "Tipo" ;
|
|
173
|
+
sh:maxCount 1 ;
|
|
174
|
+
sh:minCount 1 ;
|
|
175
|
+
] .
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
@prefix sh: <http://www.w3.org/ns/shacl#> .
|
|
2
|
+
@prefix ex: <http://example.org/shapes/> .
|
|
3
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
4
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
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/> .
|
|
8
|
+
|
|
9
|
+
ex:E7ActivityShape
|
|
10
|
+
a sh:NodeShape ;
|
|
11
|
+
sh:targetClass crm:E7_Activity ;
|
|
12
|
+
#rdfs:label "Indagine" ;
|
|
13
|
+
#sh:description "Indagine" ;
|
|
14
|
+
#sh:group ex:NameGroup ;
|
|
15
|
+
sh:property [
|
|
16
|
+
sh:path crm:P48_has_preferred_identifier ;
|
|
17
|
+
sh:node ex:E42IdentifierShape ;
|
|
18
|
+
sh:name "ID indagine" ;
|
|
19
|
+
sh:maxCount 1 ;
|
|
20
|
+
sh:minCount 1 ;
|
|
21
|
+
] ;
|
|
22
|
+
sh:property [
|
|
23
|
+
sh:path crm:P2_has_type ;
|
|
24
|
+
sh:node ex:E55Type01Shape ;
|
|
25
|
+
sh:name "Tipo indagine" ;
|
|
26
|
+
sh:maxCount 1 ;
|
|
27
|
+
sh:minCount 1 ;
|
|
28
|
+
] ;
|
|
29
|
+
sh:property [
|
|
30
|
+
sh:path crm:P17_was_motivated_by ;
|
|
31
|
+
sh:node ex:I12AdoptedBeliefShape ;
|
|
32
|
+
sh:name "Quesito diagnostico" ;
|
|
33
|
+
sh:maxCount 1 ;
|
|
34
|
+
sh:minCount 1 ;
|
|
35
|
+
] ;
|
|
36
|
+
sh:property [
|
|
37
|
+
sh:path crm:P14_was_carried_out_by ;
|
|
38
|
+
sh:node ex:E29ActorShape ;
|
|
39
|
+
sh:name "Attori" ;
|
|
40
|
+
#sh:maxCount 1 ;
|
|
41
|
+
] ;
|
|
42
|
+
sh:property [
|
|
43
|
+
sh:path crm:P16_used_specific_object ;
|
|
44
|
+
sh:node ex:S13Sample ;
|
|
45
|
+
sh:name "Campione" ;
|
|
46
|
+
sh:maxCount 1 ;
|
|
47
|
+
] ;
|
|
48
|
+
sh:property [
|
|
49
|
+
sh:path crm:xxx ;
|
|
50
|
+
sh:node ex:E7Activity1 ;
|
|
51
|
+
sh:name "Attività dignostica" ;
|
|
52
|
+
#sh:maxCount 1 ;
|
|
53
|
+
] .
|
|
54
|
+
|
|
55
|
+
ex:E42IdentifierShape
|
|
56
|
+
a sh:NodeShape ;
|
|
57
|
+
sh:targetClass crm:E42_Identifier ;
|
|
58
|
+
sh:property [
|
|
59
|
+
sh:path ex:P48_has_preferred_identifier ;
|
|
60
|
+
sh:datatype xsd:string ;
|
|
61
|
+
sh:name "ID" ;
|
|
62
|
+
sh:nodeKind sh:IRI;
|
|
63
|
+
sh:description "http://diagnostica/indagine/$UUID$" ;
|
|
64
|
+
sh:maxCount 1 ;
|
|
65
|
+
sh:minCount 1 ;
|
|
66
|
+
] .
|
|
67
|
+
|
|
68
|
+
ex:E55Type01Shape
|
|
69
|
+
a sh:NodeShape ;
|
|
70
|
+
sh:targetClass crm:E55_Type ;
|
|
71
|
+
sh:property [
|
|
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> ;
|
|
75
|
+
sh:name "Tipo" ;
|
|
76
|
+
sh:maxCount 1 ;
|
|
77
|
+
sh:minCount 1 ;
|
|
78
|
+
] .
|
|
79
|
+
|
|
80
|
+
ex:I12AdoptedBeliefShape
|
|
81
|
+
a sh:NodeShape ;
|
|
82
|
+
sh:targetClass crm:I12_Adopted_Belief ;
|
|
83
|
+
sh:property [
|
|
84
|
+
sh:path crm:P2_has_type ;
|
|
85
|
+
sh:node ex:E55Type02Shape ;
|
|
86
|
+
sh:name "Tipo quesito diagnostico" ;
|
|
87
|
+
sh:maxCount 1 ;
|
|
88
|
+
sh:minCount 1 ;
|
|
89
|
+
] .
|
|
90
|
+
|
|
91
|
+
ex:E55Type02Shape
|
|
92
|
+
a sh:NodeShape ;
|
|
93
|
+
sh:targetClass crm:E55_Type ;
|
|
94
|
+
sh:property [
|
|
95
|
+
sh:name "Tipo" ;
|
|
96
|
+
sh:maxCount 1 ;
|
|
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
|
+
|
|
107
|
+
] ;
|
|
108
|
+
sh:property [
|
|
109
|
+
sh:path crm:P3_has_note ;
|
|
110
|
+
sh:datatype xsd:string ;
|
|
111
|
+
sh:name "Altro" ;
|
|
112
|
+
sh:maxCount 1 ;
|
|
113
|
+
] .
|
|
114
|
+
|
|
115
|
+
ex:E29ActorShape
|
|
116
|
+
a sh:NodeShape ;
|
|
117
|
+
sh:targetClass crm:E29_Actor ;
|
|
118
|
+
sh:property [
|
|
119
|
+
sh:path ex:ente_richiedente ;
|
|
120
|
+
sh:datatype xsd:string ;
|
|
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/$SEQ3$" ;
|
|
128
|
+
|
|
129
|
+
] ;
|
|
130
|
+
sh:property [
|
|
131
|
+
sh:path ex:schedatore ;
|
|
132
|
+
sh:datatype xsd:string ;
|
|
133
|
+
sh:name "Schedatore" ;
|
|
134
|
+
sh:maxCount 1 ;
|
|
135
|
+
sh:minCount 1 ;
|
|
136
|
+
] .
|