@innotrade/enapso-sparql-tools
Version:
ENAPSO Platform Independent SPARQL Tools
1,262 lines (1,221 loc) • 146 kB
JavaScript
// Enapso SPARQL Tools - Module SPARQL generator
// (C) Copyright 2019-2020 Innotrade GmbH, Herzogenrath, NRW, Germany
// Authors: Alexander Schulze and Muhammad Yasir
//const { count } = require('console');
const { v4: uuidv4 } = require('uuid');
// SPARQL query and update command generator
class Generator {
constructor(args) {
args = args || {};
this.prefixManager = args.prefixManager;
this.GraphDBURL = args.GraphDB_URL_Repo;
this.triplestore=args.triplestore || "graphdb"
if (this.triplestore == "fuseki") {
this.type = "rdf:type";
this.subClass="rdfs:subClassOf"
} else {
this.type = "sesame:directType";
this.subClass="sesame:directSubClassOf"
}
}
setPrefixManager(prefixManager) {
this.prefixManager = prefixManager;
}
// retrieve all classes from the graph database
getAllClasses(graph) {
graph = this.findGraph(graph);
let sparql = `select ?class ?superClass
where {
${graph.graphStatement}
?class a owl:Class .
filter( !isBlank(?class) )
optional {
?class rdfs:subClassOf ?superClass .
?superClass a ?sctype .
filter(?sctype = owl:Class && !isBlank(?superClass))
}
${graph.graphFilter}
${graph.graphClosingBracket}
}
order by ?class
`;
return { sparql };
}
// retrieve all properties from a given class
getClassProperties(cls, graph) {
let iri = this.prefixManager.getSparqlIRI(cls);
graph = this.findGraph(graph);
let sparql = `select
?prop ?type ?range ?domain
?only ?some ?min ?max ?exactly ?value
where {
${graph.graphStatement}
bind( ${iri} as ?class ) .
?class rdfs:subClassOf ?restr .
?restr owl:onProperty ?prop .
?prop a ?type .
filter( ?type = owl:DatatypeProperty
|| ?type = owl:ObjectProperty ) .
?restr ( owl:onClass | owl:onDataRange
| owl:someValuesFrom | owl:allValuesFrom |owl:hasValue ) ?range .
bind( ?class as ?domain ) .
optional { ?restr owl:allValuesFrom ?only } .
optional { ?restr owl:someValuesFrom ?some } .
optional { ?restr (owl:minQualifiedCardinality | owl:minCardinality) ?min } .
optional { ?restr owl:qualifiedCardinality ?exactly } .
optional { ?restr (owl:maxQualifiedCardinality | owl:maxCardinality) ?max } .
optional { ?restr owl:hasValue ?value } .
${graph.graphFilter}
${graph.graphClosingBracket}
}`;
/*
let sparql =
`select ?property ?type ?range ?domain ?some ?min ?max ?exactly
where {
bind( ${iri} as ?class )
{
?property rdfs:domain ?class ; rdf:type ?type .
filter( ?type = owl:DatatypeProperty || ?type = owl:ObjectProperty ) .
optional { ?property rdfs:range ?rangeRaw } .
optional { ?property rdfs:domain ?domain } .
bind(?rangeRaw as ?rangeVar)
optional { ?rangeVar owl:allValuesFrom ?rangeRestriction } .
bind( if( isBlank(?rangeVar), ?rangeRestriction, ?rangeRaw ) as ?range )
} union {
?class rdfs:subClassOf ?restriction .
filter (isBlank(?restriction)) .
bind( owl:ObjectProperty as ?type )
bind( ?class as ?domain )
?restriction owl:onProperty ?property .
?restriction ( owl:onClass|owl:onDataRange|owl:someValuesFrom|owl:allValuesFrom ) ?range .
optional { ?restriction owl:someValuesFrom ?some } .
optional { ?restriction owl:minQualifiedCardinality ?min } .
optional { ?restriction owl:qualifiedCardinality ?exactly } .
optional { ?restriction owl:maxQualifiedCardinality ?max } .
}
}`;
*/
return { sparql };
}
// retrieve all properties from a single given class
getSingleClassProperties(cls, graph) {
let iri = this.prefixManager.getSparqlIRI(cls);
graph = this.findGraph(graph);
let sparql = `select distinct
?prop ?type ?range ?domain
?only ?some ?min ?max ?exactly ?value
where {
${graph.graphStatement}
{
bind( ${iri} as ?class ) .
?class ${this.subClass} ?restr .
?restr owl:onProperty ?prop .
?prop a ?type .
filter( ?type = owl:DatatypeProperty
|| ?type = owl:ObjectProperty ) .
?restr ( owl:onClass | owl:onDataRange
| owl:someValuesFrom | owl:allValuesFrom |owl:hasValue ) ?range .
bind( ?class as ?domain ) .
optional { ?restr owl:allValuesFrom ?only } .
optional { ?restr owl:someValuesFrom ?some } .
optional { ?restr (owl:minQualifiedCardinality | owl:minCardinality) ?min } .
optional { ?restr owl:qualifiedCardinality ?exactly } .
optional { ?restr (owl:maxQualifiedCardinality | owl:maxCardinality) ?max } .
optional { ?restr owl:hasValue ?value } .
}
${graph.graphFilter}
${graph.graphClosingBracket}
}`;
return { sparql };
}
getClassAllRestrictions(cls, graph) {
let iri = this.prefixManager.getSparqlIRI(cls);
graph = this.findGraph(graph);
let sparql = `select
?propertyType ?property ?restrict ?cardinality ?type
where {
${graph.graphStatement}
bind( ${iri} as ?class ).
?class ${this.subClass} ?restr .
?restr owl:onProperty ?property .
?property a ?propertyType .
filter( ?propertyType = owl:DatatypeProperty
|| ?propertyType = owl:ObjectProperty ) .
?restr ( owl:onClass | owl:onDataRange
| owl:someValuesFrom | owl:allValuesFrom |owl:hasValue ) ?type .
bind( ?class as ?domain ) .
optional { ?restr owl:allValuesFrom ?res.
bind("only" as ?restrict) } .
optional { ?restr owl:someValuesFrom ?res.
bind("some" as ?restrict)} .
optional { ?restr (owl:minQualifiedCardinality | owl:minCardinality) ?cardinality
bind("min" as ?restrict)} .
optional { ?restr owl:qualifiedCardinality ?cardinality
bind("exactly" as ?restrict)} .
optional { ?restr (owl:maxQualifiedCardinality | owl:maxCardinality) ?cardinality
bind("max" as ?restrict)} .
optional { ?restr owl:hasValue ?res
bind("value" as ?restrict)} .
${graph.graphFilter}
${graph.graphClosingBracket}
}`;
return { sparql };
}
/*
SPARQL example:
select ?iri ?has_Customer_ID ?has_Customer_Name ?has_Customer_Password ?has_Customer_Phone_No ?has_Customer_Email ?hasOrderline
where {
?ind a <http://ont.comsats.edu/fyp#Customer> .
bind(str(?ind) as ?iri) .
filter(?iri in ("http://ont.comsats.edu/fyp#Customer_SchulzeAlexander")) .
optional { ?ind <http://ont.comsats.edu/fyp#has_Customer_ID> ?has_Customer_ID } .
optional { ?ind <http://ont.comsats.edu/fyp#has_Customer_Name> ?has_Customer_Name } .
optional { ?ind <http://ont.comsats.edu/fyp#has_Customer_Password> ?has_Customer_Password } .
optional { ?ind <http://ont.comsats.edu/fyp#has_Customer_Phone_No> ?has_Customer_Phone_No } .
optional { ?ind <http://ont.comsats.edu/fyp#has_Customer_Email> ?has_Customer_Email } .
optional { ?ind <http://ont.comsats.edu/fyp#hasOrderline> ?hasOrderline } .
}
*/
// get all instances of a certain class from the graph
// cls: the in-memory class
// prefixProps: true = usess prefixed property identifiers
findGraph(graph, option) {
let graphStatement = '';
let graphFilter = '';
let graphClosingBracket = '';
if (graph) {
graphFilter = `filter(?graph=<${graph}> && ?graph!=<http://www.openrdf.org/schema/sesame#nil>) `;
graphClosingBracket = `}`;
graphStatement = `Graph ?graph {`;
}
if (graph && option == 'cud') {
graphStatement = `Graph <${graph}> {`;
}
return { graphStatement, graphClosingBracket, graphFilter };
}
findTemplateGraph(graph, option) {
let graphStatement = '';
let graphFilter = '';
let graphClosingBracket = '';
if (graph) {
graphFilter = `\${'\${namedGraph}' !== '' ? \`filter(?namedGraph=\${namedGraph})\` : ''} `;
graphClosingBracket = `}`;
graphStatement = `Graph \${'\${namedGraph}' !== '' ? \`\${namedGraph}\` : '?namedGraph'} {`;
}
if (graph && option == 'cud') {
graphStatement = `Graph <\${\${namedGraph} !== '' ? \${namedGraph} : '${graph}'}> {`;
}
return { graphStatement, graphClosingBracket, graphFilter };
}
getIndividualsByClass(args) {
args = args || {};
if (!args.cls) {
throw 'No classs passed';
}
args.prefixPredicates =
args.prefixPredicates === undefined ? true : args.prefixPredicates;
args.prefixFilter =
args.prefixFilter === undefined ? true : args.prefixFilter;
args.prefixClass =
args.prefixClass === undefined ? true : args.prefixClass;
args.prefixPopulations =
args.prefixPopulations === undefined
? true
: args.prefixPopulations;
let offset = args.offset === undefined ? 0 : args.offset;
let graph = this.findGraph(args.graph);
let limit = args.limit === undefined ? 100 : args.limit;
let joins = args.joins;
let filterProp = args.filterProp;
let cls = args.cls;
let checkRelation = [];
let propArray = false;
this.orderByArray = [];
if (joins) {
if (joins.length) {
for (let j = 0; j < joins.length; j++) {
if (!joins[j].parent2ChildRelation) {
let relation = joins[j].child2ParentRelation;
if (!checkRelation.includes(relation)) {
checkRelation.push(relation);
}
} else if (!joins[j].child2ParentRelation) {
let relation = joins[j].parent2ChildRelation;
if (!checkRelation.includes(relation)) {
checkRelation.push(relation);
}
}
}
}
}
// getting fields of parent/master class
let fields = '?' + 'iri';
for (let prop of cls.getProperties()) {
// console.log(prop.getName());
propArray = checkRelation.includes(prop.getName());
if (propArray == false) {
if (!fields.includes(` ${prop.getName()} `)) {
if (prop.getName() == 'sortOrder') {
this.orderByArray.push(prop.getName());
}
fields += '?' + prop.getName() + ' ';
}
}
}
// check if iri filter needs to be applied for parent/master class
let iris = args.iris;
let filters = args.filter;
let iriFilterStr = '';
if (iris) {
let filterArgs = [];
for (let arg of iris) {
let iri = args.prefixFilter
? this.prefixManager.fullToPrefixedIRI(arg)
: this.prefixManager.getSparqlIRI(arg);
filterArgs.push(iri);
}
iriFilterStr = `
filter(?ind in (${filterArgs.join(', ')})) .`;
}
let fieldFilterStr = '';
if (filters) {
for (let filter of filters) {
let filterKey = filter.property || filter.key;
let filterValue = filter.value;
// the SPARQL filter is deprecated and will be dropped due to security reasons!
if (filterKey === '$sparql') {
fieldFilterStr = `filter(${filterValue})`;
} else if (filterKey === '$json') {
if (filterValue) {
// here we need to extend the fiters according to the mongodb spec at:
// https://docs.mongodb.com/manual/reference/operator/query/
for (let fieldName in filterValue) {
let filterArgs = filterValue[fieldName];
if (filterArgs.$regex) {
fieldFilterStr = `
filter(regEx(?${fieldName}, "${filterArgs.$regex}", "${filterArgs.$options}"))`;
}
}
}
}
}
}
let filtePropWhere = '';
let clsStr = args.prefixPredicates
? this.prefixManager.fullToPrefixedIRI(cls.getIRI())
: this.prefixManager.getSparqlIRI(cls.getIRI());
//generte the query part of parent class
var parentClassPart = ``;
for (let prop of cls.getProperties()) {
// console.log(prop);
let propStr = this.prefixManager.fullToPrefixedIRI(prop.getIRI());
propArray = checkRelation.includes(prop.getIRI());
if (propArray == false) {
if (!parentClassPart.includes(propStr)) {
if (filterProp == prop.getName()) {
filtePropWhere = `?ind ${propStr} ?${prop.getName()}`;
}
parentClassPart = `${parentClassPart}
optional {?ind ${propStr} ?${prop.getName()} }.`;
}
}
}
parentClassPart = `${parentClassPart}
bind(str(?ind) as ?iri)
bind ("${cls.getName()}" as ?contentKey ).
}`;
let where = `?ind ${this.type} ${clsStr} .${iriFilterStr}
${filtePropWhere}`;
if (fieldFilterStr.length > 0) {
where = `${where}
${fieldFilterStr}`;
}
if (joins) {
if (joins.length) {
let parentPart = '';
var relationData = this.getAllRelation(joins, cls);
for (let i = 0; i < relationData.result.length; i++) {
parentPart = `${parentPart} ${relationData.result[i].parent}`;
if (relationData.result[i].child) {
let child = ``;
relationData.result[i].child.forEach(
(element) => (child = `${child} ${element}`)
);
parentPart = `${parentPart}
${child}`;
} else {
parentPart = `${parentPart}`;
}
}
parentClassPart = `${parentClassPart}
${parentPart}`;
// console.log(parentClassPart);
fields = ` ?contentKey ?contentRelation ?parentIRI ${fields} ${relationData.fields}`;
fields = fields.replace(undefined, ' ');
// this.count = 0;
// this.findAndCount(joins);
}
}
let orderby = this.findOrderByField(this.orderByArray);
var sparql = `select distinct ${fields}
where
{
${graph.graphStatement}
${where}
${this.triplestore=== "graphdb" ? "{" : ""}
${parentClassPart}
${this.triplestore=== "graphdb" ? "}" : ""}
${graph.graphFilter}
${graph.graphClosingBracket}
`;
if (offset) {
sparql = `${sparql}\noffset ${offset}`;
}
if (limit) {
sparql = `${sparql}\nlimit ${limit}`;
}
if (orderby) {
sparql = `${sparql}order by ${orderby}`;
}
// return the generated SPARQL
return { sparql };
}
findOrderByField(array) {
let order = '';
for (const item of array) {
order = `${order} ?${item}`;
}
return order;
}
getIndividualsByClassOnlyObjectProperties(args) {
args = args || {};
if (!args.cls) {
throw 'No classs passed';
}
args.prefixPredicates =
args.prefixPredicates === undefined ? true : args.prefixPredicates;
args.prefixFilter =
args.prefixFilter === undefined ? true : args.prefixFilter;
args.prefixClass =
args.prefixClass === undefined ? true : args.prefixClass;
args.prefixPopulations =
args.prefixPopulations === undefined
? true
: args.prefixPopulations;
let offset = args.offset === undefined ? 0 : args.offset;
let limit = args.limit === undefined ? 0 : args.limit;
let joins = args.joins;
let cls = args.cls;
let checkRelation = [];
let propArray = false;
// getting fields of parent/master class
let fields = '?' + 'iri';
for (let prop of cls.getProperties()) {
propArray = checkRelation.includes(prop.getName());
if (
propArray == false &&
prop.getType() == 'http://www.w3.org/2002/07/owl#ObjectProperty'
) {
if (!fields.includes(` ${prop.getName()} `)) {
fields += ' ?' + prop.getName();
}
}
}
// check if iri filter needs to be applied for parent/master class
let iris = args.iris;
let filters = args.filter;
let iriFilterStr = '';
if (iris) {
let filterArgs = [];
for (let arg of iris) {
let iri = args.prefixFilter
? this.prefixManager.fullToPrefixedIRI(arg)
: this.prefixManager.getSparqlIRI(arg);
filterArgs.push(iri);
}
iriFilterStr = `
filter(?ind in (${filterArgs.join(', ')})) .`;
}
let fieldFilterStr = '';
if (filters) {
for (let filter of filters) {
let filterKey = filter.property || filter.key;
let filterValue = filter.value;
// the SPARQL filter is deprecated and will be dropped due to security reasons!
if (filterKey === '$sparql') {
fieldFilterStr = `
filter(${filterValue})`;
} else if (filterKey === '$json') {
if (filterValue) {
// here we need to extend the fiters according to the mongodb spec at:
// https://docs.mongodb.com/manual/reference/operator/query/
for (let fieldName in filterValue) {
let filterArgs = filterValue[fieldName];
if (filterArgs.$regex) {
fieldFilterStr = `
filter(regEx(?${fieldName}, "${filterArgs.$regex}", "${filterArgs.$options}"))`;
}
}
}
}
}
}
let clsStr = args.prefixPredicates
? this.prefixManager.fullToPrefixedIRI(cls.getIRI())
: this.prefixManager.getSparqlIRI(cls.getIRI());
//generte the query part of parent class
var parentClassPart = `
bind(str(?ind) as ?iri) .`;
for (let prop of cls.getProperties()) {
// console.log(prop);
let propStr = this.prefixManager.fullToPrefixedIRI(prop.getIRI());
propArray = checkRelation.includes(prop.getIRI());
if (
propArray == false &&
prop.getType() == 'http://www.w3.org/2002/07/owl#ObjectProperty'
) {
if (!parentClassPart.includes(propStr)) {
parentClassPart = `${parentClassPart}
optional {?ind ${propStr} ?${prop.getName()} }.`;
}
}
}
parentClassPart = `${parentClassPart}
bind ("${cls.getName()}" as ?contentKey ).
}`;
let where = `?ind ${this.type} ${clsStr} .${iriFilterStr}`;
if (fieldFilterStr.length > 0) {
where = `${where}
${fieldFilterStr}`;
}
var sparql = `select distinct ${fields}
where
{
${where}
{
${parentClassPart}
}`;
if (offset) {
sparql = `${sparql}\noffset ${offset}`;
}
if (limit) {
sparql = `${sparql}\nlimit ${limit}`;
}
// return the generated SPARQL
return { sparql };
}
splitProperty(item) {
let res = item.split(':');
return res[1];
}
findAndCount(object) {
for (let i = 0; i < object.length; i++) {
if (object[i].joins && !object[i].status) {
this.count++;
object[i].status = 1;
this.findAndCount(object[i].joins, count);
}
}
return 0;
}
getFirstLevelChildren(joins, array, parent) {
let prefixPredicates = true;
let subFields = array;
var checkRelation = [];
var firstLevelChildDetail = [];
var propArray = false;
for (let i = 0; i < joins.length; i++) {
let cls = joins[i].cls;
// check the relation is it child2ParentRelation
if (joins[i].child2ParentRelation) {
// get all the relations
let relation = joins[i].child2ParentRelation;
for (let j = 0; j < relation.length; j++) {
if (!checkRelation.includes(relation)) {
checkRelation.push(relation);
}
}
if (joins[i].joins) {
let res = this.findJoinsRelation(joins[i].joins);
checkRelation = checkRelation.concat(res);
}
// getting fields of parent/master class
let fields =
'?' +
this.toLowerCase(this.removeIRI(cls.getName())) +
'Iri';
for (let prop of joins[i].cls.getProperties()) {
propArray = checkRelation.includes(prop.getIRI());
if (propArray == false) {
if (
!fields.includes(
' ?' +
this.toLowerCase(cls.getName()) +
this.toUpperCase(prop.getName())
)
) {
if (prop.getName() == 'sortOrder') {
this.orderByArray.push(
this.toLowerCase(cls.getName()) +
this.toUpperCase(prop.getName())
);
}
fields +=
' ?' +
this.toLowerCase(cls.getName()) +
this.toUpperCase(prop.getName());
}
}
}
subFields.push(fields);
let propIRI = prefixPredicates
? this.prefixManager.fullToPrefixedIRI(relation)
: this.prefixManager.getSparqlIRI(relation);
// create the query
let childProp = `?${this.toLowerCase(
cls.getName()
)} ${propIRI} ?ind.
?${this.toLowerCase(
cls.getName()
)} ${this.type} ${this.prefixManager.fullToPrefixedIRI(
cls.getIRI()
)} .
{
bind(?${this.toLowerCase(cls.getName())} as ?${this.toLowerCase(
cls.getName()
)}Iri)`;
let propertyRelation = this.splitProperty(propIRI);
// now add properties
for (let prop of cls.getProperties()) {
let propStr = prefixPredicates
? this.prefixManager.fullToPrefixedIRI(prop.getIRI())
: this.prefixManager.getSparqlIRI(prop.getIRI());
propArray = checkRelation.includes(prop.getIRI());
if (propArray == false) {
if (!childProp.includes(propStr)) {
childProp = `${childProp}
optional{?${this.toLowerCase(cls.getName())} ${propStr} ?${this.toLowerCase(
cls.getName()
)}${this.toUpperCase(prop.getName())}.}`;
}
}
}
childProp = `${childProp}
bind( "${parent.getName()}.${cls.getName()}" as ?contentKey)
bind( "${propertyRelation}" as ?contentRelation)
bind( ?ind as ?parentIRI)
}`;
let skipBracket = joins.filter(
(element) => element.cls.getName() == cls.getName()
);
if (skipBracket[0].joins) {
childProp = `union
{
${childProp}
`;
} else {
childProp = `union
{
${childProp}
}`;
}
// push the each relation against query in array
firstLevelChildDetail.push(childProp);
// check the query is it parent2ChildRelation accordingly create query
} else if (!joins.parent2ChildRelation) {
let relation = joins[i].parent2ChildRelation;
for (let j = 0; j < relation.length; j++) {
if (!checkRelation.includes(relation)) {
checkRelation.push(relation);
}
}
if (joins[i].joins) {
let res = this.findJoinsRelation(joins[i].joins);
checkRelation = checkRelation.concat(res);
}
let fields = '?' + this.toLowerCase(cls.getName()) + 'Iri';
for (let prop of joins[i].cls.getProperties()) {
propArray = checkRelation.includes(prop.getIRI());
if (propArray == false) {
if (
!fields.includes(
' ?' +
this.toLowerCase(cls.getName()) +
this.toUpperCase(prop.getName())
)
) {
if (prop.getName() == 'sortOrder') {
this.orderByArray.push(
this.toLowerCase(cls.getName()) +
this.toUpperCase(prop.getName())
);
}
fields +=
' ?' +
this.toLowerCase(cls.getName()) +
this.toUpperCase(prop.getName());
}
}
}
subFields.push(fields);
// todo: add relation prefix properties
let propIRI = prefixPredicates
? this.prefixManager.fullToPrefixedIRI(relation)
: this.prefixManager.getSparqlIRI(relation);
let propertyRelation = this.splitProperty(propIRI);
var childProp = `
?ind ${propIRI} ?${this.toLowerCase(cls.getName())} .
?${this.toLowerCase(
cls.getName()
)} ${this.type} ${this.prefixManager.fullToPrefixedIRI(cls.getIRI())} .
{
bind(?${this.toLowerCase(cls.getName())} as ?${this.toLowerCase(
cls.getName()
)}Iri)`;
for (let prop of cls.getProperties()) {
let propStr = prefixPredicates
? this.prefixManager.fullToPrefixedIRI(prop.getIRI())
: this.prefixManager.getSparqlIRI(prop.getIRI());
propArray = checkRelation.includes(prop.getIRI());
if (propArray == false) {
if (!childProp.includes(propStr)) {
childProp = `
${childProp}
optional{?${this.toLowerCase(
cls.getName()
)} ${propStr} ?${this.toLowerCase(cls.getName())}${this.toUpperCase(
prop.getName()
)}.}`;
}
}
}
childProp = `
${childProp}
bind( "${parent.getName()}.${cls.getName()}" as ?contentKey)
bind( "${propertyRelation}" as ?contentRelation)
bind( ?ind as ?parentIRI)
}`;
let skipBracket = joins.filter(
(element) => element.cls.getName() == cls.getName()
);
if (skipBracket[0].joins) {
childProp = `union
{
${childProp}
`;
} else {
childProp = `union
{
${childProp}
}`;
}
firstLevelChildDetail.push(childProp);
}
}
// firstLevelChildDetail = `${firstLevelChildDetail}
// }`;
return { subFields, firstLevelChildDetail };
}
getAllRelation(obj, cls) {
let result = [];
let fieldArray = [];
let array = [];
let fields;
let res1 = this.getFirstLevelChildren(obj, array, cls);
for (let i = 0; i < obj.length; i++) {
let subChildArray = [];
if (obj[i].joins) {
let res = this.getInnerRelation(
[obj[i]],
fieldArray,
subChildArray
);
result.push({
parent: res1.firstLevelChildDetail[i],
child: res.second
// bracket: this.count + 1
});
if (res.field) {
fields = res.field.join(' ');
}
} else {
result.push({
parent: `${res1.firstLevelChildDetail[i]}`
});
}
}
if (res1.subFields) {
fields = `${res1.subFields.join(' ')} ${fields} `;
}
return { fields, result };
}
getInnerRelation(obj, fieldArray, childArray) {
obj.forEach((element) => {
if (element.joins) {
let res = this.SubChildJoin(
element.joins,
element.cls.getName(),
fieldArray,
childArray,
element.cls.getName()
);
this.childDetail = res.subChild;
this.fields = res.subFields;
//console.log(this.childDetail);
// this.getInnerRelation(
// element.joins,
// this.fields,
// this.childDetail,
// element.cls
// );
}
});
let field = this.fields;
let second = this.childDetail;
return { field, second };
}
SubChildJoin(child, parent, field, childDetails, parentRefer) {
let prefixPredicates = true;
let subChild = childDetails;
let subFields = field;
var checkRelation = [];
var propArray = false;
for (let i = 0; i < child.length; i++) {
let cls = child[i].cls.getName();
// check the relation type
//var str = 'Class1123';
let dummyParent = parent;
var res = parent.replace(/\D/g, '');
let count = 1;
if (res.length) {
let res1 = parent.replace(res, '');
dummyParent = res1;
count = count + res.length;
}
if (dummyParent == cls) {
for (let i = 0; i < count; i++) {
cls = `${cls}1`;
}
}
if (child[i].child2ParentRelation) {
let relation = child[i].child2ParentRelation;
for (let j = 0; j < relation.length; j++) {
if (!checkRelation.includes(relation)) {
checkRelation.push(relation);
}
}
if (child[i].joins) {
let res = this.findJoinsRelation(child[i].joins);
checkRelation = checkRelation.concat(res);
}
// getting fields of parent/master class
let fields = '?' + this.toLowerCase(cls) + 'Iri';
for (let prop of child[i].cls.getProperties()) {
propArray = checkRelation.includes(prop.getIRI());
if (propArray == false) {
if (
!fields.includes(
' ?' +
this.toLowerCase(cls) +
this.toUpperCase(prop.getName())
)
) {
if (prop.getName() == 'sortOrder') {
this.orderByArray.push(
this.toLowerCase(cls) +
this.toUpperCase(prop.getName())
);
}
fields +=
' ?' +
this.toLowerCase(cls) +
this.toUpperCase(prop.getName());
}
}
}
if (!subFields.includes(` ${fields} `)) {
subFields.push(fields);
}
let propIRI = prefixPredicates
? this.prefixManager.fullToPrefixedIRI(relation)
: this.prefixManager.getSparqlIRI(relation);
let propertyRelation = this.splitProperty(propIRI);
var childDe = `
?${this.toLowerCase(cls)} ${propIRI} ?${this.toLowerCase(parent.getName())}.
?${this.toLowerCase(
cls
)} ${this.type} ${this.prefixManager.fullToPrefixedIRI(
child[i].cls.getIRI()
)} .
bind(?${this.toLowerCase(cls)} as ?${this.toLowerCase(cls)}Iri)
{`;
for (let prop of child[i].cls.getProperties()) {
let propStr = prefixPredicates
? this.prefixManager.fullToPrefixedIRI(prop.getIRI())
: this.prefixManager.getSparqlIRI(prop.getIRI());
propArray = checkRelation.includes(prop.getIRI());
if (!propArray) {
if (!childDe.includes(propStr)) {
childDe = `${childDe}
optional{?${this.toLowerCase(
child[i].cls.getName()
)} ${propStr} ?${this.toLowerCase(
child[i].cls.getName()
)}${this.toUpperCase(prop.getName())}.}`;
}
}
}
childDe = `
${childDe}
bind( "${parent.getName()}.${cls}" as ?contentKey)
bind( "${propertyRelation}" as ?contentRelation)
bind( ?${this.toLowerCase(parent.getName())} as ?parentIRI)
}`;
let skipBracket = [child[i]].filter(
(element) => element.cls.getName() == cls
);
if (skipBracket[0].joins) {
childDe = `union
{
${childDe}
`;
} else {
childDe = `union
{
${childDe}
}`;
}
// if (i == child.length - 1) {
// childDe = `${childDe}
// }`;
// }
// if (!subChild.includes(childDe)) {
subChild.push(childDe);
// }
} else if (child[i].parent2ChildRelation) {
let relation = child[i].parent2ChildRelation;
for (let j = 0; j < relation.length; j++) {
if (!checkRelation.includes(relation)) {
checkRelation.push(relation);
}
}
if (child[i].joins) {
let res = this.findJoinsRelation(child[i].joins);
checkRelation = checkRelation.concat(res);
}
let fields =
'?' + this.toLowerCase(child[i].cls.getName()) + 'Iri';
for (let prop of child[i].cls.getProperties()) {
propArray = checkRelation.includes(prop.getIRI());
if (!propArray) {
if (
!fields.includes(
' ?' +
this.toLowerCase(child[i].cls.getName()) +
this.toUpperCase(prop.getName())
)
) {
if (prop.getName() == 'sortOrder') {
this.orderByArray.push(
this.toLowerCase(child[i].cls.getName()) +
this.toUpperCase(prop.getName())
);
}
fields +=
' ?' +
this.toLowerCase(child[i].cls.getName()) +
this.toUpperCase(prop.getName());
}
}
}
if (!subFields.includes(` ${fields} `)) {
subFields.push(fields);
}
// todo: add relation prefix properties
let propIRI = prefixPredicates
? this.prefixManager.fullToPrefixedIRI(relation)
: this.prefixManager.getSparqlIRI(relation);
let propertyRelation = this.splitProperty(propIRI);
var childDe = `
?${this.toLowerCase(parent)} ${propIRI} ?${this.toLowerCase(cls)}.
?${this.toLowerCase(
cls
)} ${this.type} ${this.prefixManager.fullToPrefixedIRI(
child[i].cls.getIRI()
)} .
{
bind(?${this.toLowerCase(cls)} as ?${this.toLowerCase(
child[i].cls.getName()
)}Iri)`;
for (let prop of child[i].cls.getProperties()) {
let propStr = prefixPredicates
? this.prefixManager.fullToPrefixedIRI(prop.getIRI())
: this.prefixManager.getSparqlIRI(prop.getIRI());
propArray = checkRelation.includes(prop.getIRI());
if (propArray == false) {
if (!childDe.includes(propStr)) {
childDe = `${childDe}
optional{?${this.toLowerCase(cls)} ${propStr} ?${this.toLowerCase(
child[i].cls.getName()
)}${this.toUpperCase(prop.getName())}.}`;
}
}
}
childDe = `${childDe}
bind( "${parentRefer}.${child[i].cls.getName()}" as ?contentKey)
bind( "${propertyRelation}" as ?contentRelation)
bind( ?${this.toLowerCase(parent)} as ?parentIRI)
}`;
// if (parent.getName() == clsName) {
// cls = clsName;
// }
let skipBracket = [child[i]].filter(
(element) => element.cls.getName() == child[i].cls.getName()
);
if (skipBracket[0].joins) {
// count++;
childDe = `union
{
${childDe}
`;
} else {
childDe = `union
{
${childDe}
}`;
}
// if (i == child.length - 1 && !child[i].joins) {
// childDe = `${childDe}
// }`;
// if (count) {
// for (let i = 0; i < count; i++) {
// childDe = `${childDe}
// }`;
// }
// }
// // console.log(count);
// }
// if (i == child.length - 1 && child[i].joins) {
// count++;
// }
// if (!subChild.includes(childDe)) {
subChild.push(childDe);
// }
}
if (child[i].joins) {
//child, parent, field, childDetails
let parent1 = child[i].cls.getName();
if (`${parent}1` == cls) {
parent1 = cls;
}
this.SubChildJoin(
child[i].joins,
parent1,
subFields,
subChild,
child[i].cls.getName()
);
}
// if (child[i].joins) {
// // console.log(child[i].joins);
// this.getInnerRelation(
// child[i].joins,
// subFields,
// subChild
// // element.cls
// );
// }
}
let count = subChild.length;
let v = subChild[count - 1];
v = `${v}
}`;
subChild[count - 1] = v;
return { subChild, subFields };
}
findNoOfBrakcet(object, iterator) {
try {
// for (const key of object) {
for (const item of object) {
let index = [item].find(
(el) =>
el.cls.getName() == iterator.cls.getName() &&
el.parent2ChildRelation == iterator.parent2ChildRelation
);
if (index) {
let depth = this.findDepth(index, 0);
console.log(depth);
// return count;
} else {
if (item.joins) {
let cout = this.findNoOfBrakcet(item.joins, iterator);
console.log(cout);
}
}
}
} catch (e) {
return e;
}
}
findDepth(array, count) {
if (array.joins) {
count = +joins.length;
count = this.findDepth(array.join, count);
}
return count;
}
findJoinsRelation(joins) {
let arr = [];
for (let i = 0; i < joins.length; i++) {
if (joins[i].child2ParentRelation) {
if (!arr.includes(joins[i].child2ParentRelation)) {
arr.push(joins[i].child2ParentRelation);
}
} else if (joins[i].parent2ChildRelation) {
if (!arr.includes(joins[i].parent2ChildRelation)) {
arr.push(joins[i].parent2ChildRelation);
}
}
}
return arr;
}
/*
SPARQL example:
select ?master ?child ?has_Product_Name ?has_Product_Code ?has_Product_Price
where {
filter(?master in (fyp:SABS_ORDERLINE_01)) .
optional {
?master fyp:hasProduct ?child .
optional { ?child fyp:has_Product_Name ?has_Product_Name } .
optional { ?child fyp:has_Product_Code ?has_Product_Code } .
optional { ?child fyp:has_Product_Price ?has_Product_Price } .
}
}
*/
// get all related instances of a certain class from the graph
// cls: the in-memory class
// prefixProps: true = uses prefixed property identifiers
toLowerCase(option) {
return `${option[0].toLowerCase()}${option.substr(1)}`;
}
toUpperCase(option) {
return `${option[0].toUpperCase()}${option.substr(1)}`;
}
getRelatedIndividuals(args) {
args = args || {};
if (!args.childCls) {
throw 'No child class passed';
}
args.prefixPredicates =
args.prefixPredicates === undefined ? true : args.prefixPredicates;
args.prefixFilter =
args.prefixFilter === undefined ? true : args.prefixFilter;
args.prefixClass =
args.prefixClass === undefined ? true : args.prefixClass;
let childCls = args.childCls;
// first generate list of fields to be queried
let fields = '?master ?child';
for (let prop of childCls.getProperties()) {
fields += ' ?' + prop.getName();
}
// check if iri filter needs to be applied
let masterIris = [args.masterIri];
let filter = '';
if (masterIris) {
let filterArgs = [];
for (let arg of masterIris) {
let masterIri = args.prefixFilter
? this.prefixManager.fullToPrefixedIRI(arg)
: this.prefixManager.getSparqlIRI(arg);
filterArgs.push(masterIri);
}
filter = `filter(?master in (${filterArgs.join(', ')})) .`;
}
// now generate the where clause for the select statement
// add the iri filter, if such is requested
let propStr = args.prefixFilter
? this.prefixManager.fullToPrefixedIRI(args.propertyIri)
: this.prefixManager.getSparqlIRI(args.propertyIri);
let where = `${filter}
optional {
?master ${propStr} ?child`;
// now add all properties
for (let prop of childCls.getProperties()) {
let propStr = args.prefixPredicates
? this.prefixManager.fullToPrefixedIRI(prop.getIRI())
: this.prefixManager.getSparqlIRI(prop.getIRI());
where = `${where}
optional { ?child ${propStr} ?${prop.getName()} } .`;
}
where = `${where}
}`;
// and compose the query
let sparql = `select ${fields}
where {
${where}
}`;
// return the generated SPARQL
return { sparql };
}
// create a new instance of a certain (in-memory-)class in the graph
createIndividualByClass(args) {
let prefixPredicates = true;
args = args || {};
let cls = args.cls;
let graph = this.findGraph(args.graph, 'cud');
let options = args.options || {};
let ind = args.ind || {};
let baseiri = args.baseiri;
// if an IRI is provided use that one, if not generate an UUID
if (!baseiri) {
var iri =
ind.iri ||
this.prefixManager.getDefaultNamespace() +
cls.getName() +
'_' +
uuidv4();
} else {
var iri = baseiri + cls.getName() + '_' + uuidv4();
}
// todo: add options argument prefixClass
let classIRI = prefixPredicates
? this.prefixManager.fullToPrefixedIRI(cls.getIRI())
: this.prefixManager.getSparqlIRI(cls.getIRI());
// let fields = `?iri rdf:type owl:NamedIndividual .`;
let fields = `?iri rdf:type ${classIRI} .`;
for (let prop of cls.getProperties()) {
// get the name of the property
let name = prop.getName();
// find the value in the passed individual
let val = ind[name];
// if a value is set
if (undefined != val) {
// todo: replace this by global method to convert value
let object;
if (prop.getType().includes('DatatypeProperty')) {
// object = '"' + val + '"';
// if (object.includes('"')) {
if (typeof val == 'string') {
val = val.replace(/\"/g, '\\"');
val=this.escapeSpecialCharacters(val);
}
//}
object = '"' + val + '"';
} else {
object = this.prefixManager.fullToPrefixedIRI(val);
}
// todo: add options argument prefixProperties
let propIRI = options.prefixProperties
? this.prefixManager.fullToPrefixedIRI(prop.getIRI())
: this.prefixManager.getSparqlIRI(prop.getIRI());
fields = `${fields}
?iri ${propIRI} ${object} .`; // <${prop.getIRI()}>
}
}
// accomplish the sparql insert command
let sparql = `insert {
${graph.graphStatement}
${fields}
${graph.graphClosingBracket}
} where {
${graph.graphStatement