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, DataRange, Entity,
7    KeyProperties, ObjectPropertyExpression, StructuralModelError, SubObjectPropertyExpression,
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<L = crate::OwlLiteral, B = crate::BlankNodeId> {
15    /// An entity declaration.
16    Declaration {
17        /// Declared OWL entity.
18        entity: Entity,
19        /// Axiom<L, B> annotations.
20        annotations: AxiomAnnotations<L, B>,
21    },
22    /// A subclass axiom.
23    SubClassOf {
24        /// Subclass expression.
25        sub_class: ClassExpression,
26        /// Superclass expression.
27        super_class: ClassExpression,
28        /// Axiom<L, B> annotations.
29        annotations: AxiomAnnotations<L, B>,
30    },
31    /// An equivalent-classes axiom.
32    EquivalentClasses {
33        /// Equivalent class expressions.
34        #[serde(deserialize_with = "Axiom::<L, B>::deserialize_classes")]
35        classes: Vec<ClassExpression>,
36        /// Axiom<L, B> annotations.
37        annotations: AxiomAnnotations<L, B>,
38    },
39    /// A disjoint-classes axiom.
40    DisjointClasses {
41        /// Disjoint class expressions.
42        #[serde(deserialize_with = "Axiom::<L, B>::deserialize_classes")]
43        classes: Vec<ClassExpression>,
44        /// Axiom<L, B> annotations.
45        annotations: AxiomAnnotations<L, B>,
46    },
47    /// An object-property domain axiom.
48    ObjectPropertyDomain {
49        /// Object property expression.
50        property: ObjectPropertyExpression,
51        /// Domain class expression.
52        domain: ClassExpression,
53        /// Axiom<L, B> annotations.
54        annotations: AxiomAnnotations<L, B>,
55    },
56    /// Object subproperty inclusion, including ordered property-chain inclusion.
57    SubObjectPropertyOf {
58        /// A single property expression or an ordered chain.
59        sub_property: SubObjectPropertyExpression,
60        /// The superproperty expression.
61        super_property: ObjectPropertyExpression,
62        /// Axiom<L, B> annotations.
63        annotations: AxiomAnnotations<L, B>,
64    },
65    /// An object property expression is functional.
66    FunctionalObjectProperty {
67        /// The characterized object property expression.
68        property: ObjectPropertyExpression,
69        /// Axiom<L, B> annotations.
70        annotations: AxiomAnnotations<L, B>,
71    },
72    /// An object property expression is inverse-functional.
73    InverseFunctionalObjectProperty {
74        /// The characterized object property expression.
75        property: ObjectPropertyExpression,
76        /// Axiom<L, B> annotations.
77        annotations: AxiomAnnotations<L, B>,
78    },
79    /// An object property expression is reflexive.
80    ReflexiveObjectProperty {
81        /// The characterized object property expression.
82        property: ObjectPropertyExpression,
83        /// Axiom<L, B> annotations.
84        annotations: AxiomAnnotations<L, B>,
85    },
86    /// An object property expression is irreflexive.
87    IrreflexiveObjectProperty {
88        /// The characterized object property expression.
89        property: ObjectPropertyExpression,
90        /// Axiom<L, B> annotations.
91        annotations: AxiomAnnotations<L, B>,
92    },
93    /// An object property expression is symmetric.
94    SymmetricObjectProperty {
95        /// The characterized object property expression.
96        property: ObjectPropertyExpression,
97        /// Axiom<L, B> annotations.
98        annotations: AxiomAnnotations<L, B>,
99    },
100    /// An object property expression is asymmetric.
101    AsymmetricObjectProperty {
102        /// The characterized object property expression.
103        property: ObjectPropertyExpression,
104        /// Axiom<L, B> annotations.
105        annotations: AxiomAnnotations<L, B>,
106    },
107    /// An object property expression is transitive.
108    TransitiveObjectProperty {
109        /// The characterized object property expression.
110        property: ObjectPropertyExpression,
111        /// Axiom<L, B> annotations.
112        annotations: AxiomAnnotations<L, B>,
113    },
114    /// A data property has at most one distinct data value per individual.
115    FunctionalDataProperty {
116        /// The named data property.
117        property: Iri<String>,
118        /// Axiom<L, B> annotations.
119        annotations: AxiomAnnotations<L, B>,
120    },
121    /// Equivalent object property expressions.
122    EquivalentObjectProperties {
123        /// Equivalent object property expressions.
124        // bounded: operands of one caller-owned structural property axiom.
125        #[serde(deserialize_with = "Axiom::<L, B>::deserialize_property_pair")]
126        properties: Vec<ObjectPropertyExpression>,
127        /// Axiom<L, B> annotations.
128        annotations: AxiomAnnotations<L, B>,
129    },
130    /// Pairwise disjoint object property expressions.
131    DisjointObjectProperties {
132        /// Pairwise disjoint object property expressions.
133        // bounded: operands of one caller-owned structural property axiom.
134        #[serde(deserialize_with = "Axiom::<L, B>::deserialize_property_pair")]
135        properties: Vec<ObjectPropertyExpression>,
136        /// Axiom<L, B> annotations.
137        annotations: AxiomAnnotations<L, B>,
138    },
139    /// Two inverse object property expressions.
140    InverseObjectProperties {
141        /// First object property expression.
142        first: ObjectPropertyExpression,
143        /// Its inverse object property expression.
144        second: ObjectPropertyExpression,
145        /// Axiom<L, B> annotations.
146        annotations: AxiomAnnotations<L, B>,
147    },
148    /// An object property range.
149    ObjectPropertyRange {
150        /// The restricted object property expression.
151        property: ObjectPropertyExpression,
152        /// The range class expression.
153        range: ClassExpression,
154        /// Axiom<L, B> annotations.
155        annotations: AxiomAnnotations<L, B>,
156    },
157    /// A data subproperty inclusion.
158    SubDataPropertyOf {
159        /// The named subproperty.
160        sub_property: Iri<String>,
161        /// The named superproperty.
162        super_property: Iri<String>,
163        /// Axiom<L, B> annotations.
164        annotations: AxiomAnnotations<L, B>,
165    },
166    /// Equivalent data properties.
167    EquivalentDataProperties {
168        /// Equivalent named data properties.
169        // bounded: operands of one caller-owned structural property axiom.
170        #[serde(deserialize_with = "Axiom::<L, B>::deserialize_property_pair")]
171        properties: Vec<Iri<String>>,
172        /// Axiom<L, B> annotations.
173        annotations: AxiomAnnotations<L, B>,
174    },
175    /// Pairwise disjoint data properties.
176    DisjointDataProperties {
177        /// Pairwise disjoint named data properties.
178        // bounded: operands of one caller-owned structural property axiom.
179        #[serde(deserialize_with = "Axiom::<L, B>::deserialize_property_pair")]
180        properties: Vec<Iri<String>>,
181        /// Axiom<L, B> annotations.
182        annotations: AxiomAnnotations<L, B>,
183    },
184    /// A data property domain.
185    DataPropertyDomain {
186        /// The named data property.
187        property: Iri<String>,
188        /// The domain class expression.
189        domain: ClassExpression,
190        /// Axiom<L, B> annotations.
191        annotations: AxiomAnnotations<L, B>,
192    },
193    /// A data property range.
194    DataPropertyRange {
195        /// The named data property.
196        property: Iri<String>,
197        /// The structural data range.
198        range: DataRange<L>,
199        /// Axiom<L, B> annotations.
200        annotations: AxiomAnnotations<L, B>,
201    },
202    /// A datatype definition.
203    DatatypeDefinition {
204        /// The defined datatype.
205        datatype: Iri<String>,
206        /// The defining data range.
207        range: DataRange<L>,
208        /// Axiom<L, B> annotations.
209        annotations: AxiomAnnotations<L, B>,
210    },
211    /// An object/data property key for instances of a class expression.
212    HasKey {
213        /// The class expression identified by the key.
214        class: ClassExpression,
215        /// At least one object or data key property.
216        properties: KeyProperties,
217        /// Axiom<L, B> annotations.
218        annotations: AxiomAnnotations<L, B>,
219    },
220    /// An annotation assertion axiom.
221    AnnotationAssertion {
222        /// Annotation<L, B> property IRI.
223        property: Iri<String>,
224        /// Annotation<L, B> assertion subject.
225        subject: AnnotationSubject<B>,
226        /// Annotation<L, B> assertion value.
227        value: AnnotationValue<L, B>,
228        /// Axiom<L, B> annotations.
229        annotations: AxiomAnnotations<L, B>,
230    },
231}
232
233impl<L, B> Axiom<L, B> {
234    /// Create a declaration axiom without axiom annotations.
235    #[must_use]
236    pub fn declaration(entity: Entity) -> Self {
237        Self::Declaration {
238            entity,
239            annotations: AxiomAnnotations::empty(),
240        }
241    }
242
243    /// Create a subclass axiom without axiom annotations.
244    #[must_use]
245    pub fn sub_class_of(sub_class: ClassExpression, super_class: ClassExpression) -> Self {
246        Self::SubClassOf {
247            sub_class,
248            super_class,
249            annotations: AxiomAnnotations::empty(),
250        }
251    }
252
253    /// Create an equivalent-classes axiom without axiom annotations.
254    ///
255    /// # Errors
256    ///
257    /// Returns [`StructuralModelError::InvalidFormat`] when fewer than two
258    /// class expressions are supplied.
259    pub fn equivalent_classes(classes: Vec<ClassExpression>) -> Result<Self, StructuralModelError> {
260        Self::require_pair(&classes)?;
261        Ok(Self::EquivalentClasses {
262            classes,
263            annotations: AxiomAnnotations::empty(),
264        })
265    }
266
267    /// Create a disjoint-classes axiom without axiom annotations.
268    ///
269    /// # Errors
270    ///
271    /// Returns [`StructuralModelError::InvalidFormat`] when fewer than two
272    /// class expressions are supplied.
273    pub fn disjoint_classes(classes: Vec<ClassExpression>) -> Result<Self, StructuralModelError> {
274        Self::require_pair(&classes)?;
275        Ok(Self::DisjointClasses {
276            classes,
277            annotations: AxiomAnnotations::empty(),
278        })
279    }
280
281    fn require_pair(classes: &[ClassExpression]) -> Result<(), StructuralModelError> {
282        if classes.len() < 2 {
283            return Err(StructuralModelError::InvalidFormat {
284                kind: KIND_AXIOM_OPERANDS,
285                value: classes.len().to_string(),
286                message: "requires at least two class expressions",
287            });
288        }
289        Ok(())
290    }
291    fn deserialize_classes<'de, D: serde::Deserializer<'de>>(
292        deserializer: D,
293    ) -> Result<Vec<ClassExpression>, D::Error> {
294        // bounded: class expressions of one submitted structural axiom.
295        let classes = <Vec<ClassExpression> as serde::Deserialize>::deserialize(deserializer)?;
296        Self::require_pair(&classes).map_err(serde::de::Error::custom)?;
297        Ok(classes)
298    }
299}