Skip to content

Commit

Permalink
SPARQL generation from data schema property
Browse files Browse the repository at this point in the history
SPARQL generation: kind INSTANCE, for conditions, values
Filter icon for condition
  • Loading branch information
julijaovcinnikova committed Nov 19, 2024
1 parent dc67cb4 commit 0cbb2a1
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 31 deletions.
6 changes: 5 additions & 1 deletion app/imports/client/custom/vq/js/VQ_Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -1463,6 +1463,8 @@ VQ_Element.prototype = {
addCompartmentSubCompartments: function(compartment_name, subcompartment_value_list) {
var ct = CompartmentTypes.findOne({name: compartment_name, elementTypeId: this.obj["elementTypeId"]});
if (ct) {
let prefix = ct["prefix"] || "";
let sufix = ct["sufix"] || "";
var c_to_create = {
compartment: {
projectId: Session.get("activeProject"),
Expand All @@ -1488,7 +1490,8 @@ VQ_Element.prototype = {
c_to_create["compartment"]["subCompartments"][compartment_name] = {};
c_to_create["compartment"]["subCompartments"][compartment_name][compartment_name] = {};

if (ct.inputType.type == "custom" && ct.inputType.templateName == "multiField") {
if (ct.inputType.type == "custom") {
// if (ct.inputType.type == "custom" && ct.inputType.templateName == "multiField") {
var ct_comparts_indexes = Compartments.find({compartmentTypeId: ct._id, elementId: this._id()}, {sort: {index: 1}})
.map(function(c) {return c.index; });
// search for hole in the array of indexes
Expand Down Expand Up @@ -1535,6 +1538,7 @@ VQ_Element.prototype = {
value_array.pop();
c_to_create["compartment"]["value"] = value_array.join("");
c_to_create["compartment"]["input"] = c_to_create["compartment"]["value"];
c_to_create["compartment"]["value"] = prefix + value_array.join("") + sufix;
Utilities.callMeteorMethod("insertCompartment", c_to_create);
};
},
Expand Down
15 changes: 7 additions & 8 deletions app/imports/client/custom/vq/js/genAbstractQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ async function resolveTypesAndBuildSymbolTable(query) {
}

for (const c of obj_class.conditions) {
await parseExpObject(c,obj_class.identification);
await parseExpObject(c,obj_class.identification, "condition");
if(obj_class.isBlankNode == true ){
if(c.exp.indexOf("=") === -1 && c.exp.indexOf("->") === -1){
obj_class.isBlankNode = false;
Expand Down Expand Up @@ -1769,13 +1769,10 @@ async function resolveTypeFromSchemaForClass(id, schemaName) {
async function resolveTypeFromSchemaForIndividual(id, schemaName) {
if(schemaName.toLowerCase() == "wikidata" && ((id.indexOf("[") > -1 && id.endsWith("]"))) ){
id = "wd:"+id;
// var cls = await dataShapes.resolveIndividualByName({name: id})
// if(schemaName !== "" && schemaName !== null) dataShapes.schema.schema = schemaName;
var cls = await dataShapes.getIndividualName(id,true)
if(cls != null && cls != ""){
return {local_name: cls.substring(3), prefix: "wd"};
}

};
var cls = await dataShapes.getIndividualName(id,true)
if(cls != null && cls != ""){
return {local_name: cls.substring(3), prefix: "wd"};
}
return null;
};
Expand Down Expand Up @@ -1909,6 +1906,8 @@ async function resolveKind(id, exprType, context, symbol_table, schemaName, isSi
k="CLASS_NAME";
} else if (await resolveTypeFromSchemaForAttributeAndLink(id, schemaName)) {
k="PROPERTY_NAME";
} else if (exprType === "condition" && await resolveTypeFromSchemaForIndividual(id, schemaName)) {
k="INDIVIDUAL";
}
}
}
Expand Down
175 changes: 160 additions & 15 deletions app/imports/client/custom/vq/js/generateSPARQL_jo.js
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,15 @@ Interpreter.customMethods({
await generateSPARQLtextFromSchema();
},

ExecuteSPARQL_form_object_property_DSS: async function() {
let SPARQL_text = await generateSPARQLtextFromSchemaForObjectProperty();
executeSparqlString(SPARQL_text);
},

GenereteSPARQL_form_object_property_DSS: async function() {
await generateSPARQLtextFromSchemaForObjectProperty();
},

Collect_prefixes_from_diagram_for_all_queries: async function() {
// get _id of the active ajoo diagram
var diagramId = Session.get("activeDiagram");
Expand Down Expand Up @@ -444,6 +453,99 @@ Interpreter.customMethods({
},
});

async function generateSPARQLtextFromSchemaForObjectProperty(){
let prefixTable = [];
let prefixes = await dataShapes.getNamespaces();
let usedNames = [];

let editor = Interpreter.editor;
let elem = _.keys(editor.getSelectedElements());

let dirRole = "a";

let proj = Projects.findOne({_id: Session.get("activeProject")});
if (proj) {
if (proj.directClassMembershipRole) {
dirRole = proj.directClassMembershipRole;
}
}

let link = new VQ_Element(elem[0]);
let startElement = link.getStartElement();
let endElement = link.getEndElement();

let linkName = link.getCompartmentValue("Name");
let startElementName = startElement.getCompartmentValue("Name");
let endElementName = endElement.getCompartmentValue("Name");

let startClassSPRAQL = "";
let endClassSPRAQL = "";

let classList = startElement.getCompartmentValue("ClassList");

if(classList === null){
let startSimpleSchemaBox = await simpleSchemaBox(startElement, 1, dirRole, usedNames,true);
prefixTable = { ...prefixTable, ...startSimpleSchemaBox.prefixes};
usedNames = { ...usedNames, ...startSimpleSchemaBox.usedNames};
startElementName = startSimpleSchemaBox.className;
startClassSPRAQL = startSimpleSchemaBox.sparql;
} else {
let startGroupSchemaBox = await groupSchemaBox(startElement, 1, dirRole, classList, usedNames, true);
prefixTable = { ...prefixTable, ...startGroupSchemaBox.prefixes};
usedNames = { ...usedNames, ...startGroupSchemaBox.usedNames};
startElementName = startGroupSchemaBox.className;
startClassSPRAQL = startGroupSchemaBox.sparql;
prefixTable = { ...prefixTable, ...startGroupSchemaBox.prefixes};
}

classList = endElement.getCompartmentValue("ClassList");

if(classList === null){
let startSimpleSchemaBox = await simpleSchemaBox(endElement, 1, dirRole, usedNames, true);
prefixTable = { ...prefixTable, ...startSimpleSchemaBox.prefixes};
usedNames = { ...usedNames, ...startSimpleSchemaBox.usedNames};
endElementName = startSimpleSchemaBox.className;
endClassSPRAQL = startSimpleSchemaBox.sparql;
} else {
let startGroupSchemaBox = await groupSchemaBox(endElement, 1, dirRole, classList, usedNames, true);
prefixTable = { ...prefixTable, ...startGroupSchemaBox.prefixes};
usedNames = { ...usedNames, ...startGroupSchemaBox.usedNames};
endElementName = startGroupSchemaBox.className;
endClassSPRAQL = startGroupSchemaBox.sparql;
}

const regex = /(?:\b\w+\b)?:\b\w+\b/g;

// Find all matches in the linkName string
const objectProperties = linkName.match(regex);

let objectPropertiesUnion = [];
for(let prop = 0; prop < objectProperties.length; prop++){
let params = {name: objectProperties[prop]};
let propertyResolved = await dataShapes.resolvePropertyByName(params);
objectPropertiesUnion.push(" ?" + startElementName + " " + propertyResolved.name + " ?"+endElementName+". ");
prefixTable[propertyResolved.data[0].prefix] = "";
}

let prefixText = "";
for(let p = 0; p < prefixes.length; p++){
if(typeof prefixTable[prefixes[p]["name"]] !== "undefined"){
prefixText = prefixText+"PREFIX " + prefixes[p]["name"] + ": <" + prefixes[p]["value"] + ">\n";
}
}

// Check if the array length is more than 1
let result = objectPropertiesUnion.length > 1
? objectPropertiesUnion.map(str => `{${str}}`).join("\nUNION\n") // Wrap with "{" and "}" and join with "\nUNION\n"
: objectPropertiesUnion[0]; // If only one element, leave it as is

result = prefixText + "\nSELECT * WHERE{\n" + result + "\n\n" + startClassSPRAQL + "\n" + endClassSPRAQL + "\n}";
setText_In_SPARQL_Editor(result);

return result;
}


async function generateSPARQLtextFromSchema(){
let n = 7;

Expand All @@ -468,16 +570,33 @@ async function generateSPARQLtextFromSchema(){
}

function getClassListFromString(classList){
const stringValues = classList.match(/^[^\(]+/gm).map(str => str.trim());
// Regular expression to trim the optional beginning and ending parts
const regex = /^(?:\(\w+\)\s*)?(.*?)(?:\s*\(\d+\))?$/gm;
// Extract only the "prefix:name", ":name", or "name" part
const stringValues = classList.match(regex).map(line => line.replace(regex, '$1')).filter(Boolean);
// const stringValues = classList.match(/^[^\(]+/gm).map(str => str.trim());

return stringValues;
}

async function groupSchemaBox(selected_elem, n, dirRole, classListString){
async function groupSchemaBox(selected_elem, n, dirRole, classListString, usedNames, onlyWhere){
let classList = getClassListFromString(classListString);
let sparqlQueryText = "SELECT * WHERE{\n";
let sparqlQueryText = "";
if(!onlyWhere) sparqlQueryText = "SELECT * WHERE{\n";
let classUnionTable = [];
let propertyTable = [];
let className = "exp";
// Regular expression to match and remove the optional parts at the beginning and end
className = selected_elem.getName().replace(/^(?:\(\w+\)\s*)?(?:\w*:)?/, '') // Remove "(string) " and "prefix:" or ":"
.replace(/\s+et al\..*$/, ''); // Remove " et al. string" at the end

if(usedNames !== null && typeof usedNames[className] !== "undefined") {
className = className + "_" + usedNames[className];
usedNames[className] = usedNames[className]+1;
} else {
usedNames[className] = 1;
}

let prefixTable = [];
let prefixes = await dataShapes.getNamespaces();

Expand Down Expand Up @@ -519,27 +638,38 @@ async function groupSchemaBox(selected_elem, n, dirRole, classListString){
const firstNResults = Object.fromEntries(firstNEntries);

for(let p in firstNResults){
sparqlQueryText = sparqlQueryText + " OPTIONAL{?" + className + " " + p + " ?" + p.substring(p.indexOf(":")+1) + " .}\n";
let dataPropName = p.substring(p.indexOf(":")+1);
if(usedNames !== null && typeof usedNames[dataPropName] !== "undefined") {
dataPropName = dataPropName + "_" + usedNames[dataPropName];
usedNames[dataPropName] = usedNames[dataPropName]+1;
} else {
usedNames[dataPropName] = 1;
}

sparqlQueryText = sparqlQueryText + " OPTIONAL{?" + className + " " + p + " ?" + dataPropName + " .}\n";
prefixTable[p.substring(0, p.indexOf(":"))] = "";

}

sparqlQueryText = sparqlQueryText + "}";
if(!onlyWhere)sparqlQueryText = sparqlQueryText + "}";

let prefixText = "";
for(let p = 0; p < prefixes.length; p++){
if(typeof prefixTable[prefixes[p]["name"]] !== "undefined"){
prefixText = prefixText+"PREFIX " + prefixes[p]["name"] + ": <" + prefixes[p]["value"] + ">\n";
}
}
sparqlQueryText = prefixText + sparqlQueryText;
if(!onlyWhere)sparqlQueryText = prefixText + sparqlQueryText;

setText_In_SPARQL_Editor(sparqlQueryText);
if(!onlyWhere)setText_In_SPARQL_Editor(sparqlQueryText);
if(onlyWhere) return {sparql:sparqlQueryText, prefixes:prefixTable, className:className};
return sparqlQueryText;
}


async function simpleSchemaBox(selected_elem, n, dirRole){
async function simpleSchemaBox(selected_elem, n, dirRole, usedNames, onlyWhere){
let name = selected_elem.getCompartmentValue("Name");
if(name.startsWith("(")) name = name.substring(name.indexOf("(")+1);
let nameIndex = name.lastIndexOf(" (");
if(nameIndex === -1) nameIndex = name.length;
name = name.substring(0, nameIndex);
Expand All @@ -558,10 +688,17 @@ async function simpleSchemaBox(selected_elem, n, dirRole){
if(classifProp["name"] !== dirRole && classifProp["name"] !== "rdf:type" && dirRole !== "a") {
dirRole = classifProp["name"];
}

let sparqlQueryText = "SELECT * WHERE{\n";
let className = "";
let sparqlQueryText = "";
if(!onlyWhere) sparqlQueryText = "SELECT * WHERE{\n";
if(cls.complete === true){
let className = cls["data"][0]["local_name"];
className = cls["data"][0]["local_name"];
if(usedNames !== null && typeof usedNames[className] !== "undefined") {
className = className + "_" + usedNames[className];
usedNames[className] = usedNames[className]+1;
} else {
usedNames[className] = 1;
}

let classPrefix = cls["data"][0]["prefix"];
if(classPrefix === null || classPrefix === "null") classPrefix = "";
Expand All @@ -572,22 +709,30 @@ async function simpleSchemaBox(selected_elem, n, dirRole){
for(let prop = 0; prop < props.data.length; prop++){
let dataProperty = props.data[prop];
let dataProp = dataProperty.prefix +":"+dataProperty.local_name;
let dataPropName = dataProperty.local_name;
if(usedNames !== null && typeof usedNames[dataPropName] !== "undefined") {
dataPropName = dataPropName + "_" + usedNames[dataPropName];
usedNames[dataPropName] = usedNames[dataPropName]+1;
} else {
usedNames[dataPropName] = 1;
}

sparqlQueryText = sparqlQueryText + " OPTIONAL{?" + className + " " + dataProp + " ?" +dataProperty.local_name+ " .}\n";
sparqlQueryText = sparqlQueryText + " OPTIONAL{?" + className + " " + dataProp + " ?" +dataPropName+ " .}\n";
prefixTable[dataProperty.prefix] = "";
}
}
sparqlQueryText = sparqlQueryText + "}";
if(!onlyWhere) sparqlQueryText = sparqlQueryText + "}";

let prefixText = "";
for(let p = 0; p < prefixes.length; p++){
if(typeof prefixTable[prefixes[p]["name"]] !== "undefined"){
prefixText = prefixText+"PREFIX " + prefixes[p]["name"] + ": <" + prefixes[p]["value"] + ">\n";
}
}
sparqlQueryText = prefixText + sparqlQueryText;
if(!onlyWhere) sparqlQueryText = prefixText + sparqlQueryText;

setText_In_SPARQL_Editor(sparqlQueryText);
if(!onlyWhere) setText_In_SPARQL_Editor(sparqlQueryText);
if(onlyWhere) return {sparql:sparqlQueryText, prefixes:prefixTable, className:className, usedNames:usedNames};
return sparqlQueryText;
}

Expand Down
19 changes: 15 additions & 4 deletions app/imports/client/custom/vq/js/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -716,8 +716,11 @@ function setVariableName(varName, alias, variableData, generateNewName, useAlias
return alias;
} else {

if(typeof variableNamesTable[classID] !== "undefined" && typeof variableNamesTable[classID][varName.replace(/-/g, '_').replace(/ /g, '')] !== "undefined" && typeof variableNamesTable[classID][varName.replace(/-/g, '_').replace(/ /g, '')][fieldId] !== "undefined" ){
//is simbol table has variable, wiht kind ALIAS and ather class context
if(variableData["kind"] == "INDIVIDUAL" && variableData["type"] !== null){
return variableData["type"]["prefix"] +":"+variableData["type"]["local_name"];
}
else if(typeof variableNamesTable[classID] !== "undefined" && typeof variableNamesTable[classID][varName.replace(/-/g, '_').replace(/ /g, '')] !== "undefined" && typeof variableNamesTable[classID][varName.replace(/-/g, '_').replace(/ /g, '')][fieldId] !== "undefined" ){
//is simbol table has variable, wiht kind ALIAS and other class context
if(typeof classSimbolTable[varFullName] !== "undefined"){
for(let st = 0; st < classSimbolTable[varFullName].length; st++){
if(typeof classSimbolTable[varFullName][st] === "object"){
Expand Down Expand Up @@ -2638,6 +2641,10 @@ function generateExpression(expressionTable, SPARQLstring, className, classSchem
if(variableToUse == null && expressionTable[key]["ref"] == null) {

variable = setVariableName(varName, alias, expressionTable[key]);

if(expressionTable[key]["kind"] === "INDIVIDUAL"){
generateTriples = false;
}
}
else variable = variableToUse;

Expand All @@ -2650,8 +2657,12 @@ function generateExpression(expressionTable, SPARQLstring, className, classSchem
SPARQLstring = SPARQLstring + variable;
} else {
variable = variable.replace("/", "_")
SPARQLstring = SPARQLstring + "?" + variable;
variableTable.push("?" + variable);
if(expressionTable[key]["kind"] !== "INDIVIDUAL"){
SPARQLstring = SPARQLstring + "?" + variable;
variableTable.push("?" + variable);
} else {
SPARQLstring = SPARQLstring + variable;
}
}

if(generateTriples == true && expressionTable[key]['type'] != null && className != "[ ]" && className != "[ + ]") {
Expand Down
3 changes: 3 additions & 0 deletions app/imports/client/custom/vq/templates/add_condition_form.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ Template.AddCondition.events({
else allowMultiplication = "false";

// fullText = "\uD83D\uDD05 " + fullText;
let prefix = compart_type["prefix"] || "";
let sufix = compart_type["sufix"] || "";
fullText = prefix + fullText + sufix;
compart.subCompartments.Conditions.Conditions["Allow result multiplication"].input = allowMultiplication;
compart.subCompartments.Conditions.Conditions["Allow result multiplication"].value = allowMultiplicationInput;
compart.subCompartments.Conditions.Conditions.Expression.value = condition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<tbody>
{{#each values}}
<tr id="{{_id}}" class="multi-field-row">
<td>{{value}}</td>
<td>{{input}}</td>
<td class="pull-right">
<!-- <a class="btn btn-xs btn-primary down-multi-field"><i class="fa fa-arrow-down"></i></a> -->
<a class="btn btn-xs btn-info up-multi-field"><i class="fa fa-arrow-up"></i></a>
Expand Down
Loading

0 comments on commit 0cbb2a1

Please sign in to comment.