Coverage for rdflib_ocdm / abstract_entity.py: 100%
5 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-30 21:23 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-30 21:23 +0000
1#!/usr/bin/python
3# SPDX-FileCopyrightText: 2016 Silvio Peroni <essepuntato@gmail.com>
4# SPDX-FileCopyrightText: 2023-2026 Arcangelo Massari <arcangelo.massari@unibo.it>
5#
6# SPDX-License-Identifier: ISC
9from __future__ import annotations
11from abc import ABC
12from typing import TYPE_CHECKING
14from rdflib import RDF, RDFS, Graph, Literal, URIRef
16from rdflib_ocdm.support import create_literal, create_type
18if TYPE_CHECKING:
19 from typing import ClassVar, Dict, Iterable, List, Optional
22class AbstractEntity(ABC): # pragma: no cover
23 """
24 Abstract class which represents a generic entity.
25 It sits at the top of the entity class hierarchy.
26 """
28 short_name_to_type_iri: ClassVar[Dict[str, URIRef]] = {}
30 def __init__(self) -> None:
31 """
32 Constructor of the ``AbstractEntity`` class.
33 """
34 self.g: Graph = Graph()
35 self.res: URIRef = URIRef("")
37 def remove_every_triple(self) -> None:
38 """
39 Remover method that removes every triple from the current entity.
41 :return: None
42 """
43 self.g.remove((None, None, None))
45 # LABEL
46 def get_label(self) -> Optional[str]:
47 """
48 Getter method corresponding to the ``rdfs:label`` RDF predicate.
50 :return: The requested value if found, None otherwise
51 """
52 return self._get_literal(RDFS.label)
54 def create_label(self, string: str) -> None:
55 """
56 Setter method corresponding to the ``rdfs:label`` RDF predicate.
58 **WARNING: this is a functional property, hence any existing
59 value will be overwritten!**
61 :param string: The value that will be set as the object of the
62 property related to this method
63 :type string: str
64 :return: None
65 """
66 self.remove_label()
67 self._create_literal(RDFS.label, string)
69 def remove_label(self) -> None:
70 """
71 Remover method corresponding to the ``rdfs:label`` RDF predicate.
73 :return: None
74 """
75 self.g.remove((self.res, RDFS.label, None))
77 def _create_literal(
78 self, p: URIRef, s: str, dt: URIRef | None = None, nor: bool = True
79 ) -> None:
80 """
81 Adds an RDF triple with a literal object inside the graph of the entity
83 :param p: The predicate
84 :type p: URIRef
85 :param s: The string to add as a literal value
86 :type s: str
87 :param dt: The object's datatype, if present
88 :type dt: URIRef, optional
89 :param nor: Whether to normalize the graph or not
90 :type nor: bool, optional
91 :return: None
92 """
93 create_literal(self.g, self.res, p, s, dt, nor)
95 # TYPE
96 def get_types(self) -> List[URIRef]:
97 """
98 Getter method corresponding to the ``rdf:type`` RDF predicate.
100 :return: A list containing the requested values if found, None otherwise
101 """
102 uri_list: List[URIRef] = self._get_multiple_uri_references(RDF.type)
103 return uri_list
105 def _create_type(self, res_type: URIRef, identifier: str | None = None) -> None:
106 """
107 Setter method corresponding to the ``rdf:type`` RDF predicate.
109 :param res_type: The value that will be set as the object of
110 the property related to this method
111 :type res_type: URIRef
112 :return: None
113 """
114 create_type(self.g, self.res, res_type, identifier)
116 def remove_type(self) -> None:
117 """
118 Remover method corresponding to the ``rdf:type`` RDF predicate.
120 :return: None
121 """
122 self.g.remove((self.res, RDF.type, None))
124 # Overrides __str__ method
125 def __str__(self) -> str:
126 return str(self.res)
128 def add_triples(self, iterable_of_triples: Iterable) -> None:
129 """
130 A utility method that allows to add a batch of triples into
131 the graph of the entity.
133 **WARNING: Only triples that have this entity as their subject
134 will be imported!**
136 :param iterable_of_triples: A collection of triples to be added to the entity
137 :type iterable_of_triples: Iterable
138 :return: None
139 """
140 for s, p, o in iterable_of_triples:
141 if s == self.res:
142 self.g.add((s, p, o))
144 def _get_literal(self, predicate: URIRef) -> Optional[str]:
145 result: Optional[str] = None
146 for o in self.g.objects(self.res, predicate):
147 if isinstance(o, Literal):
148 result = str(o)
149 break
150 return result
152 def _get_multiple_literals(self, predicate: URIRef) -> List[str]:
153 result: List[str] = []
154 for o in self.g.objects(self.res, predicate):
155 if isinstance(o, Literal):
156 result.append(str(o))
157 return result
159 def _get_uri_reference(self, predicate: URIRef) -> Optional[URIRef]:
160 result: Optional[URIRef] = None
161 for o in self.g.objects(self.res, predicate):
162 if isinstance(o, URIRef):
163 result = o
164 break
165 return result
167 def _get_multiple_uri_references(self, predicate: URIRef) -> List[URIRef]:
168 result: List[URIRef] = []
169 for o in self.g.objects(self.res, predicate):
170 if isinstance(o, URIRef):
171 result.append(o)
172 return result