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

57 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 

16 from rdflib import URIRef 

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

18from oc_ocdm.graph.graph_entity import GraphEntity 

19from oc_ocdm.graph.entities.bibliographic_entity import BibliographicEntity 

20 

21 

22class AgentRole(BibliographicEntity): 

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

24 

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

26 """ 

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

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

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

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

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

32 

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

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

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

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

37 

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

39 be merged into the current entity. 

40 :type other: AgentRole 

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

42 :return: None 

43 """ 

44 super()._merge_properties(other, prefer_self) 

45 assert isinstance(other, AgentRole) 

46 

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

48 if next_ar is not None: 

49 self.has_next(next_ar) 

50 

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

52 if resp_agent is not None: 

53 self.is_held_by(resp_agent) 

54 

55 role_type: Optional[URIRef] = other.get_role_type() 

56 if role_type is not None: 

57 if role_type == GraphEntity.iri_publisher: 

58 self.create_publisher() 

59 elif role_type == GraphEntity.iri_author: 

60 self.create_author() 

61 elif role_type == GraphEntity.iri_editor: 

62 self.create_editor() 

63 

64 # HAS NEXT (AgentRole) 

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

66 """ 

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

68 

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

70 """ 

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

72 if uri is not None: 

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

74 

75 @accepts_only('ar') 

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

77 """ 

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

79 

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

81 

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

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

84 

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

86 :type ar_res: AgentRole 

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

88 :return: None 

89 """ 

90 self.remove_next() 

91 self.g.add((self.res, GraphEntity.iri_has_next, ar_res.res)) 

92 

93 def remove_next(self) -> None: 

94 """ 

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

96 

97 :return: None 

98 """ 

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

100 

101 # IS HELD BY (ResponsibleAgent) 

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

103 """ 

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

105 

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

107 """ 

108 uri: Optional[URIRef] = self._get_uri_reference(GraphEntity.iri_is_held_by, 'ra') 

109 if uri is not None: 

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

111 

112 @accepts_only('ra') 

113 def is_held_by(self, ra_res: ResponsibleAgent): 

114 """ 

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

116 

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

118 

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

120 

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

122 :type ra_res: ResponsibleAgent 

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

124 :return: None 

125 """ 

126 self.remove_is_held_by() 

127 self.g.add((self.res, GraphEntity.iri_is_held_by, ra_res.res)) 

128 

129 def remove_is_held_by(self) -> None: 

130 """ 

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

132 

133 :return: None 

134 """ 

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

136 

137 # HAS ROLE TYPE 

138 def get_role_type(self) -> Optional[URIRef]: 

139 """ 

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

141 

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

143 """ 

144 uri: Optional[URIRef] = self._get_uri_reference(GraphEntity.iri_with_role) 

145 return uri 

146 

147 def create_publisher(self) -> None: 

148 """ 

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

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

151 

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

153 

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

155 

156 :return: None 

157 """ 

158 self.remove_role_type() 

159 self.g.add((self.res, GraphEntity.iri_with_role, GraphEntity.iri_publisher)) 

160 

161 def create_author(self) -> None: 

162 """ 

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

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

165 

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

167 

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

169 

170 :return: None 

171 """ 

172 self.remove_role_type() 

173 self.g.add((self.res, GraphEntity.iri_with_role, GraphEntity.iri_author)) 

174 

175 def create_editor(self) -> None: 

176 """ 

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

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

179 

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

181 

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

183 

184 :return: None 

185 """ 

186 self.remove_role_type() 

187 self.g.add((self.res, GraphEntity.iri_with_role, GraphEntity.iri_editor)) 

188 

189 def remove_role_type(self) -> None: 

190 """ 

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

192 

193 :return: None 

194 """ 

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