@innotrade/enapso-sparql-tools
Version:
ENAPSO Platform Independent SPARQL Tools
658 lines (624 loc) • 26.3 kB
JavaScript
// Innotrade Enapso SPARQL Tools
// (C) Copyright 2019-2020 Innotrade GmbH, Herzogenrath, NRW, Germany
// Authors: Alexander Schulze and Muhammad Yasir
require('@innotrade/enapso-config');
// requires the Enapso GraphDB Client package
const { EnapsoGraphDBClient } = requireEx('@innotrade/enapso-graphdb-client'),
{ EnapsoLogger } = requireEx('@innotrade/enapso-logger'),
{ EnapsoGraphDBAdmin } = requireEx('@innotrade/enapso-graphdb-admin');
global.enlogger = new EnapsoLogger();
const _ = require('lodash');
const EnapsoSPARQLTools = {};
_.merge(
EnapsoSPARQLTools,
require('../lib/properties'),
require('../lib/classes'),
require('../lib/classCache'),
require('../lib/prefixManager'),
require('../lib/generator')
);
const GRAPHDB_BASE_URL = encfg.getConfig(
'enapsoDefaultGraphDB.baseUrl',
'http://localhost:7200'
),
GRAPHDB_REPOSITORY = encfg.getConfig(
'enapsoDefaultGraphDB.repository',
'SE-DOE-QA'
),
GRAPHDB_USERNAME = encfg.getConfig('enapsoDefaultGraphDB.userName', 'Test'),
GRAPHDB_PASSWORD = encfg.getConfig('enapsoDefaultGraphDB.password', 'Test');
const NS_AUTH = encfg.getConfig(
'enapsoDefaultGraphDB.iri',
'http://ont.enapso.com/foundation#'
),
PREFIX_AUTH = encfg.getConfig('enapsoDefaultGraphDB.prefix', 'enf');
// the default prefixes for all SPARQL queries
const AUTH_PREFIXES = [
EnapsoGraphDBClient.PREFIX_OWL,
EnapsoGraphDBClient.PREFIX_RDF,
EnapsoGraphDBClient.PREFIX_RDFS,
EnapsoGraphDBClient.PREFIX_XSD,
{
prefix: PREFIX_AUTH,
iri: NS_AUTH
},
{
prefix: 'ensr',
iri: 'http://ont.enapso.com/rdfstar#'
},
{
prefix: 'material',
iri: 'http://ont.lego.com/material#'
},
{
prefix: 'enturk',
iri: 'http://ont.enapso.com/truck#'
},
{
prefix: 'productprocessconceptmodel',
iri: 'http://semantic.bosch.com/ProductProcessConceptModel/'
},
{
prefix: 'sh',
iri: 'http://www.w3.org/ns/shacl#'
}
];
const AUTH = {
graphDBEndpoint: null,
authentication: null,
defaultBaseIRI: NS_AUTH,
defaultPrefix: PREFIX_AUTH,
defaultIRISeparator: '#',
query: async function (sparql, options) {
options = options || {};
options.dropPrefixes = options.dropPrefixes || false;
let query = await this.graphDBEndpoint.query(sparql);
let resp;
if (query.success) {
resp = await this.graphDBEndpoint.transformBindingsToResultSet(
query,
{
dropPrefixes: options.dropPrefixes
}
);
} else {
let lMsg = query.message;
if (400 === query.statusCode) {
lMsg += ', check your query for potential errors';
} else if (403 === query.statusCode) {
lMsg +=
', check if user "' +
GRAPHDB_USERNAME +
'" has appropriate access rights to the Repository ' +
'"' +
this.graphDBEndpoint.getRepository() +
'"';
}
resp = {
total: 0,
success: false,
message: lMsg
};
}
return resp;
},
update: async function (sparql, params) {
let resp = await this.graphDBEndpoint.update(sparql, params);
if (!resp.success) {
let lMsg = resp.message;
if (400 === resp.statusCode) {
lMsg += ', check your query for potential errors';
} else if (403 === resp.statusCode) {
lMsg +=
', check if user "' +
GRAPHDB_USERNAME +
'" has appropriate access rights to the Repository ' +
'"' +
this.graphDBEndpoint.getRepository() +
'"';
}
}
return resp;
},
// retrieve all classes from the graph
getAllClasses: async function (graph) {
let generated = this.enSPARQL.getAllClasses(graph);
// enlogger.log('SPARQL:\n' + generated.sparql);
return this.query(generated.sparql);
},
// retrieve all data and object properties from the graph
getProperties: async function () {
return this.query(`
select *
where {
?prop a rdf:Property ; rdf:type ?type .
optional { ?prop rdfs:domain ?domain } .
optional { ?prop rdfs:range ?range } .
filter( ?type = owl:DatatypeProperty || ?type = owl:ObjectProperty )
}`);
},
// retrieve all data properties from the graph
getDataProperties: async function () {
return this.query(`
select *
where {
?prop a owl:DatatypeProperty .
optional { ?prop rdfs:domain ?domain } .
optional { ?prop rdfs:range ?range } .
}`);
},
// retrieve all object properties from the graph
getObjectProperties: async function () {
return this.query(`
select *
where {
?prop a owl:ObjectProperty .
optional { ?prop rdfs:domain ?domain } .
optional { ?prop rdfs:range ?range } .
}`);
},
// retrieve all properties from a given class
getClassProperties: async function (cls, graph) {
let generated = this.enSPARQL.getClassProperties(cls, graph);
// enlogger.log('SPARQL:\n' + generated.sparql);
return this.query(generated.sparql);
},
// retrieve all properties from a given class
getSingleClassProperties: async function (cls, graph) {
let generated = this.enSPARQL.getSingleClassProperties(cls, graph);
// enlogger.log('SPARQL:\n' + generated.sparql);
return this.query(generated.sparql);
},
// retrieve all properties from a given class
getClassPropertiesByDomain: async function (cls, graph) {
let generated = this.enSPARQL.getClassPropertiesByDomain(cls, graph);
// enlogger.log('SPARQL:\n' + generated.sparql);
return this.query(generated.sparql);
},
getClassPropertiesByDomainAndRestrictions: async function (cls, graph) {
let generated = this.enSPARQL.getClassPropertiesByDomainAndRestrictions(
cls,
graph
);
enlogger.log('SPARQL:\n' + generated.sparql);
return this.query(generated.sparql);
},
// generates an in-memory class from a SPARQL result set
generateClassFromClassProperties: function (ns, name, classProps) {
let cls = new EnapsoSPARQLTools.Class(ns, name);
for (let propRec of classProps.records) {
// todo: here we need to add the restrictions, domain, range, min, max, exactly etc.
let propParts = this.splitIRI(propRec.prop);
let prop = new EnapsoSPARQLTools.Property(
propParts.namespace,
propParts.name,
propRec.type,
propRec.range,
propRec.domain
);
// add the property to the classs
cls.addProperty(prop);
}
return cls;
},
splitIRI(iri, options) {
let separator = '#';
let parts = iri.split(separator);
return {
namespace: parts[0] + separator,
name: parts[1]
};
},
updateMultipleRelation: async function (iri, prop, newValues) {
let generated = this.enSPARQL.updateMultipleRelation(
iri,
prop,
newValues
);
enlogger.log('SPARQL:\n' + generated.sparql);
// return this.query(generated.sparql);
},
// builds the class cache for all or selected classes
buildClassCache: async function () {
let classCache = new EnapsoSPARQLTools.ClassCache();
// get all classes of the database
let generated = this.enSPARQL.getAllClasses();
// enLogger.log('SPARQL:\n' + generated.sparql);
let classes = await this.query(generated.sparql);
// iterate through all returned classes
for (let clsRec of classes.records) {
let className = clsRec.class;
// get the properties of the given class
// get the properties of the given class
let generated = this.enSPARQL.getClassProperties(className);
// enLogger.log('SPARQL:\n' + generated.sparql);
let res = await this.query(generated.sparql, {
dropPrefixes: false // here we need the full data types and IRIs
});
let classId = this.splitIRI(className);
// generate an in-memory class of the retrieved properties
let cls = this.generateClassFromClassProperties(
classId.namespace,
classId.name,
res
);
// add the class to the cache
classCache.addClass(cls);
}
return classCache;
},
// get all instances of a certain class from the graph
getIndividualsByClass: async function (args) {
let generated = this.enSPARQL.getIndividualsByClass(args);
enlogger.log('SPARQL:\n' + generated.sparql);
return this.query(generated.sparql);
},
// show all individuals of a certain class in the enlogger
showAllIndividuals: async function (args) {
// and retrieve all instances by the given in-memory class
res = await this.getIndividualsByClass(args);
return res;
},
// create a new instance of a certain class in the graph
createIndividualByClass: async function (args) {
let generated = this.enSPARQL.createIndividualByClass(args);
enlogger.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql, { iri: generated.iri });
},
// updates an individual by its class reference and a data object with the values
updateIndividualByClass: async function (cls, iri, ind) {
let generated = this.enSPARQL.updateIndividualByClass(cls, iri, ind);
enlogger.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql);
},
// deletes an arbitray resource via its IRI
deleteIndividual: async function (args) {
let generated = this.enSPARQL.deleteResource(args);
enlogger.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql);
},
// this deletes ALL individuals of a certain class, BE CAREFUL!
deleteAllIndividualsByClass: async function (cls) {
// todo: check this method! it looks like this deletes also all specs for a class, not only the individuals!
return this.update(
`delete {
?s ?p ?o
} where {
?s ?p ?o.
filter(?s = <${cls.getIRI()}>) .
}
`
);
},
cloneIndividual(productClass, productIRI) {
let generated = this.enSPARQL.cloneIndividual(productClass, productIRI);
//enlogger.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql, { iri: generated.iri });
},
deletePropertyOfClass(args) {
let generated = this.enSPARQL.deleteGivenPropertyOfClass(args);
//enlogger.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql);
},
deleteLabelOfEachClassIndividual(args) {
let generated = this.enSPARQL.deleteLabelOfEachClassIndividual(args);
// enlogger.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql);
},
copyLabelToDataPropertyOfEachIndividual(args) {
let generated =
this.enSPARQL.copyLabelToDataPropertyOfEachIndividual(args);
//enlogger.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql);
},
copyDataPropertyToLabelOfEachIndividual(args) {
let generated =
this.enSPARQL.copyDataPropertyToLabelOfEachIndividual(args);
// enlogger.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql);
},
// add a relation between two individuals
createRelation: async function (master, property, child, graph) {
let generated = this.enSPARQL.createRelation(
master,
property,
child,
graph
);
//console.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql);
},
// delete a relation between two individuals
deleteRelation: async function (master, property, child, graph) {
let generated = this.enSPARQL.deleteRelation(
master,
property,
child,
graph
);
//console.log('SPARQL:\n' + generated.sparql);
return this.update(generated.sparql);
},
async demoUploadFromFile(arg) {
// upload a file
let resp = await this.graphDBEndpoint.uploadFromFile(arg);
// console.log('\nUploadFromFile:\n' + JSON.stringify(resp., null, 2));
return resp;
},
async login(user, pass) {
// upload a file
let resp = await this.graphDBEndpoint.login(user, pass);
// console.log('Login :\n' + JSON.stringify(resp, null, 2));
return resp;
},
demo: async function () {
// instantiate a prefix manager
enlogger.setLevel(EnapsoLogger.ALL);
this.enPrefixManager = new EnapsoSPARQLTools.PrefixManager(
AUTH_PREFIXES
);
// in case no prefix is given for a certain resource identifier use the EDO: here
this.enPrefixManager.setDefaultPrefix(PREFIX_AUTH);
// create a SPARQL generator using the prefix manager
this.enSPARQL = new EnapsoSPARQLTools.Generator({
prefixManager: this.enPrefixManager
});
// instantiate a GraphDB connector and connect to GraphDB
this.graphDBEndpoint = new EnapsoGraphDBClient.Endpoint({
baseURL: GRAPHDB_BASE_URL,
repository: "Test",
prefixes: this.enPrefixManager.getPrefixesForConnector()
});
// this.graphDBEndpoint.login(GRAPHDB_USERNAME, GRAPHDB_PASSWORD);
// let resp = await this.graphDBEndpoint.uploadFromFile({
// filename: 'EnapsoFoundation.owl',
// format: 'application/rdf+xml',
// baseIRI: 'http://ont.enapso.com/foundation#',
// context: 'http://ont.enapso.com/enf'
// });
// console.log('UploadFromFile:' + JSON.stringify(resp.success, null, 2));
this.classCache = await this.buildClassCache();
// this.Resource = this.classCache.getClassByIRI(
// 'http://ont.enapso.com/truck#Truck'
// );
// let ind1 = {
// iri: NS_AUTH + '00a5e37f_3452_4b48121212346871245',
// licenceNumber: 'Tested'
// };
// let ind = {
// // iri: NS_AUTH + '00a5e37f_3452_4b4812121234687124545',
// licenceNumber: 'Helllo Tested'
// };
// // // this.Resource = this.classCache.getClassByIRI(NS_AUTH + 'Truck');
// let res = await this.createIndividualByClass({
// graph: 'http://ont.enapso.com/truck',
// cls: this.Resource,
// ind: ind1
// });
// console.log('create a individual', res);
// let iri = NS_AUTH + '00a5e37f_3452_4b48';
// let ind = {
// name: 'Updated Test Company',
// hash: 'Tqwerhvh',
// rights: 'rwx',
// code: 'function(option){console.log(option)}',
// user: 'jnhgtresss',
// hasCapabilities:
// 'enf:Capability_00a5e37f_3452_4b48_8a0a_3089dc41ef47',
// hasAttributes:
// 'http://ont.enapso.com/foundation#Attribute_5ed0a3d9_a801_4c4b_a072_578090f60353',
// hasBehavior:
// 'http://ont.enapso.com/foundation#Behavior_03e35a1d_5dd2_44fd_a596_908a1474dec8'
// };
// let res1 = await this.updateIndividualByClass({
// // graph: 'http://ont.enapso.com/truck',
// cls: this.Resource,
// iri: NS_AUTH + '00a5e37f_3452_4b48121212346871245',
// ind: ind
// });
// console.log('update created individual', res1);
// let joins = [
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#Capability'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasCapabilities',
// joins: [
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#Argument'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasArgument'
// }
// ]
// },
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#Attribute'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasAttributes',
// joins: [
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#Argument'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasArgument'
// }
// ]
// },
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#Behavior'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasBehavior',
// joins: [
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#EventEmitter'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasEventEmitter',
// joins: [
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#Event'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasEvent'
// }
// ]
// },
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#EventListener'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasEventListener',
// joins: [
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#Event'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasEvent'
// },
// {
// cls: this.classCache.getClassByIRI(
// 'http://ont.enapso.com/foundation#Argument'
// ),
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasArgument'
// }
// ]
// }
// ]
// }
// ];
// let filter = [
// {
// key: '$sparql',
// value: 'regEx(str(?ind), "http://ont.enapso.com/foundation#00a5e37f_3452_4b48", "i")'
// }
// ];
// let cls = 'http://ont.enapso.com/truck#Truck';
// cls = this.classCache.getClassByIRI(cls);
// let res2 = await this.showAllIndividuals({
// graph: 'http://ont.enapso.com/truck',
// cls: cls
// joins: joins
// filter: filter
// });
let cls = 'http://ont.lego.com/material#Z100';
cls = this.classCache.getClassByIRI(cls);
let res2 = await this.showAllIndividuals({
cls: cls
});
// console.log('read individual of a class', res2);
// iri = 'http://ont.enapso.com/foundation#00a5e37f_3452_4b48';
// let join = [
// {
// cls: 'http://ont.enapso.com/foundation#Capability',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasCapabilities',
// joins: [
// {
// cls: 'http://ont.enapso.com/foundation#Argument',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasArgument'
// }
// ]
// },
// {
// cls: 'http://ont.enapso.com/foundation#Attribute',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasAttributes',
// joins: [
// {
// cls: 'http://ont.enapso.com/foundation#Argument',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasArgument'
// }
// ]
// },
// {
// cls: 'http://ont.enapso.com/foundation#Behavior',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasBehavior',
// joins: [
// {
// cls: 'http://ont.enapso.com/foundation#EventEmitter',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasEventEmitter',
// joins: [
// {
// cls: 'http://ont.enapso.com/foundation#Event',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasEvent'
// }
// ]
// },
// {
// cls: 'http://ont.enapso.com/foundation#EventListener',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasEventListener',
// joins: [
// {
// cls: 'http://ont.enapso.com/foundation#Event',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasEvent'
// },
// {
// cls: 'http://ont.enapso.com/foundation#Argument',
// parent2ChildRelation:
// 'http://ont.enapso.com/foundation#hasArgument'
// }
// ]
// }
// ]
// }
// ];
// let res3 = await this.deleteIndividual({
// graph: 'http://ont.enapso.com/truck',
// iri: NS_AUTH + '00a5e37f_3452_4b48121212346871245'
// });
// console.log('delete individual of the class', res3);
// let res4 = await this.getClassPropertiesByDomain(
// 'http://ont.enapso.com/rdfstar#DomainClass'
// );
// let res4 = await this.getClassProperties(
// 'http://ont.enapso.com/truck#Truck',
// 'http://ont.enapso.com/truck12'
// );
// console.log('Class Properties by Domain', res4);
// let res4 = await this.getSingleClassProperties(
// 'http://ont.enapso.com/truck#Truck'
// //'http://ont.enapso.com/truck'
// );
// console.log('getSingleClassProperties', res4);
// let res5 = await this.getAllClasses('http://ont.enapso.com/truck');
// console.log('getAllClasses', res5);
// let res4 = await this.getClassPropertiesByDomainAndRestrictions(
// 'http://semantic.bosch.com/ProductProcessConceptModel/CLASSProductProcessConceptProduct'
// );
// console.log('Class Properties by Domain', res4);
// await this.updateMultipleRelation(
// 'http://ont.telekom.de/cia/recommendation/data#CriteriaSpecification_593d011e_ce03_4463_9069_61ae9745e953',
// 'http://ont.enapso.com/recommendation#hasContext',
// [
// 'http://ont.telekom.de/cia/recommendation/data#Tariff_a5a2139e_1450_47ab_b600_f1990d36f80d',
// 'http://ont.telekom.de/cia/recommendation/data#Context_68efc906_e7ef_45ad_a1bd_47b283ca9099'
// ]
// );
}
};
(async () => {
await AUTH.demo();
})();
module.exports = {
AUTH
};