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

58 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 Optional 

18 

19 from oc_ocdm.graph.entities.bibliographic.responsible_agent import ResponsibleAgent 

20from oc_ocdm.graph.entities.bibliographic_entity import BibliographicEntity 

21from oc_ocdm.graph.graph_entity import GraphEntity 

22 

23 

24class AgentRole(BibliographicEntity): 

25 """Agent role (short: ar): a particular role held by an agent with respect to a bibliographic resource.""" 

26 

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

28 """ 

29 The merge operation allows combining two ``AgentRole`` entities into a single one, 

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

31 ``AgentRole``. Moreover, every triple from the containing ``GraphSet`` referring to the second 

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

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

34 

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

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

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

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

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

40 

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

42 be merged into the current entity. 

43 :type other: AgentRole 

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

45 :return: None 

46 """ 

47 super()._merge_properties(other, prefer_self) 

48 assert isinstance(other, AgentRole) 

49 

50 next_ar: Optional[AgentRole] = other.get_next() 

51 if next_ar is not None and self._should_merge_functional_property(self.get_next(), prefer_self): 

52 self.has_next(next_ar) 

53 

54 resp_agent: Optional[ResponsibleAgent] = other.get_is_held_by() 

55 if resp_agent is not None and self._should_merge_functional_property(self.get_is_held_by(), prefer_self): 

56 self.is_held_by(resp_agent) 

57 

58 role_type: Optional[str] = other.get_role_type() 

59 if role_type is not None and self._should_merge_functional_property(self.get_role_type(), prefer_self): 

60 if role_type == GraphEntity.iri_publisher: 

61 self.create_publisher() 

62 elif role_type == GraphEntity.iri_author: 

63 self.create_author() 

64 elif role_type == GraphEntity.iri_editor: 

65 self.create_editor() 

66 

67 # HAS NEXT (AgentRole) 

68 def get_next(self) -> Optional[AgentRole]: 

69 """ 

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

71 

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

73 """ 

74 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_has_next, "ar") 

75 if uri is not None: 

76 return self.g_set.add_ar(self.resp_agent, self.source, uri) 

77 

78 @accepts_only("ar") 

79 def has_next(self, ar_res: AgentRole) -> None: 

80 """ 

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

82 

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

84 

85 `The previous role in a sequence of agent roles of the same type associated with the 

86 same bibliographic resource (so as to define, for instance, an ordered list of authors).` 

87 

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

89 :type ar_res: AgentRole 

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

91 :return: None 

92 """ 

93 self.remove_next() 

94 self.g.add((self.res, GraphEntity.iri_has_next, RDFTerm("uri", str(ar_res.res)))) 

95 

96 def remove_next(self) -> None: 

97 """ 

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

99 

100 :return: None 

101 """ 

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

103 

104 # IS HELD BY (ResponsibleAgent) 

105 def get_is_held_by(self) -> Optional[ResponsibleAgent]: 

106 """ 

107 Getter method corresponding to the ``pro:isHeldBy`` RDF predicate. 

108 

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

110 """ 

111 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_is_held_by, "ra") 

112 if uri is not None: 

113 return self.g_set.add_ra(self.resp_agent, self.source, uri) 

114 

115 @accepts_only("ra") 

116 def is_held_by(self, ra_res: ResponsibleAgent): 

117 """ 

118 Setter method corresponding to the ``pro:isHeldBy`` RDF predicate. 

119 

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

121 

122 `The agent holding this role with respect to a particular bibliographic resource.` 

123 

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

125 :type ra_res: ResponsibleAgent 

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

127 :return: None 

128 """ 

129 self.remove_is_held_by() 

130 self.g.add((self.res, GraphEntity.iri_is_held_by, RDFTerm("uri", str(ra_res.res)))) 

131 

132 def remove_is_held_by(self) -> None: 

133 """ 

134 Remover method corresponding to the ``pro:isHeldBy`` RDF predicate. 

135 

136 :return: None 

137 """ 

138 self.g.remove((self.res, GraphEntity.iri_is_held_by, None)) 

139 

140 # HAS ROLE TYPE 

141 def get_role_type(self) -> Optional[str]: 

142 """ 

143 Getter method corresponding to the ``pro:withRole`` RDF predicate. 

144 

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

146 """ 

147 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_with_role) 

148 return uri 

149 

150 def create_publisher(self) -> None: 

151 """ 

152 Setter method corresponding to the ``pro:withRole`` RDF predicate. 

153 It implicitly sets the object value ``pro:publisher``. 

154 

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

156 

157 `The specific type of role under consideration (e.g. author, editor or publisher).` 

158 

159 :return: None 

160 """ 

161 self.remove_role_type() 

162 self.g.add((self.res, GraphEntity.iri_with_role, RDFTerm("uri", GraphEntity.iri_publisher))) 

163 

164 def create_author(self) -> None: 

165 """ 

166 Setter method corresponding to the ``pro:withRole`` RDF predicate. 

167 It implicitly sets the object value ``pro:author``. 

168 

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

170 

171 `The specific type of role under consideration (e.g. author, editor or publisher).` 

172 

173 :return: None 

174 """ 

175 self.remove_role_type() 

176 self.g.add((self.res, GraphEntity.iri_with_role, RDFTerm("uri", GraphEntity.iri_author))) 

177 

178 def create_editor(self) -> None: 

179 """ 

180 Setter method corresponding to the ``pro:withRole`` RDF predicate. 

181 It implicitly sets the object value ``pro:editor``. 

182 

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

184 

185 `The specific type of role under consideration (e.g. author, editor or publisher).` 

186 

187 :return: None 

188 """ 

189 self.remove_role_type() 

190 self.g.add((self.res, GraphEntity.iri_with_role, RDFTerm("uri", GraphEntity.iri_editor))) 

191 

192 def remove_role_type(self) -> None: 

193 """ 

194 Remover method corresponding to the ``pro:withRole`` RDF predicate. 

195 

196 :return: None 

197 """ 

198 self.g.remove((self.res, GraphEntity.iri_with_role, None))