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}