UNPKG

@innotrade/enapso-sparql-tools

Version:
1,262 lines (1,221 loc) 146 kB
// 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