Coverage for oc_ocdm / graph / entities / bibliographic / citation.py: 97%

87 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-05-08 20:23 +0000

1#!/usr/bin/python 

2 

3# SPDX-FileCopyrightText: 2020-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 triplelite import RDFTerm 

13 

14from oc_ocdm.constants import XSD_DURATION 

15from oc_ocdm.decorators import accepts_only 

16from oc_ocdm.support.support import get_datatype_from_iso_8601 

17 

18if TYPE_CHECKING: 

19 from typing import Optional 

20 

21 from oc_ocdm.graph.entities.bibliographic.bibliographic_resource import BibliographicResource 

22from oc_ocdm.graph.entities.bibliographic_entity import BibliographicEntity 

23from oc_ocdm.graph.graph_entity import GraphEntity 

24 

25 

26class Citation(BibliographicEntity): 

27 """Citation (short: ci): a permanent conceptual directional link from the citing 

28 bibliographic resource to a cited bibliographic resource. A citation is created by the 

29 performative act of an author citing a published work that is relevant to the current 

30 work by using a particular textual device. Typically, citations are made by including a 

31 bibliographic reference in the reference list of the citing work and by denoting such a 

32 bibliographic reference using one or more in-text reference pointers (e.g. '[1]'), or by 

33 the inclusion within the citing work of a link, in the form of an HTTP Uniform Resource 

34 Locator (URL), to the cited bibliographic resource on the World Wide Web.""" 

35 

36 def _merge_properties(self, other: GraphEntity, prefer_self: bool) -> None: 

37 """ 

38 The merge operation allows combining two ``Citation`` entities into a single one, 

39 by marking the second entity as to be deleted while also copying its data into the current 

40 ``Citation``. Moreover, every triple from the containing ``GraphSet`` referring to the second 

41 entity gets "redirected" to the current entity: **every other reference contained inside a 

42 different source (e.g. a triplestore) must be manually handled by the user!** 

43 

44 In case of functional properties, values from the current entity get overwritten 

45 by those coming from the second entity while, in all other cases, values from the 

46 second entity are simply appended to those of the current entity. In this context, 

47 ``rdfs:label`` is considered as a functional property, while ``rdf:type`` is not. 

48 

49 :param other: The entity which will be marked as to be deleted and whose properties will 

50 be merged into the current entity. 

51 :type other: Citation 

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

53 :return: None 

54 """ 

55 super()._merge_properties(other, prefer_self) 

56 assert isinstance(other, Citation) 

57 

58 citing_br: Optional[BibliographicResource] = other.get_citing_entity() 

59 if citing_br is not None: 

60 self.has_citing_entity(citing_br) 

61 

62 cited_br: Optional[BibliographicResource] = other.get_cited_entity() 

63 if cited_br is not None: 

64 self.has_cited_entity(cited_br) 

65 

66 creation_date: Optional[str] = other.get_citation_creation_date() 

67 if creation_date is not None: 

68 self.has_citation_creation_date(creation_date) 

69 

70 time_span: Optional[str] = other.get_citation_time_span() 

71 if time_span is not None: 

72 self.has_citation_time_span(time_span) 

73 

74 characterization: Optional[str] = other.get_citation_characterization() 

75 if characterization is not None: 

76 self.has_citation_characterization(characterization) 

77 

78 # HAS CITING DOCUMENT (BibliographicResource) 

79 def get_citing_entity(self) -> Optional[BibliographicResource]: 

80 """ 

81 Getter method corresponding to the ``cito:hasCitingEntity`` RDF predicate. 

82 

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

84 """ 

85 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_has_citing_entity, 'br') 

86 if uri is not None: 

87 return self.g_set.add_br(self.resp_agent, self.source, uri) 

88 

89 @accepts_only('br') 

90 def has_citing_entity(self, citing_res: BibliographicResource) -> None: 

91 """ 

92 Setter method corresponding to the ``cito:hasCitingEntity`` RDF predicate. 

93 

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

95 

96 `The bibliographic resource which acts as the source for the citation.` 

97 

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

99 :type citing_res: BibliographicResource 

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

101 :return: None 

102 """ 

103 self.remove_citing_entity() 

104 self.g.add((self.res, GraphEntity.iri_has_citing_entity, RDFTerm("uri", str(citing_res.res)))) 

105 

106 def remove_citing_entity(self) -> None: 

107 """ 

108 Remover method corresponding to the ``cito:hasCitingEntity`` RDF predicate. 

109 

110 :return: None 

111 """ 

112 self.g.remove((self.res, GraphEntity.iri_has_citing_entity, None)) 

113 

114 # HAS CITED DOCUMENT (BibliographicResource) 

115 def get_cited_entity(self) -> Optional[BibliographicResource]: 

116 """ 

117 Getter method corresponding to the ``cito:hasCitedEntity`` RDF predicate. 

118 

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

120 """ 

121 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_has_cited_entity, 'br') 

122 if uri is not None: 

123 return self.g_set.add_br(self.resp_agent, self.source, uri) 

124 

125 @accepts_only('br') 

126 def has_cited_entity(self, cited_res: BibliographicResource) -> None: 

127 """ 

128 Setter method corresponding to the ``cito:hasCitedEntity`` RDF predicate. 

129 

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

131 

132 `The bibliographic resource which acts as the target for the citation.` 

133 

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

135 :type cited_res: BibliographicResource 

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

137 :return: None 

138 """ 

139 self.remove_cited_entity() 

140 self.g.add((self.res, GraphEntity.iri_has_cited_entity, RDFTerm("uri", str(cited_res.res)))) 

141 

142 def remove_cited_entity(self) -> None: 

143 """ 

144 Remover method corresponding to the ``c4o:hasCitedEntity`` RDF predicate. 

145 

146 :return: None 

147 """ 

148 self.g.remove((self.res, GraphEntity.iri_has_cited_entity, None)) 

149 

150 # HAS CITATION CREATION DATE 

151 def get_citation_creation_date(self) -> Optional[str]: 

152 """ 

153 Getter method corresponding to the ``cito:hasCitationCreationDate`` RDF predicate. 

154 

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

156 """ 

157 return self._get_literal(GraphEntity.iri_has_citation_creation_date) 

158 

159 def has_citation_creation_date(self, string: str) -> None: 

160 """ 

161 Setter method corresponding to the ``cito:hasCitationCreationDate`` RDF predicate. 

162 

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

164 

165 `The date on which the citation was created. This has the same numerical value 

166 as the publication date of the citing bibliographic resource, but is a property 

167 of the citation itself. When combined with the citation time span, it permits 

168 that citation to be located in history.` 

169 

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

171 be a string compliant with the** ``ISO 8601`` **standard.** 

172 :type string: str 

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

174 :return: None 

175 """ 

176 cur_type, string = get_datatype_from_iso_8601(string) 

177 if cur_type is not None and string is not None: 

178 self.remove_citation_creation_date() 

179 self._create_literal(GraphEntity.iri_has_citation_creation_date, string, cur_type, False) 

180 

181 def remove_citation_creation_date(self) -> None: 

182 """ 

183 Remover method corresponding to the ``c4o:hasCitationCreationDate`` RDF predicate. 

184 

185 :return: None 

186 """ 

187 self.g.remove((self.res, GraphEntity.iri_has_citation_creation_date, None)) 

188 

189 # HAS CITATION TIME SPAN 

190 def get_citation_time_span(self) -> Optional[str]: 

191 """ 

192 Getter method corresponding to the ``cito:hasCitationTimeSpan`` RDF predicate. 

193 

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

195 """ 

196 return self._get_literal(GraphEntity.iri_has_citation_time_span) 

197 

198 def has_citation_time_span(self, string: str) -> None: 

199 """ 

200 Setter method corresponding to the ``cito:hasCitationTimeSpan`` RDF predicate. 

201 

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

203 

204 `The date interval between the publication date of the cited bibliographic resource and 

205 the publication date of the citing bibliographic resource.` 

206 

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

208 be a string compliant with the** ``xsd:duration`` **datatype.** 

209 :type string: str 

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

211 :return: None 

212 """ 

213 self.remove_citation_time_span() 

214 self._create_literal(GraphEntity.iri_has_citation_time_span, string, XSD_DURATION, False) 

215 

216 def remove_citation_time_span(self) -> None: 

217 """ 

218 Remover method corresponding to the ``c4o:hasCitationTimeSpan`` RDF predicate. 

219 

220 :return: None 

221 """ 

222 self.g.remove((self.res, GraphEntity.iri_has_citation_time_span, None)) 

223 

224 # HAS CITATION CHARACTERIZATION 

225 def get_citation_characterization(self) -> Optional[str]: 

226 """ 

227 Getter method corresponding to the ``cito:hasCitationCharacterisation`` RDF predicate. 

228 

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

230 """ 

231 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_citation_characterisation) 

232 return uri 

233 

234 def has_citation_characterization(self, thing_res: str) -> None: 

235 """ 

236 Setter method corresponding to the ``cito:hasCitationCharacterisation`` RDF predicate. 

237 

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

239 

240 `The citation function characterizing the purpose of the citation.` 

241 

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

243 :type thing_res: URIRef 

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

245 :return: None 

246 """ 

247 self.remove_citation_characterization() 

248 self.g.add((self.res, GraphEntity.iri_citation_characterisation, RDFTerm("uri", str(thing_res)))) 

249 

250 def remove_citation_characterization(self) -> None: 

251 """ 

252 Remover method corresponding to the ``c4o:hasCitationCharacterisation`` RDF predicate. 

253 

254 :return: None 

255 """ 

256 self.g.remove((self.res, GraphEntity.iri_citation_characterisation, None)) 

257 

258 # HAS TYPE 

259 def create_self_citation(self) -> None: 

260 """ 

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

262 It implicitly sets the object value ``cito:SelfCitation``. 

263 

264 **WARNING: the OCDM specification admits at most two types for an entity. 

265 The main type cannot be edited or removed. Any existing secondary type 

266 will be overwritten!** 

267 

268 :return: None 

269 """ 

270 self._create_type(GraphEntity.iri_self_citation) 

271 

272 def create_affiliation_self_citation(self) -> None: 

273 """ 

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

275 It implicitly sets the object value ``cito:AffiliationSelfCitation``. 

276 

277 **WARNING: the OCDM specification admits at most two types for an entity. 

278 The main type cannot be edited or removed. Any existing secondary type 

279 will be overwritten!** 

280 

281 :return: None 

282 """ 

283 self._create_type(GraphEntity.iri_affiliation_self_citation) 

284 

285 def create_author_network_self_citation(self) -> None: 

286 """ 

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

288 It implicitly sets the object value ``cito:AuthorNetworkSelfCitation``. 

289 

290 **WARNING: the OCDM specification admits at most two types for an entity. 

291 The main type cannot be edited or removed. Any existing secondary type 

292 will be overwritten!** 

293 

294 :return: None 

295 """ 

296 self._create_type(GraphEntity.iri_author_network_self_citation) 

297 

298 def create_author_self_citation(self) -> None: 

299 """ 

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

301 It implicitly sets the object value ``cito:AuthorSelfCitation``. 

302 

303 **WARNING: the OCDM specification admits at most two types for an entity. 

304 The main type cannot be edited or removed. Any existing secondary type 

305 will be overwritten!** 

306 

307 :return: None 

308 """ 

309 self._create_type(GraphEntity.iri_author_self_citation) 

310 

311 def create_funder_self_citation(self) -> None: 

312 """ 

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

314 It implicitly sets the object value ``cito:FunderSelfCitation``. 

315 

316 **WARNING: the OCDM specification admits at most two types for an entity. 

317 The main type cannot be edited or removed. Any existing secondary type 

318 will be overwritten!** 

319 

320 :return: None 

321 """ 

322 self._create_type(GraphEntity.iri_funder_self_citation) 

323 

324 def create_journal_self_citation(self) -> None: 

325 """ 

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

327 It implicitly sets the object value ``cito:JournalSelfCitation``. 

328 

329 **WARNING: the OCDM specification admits at most two types for an entity. 

330 The main type cannot be edited or removed. Any existing secondary type 

331 will be overwritten!** 

332 

333 :return: None 

334 """ 

335 self._create_type(GraphEntity.iri_journal_self_citation) 

336 

337 def create_journal_cartel_citation(self) -> None: 

338 """ 

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

340 It implicitly sets the object value ``cito:JournalCartelCitation``. 

341 

342 **WARNING: the OCDM specification admits at most two types for an entity. 

343 The main type cannot be edited or removed. Any existing secondary type 

344 will be overwritten!** 

345 

346 :return: None 

347 """ 

348 self._create_type(GraphEntity.iri_journal_cartel_citation) 

349 

350 def create_distant_citation(self) -> None: 

351 """ 

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

353 It implicitly sets the object value ``cito:DistantCitation``. 

354 

355 **WARNING: the OCDM specification admits at most two types for an entity. 

356 The main type cannot be edited or removed. Any existing secondary type 

357 will be overwritten!** 

358 

359 :return: None 

360 """ 

361 self._create_type(GraphEntity.iri_distant_citation)