diff --git a/app/imports/client/custom/vq/js/VQ_Element.js b/app/imports/client/custom/vq/js/VQ_Element.js index 04f3396a..6fbe1e4b 100644 --- a/app/imports/client/custom/vq/js/VQ_Element.js +++ b/app/imports/client/custom/vq/js/VQ_Element.js @@ -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"), @@ -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 @@ -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); }; }, diff --git a/app/imports/client/custom/vq/js/genAbstractQuery.js b/app/imports/client/custom/vq/js/genAbstractQuery.js index 2720ab1d..b3ba5479 100644 --- a/app/imports/client/custom/vq/js/genAbstractQuery.js +++ b/app/imports/client/custom/vq/js/genAbstractQuery.js @@ -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; @@ -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; }; @@ -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"; } } } diff --git a/app/imports/client/custom/vq/js/generateSPARQL_jo.js b/app/imports/client/custom/vq/js/generateSPARQL_jo.js index 3897f34b..432b7b18 100644 --- a/app/imports/client/custom/vq/js/generateSPARQL_jo.js +++ b/app/imports/client/custom/vq/js/generateSPARQL_jo.js @@ -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"); @@ -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; @@ -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(); @@ -519,11 +638,20 @@ 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++){ @@ -531,15 +659,17 @@ async function groupSchemaBox(selected_elem, n, dirRole, classListString){ 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); @@ -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 = ""; @@ -572,12 +709,19 @@ 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++){ @@ -585,9 +729,10 @@ async function simpleSchemaBox(selected_elem, n, dirRole){ 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; } diff --git a/app/imports/client/custom/vq/js/parser.js b/app/imports/client/custom/vq/js/parser.js index d3145bfb..8e086934 100644 --- a/app/imports/client/custom/vq/js/parser.js +++ b/app/imports/client/custom/vq/js/parser.js @@ -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"){ @@ -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; @@ -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 != "[ + ]") { diff --git a/app/imports/client/custom/vq/templates/add_condition_form.js b/app/imports/client/custom/vq/templates/add_condition_form.js index b176bfcd..53b84c44 100644 --- a/app/imports/client/custom/vq/templates/add_condition_form.js +++ b/app/imports/client/custom/vq/templates/add_condition_form.js @@ -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; diff --git a/app/imports/client/platform/templates/diagrams/dialog/multiField.html b/app/imports/client/platform/templates/diagrams/dialog/multiField.html index 3eb33604..07741dc5 100644 --- a/app/imports/client/platform/templates/diagrams/dialog/multiField.html +++ b/app/imports/client/platform/templates/diagrams/dialog/multiField.html @@ -24,7 +24,7 @@
{{#each values}}