be.ugent.rml.functions.FunctionUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rmlmapper Show documentation
Show all versions of rmlmapper Show documentation
The RMLMapper executes RML rules to generate high quality Linked Data from multiple originally (semi-)structured data sources.
package be.ugent.rml.functions;
import be.ugent.rml.NAMESPACES;
import be.ugent.rml.Utils;
import be.ugent.rml.store.Quad;
import be.ugent.rml.store.QuadStore;
import be.ugent.rml.term.NamedNode;
import be.ugent.rml.term.Term;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.time.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FunctionUtils {
private static final Logger logger = LoggerFactory.getLogger(FunctionUtils.class);
public static Class functionRequire(File file, String className) throws IOException {
String path = file.getPath();
if (path.endsWith(".jar")) {
return FunctionUtils.getClass(file, className, "application/java-archive");
} else if (path.endsWith(".java")) {
return FunctionUtils.getClass(file, className, "text/x-java-source");
}
throw new IOException("Not a valid path for a JAVA implementation: " + path);
}
public static List getFunctionParameterUris(QuadStore store, List parameterResources) {
List parameterPredicates = new ArrayList<>();
for (Term subject : parameterResources) {
parameterPredicates.add(Utils.getObjectsFromQuads(getQuadsByFunctionPrefix(store, subject, "predicate", null)).get(0));
}
return parameterPredicates;
}
public static Class>[] parseFunctionParameters(QuadStore store, List parameterResources) {
Class>[] args = new Class>[parameterResources.size()];
for (int i = 0; i < parameterResources.size(); i++) {
Term subject = parameterResources.get(i);
Term type = Utils.getObjectsFromQuads(getQuadsByFunctionPrefix(store, subject, "type", null)).get(0);
try {
args[i] = FunctionUtils.getParamType(type);
} catch (Exception e) {
args[i] = String.class;
}
}
return args;
}
/**
* Generates strings from a function object. Possible lists/sets/bags/... in the object are unrolled recursively
* and a string value is generated from each "simple" (i.e., not a list/set/bag/...) child object.
*
* @param o Function object, can be iterable.
* @param result A string list to which string values of objects are added
*/
public static void functionObjectToList(Object o, List result) {
if (o != null) {
// if o has child objects, recursively call this function on each child
if (o instanceof Iterable>) {
((Iterable>) o).forEach(item -> {
functionObjectToList(item, result);
});
}
// if o has no children, call toString() to serialize it into a string
else {
// numeric and boolean types are trivially serialized correctly
// times/dates objects in the java.time package use the relevant ISO-8601 standard,
// which is also used by xsd types and thus RDF types
result.add(o.toString());
}
}
}
private static Class getParamType(Term type) {
String typeStr = type.getValue();
switch (typeStr) {
// This is quite crude, based on https://www.w3.org/TR/xmlschema11-2/#built-in-datatypes
case "http://www.w3.org/2001/XMLSchema#string":
return String.class;
case "http://www.w3.org/2001/XMLSchema#unsignedLong":
case "http://www.w3.org/2001/XMLSchema#long":
return Long.class;
case "http://www.w3.org/2001/XMLSchema#integer":
case "http://www.w3.org/2001/XMLSchema#int":
case "http://www.w3.org/2001/XMLSchema#short":
case "http://www.w3.org/2001/XMLSchema#byte":
case "http://www.w3.org/2001/XMLSchema#nonNegativeInteger":
case "http://www.w3.org/2001/XMLSchema#positiveInteger":
case "http://www.w3.org/2001/XMLSchema#unsignedInt":
case "http://www.w3.org/2001/XMLSchema#unsignedShort":
case "http://www.w3.org/2001/XMLSchema#unsignedByte":
case "http://www.w3.org/2001/XMLSchema#nonPositiveInteger":
case "http://www.w3.org/2001/XMLSchema#negativeInteger":
return Integer.class;
case "http://www.w3.org/2001/XMLSchema#date":
// "Local" just means "without a time zone"
return LocalDate.class;
case "http://www.w3.org/2001/XMLSchema#dateTime":
// again "Local" means "without a time zone"
// (An xsd:dateTime actually has an OPTIONAL time zone, so there is a small semantic difference
// with java.time.LocalDateTime, this is a best effort.)
return LocalDateTime.class;
case "http://www.w3.org/2001/XMLSchema#dateTimeStamp":
return ZonedDateTime.class;
case "http://www.w3.org/2001/XMLSchema#dayTimeDuration":
case "http://www.w3.org/2001/XMLSchema#yearMonthDuration":
return Duration.class;
case "http://www.w3.org/2001/XMLSchema#gDay":
// TODO there is no java.time equivalent of xsd:day
// (There is java.time.DayOfWeek, but xsd:day would corresponds to java.time.DayOfMonth .)
throw new DateTimeException("There is no java.time equivalent of xsd:day. Crashing.");
case "http://www.w3.org/2001/XMLSchema#gMonth":
return Month.class;
case "http://www.w3.org/2001/XMLSchema#gMonthDay":
return MonthDay.class;
case "http://www.w3.org/2001/XMLSchema#gYear":
return Year.class;
case "http://www.w3.org/2001/XMLSchema#gYearMonth":
return YearMonth.class;
case "http://www.w3.org/2001/XMLSchema#decimal":
case "http://www.w3.org/2001/XMLSchema#double":
case "http://www.w3.org/2001/XMLSchema#float":
return Double.class;
case "http://www.w3.org/1999/02/22-rdf-syntax-ns#List":
return List.class;
default:
throw new Error("Couldn't derive type from " + type);
}
}
private static Class getClass(File sourceFile, String className, String mime) throws IOException {
logger.info("Found class on path " + sourceFile.getCanonicalPath());
switch (mime) {
case "text/x-java-source":
return FunctionUtils.getClassFromJAVA(sourceFile, className);
case "application/java-archive":
return FunctionUtils.getClassFromJAR(sourceFile, className);
}
return null;
}
private static Class getClassFromJAVA(File sourceFile, String className) {
Class> cls = null;
// TODO let's not recompile every time
// Compile source file.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int res = compiler.run(null, null, null, sourceFile.getPath());
if (res != 0) {
return null;
}
// Load and instantiate compiled class.
URLClassLoader classLoader = null;
try {
classLoader = URLClassLoader.newInstance(new URL[]{(new File(sourceFile.getParent())).toURI().toURL()});
cls = Class.forName(className, true, classLoader);
} catch (MalformedURLException | ClassNotFoundException e) {
e.printStackTrace();
}
return cls;
}
private static Class getClassFromJAR(File sourceFile, String className) {
Class> cls = null;
URLClassLoader child = null;
try {
child = URLClassLoader.newInstance(new URL[]{sourceFile.toURI().toURL()});
cls = Class.forName(className, true, child);
} catch (MalformedURLException | ClassNotFoundException e) {
e.printStackTrace();
}
return cls;
}
/**
* Retrieve triples of a store based on a predicate, taking into account deprecated FnO prefixed predicates
* @param store The triple store to retrieve the triples from
* @param s the subject
* @param functionTerm the unprefixed function term
* @param o the object
* @return the quads that are conform to the triple pattern fragment
*/
static List getQuadsByFunctionPrefix(QuadStore store, Term s, String functionTerm, Term o) {
List prefices = Arrays.asList(NAMESPACES.FNO_S, NAMESPACES.FNO, NAMESPACES.FNO_OLD);
return getQuadsByPrefix(store, s, functionTerm, o, prefices);
}
/**
* Retrieve triples of a store based on a predicate, taking into account multiple prefixes
* @param store The triple store to retrieve the triples from
* @param s the subject
* @param pString the unprefixed predicate term
* @param o the object
* @param prefices the list of prefices on which to look for, in order of 'correctness' (all prefixes except for the first one are assumed deprecated)
* @return the quads that are conform to the triple pattern fragment
*/
private static List getQuadsByPrefix(QuadStore store, Term s, String pString, Term o, List prefices) {
String preferredPrefix = prefices.get(0);
Term realTerm;
List quads = new ArrayList<>();
for (int i = 0; i < prefices.size(); i++) {
realTerm = new NamedNode(prefices.get(i) + pString);
quads = store.getQuads(s, realTerm, o);
if (quads.size() > 0) {
if (i != 0) {
logger.warn(prefices.get(i) + "is a deprecated prefix, please use " + preferredPrefix);
}
return quads;
}
}
return quads;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy