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

23 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.citation import Citation 

20from oc_ocdm.graph.entities.bibliographic_entity import BibliographicEntity 

21from oc_ocdm.graph.graph_entity import GraphEntity 

22 

23 

24class ReferenceAnnotation(BibliographicEntity): 

25 """Reference annotation (short: an): an annotation, attached either to an in-text 

26 reference pointer or to a bibliographic reference, describing the related citation. If an 

27 in-text reference pointer is annotated, the related citation may be characterized with a 

28 citation function (the reason for that citation) specific to the textual location of that 

29 in-text reference pointer within the citing entity. If a bibliographic reference is 

30 annotated, the related citation may be similarly characterized in a more general way 

31 with a citation function (the reason for that citation).""" 

32 

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

34 """ 

35 The merge operation allows combining two ``ReferenceAnnotation`` entities into a single one, 

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

37 ``ReferenceAnnotation``. Moreover, every triple from the containing ``GraphSet`` referring to the second 

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

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

40 

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

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

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

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

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

46 

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

48 be merged into the current entity. 

49 :type other: ReferenceAnnotation 

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

51 :return: None 

52 """ 

53 super()._merge_properties(other, prefer_self) 

54 assert isinstance(other, ReferenceAnnotation) 

55 

56 citation: Optional[Citation] = other.get_body_annotation() 

57 if citation is not None and self._should_merge_functional_property(self.get_body_annotation(), prefer_self): 

58 self.has_body_annotation(citation) 

59 

60 # HAS CITATION (Citation) 

61 def get_body_annotation(self) -> Optional[Citation]: 

62 """ 

63 Getter method corresponding to the ``oa:hasBody`` RDF predicate. 

64 

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

66 """ 

67 uri: Optional[str] = self._get_uri_reference(GraphEntity.iri_has_body, "ci") 

68 if uri is not None: 

69 return self.g_set.add_ci(self.resp_agent, self.source, uri) 

70 

71 @accepts_only("ci") 

72 def has_body_annotation(self, ci_res: Citation) -> None: 

73 """ 

74 Setter method corresponding to the ``oa:hasBody`` RDF predicate. 

75 

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

77 

78 `The citation to which the annotation relates, that is relevant either to a bibliographic 

79 reference or to an in-text reference pointer that denotes such a bibliographic reference.` 

80 

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

82 :type ci_res: Citation 

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

84 :return: None 

85 """ 

86 self.remove_body_annotation() 

87 self.g.add((self.res, GraphEntity.iri_has_body, RDFTerm("uri", str(ci_res.res)))) 

88 

89 def remove_body_annotation(self) -> None: 

90 """ 

91 Remover method corresponding to the ``oa:hasBody`` RDF predicate. 

92 

93 :return: None 

94 """ 

95 self.g.remove((self.res, GraphEntity.iri_has_body, None))