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

50 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_resource import BibliographicResource 

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 BibliographicReference(BibliographicEntity): 

26 """Bibliographic reference (short: be): the particular textual bibliographic reference, 

27 usually occurring in the reference list (and denoted by one or more in-text reference 

28 pointers within the text of a citing bibliographic resource), that references another 

29 bibliographic resource. 

30 """ 

31 

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

33 """ 

34 The merge operation allows combining two ``BibliographicReference`` entities into a single one, 

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

36 ``BibliographicReference``. Moreover, every triple from the containing ``GraphSet`` referring to the second 

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

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

39 

40 By default, functional values from the current entity get overwritten by values 

41 from the second entity. When ``prefer_self`` is True, existing functional values 

42 from the current entity are kept. Non-functional values from the second entity 

43 are appended to those of the current entity. In this context, 

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

45 

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

47 be merged into the current entity. 

48 :type other: BibliographicReference 

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

50 :return: None 

51 """ 

52 super()._merge_properties(other, prefer_self) 

53 assert isinstance(other, BibliographicReference) 

54 

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

56 if content is not None and self._should_merge_functional_property(self.get_content(), prefer_self): 

57 self.has_content(content) 

58 

59 annotations_list: List[ReferenceAnnotation] = other.get_annotations() 

60 for cur_annotation in annotations_list: 

61 self.has_annotation(cur_annotation) 

62 

63 referenced_br: Optional[BibliographicResource] = other.get_referenced_br() 

64 if referenced_br is not None and self._should_merge_functional_property(self.get_referenced_br(), prefer_self): 

65 self.references_br(referenced_br) 

66 

67 # HAS BIBLIOGRAPHIC REFERENCE 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 def has_content(self, string: str) -> None: 

77 """ 

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

79 

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

81 

82 `The literal text of a bibliographic reference occurring in the reference list (or 

83 elsewhere) within a bibliographic resource, that references another bibliographic 

84 resource. The reference text should be recorded “as given” in the citing bibliographic 

85 resource, including any errors (e.g. mis-spellings of authors’ names, or changes from 

86 “β” in the original published title to “beta” in the reference text) or omissions (e.g. 

87 omission of the title of the referenced bibliographic resource, or omission of sixth and 

88 subsequent authors’ names, as required by certain publishers), and in whatever format 

89 it has been made available. For instance, the reference text can be either as plain text 

90 or as a block of XML.` 

91 

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

93 :type string: str 

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

95 :return: None 

96 """ 

97 self.remove_content() 

98 self._create_literal(GraphEntity.iri_has_content, string) 

99 

100 def remove_content(self) -> None: 

101 """ 

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

103 

104 :return: None 

105 """ 

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

107 

108 # HAS ANNOTATION (ReferenceAnnotation) 

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

110 """ 

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

112 

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

114 """ 

115 uri_list: List[str] = self._get_multiple_uri_references(GraphEntity.iri_has_annotation, "an") 

116 result: List[ReferenceAnnotation] = [] 

117 for uri in uri_list: 

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

119 return result 

120 

121 @accepts_only("an") 

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

123 """ 

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

125 

126 `An annotation characterizing the related citation, in terms of its citation function (the 

127 reason for that citation).` 

128 

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

130 :type an_res: ReferenceAnnotation 

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

132 :return: None 

133 """ 

134 self.g.add((self.res, GraphEntity.iri_has_annotation, RDFTerm("uri", str(an_res.res)))) 

135 

136 @accepts_only("an") 

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

138 """ 

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

140 

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

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

143 

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

145 related to this method (defaults to None) 

146 :type an_res: ReferenceAnnotation 

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

148 :return: None 

149 """ 

150 if an_res is not None: 

151 self.g.remove((self.res, GraphEntity.iri_has_annotation, RDFTerm("uri", str(an_res.res)))) 

152 else: 

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

154 

155 # REFERENCES (BibliographicResource) 

156 def get_referenced_br(self) -> Optional[BibliographicResource]: 

157 """ 

158 Getter method corresponding to the ``biro:references`` RDF predicate. 

159 

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

161 """ 

162 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_references, "br") 

163 if uri is not None: 

164 return self.g_set.add_br(self.resp_agent, self.source, uri) 

165 

166 @accepts_only("br") 

167 def references_br(self, br_res: BibliographicResource) -> None: 

168 """ 

169 Setter method corresponding to the ``biro:references`` RDF predicate. 

170 

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

172 

173 `The bibliographic reference that cites this bibliographic resource.` 

174 

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

176 :type br_res: BibliographicResource 

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

178 :return: None 

179 """ 

180 self.remove_referenced_br() 

181 self.g.add((self.res, GraphEntity.iri_references, RDFTerm("uri", str(br_res.res)))) 

182 

183 def remove_referenced_br(self) -> None: 

184 """ 

185 Remover method corresponding to the ``biro:references`` RDF predicate. 

186 

187 :return: None 

188 """ 

189 self.g.remove((self.res, GraphEntity.iri_references, None))