
be.ugent.rml.functions.FunctionLoader Maven / Gradle / Ivy
package be.ugent.rml.functions;
import be.ugent.rml.NAMESPACES;
import be.ugent.rml.functions.lib.IDLabFunctions;
import be.ugent.rml.store.RDF4JStore;
import be.ugent.rml.term.NamedNode;
import be.ugent.rml.term.Term;
import be.ugent.rml.Utils;
import be.ugent.rml.functions.lib.UtilFunctions;
import be.ugent.rml.store.QuadStore;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FunctionLoader {
private static final Logger logger = LoggerFactory.getLogger(FunctionLoader.class);
private final QuadStore functionDescriptionTriples;
// updated dynamically
/**
* Cache for loaded classes
*/
private Map classMap;
/**
* Cache for library paths
*/
private Map libraryMap;
/**
* Cache for loaded functions
*/
private Map loadedMethods;
public FunctionLoader() throws Exception {
this(null, null);
}
public FunctionLoader(QuadStore functionDescriptionTriples) throws Exception {
this(functionDescriptionTriples, null);
}
public FunctionLoader(QuadStore functionDescriptionTriples, Map libraryMap) throws Exception {
if (functionDescriptionTriples == null) {
functionDescriptionTriples = new RDF4JStore();
functionDescriptionTriples.read(Utils.getInputStreamFromFile(Utils.getFile("functions_idlab.ttl")), null, RDFFormat.TURTLE);
functionDescriptionTriples.read(Utils.getInputStreamFromFile(Utils.getFile("functions_grel.ttl")), null, RDFFormat.TURTLE);
functionDescriptionTriples.read(Utils.getInputStreamFromFile(Utils.getFile("grel_java_mapping.ttl")), null, RDFFormat.TURTLE);
}
this.functionDescriptionTriples = functionDescriptionTriples;
this.libraryMap = new HashMap<>();
if (libraryMap == null) {
this.classMap = new HashMap<>();
this.classMap.put("IDLabFunctions", IDLabFunctions.class);
this.classMap.put("io.fno.grel.ArrayFunctions", io.fno.grel.ArrayFunctions.class);
this.classMap.put("io.fno.grel.BooleanFunctions", io.fno.grel.BooleanFunctions.class);
this.classMap.put("io.fno.grel.ControlsFunctions", io.fno.grel.ControlsFunctions.class);
this.classMap.put("io.fno.grel.StringFunctions", io.fno.grel.StringFunctions.class);
this.libraryMap.put("IDLabFunctions", "__local");
this.libraryMap.put("io.fno.grel.ArrayFunctions", "__local");
this.libraryMap.put("io.fno.grel.BooleanFunctions", "__local");
this.libraryMap.put("io.fno.grel.ControlsFunctions", "__local");
this.libraryMap.put("io.fno.grel.StringFunctions", "__local");
} else {
this.classMap = libraryMap;
for (String key : libraryMap.keySet()) {
this.libraryMap.put(key, "__local");
}
}
this.classMap.put("UtilFunctions", UtilFunctions.class);
this.libraryMap.put("UtilFunctions", "__local");
this.loadedMethods = new HashMap<>();
}
public FunctionModel getFunction(Term iri) throws IOException {
if (!this.loadedMethods.containsKey(iri.getValue())) {
try {
findMethodOldWay(iri);
logger.warn("Found a function using the old `lib:` way, this is deprecated");
} catch (IOException e) {
findMethodNewWay(iri);
}
}
return this.loadedMethods.get(iri);
}
public String getLibraryPath(String className) {
return this.libraryMap.get(className);
}
private void findMethodOldWay(Term iri) throws IOException {
List libraries = Utils.getObjectsFromQuads(this.functionDescriptionTriples.getQuads(iri, new NamedNode(NAMESPACES.LIB + "providedBy"), null));
if (libraries.size() > 0) {
List pathNames = Utils.getObjectsFromQuads(this.functionDescriptionTriples.getQuads(libraries.get(0), new NamedNode(NAMESPACES.LIB + "localLibrary"), null));
List classes = Utils.getObjectsFromQuads(this.functionDescriptionTriples.getQuads(libraries.get(0), new NamedNode(NAMESPACES.LIB + "class"), null));
if (pathNames.size() > 0 && classes.size() > 0) {
String pathName = pathNames.get(0).getValue();
String className = classes.get(0).getValue();
Class cls;
if (this.classMap.containsKey(className)) {
cls = this.classMap.get(className);
} else {
File functionFile = Utils.getFile(pathName);
cls = FunctionUtils.functionRequire(functionFile, className);
this.classMap.put(className, cls);
this.libraryMap.put(className, functionFile.getCanonicalPath());
}
List parameters = new ArrayList<>();
List expectList = Utils.getObjectsFromQuads(FunctionUtils.getQuadsByFunctionPrefix(this.functionDescriptionTriples, iri, "expects", null));
if (expectList.size() > 0) {
parameters = Utils.getList(this.functionDescriptionTriples, expectList.get(0));
}
Class>[] orderedParameters = FunctionUtils.parseFunctionParameters(this.functionDescriptionTriples, parameters);
List methods = Utils.getObjectsFromQuads(this.functionDescriptionTriples.getQuads(libraries.get(0), new NamedNode(NAMESPACES.LIB + "method"), null));
List outputs = Utils.getList(this.functionDescriptionTriples, Utils.getObjectsFromQuads(FunctionUtils.getQuadsByFunctionPrefix(this.functionDescriptionTriples, iri, "returns", null)).get(0));
List fnParameterUris = FunctionUtils.getFunctionParameterUris(this.functionDescriptionTriples, parameters);
List fnOutputUris = FunctionUtils.getFunctionParameterUris(this.functionDescriptionTriples, outputs);
if (methods.size() > 0) {
Method fn = null;
try {
fn = cls.getMethod(methods.get(0).getValue(), orderedParameters);
} catch (NoSuchMethodException e) {
throw new IOException("Declared method " + methods.get(0) + " does not exist for class " + classes.get(0) + ".");
}
FunctionModel fnm = new FunctionModel(iri, fn, fnParameterUris, fnOutputUris);
this.loadedMethods.put(iri, fnm);
}
} else {
throw new IOException("No library or class was found for the function with IRI " + iri + " in the function descriptions.");
}
} else {
throw new IOException("No library or class was found for the function with IRI " + iri + " in the function descriptions.");
}
}
private void findMethodNewWay(Term iri) throws IOException {
List mappings = Utils.getSubjectsFromQuads(FunctionUtils.getQuadsByFunctionPrefix(this.functionDescriptionTriples, null, "function", iri));
if (mappings.size() == 0) {
throw new IOException("No mapping was found for the function with IRI " + iri + " in the function descriptions.");
}
List libraries = Utils.getObjectsFromQuads(FunctionUtils.getQuadsByFunctionPrefix(this.functionDescriptionTriples, mappings.get(0), "implementation", null));
if (libraries.size() == 0) {
throw new IOException("No library was found for the mapping with IRI " + mappings.get(0) + " in the function descriptions.");
}
List pathNames = Utils.getObjectsFromQuads(this.functionDescriptionTriples.getQuads(libraries.get(0), new NamedNode(NAMESPACES.DOAP + "download-page"), null));
List classes = Utils.getObjectsFromQuads(this.functionDescriptionTriples.getQuads(libraries.get(0), new NamedNode(NAMESPACES.FNOI + "class-name"), null));
if (pathNames.size() == 0 || classes.size() == 0) {
throw new IOException("No path or class found for the library with IRI " + libraries.get(0) + " in the function descriptions.");
}
String pathName = pathNames.get(0).getValue();
String className = classes.get(0).getValue();
Class cls;
if (this.classMap.containsKey(className)) {
cls = this.classMap.get(className);
} else {
File functionFile = Utils.getFile(pathName);
cls = FunctionUtils.functionRequire(functionFile, className);
this.classMap.put(className, cls);
this.libraryMap.put(className, functionFile.getCanonicalPath());
}
List parameters = new ArrayList<>();
List expectList = Utils.getObjectsFromQuads(FunctionUtils.getQuadsByFunctionPrefix(this.functionDescriptionTriples, iri, "expects", null));
if (expectList.size() > 0) {
parameters = Utils.getList(this.functionDescriptionTriples, expectList.get(0));
}
List outputs = Utils.getList(this.functionDescriptionTriples, Utils.getObjectsFromQuads(FunctionUtils.getQuadsByFunctionPrefix(this.functionDescriptionTriples, iri, "returns", null)).get(0));
List methodMappings = Utils.getObjectsFromQuads(FunctionUtils.getQuadsByFunctionPrefix(this.functionDescriptionTriples, mappings.get(0), "methodMapping", null));
if (methodMappings.size() == 0) {
throw new IOException("No methodmapping found for the mapping with IRI " + mappings.get(0) + " in the function descriptions.");
}
List methods = Utils.getObjectsFromQuads(this.functionDescriptionTriples.getQuads(methodMappings.get(0), new NamedNode(NAMESPACES.FNOM + "method-name"), null));
if (methods.size() == 0) {
throw new IOException("No method found for the mapping with IRI " + mappings.get(0) + " in the function descriptions.");
}
Class>[] orderedParameters = FunctionUtils.parseFunctionParameters(this.functionDescriptionTriples, parameters);
Method fn = null;
try {
fn = cls.getDeclaredMethod(methods.get(0).getValue(), orderedParameters);
} catch (NoSuchMethodException e) {
throw new IOException("Declared method " + methods.get(0) + " does not exist for class " + classes.get(0) + ".");
}
List fnParameterUris = FunctionUtils.getFunctionParameterUris(this.functionDescriptionTriples, parameters);
List fnOutputUris = FunctionUtils.getFunctionParameterUris(this.functionDescriptionTriples, outputs);
FunctionModel fnm = new FunctionModel(iri, fn, fnParameterUris, fnOutputUris);
this.loadedMethods.put(iri, fnm);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy