I am trying to use FnO functions in RML mapper (I like to do a string_split
like here).
This is how my folder looks like:
I am executing java -jar "rmlmapper.jar" -m mapping-cuisines.ttl -o output-cuisines.ttl -s turtle
However, when I try implementing a <#FunctionMap>
i get the following error message:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:458)
at be.ugent.rml.functions.DynamicMultipleRecordsFunctionExecutor.execute(DynamicMultipleRecordsFunctionExecutor.java:66)
at be.ugent.rml.functions.AbstractSingleRecordFunctionExecutor.execute(AbstractSingleRecordFunctionExecutor.java:17)
at be.ugent.rml.termgenerator.LiteralGenerator.generate(LiteralGenerator.java:42)
at be.ugent.rml.Executor.generatePredicateObjectGraphs(Executor.java:157)
at be.ugent.rml.Executor.executeWithFunction(Executor.java:115)
at be.ugent.rml.Executor.execute(Executor.java:76)
at be.ugent.rml.cli.Main.main(Main.java:206)
Nothing makes sense to me. According to the git repo, the functions are loaded dynamically from where i execute the rmlmapper.
Dataset: https://mega.nz/file/LsJAQRaR#84lfASPXVA08zm0RbuRfNvR7tx-vklS82D1KBGhhdA8
My Code:
@base <http://example.org/data> .
@prefix ex: <http://example.org/ns#> .
@prefix rr: <http://www.w3.org/ns/r2rml#> .
@prefix rml: <http://semweb.mmlab.be/ns/rml#> .
@prefix ql: <http://semweb.mmlab.be/ns/ql#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix csvw: <http://www.w3.org/ns/csvw#> .
@prefix fnml: <http://semweb.mmlab.be/ns/fnml#> .
@prefix fno: <https://w3id.org/function/ontology#> .
@prefix grel: <http://users.ugent.be/~bjdmeest/function/grel.ttl#> .
<#LogicalSource>
a rml:LogicalSource;
rml:source "dataworld-restaurants-cuisines.csv";
rml:referenceFormulation ql:CSV.
<#MyTriplesMap>
a rr:TriplesMap;
rml:logicalSource <#LogicalSource>;
rr:subjectMap [
rr:template "http://example.org/{id}";
];
rr:predicateObjectMap [
rr:predicate ex:aProperty;
rr:objectMap <#FunctionMap>;
].
<#FunctionMap>
fnml:functionValue [
rml:logicalSource <#LogicalSource> ;
rr:predicateObjectMap [
rr:predicate fno:executes ;
rr:objectMap [ rr:constant grel:toUpperCase ]
] ;
rr:predicateObjectMap [
rr:predicate grel:valueParameter ;
rr:objectMap [
rml:reference "spicy"
]
]
] .
My functions.ttl:
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix fno: <https://w3id.org/function/ontology#> .
@prefix fnoi: <https://w3id.org/function/vocabulary/implementation#> .
@prefix fnom: <https://w3id.org/function/vocabulary/mapping#> .
@prefix grel: <http://users.ugent.be/~bjdmeest/function/grel.ttl#> .
@prefix grelm: <http://fno.io/grel/rmlmapping#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
grel:toUpperCase a fno:Function ;
fno:name "to Uppercase" ;
rdfs:label "to Uppercase" ;
dcterms:description "Returns the input with all letters in upper case." ;
fno:expects ( grel:valueParam ) ;
fno:returns ( grel:stringOut ) .
grelm:javaString
a fnoi:JavaClass ;
doap:download-page "GrelFunctions.jar" ;
fnoi:class-name "io.fno.grel.StringFunctions" .
grelm:uppercaseMapping
a fnoi:Mapping ;
fno:function grel:toUpperCase ;
fno:implementation grelm:javaString ;
fno:methodMapping [ a fnom:StringMethodMapping ;
fnom:method-name "toUppercase" ] .
I tried out your mapping file and it works correctly. Your current mapping file transforms the data in the
spicy
to upper case and generates the specified RDF triples. Since the functiongrel:toUpperCase
is included in the RMLMapper by default, you don't need tofunctions.ttl
to specify these functions. This is only necessary if you want to add your own custom functions. An overview of all included functions in the RMLMapper can be found here: https://rml.io/docs/rmlmapper/default-functions/Given example
java -jar <path to jar> -m mapping.rml.ttl
mapping.rml.ttl
Output (truncated)
FnO string_split
If you want to use a FnO's
string_split
in RML, you can achieve it like this:fno:executes
:grel:string_split
to use the GREL split function.grel:valueParameter
: the input string you want to split. I referenced here to the CSV columncuisines
.grel:p_string_sep
: the string separator on which the GREL split function must split the input string. I used,
here to separate the different cuisines for each restaurant.mapping.rml.ttl
Output (truncated)
Note: I work on RML and FnO technologies