Coverage for oc_ocdm / prov / entities / snapshot_entity.py: 96%

79 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-28 18:52 +0000

1#!/usr/bin/python 

2 

3# SPDX-FileCopyrightText: 2021-2022 Simone Persiani <iosonopersia@gmail.com> 

4# 

5# SPDX-License-Identifier: ISC 

6 

7# -*- coding: utf-8 -*- 

8from __future__ import annotations 

9 

10from typing import TYPE_CHECKING 

11 

12from rdflib import XSD 

13 

14from oc_ocdm.decorators import accepts_only 

15from oc_ocdm.graph.graph_entity import GraphEntity 

16from oc_ocdm.prov.prov_entity import ProvEntity 

17 

18if TYPE_CHECKING: 

19 from typing import List, Optional 

20 

21 from rdflib import URIRef 

22 

23 

24class SnapshotEntity(ProvEntity): 

25 """Snapshot of entity metadata (short: se): a particular snapshot recording the 

26 metadata associated with an individual entity (either a bibliographic entity or an 

27 identifier) at a particular date and time, including the agent, such as a person, 

28 organisation or automated process that created or modified the entity metadata.""" 

29 

30 # HAS CREATION DATE 

31 def get_generation_time(self) -> Optional[str]: 

32 """ 

33 Getter method corresponding to the ``prov:generatedAtTime`` RDF predicate. 

34 

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

36 """ 

37 return self._get_literal(ProvEntity.iri_generated_at_time) 

38 

39 @accepts_only('literal') 

40 def has_generation_time(self, string: str) -> None: 

41 """ 

42 Setter method corresponding to the ``prov:generatedAtTime`` RDF predicate. 

43 

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

45 

46 `The date on which a particular snapshot of a bibliographic entity's metadata was 

47 created.` 

48 

49 :param string: The value that will be set as the object of the property related to this method. **It must 

50 be a string compliant with the** ``xsd:dateTime`` **datatype.** 

51 :type string: str 

52 :raises TypeError: if the parameter is of the wrong type 

53 :return: None 

54 """ 

55 self.remove_generation_time() 

56 self._create_literal(ProvEntity.iri_generated_at_time, string, XSD.dateTime) 

57 

58 def remove_generation_time(self) -> None: 

59 """ 

60 Remover method corresponding to the ``prov:generatedAtTime`` RDF predicate. 

61 

62 :return: None 

63 """ 

64 self.g.remove((self.res, ProvEntity.iri_generated_at_time, None)) 

65 

66 # HAS INVALIDATION DATE 

67 def get_invalidation_time(self) -> Optional[str]: 

68 """ 

69 Getter method corresponding to the ``prov:invalidatedAtTime`` RDF predicate. 

70 

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

72 """ 

73 return self._get_literal(ProvEntity.iri_invalidated_at_time) 

74 

75 @accepts_only('literal') 

76 def has_invalidation_time(self, string: str) -> None: 

77 """ 

78 Setter method corresponding to the ``prov:invalidatedAtTime`` RDF predicate. 

79 

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

81 

82 `The date on which a snapshot of a bibliographic entity's metadata was invalidated due 

83 to an update (e.g. a correction, or the addition of some metadata that was not specified 

84 in the previous snapshot), or due to a merger of the entity with another one.` 

85 

86 :param string: The value that will be set as the object of the property related to this method. **It must 

87 be a string compliant with the** ``xsd:dateTime`` **datatype.** 

88 :type string: str 

89 :raises TypeError: if the parameter is of the wrong type 

90 :return: None 

91 """ 

92 self.remove_invalidation_time() 

93 self._create_literal(ProvEntity.iri_invalidated_at_time, string, XSD.dateTime) 

94 

95 def remove_invalidation_time(self) -> None: 

96 """ 

97 Remover method corresponding to the ``prov:invalidatedAtTime`` RDF predicate. 

98 

99 :return: None 

100 """ 

101 self.g.remove((self.res, ProvEntity.iri_invalidated_at_time, None)) 

102 

103 # IS SNAPSHOT OF 

104 def get_is_snapshot_of(self) -> Optional[URIRef]: 

105 """ 

106 Getter method corresponding to the ``prov:specializationOf`` RDF predicate. 

107 

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

109 """ 

110 uri: Optional[URIRef] = self._get_uri_reference(ProvEntity.iri_specialization_of) 

111 return uri 

112 

113 def is_snapshot_of(self, en_res: GraphEntity) -> None: 

114 """ 

115 Setter method corresponding to the ``prov:specializationOf`` RDF predicate. 

116 

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

118 

119 `This property is used to link a snapshot of entity metadata to the bibliographic entity 

120 to which the snapshot refers.` 

121 

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

123 :type en_res: GraphEntity 

124 :return: None 

125 """ 

126 self.remove_is_snapshot_of() 

127 self.g.add((self.res, ProvEntity.iri_specialization_of, en_res.res)) 

128 

129 def remove_is_snapshot_of(self) -> None: 

130 """ 

131 Remover method corresponding to the ``prov:specializationOf`` RDF predicate. 

132 

133 :return: None 

134 """ 

135 self.g.remove((self.res, ProvEntity.iri_specialization_of, None)) 

136 

137 # IS DERIVED FROM 

138 def get_derives_from(self) -> List[ProvEntity]: 

139 """ 

140 Getter method corresponding to the ``prov:wasDerivedFrom`` RDF predicate. 

141 

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

143 """ 

144 uri_list: List[URIRef] = self._get_multiple_uri_references(ProvEntity.iri_was_derived_from, 'se') 

145 result: List[ProvEntity] = [] 

146 for uri in uri_list: 

147 # TODO: what is the prov_subject of these snapshots? 

148 result.append(self.p_set.add_se(self.prov_subject, uri)) 

149 return result 

150 

151 @accepts_only('se') 

152 def derives_from(self, se_res: ProvEntity) -> None: 

153 """ 

154 Setter method corresponding to the ``prov:wasDerivedFrom`` RDF predicate. 

155 

156 `This property is used to identify the immediately previous snapshot of entity metadata 

157 associated with the same bibliographic entity.` 

158 

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

160 :type se_res: ProvEntity 

161 :raises TypeError: if the parameter is of the wrong type 

162 :return: None 

163 """ 

164 self.g.add((self.res, ProvEntity.iri_was_derived_from, se_res.res)) 

165 

166 @accepts_only('se') 

167 def remove_derives_from(self, se_res: Optional[ProvEntity] = None) -> None: 

168 """ 

169 Remover method corresponding to the ``prov:wasDerivedFrom`` RDF predicate. 

170 

171 **WARNING: this is a non-functional property, hence, if the parameter 

172 is None, any existing value will be removed!** 

173 

174 :param se_res: If not None, the specific object value that will be removed from the property 

175 related to this method (defaults to None) 

176 :type se_res: SnapshotEntity 

177 :raises TypeError: if the parameter is of the wrong type 

178 :return: None 

179 """ 

180 if se_res is not None: 

181 self.g.remove((self.res, ProvEntity.iri_was_derived_from, se_res.res)) 

182 else: 

183 self.g.remove((self.res, ProvEntity.iri_was_derived_from, None)) 

184 

185 # HAS PRIMARY SOURCE 

186 def get_primary_source(self) -> Optional[URIRef]: 

187 """ 

188 Getter method corresponding to the ``prov:hadPrimarySource`` RDF predicate. 

189 

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

191 """ 

192 uri: Optional[URIRef] = self._get_uri_reference(ProvEntity.iri_had_primary_source) 

193 return uri 

194 

195 @accepts_only('thing') 

196 def has_primary_source(self, any_res: URIRef) -> None: 

197 """ 

198 Setter method corresponding to the ``prov:hadPrimarySource`` RDF predicate. 

199 

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

201 

202 `This property is used to identify the primary source from which the metadata 

203 described in the snapshot are derived (e.g. Crossref, as the result of querying the 

204 CrossRef API).` 

205 

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

207 :type any_res: URIRef 

208 :return: None 

209 """ 

210 self.remove_primary_source() 

211 self.g.add((self.res, ProvEntity.iri_had_primary_source, any_res)) 

212 

213 def remove_primary_source(self) -> None: 

214 """ 

215 Remover method corresponding to the ``prov:hadPrimarySource`` RDF predicate. 

216 

217 :return: None 

218 """ 

219 self.g.remove((self.res, ProvEntity.iri_had_primary_source, None)) 

220 

221 # HAS UPDATE ACTION 

222 def get_update_action(self) -> Optional[str]: 

223 """ 

224 Getter method corresponding to the ``oco:hasUpdateQuery`` RDF predicate. 

225 

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

227 """ 

228 return self._get_literal(ProvEntity.iri_has_update_query) 

229 

230 @accepts_only('literal') 

231 def has_update_action(self, string: str) -> None: 

232 """ 

233 Setter method corresponding to the ``oco:hasUpdateQuery`` RDF predicate. 

234 

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

236 

237 `The UPDATE SPARQL query that specifies which data, associated to the bibliographic 

238 entity in consideration, have been modified (e.g. for correcting a mistake) in the 

239 current snapshot starting from those associated to the previous snapshot of the entity.` 

240 

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

242 :type string: str 

243 :return: None 

244 """ 

245 self.remove_update_action() 

246 self._create_literal(ProvEntity.iri_has_update_query, string) 

247 

248 def remove_update_action(self) -> None: 

249 """ 

250 Remover method corresponding to the ``oco:hasUpdateQuery`` RDF predicate. 

251 

252 :return: None 

253 """ 

254 self.g.remove((self.res, ProvEntity.iri_has_update_query, None)) 

255 

256 # HAS DESCRIPTION 

257 def get_description(self) -> Optional[str]: 

258 """ 

259 Getter method corresponding to the ``dcterms:description`` RDF predicate. 

260 

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

262 """ 

263 return self._get_literal(ProvEntity.iri_description) 

264 

265 @accepts_only('literal') 

266 def has_description(self, string: str) -> None: 

267 """ 

268 Setter method corresponding to the ``dcterms:description`` RDF predicate. 

269 

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

271 

272 `A textual description of the events that have resulted in the current snapshot (e.g. the 

273 creation of the initial snapshot, the creation of a new snapshot following the 

274 modification of the entity to which the metadata relate, or the creation of a new 

275 snapshot following the merger with another entity of the entity to which the previous 

276 snapshot related).` 

277 

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

279 :type string: str 

280 :return: None 

281 """ 

282 self.remove_description() 

283 self._create_literal(ProvEntity.iri_description, string) 

284 

285 def remove_description(self) -> None: 

286 """ 

287 Remover method corresponding to the ``dcterms:description`` RDF predicate. 

288 

289 :return: None 

290 """ 

291 self.g.remove((self.res, ProvEntity.iri_description, None)) 

292 

293 # IS ATTRIBUTED TO 

294 def get_resp_agent(self) -> Optional[URIRef]: 

295 """ 

296 Getter method corresponding to the ``prov:wasAttributedTo`` RDF predicate. 

297 

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

299 """ 

300 uri: Optional[URIRef] = self._get_uri_reference(ProvEntity.iri_was_attributed_to) 

301 return uri 

302 

303 @accepts_only('thing') 

304 def has_resp_agent(self, se_agent: URIRef) -> None: 

305 """ 

306 Setter method corresponding to the ``prov:wasAttributedTo`` RDF predicate. 

307 

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

309 

310 `The agent responsible for the creation of the current entity snapshot.` 

311 

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

313 :type se_agent: URIRef 

314 :return: None 

315 """ 

316 self.remove_resp_agent() 

317 self.g.add((self.res, ProvEntity.iri_was_attributed_to, se_agent)) 

318 

319 def remove_resp_agent(self) -> None: 

320 """ 

321 Remover method corresponding to the ``prov:wasAttributedTo`` RDF predicate. 

322 

323 :return: None 

324 """ 

325 self.g.remove((self.res, ProvEntity.iri_was_attributed_to, None))