Coverage for oc_ocdm / graph / entities / bibliographic / citation.py: 98%
86 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-07-06 20:05 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-07-06 20:05 +0000
1#!/usr/bin/python
3# SPDX-FileCopyrightText: 2020-2022 Simone Persiani <iosonopersia@gmail.com>
4#
5# SPDX-License-Identifier: ISC
7# -*- coding: utf-8 -*-
8from __future__ import annotations
10from typing import TYPE_CHECKING
12from triplelite import RDFTerm
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
18if TYPE_CHECKING:
19 from typing import Optional
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
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."""
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!**
44 By default, functional values from the current entity get overwritten by values
45 from the second entity. When ``prefer_self`` is True, existing functional values
46 from the current entity are kept. Non-functional values from the second entity
47 are appended to those of the current entity. In this context,
48 ``rdfs:label`` is considered as a functional property, while ``rdf:type`` is not.
50 :param other: The entity which will be marked as to be deleted and whose properties will
51 be merged into the current entity.
52 :type other: Citation
53 :raises TypeError: if the parameter is of the wrong type
54 :return: None
55 """
56 super()._merge_properties(other, prefer_self)
57 assert isinstance(other, Citation)
59 citing_br: Optional[BibliographicResource] = other.get_citing_entity()
60 if citing_br is not None and self._should_merge_functional_property(self.get_citing_entity(), prefer_self):
61 self.has_citing_entity(citing_br)
63 cited_br: Optional[BibliographicResource] = other.get_cited_entity()
64 if cited_br is not None and self._should_merge_functional_property(self.get_cited_entity(), prefer_self):
65 self.has_cited_entity(cited_br)
67 creation_date: Optional[str] = other.get_citation_creation_date()
68 if creation_date is not None and self._should_merge_functional_property(
69 self.get_citation_creation_date(),
70 prefer_self,
71 ):
72 self.has_citation_creation_date(creation_date)
74 time_span: Optional[str] = other.get_citation_time_span()
75 if time_span is not None and self._should_merge_functional_property(
76 self.get_citation_time_span(),
77 prefer_self,
78 ):
79 self.has_citation_time_span(time_span)
81 characterization: Optional[str] = other.get_citation_characterization()
82 if characterization is not None and self._should_merge_functional_property(
83 self.get_citation_characterization(),
84 prefer_self,
85 ):
86 self.has_citation_characterization(characterization)
88 # HAS CITING DOCUMENT (BibliographicResource)
89 def get_citing_entity(self) -> Optional[BibliographicResource]:
90 """
91 Getter method corresponding to the ``cito:hasCitingEntity`` RDF predicate.
93 :return: The requested value if found, None otherwise
94 """
95 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_has_citing_entity, "br")
96 if uri is not None:
97 return self.g_set.add_br(self.resp_agent, self.source, uri)
99 @accepts_only("br")
100 def has_citing_entity(self, citing_res: BibliographicResource) -> None:
101 """
102 Setter method corresponding to the ``cito:hasCitingEntity`` RDF predicate.
104 **WARNING: this is a functional property, hence any existing value will be overwritten!**
106 `The bibliographic resource which acts as the source for the citation.`
108 :param citing_res: The value that will be set as the object of the property related to this method
109 :type citing_res: BibliographicResource
110 :raises TypeError: if the parameter is of the wrong type
111 :return: None
112 """
113 self.remove_citing_entity()
114 self.g.add((self.res, GraphEntity.iri_has_citing_entity, RDFTerm("uri", str(citing_res.res))))
116 def remove_citing_entity(self) -> None:
117 """
118 Remover method corresponding to the ``cito:hasCitingEntity`` RDF predicate.
120 :return: None
121 """
122 self.g.remove((self.res, GraphEntity.iri_has_citing_entity, None))
124 # HAS CITED DOCUMENT (BibliographicResource)
125 def get_cited_entity(self) -> Optional[BibliographicResource]:
126 """
127 Getter method corresponding to the ``cito:hasCitedEntity`` RDF predicate.
129 :return: The requested value if found, None otherwise
130 """
131 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_has_cited_entity, "br")
132 if uri is not None:
133 return self.g_set.add_br(self.resp_agent, self.source, uri)
135 @accepts_only("br")
136 def has_cited_entity(self, cited_res: BibliographicResource) -> None:
137 """
138 Setter method corresponding to the ``cito:hasCitedEntity`` RDF predicate.
140 **WARNING: this is a functional property, hence any existing value will be overwritten!**
142 `The bibliographic resource which acts as the target for the citation.`
144 :param cited_res: The value that will be set as the object of the property related to this method
145 :type cited_res: BibliographicResource
146 :raises TypeError: if the parameter is of the wrong type
147 :return: None
148 """
149 self.remove_cited_entity()
150 self.g.add((self.res, GraphEntity.iri_has_cited_entity, RDFTerm("uri", str(cited_res.res))))
152 def remove_cited_entity(self) -> None:
153 """
154 Remover method corresponding to the ``c4o:hasCitedEntity`` RDF predicate.
156 :return: None
157 """
158 self.g.remove((self.res, GraphEntity.iri_has_cited_entity, None))
160 # HAS CITATION CREATION DATE
161 def get_citation_creation_date(self) -> Optional[str]:
162 """
163 Getter method corresponding to the ``cito:hasCitationCreationDate`` RDF predicate.
165 :return: The requested value if found, None otherwise
166 """
167 return self._get_literal(GraphEntity.iri_has_citation_creation_date)
169 def has_citation_creation_date(self, string: str) -> None:
170 """
171 Setter method corresponding to the ``cito:hasCitationCreationDate`` RDF predicate.
173 **WARNING: this is a functional property, hence any existing value will be overwritten!**
175 `The date on which the citation was created. This has the same numerical value
176 as the publication date of the citing bibliographic resource, but is a property
177 of the citation itself. When combined with the citation time span, it permits
178 that citation to be located in history.`
180 :param string: The value that will be set as the object of the property related to this method. **It must
181 be a string compliant with the** ``ISO 8601`` **standard.**
182 :type string: str
183 :raises TypeError: if the parameter is of the wrong type
184 :return: None
185 """
186 cur_type, string = get_datatype_from_iso_8601(string)
187 self.remove_citation_creation_date()
188 self._create_literal(GraphEntity.iri_has_citation_creation_date, string, cur_type, False)
190 def remove_citation_creation_date(self) -> None:
191 """
192 Remover method corresponding to the ``c4o:hasCitationCreationDate`` RDF predicate.
194 :return: None
195 """
196 self.g.remove((self.res, GraphEntity.iri_has_citation_creation_date, None))
198 # HAS CITATION TIME SPAN
199 def get_citation_time_span(self) -> Optional[str]:
200 """
201 Getter method corresponding to the ``cito:hasCitationTimeSpan`` RDF predicate.
203 :return: The requested value if found, None otherwise
204 """
205 return self._get_literal(GraphEntity.iri_has_citation_time_span)
207 def has_citation_time_span(self, string: str) -> None:
208 """
209 Setter method corresponding to the ``cito:hasCitationTimeSpan`` RDF predicate.
211 **WARNING: this is a functional property, hence any existing value will be overwritten!**
213 `The date interval between the publication date of the cited bibliographic resource and
214 the publication date of the citing bibliographic resource.`
216 :param string: The value that will be set as the object of the property related to this method. **It must
217 be a string compliant with the** ``xsd:duration`` **datatype.**
218 :type string: str
219 :raises TypeError: if the parameter is of the wrong type
220 :return: None
221 """
222 self.remove_citation_time_span()
223 self._create_literal(GraphEntity.iri_has_citation_time_span, string, XSD_DURATION, False)
225 def remove_citation_time_span(self) -> None:
226 """
227 Remover method corresponding to the ``c4o:hasCitationTimeSpan`` RDF predicate.
229 :return: None
230 """
231 self.g.remove((self.res, GraphEntity.iri_has_citation_time_span, None))
233 # HAS CITATION CHARACTERIZATION
234 def get_citation_characterization(self) -> Optional[str]:
235 """
236 Getter method corresponding to the ``cito:hasCitationCharacterisation`` RDF predicate.
238 :return: The requested value if found, None otherwise
239 """
240 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_citation_characterisation)
241 return uri
243 def has_citation_characterization(self, thing_res: str) -> None:
244 """
245 Setter method corresponding to the ``cito:hasCitationCharacterisation`` RDF predicate.
247 **WARNING: this is a functional property, hence any existing value will be overwritten!**
249 `The citation function characterizing the purpose of the citation.`
251 :param thing_res: The value that will be set as the object of the property related to this method
252 :type thing_res: URIRef
253 :raises TypeError: if the parameter is of the wrong type
254 :return: None
255 """
256 self.remove_citation_characterization()
257 self.g.add((self.res, GraphEntity.iri_citation_characterisation, RDFTerm("uri", str(thing_res))))
259 def remove_citation_characterization(self) -> None:
260 """
261 Remover method corresponding to the ``c4o:hasCitationCharacterisation`` RDF predicate.
263 :return: None
264 """
265 self.g.remove((self.res, GraphEntity.iri_citation_characterisation, None))
267 # HAS TYPE
268 def create_self_citation(self) -> None:
269 """
270 Setter method corresponding to the ``rdf:type`` RDF predicate.
271 It implicitly sets the object value ``cito:SelfCitation``.
273 **WARNING: the OCDM specification admits at most two types for an entity.
274 The main type cannot be edited or removed. Any existing secondary type
275 will be overwritten!**
277 :return: None
278 """
279 self._create_type(GraphEntity.iri_self_citation)
281 def create_affiliation_self_citation(self) -> None:
282 """
283 Setter method corresponding to the ``rdf:type`` RDF predicate.
284 It implicitly sets the object value ``cito:AffiliationSelfCitation``.
286 **WARNING: the OCDM specification admits at most two types for an entity.
287 The main type cannot be edited or removed. Any existing secondary type
288 will be overwritten!**
290 :return: None
291 """
292 self._create_type(GraphEntity.iri_affiliation_self_citation)
294 def create_author_network_self_citation(self) -> None:
295 """
296 Setter method corresponding to the ``rdf:type`` RDF predicate.
297 It implicitly sets the object value ``cito:AuthorNetworkSelfCitation``.
299 **WARNING: the OCDM specification admits at most two types for an entity.
300 The main type cannot be edited or removed. Any existing secondary type
301 will be overwritten!**
303 :return: None
304 """
305 self._create_type(GraphEntity.iri_author_network_self_citation)
307 def create_author_self_citation(self) -> None:
308 """
309 Setter method corresponding to the ``rdf:type`` RDF predicate.
310 It implicitly sets the object value ``cito:AuthorSelfCitation``.
312 **WARNING: the OCDM specification admits at most two types for an entity.
313 The main type cannot be edited or removed. Any existing secondary type
314 will be overwritten!**
316 :return: None
317 """
318 self._create_type(GraphEntity.iri_author_self_citation)
320 def create_funder_self_citation(self) -> None:
321 """
322 Setter method corresponding to the ``rdf:type`` RDF predicate.
323 It implicitly sets the object value ``cito:FunderSelfCitation``.
325 **WARNING: the OCDM specification admits at most two types for an entity.
326 The main type cannot be edited or removed. Any existing secondary type
327 will be overwritten!**
329 :return: None
330 """
331 self._create_type(GraphEntity.iri_funder_self_citation)
333 def create_journal_self_citation(self) -> None:
334 """
335 Setter method corresponding to the ``rdf:type`` RDF predicate.
336 It implicitly sets the object value ``cito:JournalSelfCitation``.
338 **WARNING: the OCDM specification admits at most two types for an entity.
339 The main type cannot be edited or removed. Any existing secondary type
340 will be overwritten!**
342 :return: None
343 """
344 self._create_type(GraphEntity.iri_journal_self_citation)
346 def create_journal_cartel_citation(self) -> None:
347 """
348 Setter method corresponding to the ``rdf:type`` RDF predicate.
349 It implicitly sets the object value ``cito:JournalCartelCitation``.
351 **WARNING: the OCDM specification admits at most two types for an entity.
352 The main type cannot be edited or removed. Any existing secondary type
353 will be overwritten!**
355 :return: None
356 """
357 self._create_type(GraphEntity.iri_journal_cartel_citation)
359 def create_distant_citation(self) -> None:
360 """
361 Setter method corresponding to the ``rdf:type`` RDF predicate.
362 It implicitly sets the object value ``cito:DistantCitation``.
364 **WARNING: the OCDM specification admits at most two types for an entity.
365 The main type cannot be edited or removed. Any existing secondary type
366 will be overwritten!**
368 :return: None
369 """
370 self._create_type(GraphEntity.iri_distant_citation)