Skip to main content

owl_structural_model/
annotation.rs

1//! OWL annotation values.
2
3use iri_rfc3987::Iri;
4
5use crate::{OwlLiteral, StructuralModelError};
6
7const KIND_ANONYMOUS_INDIVIDUAL: &str = "anonymous individual";
8
9/// An OWL annotation.
10#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
11pub struct Annotation {
12    property: Iri<String>,
13    value: AnnotationValue,
14}
15
16impl Annotation {
17    /// Create an annotation from an annotation property IRI and value.
18    #[must_use]
19    pub fn new(property: Iri<String>, value: AnnotationValue) -> Self { Self { property, value } }
20
21    /// Return the annotation property IRI.
22    #[must_use]
23    pub fn property(&self) -> &Iri<String> { &self.property }
24
25    /// Return the annotation value.
26    #[must_use]
27    pub fn value(&self) -> &AnnotationValue { &self.value }
28}
29
30/// A value that can appear in an OWL annotation.
31#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
32pub enum AnnotationValue {
33    /// An IRI-valued annotation.
34    Iri(Iri<String>),
35    /// An anonymous-individual-valued annotation.
36    AnonymousIndividual(String),
37    /// A literal-valued annotation.
38    Literal(OwlLiteral),
39}
40
41impl AnnotationValue {
42    /// Construct an anonymous individual annotation value.
43    ///
44    /// # Errors
45    ///
46    /// Returns [`StructuralModelError::Empty`] when the label is empty.
47    pub fn anonymous_individual(label: impl Into<String>) -> Result<Self, StructuralModelError> {
48        let label = label.into();
49        if label.is_empty() {
50            return Err(StructuralModelError::Empty { kind: KIND_ANONYMOUS_INDIVIDUAL });
51        }
52        Ok(Self::AnonymousIndividual(label))
53    }
54}
55
56/// Subject of an OWL annotation assertion.
57#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
58pub enum AnnotationSubject {
59    /// An IRI subject.
60    Iri(Iri<String>),
61    /// An anonymous individual subject.
62    AnonymousIndividual(String),
63}
64
65/// Axiom annotations attached to one structural axiom.
66#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
67pub struct AxiomAnnotations {
68    // bounded: annotations belong to one structural axiom.
69    annotations: Vec<Annotation>,
70}
71
72impl AxiomAnnotations {
73    /// Create an empty annotation set.
74    #[must_use]
75    pub fn empty() -> Self { Self::default() }
76
77    /// Create annotations from a bounded axiom-local collection.
78    #[must_use]
79    pub fn new(annotations: Vec<Annotation>) -> Self { Self { annotations } }
80
81    /// Return the annotations.
82    #[must_use]
83    pub fn as_slice(&self) -> &[Annotation] { &self.annotations }
84
85    /// Return the annotation count.
86    #[must_use]
87    pub fn len(&self) -> usize { self.annotations.len() }
88
89    /// Return whether no annotations are present.
90    #[must_use]
91    pub fn is_empty(&self) -> bool { self.annotations.is_empty() }
92}
93