Skip to content

Commit

Permalink
add datatyping
Browse files Browse the repository at this point in the history
  • Loading branch information
MBueschelberger committed Oct 24, 2024
1 parent 13e6fd7 commit 29a0f0c
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 22 deletions.
68 changes: 55 additions & 13 deletions data2rdf/models/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
model_validator,
)

from data2rdf.models.base import BasicGraphModel, BasicSuffixModel
from data2rdf.qudt.utils import _get_query_match
from data2rdf.utils import is_bool, is_float, is_integer, is_uri, make_prefix

from .base import BasicGraphModel, BasicSuffixModel
from data2rdf.warnings import MappingMissmatchWarning


class ValueRelationMapping(BaseModel):
Expand Down Expand Up @@ -56,12 +56,12 @@ class ClassTypeGraph(BasicGraphModel):
@classmethod
def value_json(cls, value) -> "Dict[str, Any]":
"""Return json with value definition"""
if is_float(value):
dtype = "xsd:float"
value = float(value)
elif is_integer(value):
if is_integer(value):
dtype = "xsd:integer"
value = int(value)
elif is_float(value):
dtype = "xsd:float"
value = float(value)
elif is_bool(value):
dtype = "xsd:bool"
value = bool(value)
Expand Down Expand Up @@ -192,12 +192,12 @@ def unit_json(self) -> "Dict[str, Any]":
def value_json(self) -> "Dict[str, Any]":
"""Return json with value definition"""
if self.value:
if is_float(self.value):
dtype = "xsd:float"
value = float(self.value)
elif is_integer(self.value):
if is_integer(self.value):
dtype = "xsd:integer"
value = int(self.value)
elif is_float(self.value):
dtype = "xsd:float"
value = float(self.value)
elif is_bool(self.value):
dtype = "xsd:bool"
value = bool(self.value)
Expand Down Expand Up @@ -273,9 +273,51 @@ def json_ld(cls) -> Dict[str, Any]:
}

@property
def value_json(cls) -> "Optional[Dict[str, str]]":
if not isinstance(cls.value, type(None)):
response = {cls.value_relation: cls.value}
def value_json(self) -> "Optional[Dict[str, str]]":
if not isinstance(self.value, type(None)):
if not self.datatype:
if is_integer(self.value):
dtype = "xsd:integer"
value = int(self.value)
elif is_float(self.value):
dtype = "xsd:float"
value = float(self.value)
elif is_bool(self.value):
dtype = "xsd:bool"
value = bool(self.value)
elif is_uri(self.value):
dtype = "xsd:anyURI"
value = str(self.value)
else:
warnings.warn(
f"""Datatype not recognized for concept with iri
`{self.iri}` and value:
`{self.value}`. Will be set to string""",
MappingMissmatchWarning,
)
value = str(self.value)
dtype = "xsd:string"
else:
dtype = f"xsd:{self.datatype}"
if dtype == "xsd:anyURI":
value = str(self.value)
elif dtype == "xsd:bool":
value = bool(self.value)
elif dtype == "xsd:integer":
value = int(self.value)
elif dtype == "xsd:float":
value = float(self.value)
elif dtype == "xsd:string":
value = str(self.value)
else:
raise ValueError(
f"""Datatype not recognized for concept with iri
`{self.iri}` and value:
`{self.value}`"""
)

response = {self.value_relation: {"@type": dtype, "@value": value}}

else:
response = {}
return response
Expand Down
1 change: 1 addition & 0 deletions data2rdf/parsers/excel.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ def _run_parser(
value=value,
iri=datum.iri,
suffix=suffix,
datatype=relation.object_data_type,
config=self.config,
)
self._general_metadata.append(model)
Expand Down
1 change: 1 addition & 0 deletions data2rdf/parsers/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ def _make_custom_relation(
value=value,
iri=datum.iri,
suffix=suffix,
datatype=relation.object_data_type,
config=self.config,
)
self._general_metadata.append(model)
Expand Down
147 changes: 138 additions & 9 deletions tests/abox/json_custom_relations/test_json_custom_relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,37 @@
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ns2: <https://w3id.org/emmo/domain/domain-nanoindentation/nanoindentation#> .
@prefix ns3: <https://w3id.org/steel/ProcessOntology/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ns2:Jane a ns1:Operator ;
foaf:name "Jane" ;
foaf:age 28 ;
ns3:hasLaboratory 123 .
foaf:name "Jane"^^xsd:string ;
foaf:age "28"^^xsd:integer ;
ns3:hasLaboratory "123"^^xsd:integer .
ns2:John a ns1:Operator ;
foaf:name "John" ;
foaf:age 32 ;
ns3:hasLaboratory 345 .
foaf:name "John"^^xsd:string ;
foaf:age "32"^^xsd:integer ;
ns3:hasLaboratory "345"^^xsd:integer .
"""

EXPECTED_DATATYPE = """
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix ns1: <https://w3id.org/emmo/domain/characterisation-methodology/chameo#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ns2: <https://w3id.org/emmo/domain/domain-nanoindentation/nanoindentation#> .
@prefix ns3: <https://w3id.org/steel/ProcessOntology/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ns2:Jane a ns1:Operator ;
foaf:name "Jane"^^xsd:string ;
foaf:age "28"^^xsd:string ;
ns3:hasLaboratory "123"^^xsd:string .
ns2:John a ns1:Operator ;
foaf:name "John"^^xsd:string ;
foaf:age "32"^^xsd:string ;
ns3:hasLaboratory "345"^^xsd:string .
"""

MAPPING_WILDCARD = [
{
Expand Down Expand Up @@ -99,13 +118,124 @@
},
]


MAPPING_WILDCARD_DATATYPE = [
{
"iri": "https://w3id.org/emmo/domain/characterisation-methodology/chameo#Operator",
"suffix": "name",
"source": "data[*]",
"suffix_from_location": True,
"custom_relations": [
{
"object_location": "name",
"relation": "http://xmlns.com/foaf/0.1/name",
"object_data_type": "string",
},
{
"object_location": "age",
"relation": "http://xmlns.com/foaf/0.1/age",
"object_data_type": "string",
},
{
"object_location": "lab_no",
"relation": "https://w3id.org/steel/ProcessOntology/hasLaboratory",
"object_data_type": "string",
},
],
}
]

MAPPING_INDEX_DATATYPE = [
{
"iri": "https://w3id.org/emmo/domain/characterisation-methodology/chameo#Operator",
"suffix": "data[0].name",
"suffix_from_location": True,
"custom_relations": [
{
"object_location": "data[0].name",
"relation": "http://xmlns.com/foaf/0.1/name",
"object_data_type": "string",
},
{
"object_location": "data[0].age",
"relation": "http://xmlns.com/foaf/0.1/age",
"object_data_type": "string",
},
{
"object_location": "data[0].lab_no",
"relation": "https://w3id.org/steel/ProcessOntology/hasLaboratory",
"object_data_type": "string",
},
],
},
{
"iri": "https://w3id.org/emmo/domain/characterisation-methodology/chameo#Operator",
"suffix": "data[1].name",
"suffix_from_location": True,
"custom_relations": [
{
"object_location": "data[1].name",
"relation": "http://xmlns.com/foaf/0.1/name",
"object_data_type": "string",
},
{
"object_location": "data[1].age",
"relation": "http://xmlns.com/foaf/0.1/age",
"object_data_type": "string",
},
{
"object_location": "data[1].lab_no",
"relation": "https://w3id.org/steel/ProcessOntology/hasLaboratory",
"object_data_type": "string",
},
],
},
]

BASE_IRI = (
"https://w3id.org/emmo/domain/domain-nanoindentation/nanoindentation"
)


@pytest.mark.parametrize("mapping", [MAPPING_WILDCARD, MAPPING_INDEX])
def test_pipeline_dict_custom_properties(mapping) -> None:
def test_pipeline_json_custom_relations(mapping) -> None:
from rdflib import Graph

from data2rdf import Data2RDF, Parser
from data2rdf.warnings import MappingMissmatchWarning

with pytest.warns(
UserWarning, match="Datatype not recognized for concept"
) as warnings:
pipeline = Data2RDF(
raw_data=DATA,
mapping=mapping,
parser=Parser.json,
config={
"base_iri": BASE_IRI,
"separator": "#",
"prefix_name": "nanoindentation",
"suppress_file_description": True,
},
)
expected_graph = Graph()
expected_graph.parse(data=EXPECTED)

assert pipeline.graph.isomorphic(expected_graph)
missmatches = [
warning
for warning in warnings
if warning.category == MappingMissmatchWarning
]
assert len(missmatches) == 2


@pytest.mark.parametrize(
"mapping", [MAPPING_WILDCARD_DATATYPE, MAPPING_INDEX_DATATYPE]
)
def test_pipeline_json_custom_relations_datatype(mapping) -> None:
"""Test with custom relations and datatypes"""

from rdflib import Graph

from data2rdf import Data2RDF, Parser
Expand All @@ -123,7 +253,6 @@ def test_pipeline_dict_custom_properties(mapping) -> None:
)

expected_graph = Graph()
expected_graph.parse(data=EXPECTED)
print(pipeline.graph.serialize())
expected_graph.parse(data=EXPECTED_DATATYPE)

assert pipeline.graph.isomorphic(expected_graph)

0 comments on commit 29a0f0c

Please sign in to comment.