Coverage for oc_ocdm / graph / entities / bibliographic / reference_pointer.py: 100%

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

13 

14if TYPE_CHECKING: 

15 from typing import Optional, List 

16 from rdflib import URIRef 

17 from oc_ocdm.graph.entities.bibliographic.bibliographic_reference import BibliographicReference 

18 from oc_ocdm.graph.entities.bibliographic.reference_annotation import ReferenceAnnotation 

19from oc_ocdm.graph.graph_entity import GraphEntity 

20from oc_ocdm.graph.entities.bibliographic_entity import BibliographicEntity 

21 

22 

23class ReferencePointer(BibliographicEntity): 

24 """Reference pointer (long: in-text reference pointer; short: rp): a textual device (e.g. 

25 '[1]'), denoting a single bibliographic reference, that is embedded in the text of a 

26 document within the context of a particular sentence or text chunk. A bibliographic 

27 reference can be denoted in the text by one or more in-text reference pointers.""" 

28 

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

30 """ 

31 The merge operation allows combining two ``ReferencePointer`` entities into a single one, 

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

33 ``ReferencePointer``. Moreover, every triple from the containing ``GraphSet`` referring to the second 

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

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

36 

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

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

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

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

41 

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

43 be merged into the current entity. 

44 :type other: ReferencePointer 

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

46 :return: None 

47 """ 

48 super()._merge_properties(other, prefer_self) 

49 assert isinstance(other, ReferencePointer) 

50 

51 content: Optional[str] = other.get_content() 

52 if content is not None: 

53 self.has_content(content) 

54 

55 next_rp: Optional[ReferencePointer] = other.get_next_rp() 

56 if next_rp is not None: 

57 self.has_next_rp(next_rp) 

58 

59 denoted_be: Optional[BibliographicReference] = other.get_denoted_be() 

60 if denoted_be is not None: 

61 self.denotes_be(denoted_be) 

62 

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

64 for cur_an in an_list: 

65 self.has_annotation(cur_an) 

66 

67 # HAS REFERENCE POINTER TEXT 

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

69 """ 

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

71 

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

73 """ 

74 return self._get_literal(GraphEntity.iri_has_content) 

75 

76 @accepts_only('literal') 

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

78 """ 

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

80 

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

82 

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

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

85 

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

87 :type string: str 

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

89 :return: None 

90 """ 

91 self.remove_content() 

92 self._create_literal(GraphEntity.iri_has_content, string) 

93 

94 def remove_content(self) -> None: 

95 """ 

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

97 

98 :return: None 

99 """ 

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

101 

102 # HAS NEXT (ReferencePointer) 

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

104 """ 

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

106 

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

108 """ 

109 uri: Optional[URIRef] = self._get_uri_reference(GraphEntity.iri_has_next, 'rp') 

110 if uri is not None: 

111 return self.g_set.add_rp(self.resp_agent, self.source, uri) 

112 

113 @accepts_only('rp') 

114 def has_next_rp(self, rp_res: ReferencePointer) -> None: 

115 """ 

116 Setter method corresponding to the ``oco:hasNext`` RDF predicate. 

117 

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

119 

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

121 pointer list.` 

122 

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

124 :type rp_res: ReferencePointer 

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

126 :return: None 

127 """ 

128 self.remove_next_rp() 

129 self.g.add((self.res, GraphEntity.iri_has_next, rp_res.res)) 

130 

131 def remove_next_rp(self) -> None: 

132 """ 

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

134 

135 :return: None 

136 """ 

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

138 

139 # DENOTES (BibliographicReference) 

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

141 """ 

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

143 

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

145 """ 

146 uri: Optional[URIRef] = self._get_uri_reference(GraphEntity.iri_denotes, 'be') 

147 if uri is not None: 

148 return self.g_set.add_be(self.resp_agent, self.source, uri) 

149 

150 @accepts_only('be') 

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

152 """ 

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

154 

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

156 

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

158 the in-text reference pointer.` 

159 

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

161 :type be_res: BibliographicReference 

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

163 :return: None 

164 """ 

165 self.remove_denoted_be() 

166 self.g.add((self.res, GraphEntity.iri_denotes, be_res.res)) 

167 

168 def remove_denoted_be(self) -> None: 

169 """ 

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

171 

172 :return: None 

173 """ 

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

175 

176 # HAS ANNOTATION (ReferenceAnnotation) 

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

178 """ 

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

180 

181 :return: A list containing the requested values if found, None otherwise 

182 """ 

183 uri_list: List[URIRef] = self._get_multiple_uri_references(GraphEntity.iri_has_annotation, 'an') 

184 result: List[ReferenceAnnotation] = [] 

185 for uri in uri_list: 

186 result.append(self.g_set.add_an(self.resp_agent, self.source, uri)) 

187 return result 

188 

189 @accepts_only('an') 

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

191 """ 

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

193 

194 `An annotation characterizing the citation to which the in-text reference pointer relates 

195 in terms of its citation function (the reason for that citation) specific to the textual 

196 location of that in-text reference pointer within the citing entity.` 

197 

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

199 :type an_res: ReferenceAnnotation 

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

201 :return: None 

202 """ 

203 self.g.add((self.res, GraphEntity.iri_has_annotation, an_res.res)) 

204 

205 @accepts_only('an') 

206 def remove_annotation(self, an_res: ReferenceAnnotation | None = None) -> None: 

207 """ 

208 Remover method corresponding to the ``oco:hasAnnotation`` RDF predicate. 

209 

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

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

212 

213 :param an_res: If not None, the specific object value that will be removed from the property 

214 related to this method (defaults to None) 

215 :type an_res: ReferenceAnnotation 

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

217 :return: None 

218 """ 

219 if an_res is not None: 

220 self.g.remove((self.res, GraphEntity.iri_has_annotation, an_res.res)) 

221 else: 

222 self.g.remove((self.res, GraphEntity.iri_has_annotation, None))