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

89 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: 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 rdflib import XSD 

13 

14from oc_ocdm.decorators import accepts_only 

15from oc_ocdm.support.support import get_datatype_from_iso_8601 

16 

17if TYPE_CHECKING: 

18 from typing import Optional 

19 from rdflib import URIRef 

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

21from oc_ocdm.graph.graph_entity import GraphEntity 

22from oc_ocdm.graph.entities.bibliographic_entity import BibliographicEntity 

23 

24 

25class Citation(BibliographicEntity): 

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

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

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

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

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

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

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

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

34 

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

36 """ 

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

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

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

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

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

42 

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

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

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

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

47 

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

49 be merged into the current entity. 

50 :type other: Citation 

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

52 :return: None 

53 """ 

54 super()._merge_properties(other, prefer_self) 

55 assert isinstance(other, Citation) 

56 

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

58 if citing_br is not None: 

59 self.has_citing_entity(citing_br) 

60 

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

62 if cited_br is not None: 

63 self.has_cited_entity(cited_br) 

64 

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

66 if creation_date is not None: 

67 self.has_citation_creation_date(creation_date) 

68 

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

70 if time_span is not None: 

71 self.has_citation_time_span(time_span) 

72 

73 characterization: Optional[URIRef] = other.get_citation_characterization() 

74 if characterization is not None: 

75 self.has_citation_characterization(characterization) 

76 

77 # HAS CITING DOCUMENT (BibliographicResource) 

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

79 """ 

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

81 

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

83 """ 

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

85 if uri is not None: 

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

87 

88 @accepts_only('br') 

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

90 """ 

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

92 

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

94 

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

96 

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

98 :type citing_res: BibliographicResource 

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

100 :return: None 

101 """ 

102 self.remove_citing_entity() 

103 self.g.add((self.res, GraphEntity.iri_has_citing_entity, citing_res.res)) 

104 

105 def remove_citing_entity(self) -> None: 

106 """ 

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

108 

109 :return: None 

110 """ 

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

112 

113 # HAS CITED DOCUMENT (BibliographicResource) 

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

115 """ 

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

117 

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

119 """ 

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

121 if uri is not None: 

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

123 

124 @accepts_only('br') 

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

126 """ 

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

128 

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

130 

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

132 

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

134 :type cited_res: BibliographicResource 

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

136 :return: None 

137 """ 

138 self.remove_cited_entity() 

139 self.g.add((self.res, GraphEntity.iri_has_cited_entity, cited_res.res)) 

140 

141 def remove_cited_entity(self) -> None: 

142 """ 

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

144 

145 :return: None 

146 """ 

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

148 

149 # HAS CITATION CREATION DATE 

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

151 """ 

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

153 

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

155 """ 

156 return self._get_literal(GraphEntity.iri_has_citation_creation_date) 

157 

158 @accepts_only('literal') 

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 @accepts_only('literal') 

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

200 """ 

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

202 

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

204 

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

206 the publication date of the citing bibliographic resource.` 

207 

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

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

210 :type string: str 

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

212 :return: None 

213 """ 

214 self.remove_citation_time_span() 

215 self._create_literal(GraphEntity.iri_has_citation_time_span, string, XSD.duration, False) 

216 

217 def remove_citation_time_span(self) -> None: 

218 """ 

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

220 

221 :return: None 

222 """ 

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

224 

225 # HAS CITATION CHARACTERIZATION 

226 def get_citation_characterization(self) -> Optional[URIRef]: 

227 """ 

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

229 

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

231 """ 

232 uri: Optional[URIRef] = self._get_uri_reference(GraphEntity.iri_citation_characterisation) 

233 return uri 

234 

235 @accepts_only('thing') 

236 def has_citation_characterization(self, thing_res: URIRef) -> None: 

237 """ 

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

239 

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

241 

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

243 

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

245 :type thing_res: URIRef 

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

247 :return: None 

248 """ 

249 self.remove_citation_characterization() 

250 self.g.add((self.res, GraphEntity.iri_citation_characterisation, thing_res)) 

251 

252 def remove_citation_characterization(self) -> None: 

253 """ 

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

255 

256 :return: None 

257 """ 

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

259 

260 # HAS TYPE 

261 def create_self_citation(self) -> None: 

262 """ 

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

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

265 

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

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

268 will be overwritten!** 

269 

270 :return: None 

271 """ 

272 self._create_type(GraphEntity.iri_self_citation) 

273 

274 def create_affiliation_self_citation(self) -> None: 

275 """ 

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

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

278 

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

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

281 will be overwritten!** 

282 

283 :return: None 

284 """ 

285 self._create_type(GraphEntity.iri_affiliation_self_citation) 

286 

287 def create_author_network_self_citation(self) -> None: 

288 """ 

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

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

291 

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

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

294 will be overwritten!** 

295 

296 :return: None 

297 """ 

298 self._create_type(GraphEntity.iri_author_network_self_citation) 

299 

300 def create_author_self_citation(self) -> None: 

301 """ 

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

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

304 

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

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

307 will be overwritten!** 

308 

309 :return: None 

310 """ 

311 self._create_type(GraphEntity.iri_author_self_citation) 

312 

313 def create_funder_self_citation(self) -> None: 

314 """ 

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

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

317 

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

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

320 will be overwritten!** 

321 

322 :return: None 

323 """ 

324 self._create_type(GraphEntity.iri_funder_self_citation) 

325 

326 def create_journal_self_citation(self) -> None: 

327 """ 

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

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

330 

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

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

333 will be overwritten!** 

334 

335 :return: None 

336 """ 

337 self._create_type(GraphEntity.iri_journal_self_citation) 

338 

339 def create_journal_cartel_citation(self) -> None: 

340 """ 

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

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

343 

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

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

346 will be overwritten!** 

347 

348 :return: None 

349 """ 

350 self._create_type(GraphEntity.iri_journal_cartel_citation) 

351 

352 def create_distant_citation(self) -> None: 

353 """ 

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

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

356 

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

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

359 will be overwritten!** 

360 

361 :return: None 

362 """ 

363 self._create_type(GraphEntity.iri_distant_citation)