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

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.decorators import accepts_only 

15 

16if TYPE_CHECKING: 

17 from typing import List, Optional 

18 

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 

23 

24 

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.""" 

30 

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!** 

38 

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. 

44 

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) 

53 

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) 

57 

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) 

61 

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) 

65 

66 an_list: List[ReferenceAnnotation] = other.get_annotations() 

67 for cur_an in an_list: 

68 self.has_annotation(cur_an) 

69 

70 # HAS REFERENCE POINTER TEXT 

71 def get_content(self) -> Optional[str]: 

72 """ 

73 Getter method corresponding to the ``c4o:hasContent`` RDF predicate. 

74 

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

76 """ 

77 return self._get_literal(GraphEntity.iri_has_content) 

78 

79 def has_content(self, string: str) -> None: 

80 """ 

81 Setter method corresponding to the ``c4o:hasContent`` RDF predicate. 

82 

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

84 

85 `The literal text of the textual device forming an in-text reference pointer and denoting 

86 a single bibliographic reference (e.g. “[1]”).` 

87 

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) 

95 

96 def remove_content(self) -> None: 

97 """ 

98 Remover method corresponding to the ``c4o:hasContent`` RDF predicate. 

99 

100 :return: None 

101 """ 

102 self.g.remove((self.res, GraphEntity.iri_has_content, None)) 

103 

104 # HAS NEXT (ReferencePointer) 

105 def get_next_rp(self) -> Optional[ReferencePointer]: 

106 """ 

107 Getter method corresponding to the ``oco:hasNext`` RDF predicate. 

108 

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) 

114 

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. 

119 

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

121 

122 `The following in-text reference pointer, when included within a single in-text reference 

123 pointer list.` 

124 

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)))) 

132 

133 def remove_next_rp(self) -> None: 

134 """ 

135 Remover method corresponding to the ``oco:hasNext`` RDF predicate. 

136 

137 :return: None 

138 """ 

139 self.g.remove((self.res, GraphEntity.iri_has_next, None)) 

140 

141 # DENOTES (BibliographicReference) 

142 def get_denoted_be(self) -> Optional[BibliographicReference]: 

143 """ 

144 Getter method corresponding to the ``c4o:denotes`` RDF predicate. 

145 

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) 

151 

152 @accepts_only("be") 

153 def denotes_be(self, be_res: BibliographicReference) -> None: 

154 """ 

155 Setter method corresponding to the ``c4o:denotes`` RDF predicate. 

156 

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

158 

159 `The bibliographic reference included in the list of bibliographic references, denoted by 

160 the in-text reference pointer.` 

161 

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)))) 

169 

170 def remove_denoted_be(self) -> None: 

171 """ 

172 Remover method corresponding to the ``c4o:denotes`` RDF predicate. 

173 

174 :return: None 

175 """ 

176 self.g.remove((self.res, GraphEntity.iri_denotes, None)) 

177 

178 # HAS ANNOTATION (ReferenceAnnotation) 

179 def get_annotations(self) -> List[ReferenceAnnotation]: 

180 """ 

181 Getter method corresponding to the ``oco:hasAnnotation`` RDF predicate. 

182 

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 

190 

191 @accepts_only("an") 

192 def has_annotation(self, an_res: ReferenceAnnotation) -> None: 

193 """ 

194 Setter method corresponding to the ``oco:hasAnnotation`` RDF predicate. 

195 

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.` 

199 

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)))) 

206 

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. 

211 

212 **WARNING: this is a non-functional property, hence, if the parameter 

213 is None, any existing value will be removed!** 

214 

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))