Coverage for rdflib_ocdm/abstract_entity.py: 86%
7 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-11-01 22:02 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-11-01 22:02 +0000
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3# Copyright (c) 2016, Silvio Peroni <essepuntato@gmail.com>
4# Copyright (c) 2023, Arcangelo Massari <arcangelo.massari@unibo.it>
5#
6# Permission to use, copy, modify, and/or distribute this software for any purpose
7# with or without fee is hereby granted, provided that the above copyright notice
8# and this permission notice appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
12# FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
13# OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
14# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16# SOFTWARE.
19from __future__ import annotations
21from abc import ABC
22from typing import TYPE_CHECKING
24from rdflib import RDF, RDFS, Graph, Literal, URIRef
26from rdflib_ocdm.support import create_literal, create_type
28if TYPE_CHECKING:
29 from typing import ClassVar, Dict, Iterable, List, Optional
31class AbstractEntity(ABC): # pragma: no cover
32 """
33 Abstract class which represents a generic entity.
34 It sits at the top of the entity class hierarchy.
35 """
37 short_name_to_type_iri: ClassVar[Dict[str, URIRef]] = {}
39 def __init__(self) -> None:
40 """
41 Constructor of the ``AbstractEntity`` class.
42 """
43 self.g: Graph = Graph()
44 self.res: URIRef = URIRef("")
46 def remove_every_triple(self) -> None:
47 """
48 Remover method that removes every triple from the current entity.
50 :return: None
51 """
52 self.g.remove((None, None, None))
54 # LABEL
55 def get_label(self) -> Optional[str]:
56 """
57 Getter method corresponding to the ``rdfs:label`` RDF predicate.
59 :return: The requested value if found, None otherwise
60 """
61 return self._get_literal(RDFS.label)
63 def create_label(self, string: str) -> None:
64 """
65 Setter method corresponding to the ``rdfs:label`` RDF predicate.
67 **WARNING: this is a functional property, hence any existing value will be overwritten!**
69 :param string: The value that will be set as the object of the property related to this method
70 :type string: str
71 :return: None
72 """
73 self.remove_label()
74 self._create_literal(RDFS.label, string)
76 def remove_label(self) -> None:
77 """
78 Remover method corresponding to the ``rdfs:label`` RDF predicate.
80 :return: None
81 """
82 self.g.remove((self.res, RDFS.label, None))
84 def _create_literal(self, p: URIRef, s: str, dt: URIRef = None, nor: bool = True) -> None:
85 """
86 Adds an RDF triple with a literal object inside the graph of the entity
88 :param p: The predicate
89 :type p: URIRef
90 :param s: The string to add as a literal value
91 :type s: str
92 :param dt: The object's datatype, if present
93 :type dt: URIRef, optional
94 :param nor: Whether to normalize the graph or not
95 :type nor: bool, optional
96 :return: None
97 """
98 create_literal(self.g, self.res, p, s, dt, nor)
100 # TYPE
101 def get_types(self) -> List[URIRef]:
102 """
103 Getter method corresponding to the ``rdf:type`` RDF predicate.
105 :return: A list containing the requested values if found, None otherwise
106 """
107 uri_list: List[URIRef] = self._get_multiple_uri_references(RDF.type)
108 return uri_list
110 def _create_type(self, res_type: URIRef, identifier: str = None) -> None:
111 """
112 Setter method corresponding to the ``rdf:type`` RDF predicate.
114 :param res_type: The value that will be set as the object of the property related to this method
115 :type res_type: URIRef
116 :return: None
117 """
118 create_type(self.g, self.res, res_type, identifier)
120 def remove_type(self) -> None:
121 """
122 Remover method corresponding to the ``rdf:type`` RDF predicate.
124 :return: None
125 """
126 self.g.remove((self.res, RDF.type, None))
128 # Overrides __str__ method
129 def __str__(self) -> str:
130 return str(self.res)
132 def add_triples(self, iterable_of_triples: Iterable) -> None:
133 """
134 A utility method that allows to add a batch of triples into the graph of the entity.
136 **WARNING: Only triples that have this entity as their subject will be imported!**
138 :param iterable_of_triples: A collection of triples to be added to the entity
139 :type iterable_of_triples: Iterable
140 :return: None
141 """
142 for s, p, o in iterable_of_triples:
143 if s == self.res: # This guarantees that only triples belonging to the resource will be added
144 self.g.add((s, p, o))
146 def _get_literal(self, predicate: URIRef) -> Optional[str]:
147 result: Optional[str] = None
148 for o in self.g.objects(self.res, predicate):
149 if type(o) == Literal:
150 result = str(o)
151 break
152 return result
154 def _get_multiple_literals(self, predicate: URIRef) -> List[str]:
155 result: List[str] = []
156 for o in self.g.objects(self.res, predicate):
157 if type(o) == Literal:
158 result.append(str(o))
159 return result
161 def _get_uri_reference(self, predicate: URIRef) -> Optional[URIRef]:
162 result: Optional[URIRef] = None
163 for o in self.g.objects(self.res, predicate):
164 if type(o) == URIRef:
165 result = o
166 break
167 return result
169 def _get_multiple_uri_references(self, predicate: URIRef) -> List[URIRef]:
170 result: List[URIRef] = []
171 for o in self.g.objects(self.res, predicate):
172 if type(o) == URIRef:
173 result.append(o)
174 return result