Skip to main content

owl_structural_model/
axiom.rs

1//! OWL structural axioms.
2
3use iri_rfc3987::Iri;
4
5use crate::{
6    AnnotationSubject, AnnotationValue, AxiomAnnotations, ClassExpression, Entity,
7    ObjectPropertyExpression, StructuralModelError,
8};
9
10const KIND_AXIOM_OPERANDS: &str = "axiom operands";
11
12/// An OWL structural axiom.
13#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
14pub enum Axiom {
15    /// An entity declaration.
16    Declaration {
17        /// Declared OWL entity.
18        entity: Entity,
19        /// Axiom annotations.
20        annotations: AxiomAnnotations,
21    },
22    /// A subclass axiom.
23    SubClassOf {
24        /// Subclass expression.
25        sub_class: ClassExpression,
26        /// Superclass expression.
27        super_class: ClassExpression,
28        /// Axiom annotations.
29        annotations: AxiomAnnotations,
30    },
31    /// An equivalent-classes axiom.
32    EquivalentClasses {
33        /// Equivalent class expressions.
34        classes: Vec<ClassExpression>,
35        /// Axiom annotations.
36        annotations: AxiomAnnotations,
37    },
38    /// A disjoint-classes axiom.
39    DisjointClasses {
40        /// Disjoint class expressions.
41        classes: Vec<ClassExpression>,
42        /// Axiom annotations.
43        annotations: AxiomAnnotations,
44    },
45    /// An object-property domain axiom.
46    ObjectPropertyDomain {
47        /// Object property expression.
48        property: ObjectPropertyExpression,
49        /// Domain class expression.
50        domain: ClassExpression,
51        /// Axiom annotations.
52        annotations: AxiomAnnotations,
53    },
54    /// An annotation assertion axiom.
55    AnnotationAssertion {
56        /// Annotation property IRI.
57        property: Iri<String>,
58        /// Annotation assertion subject.
59        subject: AnnotationSubject,
60        /// Annotation assertion value.
61        value: AnnotationValue,
62        /// Axiom annotations.
63        annotations: AxiomAnnotations,
64    },
65}
66
67impl Axiom {
68    /// Create a declaration axiom without axiom annotations.
69    #[must_use]
70    pub fn declaration(entity: Entity) -> Self {
71        Self::Declaration {
72            entity,
73            annotations: AxiomAnnotations::empty(),
74        }
75    }
76
77    /// Create a subclass axiom without axiom annotations.
78    #[must_use]
79    pub fn sub_class_of(sub_class: ClassExpression, super_class: ClassExpression) -> Self {
80        Self::SubClassOf {
81            sub_class,
82            super_class,
83            annotations: AxiomAnnotations::empty(),
84        }
85    }
86
87    /// Create an equivalent-classes axiom without axiom annotations.
88    ///
89    /// # Errors
90    ///
91    /// Returns [`StructuralModelError::InvalidFormat`] when fewer than two
92    /// class expressions are supplied.
93    pub fn equivalent_classes(classes: Vec<ClassExpression>) -> Result<Self, StructuralModelError> {
94        Self::require_pair(&classes)?;
95        Ok(Self::EquivalentClasses {
96            classes,
97            annotations: AxiomAnnotations::empty(),
98        })
99    }
100
101    /// Create a disjoint-classes axiom without axiom annotations.
102    ///
103    /// # Errors
104    ///
105    /// Returns [`StructuralModelError::InvalidFormat`] when fewer than two
106    /// class expressions are supplied.
107    pub fn disjoint_classes(classes: Vec<ClassExpression>) -> Result<Self, StructuralModelError> {
108        Self::require_pair(&classes)?;
109        Ok(Self::DisjointClasses {
110            classes,
111            annotations: AxiomAnnotations::empty(),
112        })
113    }
114
115    fn require_pair(classes: &[ClassExpression]) -> Result<(), StructuralModelError> {
116        if classes.len() < 2 {
117            return Err(StructuralModelError::InvalidFormat {
118                kind: KIND_AXIOM_OPERANDS,
119                value: classes.len().to_string(),
120                message: "requires at least two class expressions",
121            });
122        }
123        Ok(())
124    }
125}