Coverage for oc_ocdm / graph / entities / bibliographic / reference_pointer.py: 100%
63 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.decorators import accepts_only
16if TYPE_CHECKING:
17 from typing import List, Optional
19 from oc_ocdm.graph.entities.bibliographic.bibliographic_reference import BibliographicReference
20 from oc_ocdm.graph.entities.bibliographic.reference_annotation import ReferenceAnnotation
21from oc_ocdm.graph.entities.bibliographic_entity import BibliographicEntity
22from oc_ocdm.graph.graph_entity import GraphEntity
25class ReferencePointer(BibliographicEntity):
26 """Reference pointer (long: in-text reference pointer; short: rp): a textual device (e.g.
27 '[1]'), denoting a single bibliographic reference, that is embedded in the text of a
28 document within the context of a particular sentence or text chunk. A bibliographic
29 reference can be denoted in the text by one or more in-text reference pointers."""
31 def _merge_properties(self, other: GraphEntity, prefer_self: bool) -> None:
32 """
33 The merge operation allows combining two ``ReferencePointer`` entities into a single one,
34 by marking the second entity as to be deleted while also copying its data into the current
35 ``ReferencePointer``. Moreover, every triple from the containing ``GraphSet`` referring to the second
36 entity gets "redirected" to the current entity: **every other reference contained inside a
37 different source (e.g. a triplestore) must be manually handled by the user!**
39 By default, functional values from the current entity get overwritten by values
40 from the second entity. When ``prefer_self`` is True, existing functional values
41 from the current entity are kept. Non-functional values from the second entity
42 are appended to those of the current entity. In this context,
43 ``rdfs:label`` is considered as a functional property, while ``rdf:type`` is not.
45 :param other: The entity which will be marked as to be deleted and whose properties will
46 be merged into the current entity.
47 :type other: ReferencePointer
48 :raises TypeError: if the parameter is of the wrong type
49 :return: None
50 """
51 super()._merge_properties(other, prefer_self)
52 assert isinstance(other, ReferencePointer)
54 content: Optional[str] = other.get_content()
55 if content is not None and self._should_merge_functional_property(self.get_content(), prefer_self):
56 self.has_content(content)
58 next_rp: Optional[ReferencePointer] = other.get_next_rp()
59 if next_rp is not None and self._should_merge_functional_property(self.get_next_rp(), prefer_self):
60 self.has_next_rp(next_rp)
62 denoted_be: Optional[BibliographicReference] = other.get_denoted_be()
63 if denoted_be is not None and self._should_merge_functional_property(self.get_denoted_be(), prefer_self):
64 self.denotes_be(denoted_be)
66 an_list: List[ReferenceAnnotation] = other.get_annotations()
67 for cur_an in an_list:
68 self.has_annotation(cur_an)
70 # HAS REFERENCE POINTER TEXT
71 def get_content(self) -> Optional[str]:
72 """
73 Getter method corresponding to the ``c4o:hasContent`` RDF predicate.
75 :return: The requested value if found, None otherwise
76 """
77 return self._get_literal(GraphEntity.iri_has_content)
79 def has_content(self, string: str) -> None:
80 """
81 Setter method corresponding to the ``c4o:hasContent`` RDF predicate.
83 **WARNING: this is a functional property, hence any existing value will be overwritten!**
85 `The literal text of the textual device forming an in-text reference pointer and denoting
86 a single bibliographic reference (e.g. “[1]”).`
88 :param string: The value that will be set as the object of the property related to this method
89 :type string: str
90 :raises TypeError: if the parameter is of the wrong type
91 :return: None
92 """
93 self.remove_content()
94 self._create_literal(GraphEntity.iri_has_content, string)
96 def remove_content(self) -> None:
97 """
98 Remover method corresponding to the ``c4o:hasContent`` RDF predicate.
100 :return: None
101 """
102 self.g.remove((self.res, GraphEntity.iri_has_content, None))
104 # HAS NEXT (ReferencePointer)
105 def get_next_rp(self) -> Optional[ReferencePointer]:
106 """
107 Getter method corresponding to the ``oco:hasNext`` RDF predicate.
109 :return: The requested value if found, None otherwise
110 """
111 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_has_next, "rp")
112 if uri is not None:
113 return self.g_set.add_rp(self.resp_agent, self.source, uri)
115 @accepts_only("rp")
116 def has_next_rp(self, rp_res: ReferencePointer) -> None:
117 """
118 Setter method corresponding to the ``oco:hasNext`` RDF predicate.
120 **WARNING: this is a functional property, hence any existing value will be overwritten!**
122 `The following in-text reference pointer, when included within a single in-text reference
123 pointer list.`
125 :param rp_res: The value that will be set as the object of the property related to this method
126 :type rp_res: ReferencePointer
127 :raises TypeError: if the parameter is of the wrong type
128 :return: None
129 """
130 self.remove_next_rp()
131 self.g.add((self.res, GraphEntity.iri_has_next, RDFTerm("uri", str(rp_res.res))))
133 def remove_next_rp(self) -> None:
134 """
135 Remover method corresponding to the ``oco:hasNext`` RDF predicate.
137 :return: None
138 """
139 self.g.remove((self.res, GraphEntity.iri_has_next, None))
141 # DENOTES (BibliographicReference)
142 def get_denoted_be(self) -> Optional[BibliographicReference]:
143 """
144 Getter method corresponding to the ``c4o:denotes`` RDF predicate.
146 :return: The requested value if found, None otherwise
147 """
148 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_denotes, "be")
149 if uri is not None:
150 return self.g_set.add_be(self.resp_agent, self.source, uri)
152 @accepts_only("be")
153 def denotes_be(self, be_res: BibliographicReference) -> None:
154 """
155 Setter method corresponding to the ``c4o:denotes`` RDF predicate.
157 **WARNING: this is a functional property, hence any existing value will be overwritten!**
159 `The bibliographic reference included in the list of bibliographic references, denoted by
160 the in-text reference pointer.`
162 :param be_res: The value that will be set as the object of the property related to this method
163 :type be_res: BibliographicReference
164 :raises TypeError: if the parameter is of the wrong type
165 :return: None
166 """
167 self.remove_denoted_be()
168 self.g.add((self.res, GraphEntity.iri_denotes, RDFTerm("uri", str(be_res.res))))
170 def remove_denoted_be(self) -> None:
171 """
172 Remover method corresponding to the ``c4o:denotes`` RDF predicate.
174 :return: None
175 """
176 self.g.remove((self.res, GraphEntity.iri_denotes, None))
178 # HAS ANNOTATION (ReferenceAnnotation)
179 def get_annotations(self) -> List[ReferenceAnnotation]:
180 """
181 Getter method corresponding to the ``oco:hasAnnotation`` RDF predicate.
183 :return: A list containing the requested values if found, None otherwise
184 """
185 uri_list: List[str] = self._get_multiple_uri_references(GraphEntity.iri_has_annotation, "an")
186 result: List[ReferenceAnnotation] = []
187 for uri in uri_list:
188 result.append(self.g_set.add_an(self.resp_agent, self.source, uri))
189 return result
191 @accepts_only("an")
192 def has_annotation(self, an_res: ReferenceAnnotation) -> None:
193 """
194 Setter method corresponding to the ``oco:hasAnnotation`` RDF predicate.
196 `An annotation characterizing the citation to which the in-text reference pointer relates
197 in terms of its citation function (the reason for that citation) specific to the textual
198 location of that in-text reference pointer within the citing entity.`
200 :param an_res: The value that will be set as the object of the property related to this method
201 :type an_res: ReferenceAnnotation
202 :raises TypeError: if the parameter is of the wrong type
203 :return: None
204 """
205 self.g.add((self.res, GraphEntity.iri_has_annotation, RDFTerm("uri", str(an_res.res))))
207 @accepts_only("an")
208 def remove_annotation(self, an_res: ReferenceAnnotation | None = None) -> None:
209 """
210 Remover method corresponding to the ``oco:hasAnnotation`` RDF predicate.
212 **WARNING: this is a non-functional property, hence, if the parameter
213 is None, any existing value will be removed!**
215 :param an_res: If not None, the specific object value that will be removed from the property
216 related to this method (defaults to None)
217 :type an_res: ReferenceAnnotation
218 :raises TypeError: if the parameter is of the wrong type
219 :return: None
220 """
221 if an_res is not None:
222 self.g.remove((self.res, GraphEntity.iri_has_annotation, RDFTerm("uri", str(an_res.res))))
223 else:
224 self.g.remove((self.res, GraphEntity.iri_has_annotation, None))