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
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-28 18:52 +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 rdflib import XSD
14from oc_ocdm.decorators import accepts_only
15from oc_ocdm.support.support import get_datatype_from_iso_8601
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
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."""
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!**
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.
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)
57 citing_br: Optional[BibliographicResource] = other.get_citing_entity()
58 if citing_br is not None:
59 self.has_citing_entity(citing_br)
61 cited_br: Optional[BibliographicResource] = other.get_cited_entity()
62 if cited_br is not None:
63 self.has_cited_entity(cited_br)
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)
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)
73 characterization: Optional[URIRef] = other.get_citation_characterization()
74 if characterization is not None:
75 self.has_citation_characterization(characterization)
77 # HAS CITING DOCUMENT (BibliographicResource)
78 def get_citing_entity(self) -> Optional[BibliographicResource]:
79 """
80 Getter method corresponding to the ``cito:hasCitingEntity`` RDF predicate.
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)
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.
93 **WARNING: this is a functional property, hence any existing value will be overwritten!**
95 `The bibliographic resource which acts as the source for the citation.`
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))
105 def remove_citing_entity(self) -> None:
106 """
107 Remover method corresponding to the ``cito:hasCitingEntity`` RDF predicate.
109 :return: None
110 """
111 self.g.remove((self.res, GraphEntity.iri_has_citing_entity, None))
113 # HAS CITED DOCUMENT (BibliographicResource)
114 def get_cited_entity(self) -> Optional[BibliographicResource]:
115 """
116 Getter method corresponding to the ``cito:hasCitedEntity`` RDF predicate.
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)
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.
129 **WARNING: this is a functional property, hence any existing value will be overwritten!**
131 `The bibliographic resource which acts as the target for the citation.`
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))
141 def remove_cited_entity(self) -> None:
142 """
143 Remover method corresponding to the ``c4o:hasCitedEntity`` RDF predicate.
145 :return: None
146 """
147 self.g.remove((self.res, GraphEntity.iri_has_cited_entity, None))
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.
154 :return: The requested value if found, None otherwise
155 """
156 return self._get_literal(GraphEntity.iri_has_citation_creation_date)
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.
163 **WARNING: this is a functional property, hence any existing value will be overwritten!**
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.`
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)
181 def remove_citation_creation_date(self) -> None:
182 """
183 Remover method corresponding to the ``c4o:hasCitationCreationDate`` RDF predicate.
185 :return: None
186 """
187 self.g.remove((self.res, GraphEntity.iri_has_citation_creation_date, None))
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.
194 :return: The requested value if found, None otherwise
195 """
196 return self._get_literal(GraphEntity.iri_has_citation_time_span)
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.
203 **WARNING: this is a functional property, hence any existing value will be overwritten!**
205 `The date interval between the publication date of the cited bibliographic resource and
206 the publication date of the citing bibliographic resource.`
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)
217 def remove_citation_time_span(self) -> None:
218 """
219 Remover method corresponding to the ``c4o:hasCitationTimeSpan`` RDF predicate.
221 :return: None
222 """
223 self.g.remove((self.res, GraphEntity.iri_has_citation_time_span, None))
225 # HAS CITATION CHARACTERIZATION
226 def get_citation_characterization(self) -> Optional[URIRef]:
227 """
228 Getter method corresponding to the ``cito:hasCitationCharacterisation`` RDF predicate.
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
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.
240 **WARNING: this is a functional property, hence any existing value will be overwritten!**
242 `The citation function characterizing the purpose of the citation.`
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))
252 def remove_citation_characterization(self) -> None:
253 """
254 Remover method corresponding to the ``c4o:hasCitationCharacterisation`` RDF predicate.
256 :return: None
257 """
258 self.g.remove((self.res, GraphEntity.iri_citation_characterisation, None))
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``.
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!**
270 :return: None
271 """
272 self._create_type(GraphEntity.iri_self_citation)
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``.
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!**
283 :return: None
284 """
285 self._create_type(GraphEntity.iri_affiliation_self_citation)
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``.
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!**
296 :return: None
297 """
298 self._create_type(GraphEntity.iri_author_network_self_citation)
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``.
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!**
309 :return: None
310 """
311 self._create_type(GraphEntity.iri_author_self_citation)
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``.
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!**
322 :return: None
323 """
324 self._create_type(GraphEntity.iri_funder_self_citation)
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``.
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!**
335 :return: None
336 """
337 self._create_type(GraphEntity.iri_journal_self_citation)
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``.
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!**
348 :return: None
349 """
350 self._create_type(GraphEntity.iri_journal_cartel_citation)
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``.
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!**
361 :return: None
362 """
363 self._create_type(GraphEntity.iri_distant_citation)