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

1#!/usr/bin/python 

2 

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 

7 

8 

9from __future__ import annotations 

10 

11from abc import ABC 

12from typing import TYPE_CHECKING 

13 

14from rdflib import RDF, RDFS, Graph, Literal, URIRef 

15 

16from rdflib_ocdm.support import create_literal, create_type 

17 

18if TYPE_CHECKING: 

19 from typing import ClassVar, Dict, Iterable, List, Optional 

20 

21 

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 """ 

27 

28 short_name_to_type_iri: ClassVar[Dict[str, URIRef]] = {} 

29 

30 def __init__(self) -> None: 

31 """ 

32 Constructor of the ``AbstractEntity`` class. 

33 """ 

34 self.g: Graph = Graph() 

35 self.res: URIRef = URIRef("") 

36 

37 def remove_every_triple(self) -> None: 

38 """ 

39 Remover method that removes every triple from the current entity. 

40 

41 :return: None 

42 """ 

43 self.g.remove((None, None, None)) 

44 

45 # LABEL 

46 def get_label(self) -> Optional[str]: 

47 """ 

48 Getter method corresponding to the ``rdfs:label`` RDF predicate. 

49 

50 :return: The requested value if found, None otherwise 

51 """ 

52 return self._get_literal(RDFS.label) 

53 

54 def create_label(self, string: str) -> None: 

55 """ 

56 Setter method corresponding to the ``rdfs:label`` RDF predicate. 

57 

58 **WARNING: this is a functional property, hence any existing 

59 value will be overwritten!** 

60 

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) 

68 

69 def remove_label(self) -> None: 

70 """ 

71 Remover method corresponding to the ``rdfs:label`` RDF predicate. 

72 

73 :return: None 

74 """ 

75 self.g.remove((self.res, RDFS.label, None)) 

76 

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 

82 

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) 

94 

95 # TYPE 

96 def get_types(self) -> List[URIRef]: 

97 """ 

98 Getter method corresponding to the ``rdf:type`` RDF predicate. 

99 

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 

104 

105 def _create_type(self, res_type: URIRef, identifier: str | None = None) -> None: 

106 """ 

107 Setter method corresponding to the ``rdf:type`` RDF predicate. 

108 

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) 

115 

116 def remove_type(self) -> None: 

117 """ 

118 Remover method corresponding to the ``rdf:type`` RDF predicate. 

119 

120 :return: None 

121 """ 

122 self.g.remove((self.res, RDF.type, None)) 

123 

124 # Overrides __str__ method 

125 def __str__(self) -> str: 

126 return str(self.res) 

127 

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. 

132 

133 **WARNING: Only triples that have this entity as their subject 

134 will be imported!** 

135 

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)) 

143 

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 

151 

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 

158 

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 

166 

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