Skip to content

Commit

Permalink
Merge pull request #70 from oeg-upm/blank-node-implementation
Browse files Browse the repository at this point in the history
supporting blank nodes with data reference
  • Loading branch information
dachafra authored Dec 5, 2023
2 parents da6e9c0 + ea60c41 commit 75b4e3a
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 9 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.1.1
3 changes: 3 additions & 0 deletions src/yatter/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
R2RML_TERMTYPE = 'rr:termType'
R2RML_LANGUAGE = 'rr:language'
R2RML_IRI = 'rr:IRI'
R2RML_BLANK_NODE = 'rr:BlankNode'
R2RML_LITERAL = 'rr:Literal'
R2RML_REFOBJECT_CLASS = 'rr:RefObjectMap'
R2RML_PARENT_TRIPLESMAP = 'rr:parentTriplesMap'
Expand All @@ -92,6 +93,7 @@
R2RML_TABLE_NAME = 'rr:tableName'
R2RML_COLUMN = 'rr:column'


##############################################################################
############################# D2RQ CONSTANTS ###########################
##############################################################################
Expand Down Expand Up @@ -154,6 +156,7 @@

YARRRML_IRI = '~iri'
YARRRML_LANG = '~lang'
YARRRML_BLANK = 'blank'

YARRRML_QUOTED = 'quoted'
YARRRML_NON_ASSERTED = 'quotedNonAsserted'
Expand Down
12 changes: 11 additions & 1 deletion src/yatter/predicateobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,15 @@ def add_predicate_object(data, mapping, predicate_object, mapping_format=RML_URI

for om in object_list:
iri = False
blank = False
if type(om) == list:
object_value = om[0]
if YARRRML_IRI in om[0]:
object_value = om[0].split(YARRRML_IRI)[0]
object_value = om[0].split("~")[0]
iri = True
if YARRRML_BLANK in om[0]:
object_value = om[0].split("~")[0]
blank = True
if mapping_format == STAR_URI:
template += generate_rml_termmap(STAR_OBJECT, R2RML_OBJECT_CLASS,
object_value, "\t\t\t", mapping_format)
Expand Down Expand Up @@ -195,6 +199,9 @@ def add_predicate_object(data, mapping, predicate_object, mapping_format=RML_URI
if iri:
template = template[0:len(template) - 5] + "\t\t\t" + R2RML_TERMTYPE + " " \
+ R2RML_IRI + "\n\t\t];\n"
if blank:
template = template[0:len(template) - 5] + "\t\t\t" + R2RML_TERMTYPE + " " \
+ R2RML_BLANK_NODE + "\n\t\t];\n"
elif YARRRML_MAPPING in om or YARRRML_NON_ASSERTED in om or YARRRML_QUOTED in om:
if YARRRML_MAPPING in om:
template += ref_mapping(data, mapping, om, YARRRML_MAPPING, R2RML_PARENT_TRIPLESMAP, mapping_format)
Expand Down Expand Up @@ -236,6 +243,9 @@ def add_predicate_object(data, mapping, predicate_object, mapping_format=RML_URI
elif om.get(YARRRML_TYPE) == "literal":
template = template[0:len(template) - 5] + "\t\t\t" + R2RML_TERMTYPE + " " \
+ R2RML_LITERAL + "\n\t\t];\n"
elif om.get(YARRRML_TYPE) == YARRRML_BLANK:
template = template[0:len(template) - 5] + "\t\t\t" + R2RML_TERMTYPE + " " \
+ R2RML_BLANK_NODE + "\n\t\t];\n"
if YARRRML_TARGETS in om:
template = template[0:len(template) - 5] + "\t\t\t" + RML_LOGICAL_TARGET + " <"+ om.get(YARRRML_TARGETS) + ">\n\t\t];\n"

Expand Down
4 changes: 4 additions & 0 deletions src/yatter/subject.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ def add_subject(data, mapping, mapping_format):
if YARRRML_TARGETS in individual_subject:
subject_termmap = subject_termmap[0:-3]+"\t"+RML_LOGICAL_TARGET+" <"+individual_subject[YARRRML_TARGETS]+">\n\t];\n"

if YARRRML_TYPE in individual_subject:
if individual_subject.get(YARRRML_TYPE) == YARRRML_BLANK:
subject_termmap = subject_termmap[0:-3] + "\t" + R2RML_TERMTYPE + " " + R2RML_BLANK_NODE +"\n\t];\n"

rml_subjects.append(subject_termmap)

if YARRRML_GRAPHS in data.get(YARRRML_MAPPINGS).get(mapping):
Expand Down
14 changes: 7 additions & 7 deletions src/yatter/termmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ def get_termmap_type(text, mapping_format):


## Generates a TermMap (subject, predicate, object) based on the property, class and the text
def generate_rml_termmap(rml_property, rml_class, text, identation, mapping_format=RML_URI):
template = identation[0:-1] + rml_property + " [\n"+identation+"a " + rml_class + ";\n" + identation
def generate_rml_termmap(rml_property, rml_class, text, indentation, mapping_format=RML_URI):
template = indentation[0:-1] + rml_property + " [\n"+indentation+"a " + rml_class + ";\n" + indentation
term_map = get_termmap_type(text, mapping_format)
if term_map == R2RML_TEMPLATE:
text = generate_rml_template(text)
Expand All @@ -32,16 +32,16 @@ def generate_rml_termmap(rml_property, rml_class, text, identation, mapping_form

if term_map == STAR_QUOTED:
if 'quoted' in text:
template += term_map + " <" + text[YARRRML_QUOTED] + "_0>;\n" + identation[0:-1] + "];\n"
template += term_map + " <" + text[YARRRML_QUOTED] + "_0>;\n" + indentation[0:-1] + "];\n"
else:
template += term_map + " <" + text[YARRRML_NON_ASSERTED] + "_0>;\n" + identation[0:-1] + "];\n"
template += term_map + " <" + text[YARRRML_NON_ASSERTED] + "_0>;\n" + indentation[0:-1] + "];\n"
elif term_map != "rr:constant":
template += term_map + " \"" + text + "\";\n"+identation[0:-1]+"];\n"
template += term_map + " \"" + text + "\";\n"+indentation[0:-1]+"];\n"
else:
if text.startswith("http"):
template += term_map + " <" + text + ">;\n" + identation[0:-1] + "];\n"
template += term_map + " <" + text + ">;\n" + indentation[0:-1] + "];\n"
else:
template += term_map + " " + text + ";\n"+identation[0:-1]+"];\n"
template += term_map + " " + text + ";\n"+indentation[0:-1]+"];\n"

return template

Expand Down
57 changes: 57 additions & 0 deletions test/r2rml/YARRRMLTC-r2rml-0016/mapping.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix ex: <http://example.com/>.
@prefix rr: <http://www.w3.org/ns/r2rml#>.
@prefix rml: <http://semweb.mmlab.be/ns/rml#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix ql: <http://semweb.mmlab.be/ns/ql#>.
@prefix d2rq: <http://www.wiwiss.fu-berlin.de/suhl/bizer/D2RQ/0.1#>.
@prefix schema: <http://schema.org/>.
@prefix formats: <http://www.w3.org/ns/formats/>.
@prefix comp: <http://semweb.mmlab.be/ns/rml-compression#>.
@prefix void: <http://rdfs.org/ns/void#>.
@prefix fnml: <http://semweb.mmlab.be/ns/fnml#>.
@prefix grel: <http://users.ugent.be/~bjdmeest/function/grel.ttl#>.
@base <http://example.com/ns#>.


<TriplesMap1_0> a rr:TriplesMap;

rr:logicalTable [
a rr:LogicalTable;
rr:tableName "Student";
rr:sqlVersion rr:SQL2008
];
rr:subjectMap [
a rr:SubjectMap;
rr:column "Name";
rr:termType rr:BlankNode
];
rr:predicateObjectMap [
rr:predicateMap [
a rr:PredicateMap;
rr:constant rdf:type;
];
rr:objectMap [
a rr:ObjectMap;
rr:constant foaf:Person;
];
rr:objectMap [
a rr:ObjectMap;
rr:constant ex:Student;
];
];
rr:predicateObjectMap [
rr:predicateMap [
a rr:PredicateMap;
rr:constant foaf:Name;
];
rr:objectMap [
a rr:ObjectMap;
rr:column "Name";
rr:termType rr:BlankNode
];
].


19 changes: 19 additions & 0 deletions test/r2rml/YARRRMLTC-r2rml-0016/mapping.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
prefixes:
foaf: http://xmlns.com/foaf/0.1/
rdfs: http://www.w3.org/2000/01/rdf-schema#
ex: http://example.com/

mappings:
TriplesMap1:
sources:
- table: Student
s:
value: $(Name)
type: blank
po:
- p: rdf:type
o: [foaf:Person, ex:Student]
- p: foaf:Name
o:
value: $(Name)
type: blank
27 changes: 27 additions & 0 deletions test/r2rml/YARRRMLTC-r2rml-0016/test_yarrrmltc_r2rml_0016.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
__author__ = "Marino Gonzalez Garcia"
__credits__ = ["Marino Gonzalez Garcia"]

__license__ = "Apache-2.0"
__maintainer__ = "David Chaves-Fraga"
__email__ = "david.chaves@upm.es"


import os
from ruamel.yaml import YAML
import yatter
from rdflib.graph import Graph
from rdflib import compare
R2RML_URI = 'http://www.w3.org/ns/r2rml#'


def test_r2rml_yarrrmltc0016():
expected_mapping = Graph()
expected_mapping.parse(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mapping.ttl'), format="ttl")

translated_mapping = Graph()
yaml = YAML(typ='safe', pure=True)
mapping_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mapping.yml')
translated_mapping.parse(data=yatter.translate(yaml.load(open(mapping_path)), mapping_format=R2RML_URI), format="ttl")
translated_mapping.serialize(destination="mapping.rml.ttl",format="ttl")

assert compare.isomorphic(expected_mapping, translated_mapping)

0 comments on commit 75b4e3a

Please sign in to comment.