diff --git a/apis_ontology/renderer.py b/apis_ontology/renderer.py new file mode 100644 index 0000000..3098880 --- /dev/null +++ b/apis_ontology/renderer.py @@ -0,0 +1,53 @@ +from rest_framework import renderers +from rdflib import Graph + + +class BaseRdfRenderer(renderers.BaseRenderer): + def render(self, data, accepted_media_type=None, renderer_context=None): + result = Graph() + + if isinstance(data, dict) and "results" in data: + # Handle case where data is a dict with multiple graphs + for graph in data["results"]: + if isinstance(graph, Graph): + # Merge triples + for triple in graph: + result.add(triple) + # Merge namespace bindings + for prefix, namespace in graph.namespaces(): + result.bind(prefix, namespace, override=False) + elif isinstance(data, Graph): + # Handle case where data is a single graph + result = data + # Ensure namespaces are properly bound in the single graph case + for prefix, namespace in data.namespaces(): + result.bind(prefix, namespace, override=False) + else: + raise ValueError( + "Invalid data format. Expected rdflib Graph or dict with 'results' key containing graphs" + ) + return result + + +class CidocTTLRenderer(BaseRdfRenderer): + format = "Cidoc" + media_type = "text/ttl" + + def render(self, data, accepted_media_type=None, renderer_context=None): + return ( + super() + .render(data, accepted_media_type, renderer_context) + .serialize(format="ttl") + ) + + +class CidocXMLRenderer(BaseRdfRenderer): + format = "Cidoc" + media_type = "application/rdf+xml" + + def render(self, data, accepted_media_type=None, renderer_context=None): + return ( + super() + .render(data, accepted_media_type, renderer_context) + .serialize(format="xml") + ) diff --git a/apis_ontology/serializers.py b/apis_ontology/serializers.py new file mode 100644 index 0000000..6525c12 --- /dev/null +++ b/apis_ontology/serializers.py @@ -0,0 +1,70 @@ +from rest_framework.renderers import serializers +from rdflib import Graph, Literal, URIRef, Namespace +from rdflib.namespace import RDF, RDFS, XSD + + +class PersonCidocSerializer(serializers.BaseSerializer): + def to_representation(self, instance): + g = Graph() + + # Define namespaces + crm = Namespace("http://www.cidoc-crm.org/cidoc-crm/") + apis = Namespace("http://apis.acdh.oeaw.ac.at/") + + g.namespace_manager.bind("crm", crm, replace=True) + g.namespace_manager.bind("apis", apis, replace=True) + + # Create the Person instance + person_uri = URIRef(apis[str(instance.id)]) + g.add((person_uri, RDF.type, crm.E21_Person)) + + # Add properties + appellation_uri = URIRef(apis[f"appellation_{instance.id}"]) + g.add((appellation_uri, RDF.type, crm.E41_Appellation)) + g.add((person_uri, crm.P1_is_identified_by, appellation_uri)) + g.add( + ( + appellation_uri, + RDFS.label, + Literal(f"{instance.forename} {instance.surname}"), + ) + ) + + if hasattr(instance, "forename"): + forename_uri = URIRef(apis[f"forename_{instance.id}"]) + g.add((forename_uri, RDF.type, crm.E41_Appellation)) + g.add((appellation_uri, crm.P106_is_composed_of, forename_uri)) + g.add((forename_uri, RDFS.label, Literal(instance.forename))) + + if hasattr(instance, "surname"): + surname_uri = URIRef(apis[f"surname_{instance.id}"]) + g.add((surname_uri, RDF.type, crm.E41_Appellation)) + g.add((appellation_uri, crm.P106_is_composed_of, surname_uri)) + g.add((surname_uri, RDFS.label, Literal(instance.surname))) + + if hasattr(instance, "birth_date"): + birth_event = URIRef(apis[f"birth_{instance.id}"]) + g.add((birth_event, RDF.type, crm.E67_Birth)) + g.add((birth_event, crm.P98_brought_into_life, person_uri)) + g.add( + ( + birth_event, + crm.P4_has_time_span, + Literal(instance.birth_date, datatype=XSD.date), + ) + ) + + if hasattr(instance, "death_date"): + death_event = URIRef(apis[f"death_{instance.id}"]) + g.add((death_event, RDF.type, crm.E69_Death)) + g.add((death_event, crm.P100_was_death_of, person_uri)) + g.add( + ( + death_event, + crm.P4_has_time_span, + Literal(instance.death_date, datatype=XSD.date), + ) + ) + + # Serialize the graph to RDF/XML + return g diff --git a/apis_ontology/settings.py b/apis_ontology/settings.py index e7f9b78..208457a 100644 --- a/apis_ontology/settings.py +++ b/apis_ontology/settings.py @@ -25,6 +25,12 @@ "simple_history.middleware.HistoryRequestMiddleware", ] +REST_FRAMEWORK["DEFAULT_RENDERER_CLASSES"] = [ # noqa: F405 + "rest_framework.renderers.JSONRenderer", + "rest_framework.renderers.BrowsableAPIRenderer", + "apis_ontology.renderer.CidocTTLRenderer", + "apis_ontology.renderer.CidocXMLRenderer", +] # this is a workaround to disable pagintation in the relations # listing on the entities pages APIS_ENTITIES = {