Skip to main content

owl_structural_model/
class_expression.rs

1//! OWL class and object-property expressions.
2
3use iri_rfc3987::Iri;
4
5use crate::StructuralModelError;
6
7const KIND_CLASS_EXPRESSION_OPERANDS: &str = "class expression operands";
8
9/// An OWL object property expression.
10#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
11pub enum ObjectPropertyExpression {
12    /// A named object property.
13    Named(Iri<String>),
14    /// The inverse of another object property expression.
15    InverseOf(Box<ObjectPropertyExpression>),
16}
17
18impl ObjectPropertyExpression {
19    /// Create a named object property expression.
20    #[must_use]
21    pub fn named(iri: Iri<String>) -> Self {
22        Self::Named(iri)
23    }
24
25    /// Create an inverse object property expression.
26    #[must_use]
27    pub fn inverse_of(property: Self) -> Self {
28        Self::InverseOf(Box::new(property))
29    }
30}
31
32/// An OWL class expression.
33#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
34pub enum ClassExpression {
35    /// A named class.
36    Named(Iri<String>),
37    /// `owl:Thing`.
38    Thing,
39    /// `owl:Nothing`.
40    Nothing,
41    /// An intersection of class expressions.
42    ObjectIntersectionOf(
43        #[serde(deserialize_with = "ClassExpression::deserialize_operands")] Vec<Self>,
44    ),
45    /// A union of class expressions.
46    ObjectUnionOf(#[serde(deserialize_with = "ClassExpression::deserialize_operands")] Vec<Self>),
47    /// A complement of a class expression.
48    ObjectComplementOf(Box<Self>),
49    /// An existential object-property restriction.
50    ObjectSomeValuesFrom {
51        /// Restricted property.
52        property: ObjectPropertyExpression,
53        /// Required filler.
54        filler: Box<Self>,
55    },
56    /// A universal object-property restriction.
57    ObjectAllValuesFrom {
58        /// Restricted property.
59        property: ObjectPropertyExpression,
60        /// Required filler.
61        filler: Box<Self>,
62    },
63}
64
65impl ClassExpression {
66    /// Create a named class expression.
67    #[must_use]
68    pub fn named(iri: Iri<String>) -> Self {
69        Self::Named(iri)
70    }
71
72    /// Create an intersection expression.
73    ///
74    /// # Errors
75    ///
76    /// Returns [`StructuralModelError::InvalidFormat`] for zero operands.
77    pub fn object_intersection_of(operands: Vec<Self>) -> Result<Self, StructuralModelError> {
78        Self::require_operands(&operands)?;
79        Ok(Self::ObjectIntersectionOf(operands))
80    }
81
82    /// Create a union expression.
83    ///
84    /// # Errors
85    ///
86    /// Returns [`StructuralModelError::InvalidFormat`] for zero operands.
87    pub fn object_union_of(operands: Vec<Self>) -> Result<Self, StructuralModelError> {
88        Self::require_operands(&operands)?;
89        Ok(Self::ObjectUnionOf(operands))
90    }
91
92    /// Create a complement expression.
93    #[must_use]
94    pub fn object_complement_of(operand: Self) -> Self {
95        Self::ObjectComplementOf(Box::new(operand))
96    }
97
98    /// Create an existential object-property restriction.
99    #[must_use]
100    pub fn object_some_values_from(property: ObjectPropertyExpression, filler: Self) -> Self {
101        Self::ObjectSomeValuesFrom {
102            property,
103            filler: Box::new(filler),
104        }
105    }
106
107    /// Create a universal object-property restriction.
108    #[must_use]
109    pub fn object_all_values_from(property: ObjectPropertyExpression, filler: Self) -> Self {
110        Self::ObjectAllValuesFrom {
111            property,
112            filler: Box::new(filler),
113        }
114    }
115
116    fn require_operands(operands: &[Self]) -> Result<(), StructuralModelError> {
117        if operands.is_empty() {
118            return Err(StructuralModelError::InvalidFormat {
119                kind: KIND_CLASS_EXPRESSION_OPERANDS,
120                value: "0".to_owned(),
121                message: "requires at least one operand",
122            });
123        }
124        Ok(())
125    }
126    fn deserialize_operands<'de, D: serde::Deserializer<'de>>(
127        deserializer: D,
128    ) -> Result<Vec<Self>, D::Error> {
129        // bounded: operands of one submitted class expression.
130        let operands = <Vec<Self> as serde::Deserialize>::deserialize(deserializer)?;
131        Self::require_operands(&operands).map_err(serde::de::Error::custom)?;
132        Ok(operands)
133    }
134}