@igea/oac_backend 1.0.19 → 1.0.20

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.19",
3
+ "version": "1.0.20",
4
4
  "description": "Backend service for the OAC project",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -10,10 +10,13 @@ const configFuseki = config.fuseki || {
10
10
  "port": "3030",
11
11
  "dataset": "oac"
12
12
  }
13
- const fusekiUrl = `${configFuseki.protocol}://${configFuseki.host}:${configFuseki.port}/${configFuseki.dataset}/sparql`;
13
+ const fusekiUrlDataset = `${configFuseki.protocol}://${configFuseki.host}:${configFuseki.port}/${configFuseki.dataset}`;
14
+ const fusekiUrl = `${fusekiUrlDataset}/sparql`;
15
+ const fusekiUrlUpdate = `${fusekiUrlDataset}/update`;
14
16
  const axios = require('axios');
15
17
  const Fuseki = require('../models/fuseki');
16
- const VocabParser = require('../models/vocabolaries/parser').GET_INSTANCE();
18
+ const { Parser, transformMode } = require('../models/vocabolaries/parser');
19
+ const VocabParser = Parser.GET_INSTANCE();
17
20
 
18
21
  //---------------------------------------------------------------
19
22
  const uploadFolder = path.join(__dirname, '../data/import');
@@ -47,7 +50,7 @@ const deleteFiles = function(files){
47
50
  * @param {Array} files - Array of files to be uploaded
48
51
  * @returns {Object} - Response object with message and file details
49
52
  *
50
- * curl -X POST -F "files=@vocabolaries.xsd" http://localhost:5000/backend/fuseki/upload/vocabularies
53
+ * curl -X POST -F "files=@vocabolaries.xml" http://localhost:5000/backend/fuseki/upload/vocabularies
51
54
  *
52
55
  * */
53
56
  router.post('/upload/vocabularies', upload.array('files'), (req, res) => {
@@ -68,13 +71,32 @@ router.post('/upload/vocabularies', upload.array('files'), (req, res) => {
68
71
 
69
72
  if(xmlFiles.length == 1) {
70
73
  let xmlFile = uploadedFiles[0];
71
- VocabParser.transform(xmlFile.path).then(terms => {
72
- console.log(terms)
74
+ VocabParser.insertQuery(xmlFile.path).then(query => {
75
+ console.log("Query to insert vocabularies: ", query);
76
+
73
77
  deleteFiles(uploadedFiles)
74
- res.json({
75
- message: 'File correctly uploaded',
76
- files: uploadedFiles
78
+
79
+
80
+ axios.post(fusekiUrlUpdate, query, {
81
+ headers: {
82
+ 'Content-Type': 'application/sparql-update',
83
+ 'Accept': 'application/sparql-results+json'
84
+ }
85
+ })
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
+ });
77
98
  });
99
+
78
100
  }).catch(err => {
79
101
  deleteFiles(uploadedFiles)
80
102
  console.error('Error transforming XML:', err);
@@ -7,16 +7,24 @@ const config = require('../../config');
7
7
  const VocabPrefix = config.fuseki.vocabularies.prefix || 'diagnostica';
8
8
 
9
9
 
10
+ const transformMode = {
11
+ default: 'default',
12
+ forInsert: 'forInsert'
13
+ }
14
+
10
15
  class Parser{
11
16
 
12
17
  static _INSTANCE = null;
13
18
 
14
19
  constructor(){
15
20
  let xsdPath = path.join(__dirname, 'vocabolaries.xsd');
16
- this.xsltPath = path.join(__dirname, 'vocabolaries.xslt');
21
+ this.xsltPath = {
22
+ default: path.join(__dirname, 'vocabolaries.xslt'),
23
+ forInsert: path.join(__dirname, 'vocabolaries_for_insert.xslt')
24
+ };
17
25
  this.xsdData = fs.readFileSync(xsdPath, 'utf8');
18
26
  this.xsdDoc = libxmljs.parseXml(this.xsdData);
19
- this.xsltData = fs.readFileSync(this.xsltPath, 'utf8');
27
+ //this.xsltData = fs.readFileSync(this.xsltPath, 'utf8');
20
28
  //this.xslt = xmlParser.xmlParse(this.xsltData);
21
29
  this.xsltDoc = libxmljs.parseXml(this.xsdData);
22
30
  }
@@ -50,11 +58,12 @@ class Parser{
50
58
  return result
51
59
  }
52
60
 
53
- transform(xmlPath){
61
+ transform(xmlPath, using=transformMode.default){
54
62
  return new Promise((resolve, reject) => {
63
+ let xsltPath = this.xsltPath[using] || this.xsltPath.default;
55
64
  try{
56
65
  let command = 'xsltproc --stringparam prefix ' + VocabPrefix + ' ';
57
- command += this.xsltPath + ' ' + xmlPath
66
+ command += xsltPath + ' ' + xmlPath
58
67
  exec(command, (err, stdout, stderr) => {
59
68
  if (err) {
60
69
  reject(err)
@@ -81,6 +90,33 @@ class Parser{
81
90
  });
82
91
  }
83
92
 
93
+ insertQuery(xmlPath){
94
+ return new Promise((resolve, reject) => {
95
+ this.transform(xmlPath, transformMode.forInsert).then(terms => {
96
+ let query = `
97
+ PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
98
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
99
+
100
+ INSERT {
101
+ ?term a crm:E55_Type ;
102
+ rdfs:label ?label ;
103
+ crm:P127_has_broader_term ?broader .
104
+ }
105
+ WHERE {
106
+ VALUES (?term ?label ?broader) {
107
+ ${terms.join(' \n')}
108
+ }
109
+ FILTER NOT EXISTS {
110
+ ?term rdfs:label ?label .
111
+ }
112
+ }`
113
+ resolve(query);
114
+ }).catch(err => {
115
+ reject(err);
116
+ });
117
+ })
118
+ }
119
+
84
120
  static GET_INSTANCE(){
85
121
  if (Parser._INSTANCE === null) {
86
122
  Parser._INSTANCE = new Parser();
@@ -89,4 +125,4 @@ class Parser{
89
125
  }
90
126
  }
91
127
 
92
- module.exports = Parser
128
+ module.exports = { Parser, transformMode };
@@ -20,7 +20,7 @@
20
20
  <!-- Vocabolario -->
21
21
  <xsl:template match="vocabulary">
22
22
  <xsl:param name="prefix"/>
23
- <xsl:variable name="vocab-id" select="@id"/>
23
+ <xsl:variable name="vocab-id" select="normalize-space(@id)"/>
24
24
  <xsl:apply-templates select="term">
25
25
  <xsl:with-param name="path" select="concat('http://', $prefix, $vocab-id)"/>
26
26
  </xsl:apply-templates>
@@ -29,7 +29,7 @@
29
29
  <!-- Term ricorsivo -->
30
30
  <xsl:template match="term">
31
31
  <xsl:param name="path"/>
32
- <xsl:variable name="current-id" select="@id"/>
32
+ <xsl:variable name="current-id" select="normalize-space(@id)"/>
33
33
  <xsl:variable name="new-path" select="concat($path, '/', $current-id)"/>
34
34
 
35
35
  <xsl:choose>
@@ -48,7 +48,7 @@
48
48
  </xsl:when>
49
49
  <xsl:otherwise>
50
50
 
51
- <xsl:variable name="cid" select="@id"/>
51
+ <xsl:variable name="cid" select="normalize-space(@id)"/>
52
52
  <xsl:variable name="npath" select="concat($path, '/', $current-id)"/>
53
53
 
54
54
  <xsl:for-each select="name">
@@ -0,0 +1,71 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3
+ version="1.0">
4
+
5
+ <xsl:output method="text" encoding="UTF-8"/>
6
+
7
+ <xsl:param name="prefix"/>
8
+
9
+ <!-- Prendi il prefix e passa ai vocabolari -->
10
+ <xsl:template match="/vocabularies">
11
+ <!--
12
+ <xsl:variable name="prefix" select="prefix/@value"/>
13
+ -->
14
+
15
+ <xsl:apply-templates select="vocabulary">
16
+ <xsl:with-param name="prefix" select="concat($prefix,'/vocabularies')"/>
17
+ </xsl:apply-templates>
18
+ </xsl:template>
19
+
20
+ <!-- Vocabolario -->
21
+ <xsl:template match="vocabulary">
22
+ <xsl:param name="prefix"/>
23
+ <xsl:variable name="vocab-id" select="normalize-space(@id)"/>
24
+ <xsl:apply-templates select="term">
25
+ <xsl:with-param name="path" select="concat('http://', $prefix, $vocab-id)"/>
26
+ </xsl:apply-templates>
27
+ </xsl:template>
28
+
29
+ <!-- Term ricorsivo -->
30
+ <xsl:template match="term">
31
+ <xsl:param name="path"/>
32
+ <xsl:variable name="current-id" select="normalize-space(@id)"/>
33
+ <xsl:variable name="new-path" select="concat($path, '/', $current-id)"/>
34
+
35
+ <xsl:choose>
36
+ <!-- Se NON ha sub-terms/term -->
37
+ <xsl:when test="not(sub-terms/term)">
38
+ <xsl:for-each select="name">
39
+ <xsl:value-of select="concat('(', '&lt;',$new-path,'&gt; ')"/>
40
+ <xsl:text>"</xsl:text>
41
+ <xsl:value-of select="."/>
42
+ <xsl:text>"@</xsl:text>
43
+ <xsl:value-of select="@lang"/>
44
+ <xsl:value-of select="concat(' &lt;',$path,'&gt;', ') ')"/>
45
+ <xsl:text>&#10;</xsl:text>
46
+ </xsl:for-each>
47
+ </xsl:when>
48
+ <xsl:otherwise>
49
+
50
+ <xsl:variable name="cid" select="normalize-space(@id)"/>
51
+ <xsl:variable name="npath" select="concat($path, '/', $current-id)"/>
52
+
53
+ <xsl:for-each select="name">
54
+ <xsl:value-of select="concat('(','&lt;',$npath,'&gt; ')"/>
55
+ <xsl:text>"</xsl:text>
56
+ <xsl:value-of select="."/>
57
+ <xsl:text>"@</xsl:text>
58
+ <xsl:value-of select="@lang"/>
59
+ <xsl:value-of select="concat(' &lt;',$path,'&gt;',') ')"/>
60
+ <xsl:text>&#10;</xsl:text>
61
+ </xsl:for-each>
62
+
63
+ <xsl:apply-templates select="sub-terms/term">
64
+ <xsl:with-param name="prev-path" select="$path"/>
65
+ <xsl:with-param name="path" select="$new-path"/>
66
+ </xsl:apply-templates>
67
+ </xsl:otherwise>
68
+ </xsl:choose>
69
+ </xsl:template>
70
+
71
+ </xsl:stylesheet>
@@ -1,7 +1,8 @@
1
1
  const chai = require('chai');
2
2
  const expect = chai.expect;
3
3
  const request = require('supertest');
4
- const Parser = require('../../../src/models/vocabolaries/parser');
4
+ //const Parser = require('../../../src/models/vocabolaries/parser');
5
+ const { Parser, transformMode } = require('../../../src/models/vocabolaries/parser');
5
6
 
6
7
 
7
8
  describe('Vocabolaries.Parsers', () => {
@@ -23,7 +24,7 @@ describe('Vocabolaries.Parsers', () => {
23
24
  expect(nodes.length).to.be.equal(10);
24
25
  });
25
26
 
26
- it('should transform the vocabolaries.xml file', async () => {
27
+ it('should transform the vocabolaries.xml file (default)', async () => {
27
28
  const parser = Parser.GET_INSTANCE();
28
29
  var terms = await parser.transform(__dirname + '/vocabolaries.xml');
29
30
  console.log(terms.filter(n => n.indexOf('P127_has_broader_term') == -1))
@@ -31,5 +32,19 @@ describe('Vocabolaries.Parsers', () => {
31
32
  expect(terms[0]).to.be.equal('<http://diagnostica/vocabularies/condizioni-ambientali> a crm:E55_Type rdfs:label "Condizioni ambientali"@it ; crm:P127_has_broader_term <http://diagnostica/vocabularies> .');
32
33
  expect(terms[1]).to.be.equal('<http://diagnostica/vocabularies/condizioni-ambientali/ambiente> a crm:E55_Type rdfs:label "Ambiente"@it ; crm:P127_has_broader_term <http://diagnostica/vocabularies/condizioni-ambientali> .');
33
34
  });
35
+
36
+ it('should transform the vocabolaries.xml file (for insert)', async () => {
37
+ const parser = Parser.GET_INSTANCE();
38
+ var terms = await parser.transform(__dirname + '/vocabolaries.xml', transformMode.forInsert);
39
+ expect(terms.length).to.be.equal(246);
40
+ expect(terms[0]).to.be.equal('(<http://diagnostica/vocabularies/condizioni-ambientali> "Condizioni ambientali"@it <http://diagnostica/vocabularies>)');
41
+ expect(terms[1]).to.be.equal('(<http://diagnostica/vocabularies/condizioni-ambientali/ambiente> "Ambiente"@it <http://diagnostica/vocabularies/condizioni-ambientali>)');
42
+ });
34
43
 
44
+ it('should get the insert query for the vocabolaries.xml file', async () => {
45
+ const parser = Parser.GET_INSTANCE();
46
+ var query = await parser.insertQuery(__dirname + '/vocabolaries.xml');
47
+ expect(query.length).to.be.equal(40619);
48
+ });
49
+
35
50
  });