Skip to content

Commit

Permalink
Merge pull request #31 from comake/fix/nested-functions
Browse files Browse the repository at this point in the history
fix: Execute nested functions
  • Loading branch information
ThibaultGerrier authored Jul 6, 2022
2 parents 98eead2 + 66dfcb2 commit c4bc395
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 131 deletions.
3 changes: 3 additions & 0 deletions src/function/function.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ const findParameters = (data, predicateObjectMap, prefixes) => {
if (param.template) {
type = 'template';
}
if (param.functionValue) {
type = 'functionValue'
}
if (param[type] && param[type].length === 1) {
param[type] = param[type][0];
}
Expand Down
54 changes: 31 additions & 23 deletions src/input-parser/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,44 @@ const subjFunctionExecution = async (Parser, functionMap, prefixes, data, index,
const functionValue = functionMap.functionValue;
const definition = functionHelper.findDefinition(data, functionValue.predicateObjectMap, prefixes);
const parameters = functionHelper.findParameters(data, functionValue.predicateObjectMap, prefixes);
const params = calculateParams(Parser, parameters, index, options);
const params = await calculateParams(Parser, parameters, index, options);

return functionHelper.executeFunction(definition, params, options);
};

const calculateParams = (Parser, parameters, index, options) => {
const calculateParams = async (Parser, parameters, index, options, data, prefixes) => {
const result = [];
parameters.forEach((p) => {
let temp = [];
if (p.type === 'constant') {
temp.push(p.data);
} else if (p.type === 'reference') {
temp = getDataFromParser(Parser, index, p.data, options);
} else if (p.type === 'template') {
let resolveTemplate = p.data
var templateRegex = /(?:\{(.*?)\})/g;
while (match = templateRegex.exec(p.data)) {
// Retrieve all matches of the regex group {myvar}
const variableValue = getDataFromParser(Parser, index, match[1], options);
resolveTemplate = resolveTemplate.replace("{" + match[1] + "}", variableValue.toString())
await Promise.all(
parameters.map(async (p) => {
let temp = [];
if (p.type === 'constant') {
temp.push(p.data);
} else if (p.type === 'reference') {
temp = getDataFromParser(Parser, index, p.data, options);
} else if (p.type === 'template') {
let resolveTemplate = p.data
var templateRegex = /(?:\{(.*?)\})/g;
while (match = templateRegex.exec(p.data)) {
// Retrieve all matches of the regex group {myvar}
const variableValue = getDataFromParser(Parser, index, match[1], options);
resolveTemplate = resolveTemplate.replace("{" + match[1] + "}", variableValue.toString())
}
temp.push(resolveTemplate);
} else if (p.type === 'functionValue') {
const definition = functionHelper.findDefinition(data, p.data.predicateObjectMap, prefixes);
const functionParameters = functionHelper.findParameters(data, p.data.predicateObjectMap, prefixes);
const calcParameters = await calculateParams(Parser, functionParameters, index, options);
const res = await functionHelper.executeFunction(definition, calcParameters, options);
temp.push(res);
}
temp.push(resolveTemplate);
}

if (temp && temp.length === 1) {
temp = temp[0];
}
result[p.predicate] = temp;
result.push(temp)
});
if (temp && temp.length === 1) {
temp = temp[0];
}
result[p.predicate] = temp;
result.push(temp)
}),
);
return result;
};

Expand Down
217 changes: 109 additions & 108 deletions src/input-parser/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const parseFile = async (data, currObject, prefixes, source, iterator, options,
Parser: the parser object
data: the whole ttl mapfile in json
currObject: the current object from thje mapfile that is parsed
currObject: the current object from the mapfile that is parsed
prefixes: all prefixes,
options: the options,
ql: the querylanguage
Expand Down Expand Up @@ -281,128 +281,129 @@ const handleSingleMapping = async (Parser, index, obj, mapping, predicate, prefi
if (object) {
helper.addToObj(obj, predicate, object);
} else {
for (const objectmap of objectmaps) {
const reference = objectmap.reference;
let constant = objectmap.constant;
let language = objectmap.language;
const datatype = helper.isURL(objectmap.datatype) ? objectmap.datatype : prefixhelper.replacePrefixWithURL(objectmap.datatype, prefixes);
const template = objectmap.template;
let termtype = objectmap.termType;
await Promise.all(
objectmaps.map(async (objectmap) => {
const reference = objectmap.reference;
let constant = objectmap.constant;
let language = objectmap.language;
const datatype = helper.isURL(objectmap.datatype) ? objectmap.datatype : prefixhelper.replacePrefixWithURL(objectmap.datatype, prefixes);
const template = objectmap.template;
let termtype = objectmap.termType;

if (objectmap.languageMap) {
language = useLanguageMap(Parser, index, objectmap.languageMap, prefixes, options);
}
if (objectmap.languageMap) {
language = useLanguageMap(Parser, index, objectmap.languageMap, prefixes, options);
}

if (language) {
if (!tags(language).valid()) {
throw (`Language tag: ${language} invalid!`);
if (language) {
if (!tags(language).valid()) {
throw (`Language tag: ${language} invalid!`);
}
}
}

const functionValue = objectmap.functionValue;
if (template) {
// we have a template definition
const temp = calculateTemplate(Parser, index, template, prefixes, termtype, options);
temp.forEach((t) => {
if (termtype) {
termtype = prefixhelper.replacePrefixWithURL(termtype, prefixes);
switch (termtype) {
case 'http://www.w3.org/ns/r2rml#BlankNode':
t = {
'@id': `_:${t}`,
};
break;
case 'http://www.w3.org/ns/r2rml#IRI':
if (!helper.isURL(t)) {
t = {
'@id': helper.addBase(t, prefixes),
};
} else {
const functionValue = objectmap.functionValue;
if (template) {
// we have a template definition
const temp = calculateTemplate(Parser, index, template, prefixes, termtype, options);
temp.forEach((t) => {
if (termtype) {
termtype = prefixhelper.replacePrefixWithURL(termtype, prefixes);
switch (termtype) {
case 'http://www.w3.org/ns/r2rml#BlankNode':
t = {
'@id': t,
'@id': `_:${t}`,
};
}
break;
case 'http://www.w3.org/ns/r2rml#Literal':
break;
default:
throw (`Don't know: ${termtype['@id']}`);
break;
case 'http://www.w3.org/ns/r2rml#IRI':
if (!helper.isURL(t)) {
t = {
'@id': helper.addBase(t, prefixes),
};
} else {
t = {
'@id': t,
};
}
break;
case 'http://www.w3.org/ns/r2rml#Literal':
break;
default:
throw (`Don't know: ${termtype['@id']}`);
}
} else {
t = {
'@id': t,
};
}
} else {
t = {
'@id': t,
};
t = helper.cutArray(t);
helper.setObjPredicate(obj, predicate, t, language, datatype);
});
} else if (reference) {
// we have a reference definition
let ns = getDataFromParser(Parser, index, reference, options);
let arr = [];
ns = helper.addArray(ns);
ns.forEach((n) => {
arr.push(n);
});
if (arr && arr.length > 0) {
arr = helper.cutArray(arr);
helper.setObjPredicate(obj, predicate, arr, language, datatype);
}
t = helper.cutArray(t);
helper.setObjPredicate(obj, predicate, t, language, datatype);
});
} else if (reference) {
// we have a reference definition
let ns = getDataFromParser(Parser, index, reference, options);
let arr = [];
ns = helper.addArray(ns);
ns.forEach((n) => {
arr.push(n);
});
if (arr && arr.length > 0) {
arr = helper.cutArray(arr);
helper.setObjPredicate(obj, predicate, arr, language, datatype);
}
} else if (constant) {
// we have a constant definition
constant = helper.cutArray(constant);
constant = helper.getConstant(constant, prefixes);
} else if (constant) {
// we have a constant definition
constant = helper.cutArray(constant);
constant = helper.getConstant(constant, prefixes);

if (prefixhelper.replacePrefixWithURL(predicate, prefixes) !== 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' && termtype && prefixhelper.replacePrefixWithURL(termtype, prefixes) === 'http://www.w3.org/ns/r2rml#IRI') {
if (!helper.isURL(constant)) {
constant = {
'@id': helper.addBase(constant, prefixes),
};
} else {
constant = {
'@id': constant,
};
if (prefixhelper.replacePrefixWithURL(predicate, prefixes) !== 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' && termtype && prefixhelper.replacePrefixWithURL(termtype, prefixes) === 'http://www.w3.org/ns/r2rml#IRI') {
if (!helper.isURL(constant)) {
constant = {
'@id': helper.addBase(constant, prefixes),
};
} else {
constant = {
'@id': constant,
};
}
}
}
helper.setObjPredicate(obj, predicate, constant, language, datatype);
} else if (objectmap.parentTriplesMap && objectmap.parentTriplesMap['@id']) {
// we have a parentTriplesmap
helper.setObjPredicate(obj, predicate, constant, language, datatype);
} else if (objectmap.parentTriplesMap && objectmap.parentTriplesMap['@id']) {
// we have a parentTriplesmap

if (!obj.$parentTriplesMap) {
obj.$parentTriplesMap = {};
}
if (objectmap.joinCondition) {
const joinConditions = helper.addArray(objectmap.joinCondition);
if (!obj.$parentTriplesMap) {
obj.$parentTriplesMap = {};
}
if (objectmap.joinCondition) {
const joinConditions = helper.addArray(objectmap.joinCondition);

if (!obj.$parentTriplesMap[predicate]) {
if (!obj.$parentTriplesMap[predicate]) {
obj.$parentTriplesMap[predicate] = [];
}
obj.$parentTriplesMap[predicate].push({
joinCondition: joinConditions.map((cond) => ({
parentPath: cond.parent,
child: getDataFromParser(Parser, index, cond.child, options),
})),
mapID: objectmap['@id'],
});
} else if (obj.$parentTriplesMap[predicate]) {
obj.$parentTriplesMap[predicate].push({
mapID: objectmap['@id'],
});
} else {
obj.$parentTriplesMap[predicate] = [];
obj.$parentTriplesMap[predicate].push({
mapID: objectmap['@id'],
});
}
obj.$parentTriplesMap[predicate].push({
joinCondition: joinConditions.map((cond) => ({
parentPath: cond.parent,
child: getDataFromParser(Parser, index, cond.child, options),
})),
mapID: objectmap['@id'],
});
} else if (obj.$parentTriplesMap[predicate]) {
obj.$parentTriplesMap[predicate].push({
mapID: objectmap['@id'],
});
} else {
obj.$parentTriplesMap[predicate] = [];
obj.$parentTriplesMap[predicate].push({
mapID: objectmap['@id'],
});
} else if (functionValue) {
const definition = functionHelper.findDefinition(data, functionValue.predicateObjectMap, prefixes);
const parameters = functionHelper.findParameters(data, functionValue.predicateObjectMap, prefixes);
const calcParameters = await helper.calculateParams(Parser, parameters, index, options, data, prefixes);
const result = await functionHelper.executeFunction(definition, calcParameters, options);
helper.setObjPredicate(obj, predicate, result, language, datatype);
}
} else if (functionValue) {
const functionMap = functionValue;
const definition = functionHelper.findDefinition(data, functionMap.predicateObjectMap, prefixes);
const parameters = functionHelper.findParameters(data, functionMap.predicateObjectMap, prefixes);
const calcParameters = helper.calculateParams(Parser, parameters, index, options);
const result = await functionHelper.executeFunction(definition, calcParameters, options);
helper.setObjPredicate(obj, predicate, result, language, datatype);
}
}
})
);
}
};

Expand Down
8 changes: 8 additions & 0 deletions tests/nestedPredefinedFunctionMapping/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name":"Tom A.",
"age":15,
"sports": {
"School": "Tennis",
"Private":"Football"
}
}
Loading

0 comments on commit c4bc395

Please sign in to comment.