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
« prev ^ index » next coverage.py v7.13.4, created at 2026-07-06 20:05 +0000
1#!/usr/bin/python
3# SPDX-FileCopyrightText: 2020-2022 Simone Persiani <iosonopersia@gmail.com>
4#
5# SPDX-License-Identifier: ISC
7# -*- coding: utf-8 -*-
8from __future__ import annotations
10from typing import TYPE_CHECKING
12from triplelite import RDFTerm
14from oc_ocdm.decorators import accepts_only
16if TYPE_CHECKING:
17 from typing import Optional
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
24class AgentRole(BibliographicEntity):
25 """Agent role (short: ar): a particular role held by an agent with respect to a bibliographic resource."""
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!**
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.
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)
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)
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)
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()
67 # HAS NEXT (AgentRole)
68 def get_next(self) -> Optional[AgentRole]:
69 """
70 Getter method corresponding to the ``oco:hasNext`` RDF predicate.
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)
78 @accepts_only("ar")
79 def has_next(self, ar_res: AgentRole) -> None:
80 """
81 Setter method corresponding to the ``oco:hasNext`` RDF predicate.
83 **WARNING: this is a functional property, hence any existing value will be overwritten!**
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).`
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))))
96 def remove_next(self) -> None:
97 """
98 Remover method corresponding to the ``oco:hasNext`` RDF predicate.
100 :return: None
101 """
102 self.g.remove((self.res, GraphEntity.iri_has_next, None))
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.
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)
115 @accepts_only("ra")
116 def is_held_by(self, ra_res: ResponsibleAgent):
117 """
118 Setter method corresponding to the ``pro:isHeldBy`` RDF predicate.
120 **WARNING: this is a functional property, hence any existing value will be overwritten!**
122 `The agent holding this role with respect to a particular bibliographic resource.`
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))))
132 def remove_is_held_by(self) -> None:
133 """
134 Remover method corresponding to the ``pro:isHeldBy`` RDF predicate.
136 :return: None
137 """
138 self.g.remove((self.res, GraphEntity.iri_is_held_by, None))
140 # HAS ROLE TYPE
141 def get_role_type(self) -> Optional[str]:
142 """
143 Getter method corresponding to the ``pro:withRole`` RDF predicate.
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
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``.
155 **WARNING: this is a functional property, hence any existing value will be overwritten!**
157 `The specific type of role under consideration (e.g. author, editor or publisher).`
159 :return: None
160 """
161 self.remove_role_type()
162 self.g.add((self.res, GraphEntity.iri_with_role, RDFTerm("uri", GraphEntity.iri_publisher)))
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``.
169 **WARNING: this is a functional property, hence any existing value will be overwritten!**
171 `The specific type of role under consideration (e.g. author, editor or publisher).`
173 :return: None
174 """
175 self.remove_role_type()
176 self.g.add((self.res, GraphEntity.iri_with_role, RDFTerm("uri", GraphEntity.iri_author)))
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``.
183 **WARNING: this is a functional property, hence any existing value will be overwritten!**
185 `The specific type of role under consideration (e.g. author, editor or publisher).`
187 :return: None
188 """
189 self.remove_role_type()
190 self.g.add((self.res, GraphEntity.iri_with_role, RDFTerm("uri", GraphEntity.iri_editor)))
192 def remove_role_type(self) -> None:
193 """
194 Remover method corresponding to the ``pro:withRole`` RDF predicate.
196 :return: None
197 """
198 self.g.remove((self.res, GraphEntity.iri_with_role, None))