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 function grel:toUpperCase
is included in the RMLMapper by default,
you don't need to functions.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/
java -jar <path to jar> -m mapping.rml.ttl
mapping.rml.ttl
@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"
]
]
] .
Output (truncated)
<http://example.org/afghani> <http://example.org/ns#aProperty> "NO".
<http://example.org/african> <http://example.org/ns#aProperty> "YES".
<http://example.org/african_portuguese> <http://example.org/ns#aProperty> "YES".
<http://example.org/american> <http://example.org/ns#aProperty> "NO".
<http://example.org/andhra> <http://example.org/ns#aProperty> "YES".
<http://example.org/arabian> <http://example.org/ns#aProperty> "NO".
<http://example.org/arabian_lebanese> <http://example.org/ns#aProperty> "NO".
<http://example.org/arabian_mexican> <http://example.org/ns#aProperty> "NO".
<http://example.org/arabian_middle_eastern> <http://example.org/ns#aProperty> "YES".
<http://example.org/asian> <http://example.org/ns#aProperty> "YES".
<http://example.org/assamese> <http://example.org/ns#aProperty> "NO".
<http://example.org/australian> <http://example.org/ns#aProperty> "YES".
<http://example.org/awadhi> <http://example.org/ns#aProperty> "YES".
<http://example.org/awadhi_mughlai> <http://example.org/ns#aProperty> "NO".
<http://example.org/bakery> <http://example.org/ns#aProperty> "NO".
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 column cuisines
.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
@base <http://example.org> .
@prefix rml: <http://semweb.mmlab.be/ns/rml#> .
@prefix rr: <http://www.w3.org/ns/r2rml#> .
@prefix ql: <http://semweb.mmlab.be/ns/ql#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@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#> .
@prefix ex: <http://example.org/ns#> .
<#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:cuisine;
rr:objectMap <#FunctionMap>;
];
.
<#FunctionMap>
fnml:functionValue [
rml:logicalSource <#LogicalSource>;
rr:predicateObjectMap [
rr:predicate fno:executes;
rr:objectMap [
rr:constant grel:string_split
];
];
rr:predicateObjectMap [
rr:predicate grel:valueParameter;
rr:objectMap [
rml:reference "cuisines"
];
];
rr:predicateObjectMap [
rr:predicate grel:p_string_sep;
rr:objectMap [
rr:constant ", ";
];
];
].
Output (truncated)
<http://example.org/afghani> <http://example.org/ns#cuisine> "Afghani".
<http://example.org/african> <http://example.org/ns#cuisine> "African".
<http://example.org/african_portuguese> <http://example.org/ns#cuisine> "African".
<http://example.org/african_portuguese> <http://example.org/ns#cuisine> "Portuguese".
<http://example.org/american> <http://example.org/ns#cuisine> "american".
<http://example.org/andhra> <http://example.org/ns#cuisine> "Andhra".
<http://example.org/arabian> <http://example.org/ns#cuisine> "Arabian".
<http://example.org/arabian_lebanese> <http://example.org/ns#cuisine> "Arabian".
<http://example.org/arabian_lebanese> <http://example.org/ns#cuisine> "Lebanese".
<http://example.org/arabian_mexican> <http://example.org/ns#cuisine> "Arabian".
<http://example.org/arabian_mexican> <http://example.org/ns#cuisine> "Mexican".
<http://example.org/arabian_middle_eastern> <http://example.org/ns#cuisine> "Arabian".
<http://example.org/arabian_middle_eastern> <http://example.org/ns#cuisine> "Middle Eastern".
<http://example.org/asian> <http://example.org/ns#cuisine> "Asian".
<http://example.org/assamese> <http://example.org/ns#cuisine> "Assamese".
<http://example.org/australian> <http://example.org/ns#cuisine> "Australian".
<http://example.org/awadhi> <http://example.org/ns#cuisine> "Awadhi".
<http://example.org/awadhi_mughlai> <http://example.org/ns#cuisine> "Awadhi".
<http://example.org/awadhi_mughlai> <http://example.org/ns#cuisine> "Mughlai".
<http://example.org/bakery> <http://example.org/ns#cuisine> "bakery".
<http://example.org/bar_food> <http://example.org/ns#cuisine> "Bar Food".
<http://example.org/bar_food_brazilian> <http://example.org/ns#cuisine> "Bar Food".
<http://example.org/bar_food_brazilian> <http://example.org/ns#cuisine> "Brazilian".
Note: I work on RML and FnO technologies