Coverage for rdflib_ocdm / abstract_entity.py: 100%

5 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-21 12:35 +0000

1#!/usr/bin/python 

2 

3# SPDX-FileCopyrightText: 2016 Silvio Peroni <essepuntato@gmail.com> 

4# SPDX-FileCopyrightText: 2023-2025 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 

21class AbstractEntity(ABC): # pragma: no cover 

22 """ 

23 Abstract class which represents a generic entity.  

24 It sits at the top of the entity class hierarchy. 

25 """ 

26 

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

28 

29 def __init__(self) -> None: 

30 """ 

31 Constructor of the ``AbstractEntity`` class. 

32 """ 

33 self.g: Graph = Graph() 

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

35 

36 def remove_every_triple(self) -> None: 

37 """ 

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

39 

40 :return: None 

41 """ 

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

43 

44 # LABEL 

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

46 """ 

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

48 

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

50 """ 

51 return self._get_literal(RDFS.label) 

52 

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

54 """ 

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

56 

57 **WARNING: this is a functional property, hence any existing value will be overwritten!** 

58 

59 :param string: The value that will be set as the object of the property related to this method 

60 :type string: str 

61 :return: None 

62 """ 

63 self.remove_label() 

64 self._create_literal(RDFS.label, string) 

65 

66 def remove_label(self) -> None: 

67 """ 

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

69 

70 :return: None 

71 """ 

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

73 

74 def _create_literal(self, p: URIRef, s: str, dt: URIRef = None, nor: bool = True) -> None: 

75 """ 

76 Adds an RDF triple with a literal object inside the graph of the entity 

77 

78 :param p: The predicate 

79 :type p: URIRef 

80 :param s: The string to add as a literal value 

81 :type s: str 

82 :param dt: The object's datatype, if present 

83 :type dt: URIRef, optional 

84 :param nor: Whether to normalize the graph or not 

85 :type nor: bool, optional 

86 :return: None 

87 """ 

88 create_literal(self.g, self.res, p, s, dt, nor) 

89 

90 # TYPE 

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

92 """ 

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

94 

95 :return: A list containing the requested values if found, None otherwise 

96 """ 

97 uri_list: List[URIRef] = self._get_multiple_uri_references(RDF.type) 

98 return uri_list 

99 

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

101 """ 

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

103 

104 :param res_type: The value that will be set as the object of the property related to this method 

105 :type res_type: URIRef 

106 :return: None 

107 """ 

108 create_type(self.g, self.res, res_type, identifier) 

109 

110 def remove_type(self) -> None: 

111 """ 

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

113 

114 :return: None 

115 """ 

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

117 

118 # Overrides __str__ method 

119 def __str__(self) -> str: 

120 return str(self.res) 

121 

122 def add_triples(self, iterable_of_triples: Iterable) -> None: 

123 """ 

124 A utility method that allows to add a batch of triples into the graph of the entity. 

125 

126 **WARNING: Only triples that have this entity as their subject will be imported!** 

127 

128 :param iterable_of_triples: A collection of triples to be added to the entity 

129 :type iterable_of_triples: Iterable 

130 :return: None 

131 """ 

132 for s, p, o in iterable_of_triples: 

133 if s == self.res: # This guarantees that only triples belonging to the resource will be added 

134 self.g.add((s, p, o)) 

135 

136 def _get_literal(self, predicate: URIRef) -> Optional[str]: 

137 result: Optional[str] = None 

138 for o in self.g.objects(self.res, predicate): 

139 if type(o) == Literal: 

140 result = str(o) 

141 break 

142 return result 

143 

144 def _get_multiple_literals(self, predicate: URIRef) -> List[str]: 

145 result: List[str] = [] 

146 for o in self.g.objects(self.res, predicate): 

147 if type(o) == Literal: 

148 result.append(str(o)) 

149 return result 

150 

151 def _get_uri_reference(self, predicate: URIRef) -> Optional[URIRef]: 

152 result: Optional[URIRef] = None 

153 for o in self.g.objects(self.res, predicate): 

154 if type(o) == URIRef: 

155 result = o 

156 break 

157 return result 

158 

159 def _get_multiple_uri_references(self, predicate: URIRef) -> List[URIRef]: 

160 result: List[URIRef] = [] 

161 for o in self.g.objects(self.res, predicate): 

162 if type(o) == URIRef: 

163 result.append(o) 

164 return result