RMLio / yarrrml-parser

A YARRRML parser library and CLI in Javascript
MIT License
43 stars 17 forks source link

Implement rr:class on rml subject maps #65

Closed w0xter closed 4 years ago

w0xter commented 4 years ago

Issue type: :unicorn: Feature

Implement rr:class on rml subject maps

Also it will be very useful if you implement all of this into R2RML translation.

If we have a yarrrml mapping like this:

prefixes:
  ex: http://example.com
mappings:
  person:
    sources:
      - ['./data.csv~csv']
    s: ex:PersonInfo#$(id)
    po:
      - [a,ex:Person]
      - [ex:Name,$(name)]
      - [ex:Role,$(role)]

the result of yarrrml-parser is this:

@prefix rr: <http://www.w3.org/ns/r2rml#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix fnml: <http://semweb.mmlab.be/ns/fnml#>.
@prefix fno: <https://w3id.org/function/ontology#>.
@prefix d2rq: <http://www.wiwiss.fu-berlin.de/suhl/bizer/D2RQ/0.1#>.
@prefix rml: <http://semweb.mmlab.be/ns/rml#>.
@prefix ql: <http://semweb.mmlab.be/ns/ql#>.
@prefix : <http://mapping.example.com/>.
@prefix ex: <http://example.com>.

:map_person_0 rml:logicalSource :source_0.
:source_0 a rml:LogicalSource;
    rml:source "data.csv";
    rml:referenceFormulation ql:CSV.
:map_person_0 a rr:TriplesMap;
    rdfs:label "person".
:s_0 a rr:SubjectMap.
:map_person_0 rr:subjectMap :s_0.
:s_0 rr:template "http://example.comPersonInfo#{id}".
:pom_0 a rr:PredicateObjectMap.
:map_person_0 rr:predicateObjectMap :pom_0.
:pm_0 a rr:PredicateMap.
:pom_0 rr:predicateMap :pm_0.
:pm_0 rr:constant rdf:type.
:pom_0 rr:objectMap :om_0.
:om_0 a rr:ObjectMap;
    rr:constant "http://example.comPerson";
    rr:termType rr:IRI.
:pom_1 a rr:PredicateObjectMap.
:map_person_0 rr:predicateObjectMap :pom_1.
:pm_1 a rr:PredicateMap.
:pom_1 rr:predicateMap :pm_1.
:pm_1 rr:constant ex:Name.
:pom_1 rr:objectMap :om_1.
:om_1 a rr:ObjectMap;
    rml:reference "name";
    rr:termType rr:Literal.
:pom_2 a rr:PredicateObjectMap.
:map_person_0 rr:predicateObjectMap :pom_2.
:pm_2 a rr:PredicateMap.
:pom_2 rr:predicateMap :pm_2.
:pm_2 rr:constant ex:Role.
:pom_2 rr:objectMap :om_2.
:om_2 a rr:ObjectMap;
    rml:reference "role";
    rr:termType rr:Literal.

But some OBDA engines like Morph-CSV requires to specify the subject rr:class to work properly, due to this I can't automate process like Virtual Knowledge Graph Generation using YARRRML mappings because I have to generate the RML mapping then stop the process, add the rr:class and finally trigger the OBDA engine. The final RML that I've use was this:

@prefix rr: <http://www.w3.org/ns/r2rml#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix fnml: <http://semweb.mmlab.be/ns/fnml#>.
@prefix fno: <https://w3id.org/function/ontology#>.
@prefix d2rq: <http://www.wiwiss.fu-berlin.de/suhl/bizer/D2RQ/0.1#>.
@prefix rml: <http://semweb.mmlab.be/ns/rml#>.
@prefix ql: <http://semweb.mmlab.be/ns/ql#>.
@prefix : <http://mapping.example.com/>.
@prefix ex: <http://example.com>.

:map_person_0 rml:logicalSource :source_0.
:source_0 a rml:LogicalSource;
    rml:source "data.csv";
    rml:referenceFormulation ql:CSV.
:map_person_0 a rr:TriplesMap;
    rdfs:label "person".
:s_0 a rr:SubjectMap.
:map_person_0 rr:subjectMap :s_0.
:s_0 rr:template "http://example.comPersonInfo#{id}".
:s_0 rr:class ex:Person. 
:pom_0 a rr:PredicateObjectMap.
:map_person_0 rr:predicateObjectMap :pom_0.
:pm_0 a rr:PredicateMap.
:pom_0 rr:predicateMap :pm_0.
:pm_0 rr:constant rdf:type.
:pom_0 rr:objectMap :om_0.
:om_0 a rr:ObjectMap;
    rr:constant "http://example.comPerson";
    rr:termType rr:IRI.
:pom_1 a rr:PredicateObjectMap.
:map_person_0 rr:predicateObjectMap :pom_1.
:pm_1 a rr:PredicateMap.
:pom_1 rr:predicateMap :pm_1.
:pm_1 rr:constant ex:Name.
:pom_1 rr:objectMap :om_1.
:om_1 a rr:ObjectMap;
    rml:reference "name";
    rr:termType rr:Literal.
:pom_2 a rr:PredicateObjectMap.
:map_person_0 rr:predicateObjectMap :pom_2.
:pm_2 a rr:PredicateMap.
:pom_2 rr:predicateMap :pm_2.
:pm_2 rr:constant ex:Role.
:pom_2 rr:objectMap :om_2.
:om_2 a rr:ObjectMap;
    rml:reference "role";
    rr:termType rr:Literal.

The modification is easy you only have to add the rdf:type of the yarrml TriplesMap to the corresponding RML subjectMap, in this case :s_0 rr:class ex:Person. but broke the flow of my application and causes problems if we want to standardize the use of YARRRML instead of RML.

Thaks for your time, you did a great work guys!!

pheyvaer commented 4 years ago

Hi @w0xter

Thanks for the issue. The output generated by the parser is valid RML. Is the issue then not caused by Morph-CSV?

dachafra commented 4 years ago

hey @pheyvaer! Yes, we know that the RML generated is valid, and also is parseable by Morph-CSV as it follows the RML specification. What we would like to ask is if there is any reason why yarrrml does not transform the [rdf:type, class] POMs using the rr:class property of [R2]RML. This property is used by these OBDA engines for some steps such as reasoning or efficient query translation.

In summary, the "semantics" of one option or the other is exactly the same, but it's mostly a technical issue that we are having using the yarrrrml-parser over these engines, bc they need to have explicitly defined the rr:class property in the mapping (and we are solving it manually right now).

pheyvaer commented 4 years ago

Hi @dachafra

The reason is that rr:class is sugar syntax meant for humans and thus in our opinion does not belong in [R2]RML. However, what you can do automatically though is reading the generated RML rules and add the rr:class based on a Predicate Object Map with rdf:type as predicate. That would actually be the fastest I think :smile:

dachafra commented 4 years ago

I completely agree with you about the syntactic sugar issue of the rr:class ;-) Thanks for your rapid answers !