owl_structural_model/
property_schema.rs1use iri_rfc3987::Iri;
4use serde::{Deserialize, Deserializer};
5
6use crate::{
7 Axiom, AxiomAnnotations, ClassExpression, DataRange, KeyProperties, ObjectPropertyExpression,
8 StructuralModelError,
9};
10
11impl<L, B> Axiom<L, B> {
12 #[must_use]
14 pub fn object_property_domain(
15 property: ObjectPropertyExpression,
16 domain: ClassExpression,
17 ) -> Self {
18 Self::ObjectPropertyDomain {
19 property,
20 domain,
21 annotations: AxiomAnnotations::empty(),
22 }
23 }
24
25 pub fn equivalent_object_properties(
31 properties: Vec<ObjectPropertyExpression>,
32 ) -> Result<Self, StructuralModelError> {
33 Self::require_property_pair(properties.len())?;
34 Ok(Self::EquivalentObjectProperties {
35 properties,
36 annotations: AxiomAnnotations::empty(),
37 })
38 }
39
40 pub fn disjoint_object_properties(
46 properties: Vec<ObjectPropertyExpression>,
47 ) -> Result<Self, StructuralModelError> {
48 Self::require_property_pair(properties.len())?;
49 Ok(Self::DisjointObjectProperties {
50 properties,
51 annotations: AxiomAnnotations::empty(),
52 })
53 }
54
55 #[must_use]
57 pub fn inverse_object_properties(
58 first: ObjectPropertyExpression,
59 second: ObjectPropertyExpression,
60 ) -> Self {
61 Self::InverseObjectProperties {
62 first,
63 second,
64 annotations: AxiomAnnotations::empty(),
65 }
66 }
67
68 #[must_use]
70 pub fn object_property_range(
71 property: ObjectPropertyExpression,
72 range: ClassExpression,
73 ) -> Self {
74 Self::ObjectPropertyRange {
75 property,
76 range,
77 annotations: AxiomAnnotations::empty(),
78 }
79 }
80
81 #[must_use]
83 pub fn sub_data_property_of(sub_property: Iri<String>, super_property: Iri<String>) -> Self {
84 Self::SubDataPropertyOf {
85 sub_property,
86 super_property,
87 annotations: AxiomAnnotations::empty(),
88 }
89 }
90
91 pub fn equivalent_data_properties(
97 properties: Vec<Iri<String>>,
98 ) -> Result<Self, StructuralModelError> {
99 Self::require_property_pair(properties.len())?;
100 Ok(Self::EquivalentDataProperties {
101 properties,
102 annotations: AxiomAnnotations::empty(),
103 })
104 }
105
106 pub fn disjoint_data_properties(
112 properties: Vec<Iri<String>>,
113 ) -> Result<Self, StructuralModelError> {
114 Self::require_property_pair(properties.len())?;
115 Ok(Self::DisjointDataProperties {
116 properties,
117 annotations: AxiomAnnotations::empty(),
118 })
119 }
120
121 #[must_use]
123 pub fn data_property_domain(property: Iri<String>, domain: ClassExpression) -> Self {
124 Self::DataPropertyDomain {
125 property,
126 domain,
127 annotations: AxiomAnnotations::empty(),
128 }
129 }
130
131 #[must_use]
133 pub fn data_property_range(property: Iri<String>, range: DataRange<L>) -> Self {
134 Self::DataPropertyRange {
135 property,
136 range,
137 annotations: AxiomAnnotations::empty(),
138 }
139 }
140
141 #[must_use]
143 pub fn datatype_definition(datatype: Iri<String>, range: DataRange<L>) -> Self {
144 Self::DatatypeDefinition {
145 datatype,
146 range,
147 annotations: AxiomAnnotations::empty(),
148 }
149 }
150
151 #[must_use]
153 pub fn has_key(class: ClassExpression, properties: KeyProperties) -> Self {
154 Self::HasKey {
155 class,
156 properties,
157 annotations: AxiomAnnotations::empty(),
158 }
159 }
160
161 fn require_property_pair(count: usize) -> Result<(), StructuralModelError> {
162 if count < 2 {
163 return Err(StructuralModelError::InvalidFormat {
164 kind: "property axiom operands",
165 value: count.to_string(),
166 message: "requires at least two property expressions",
167 });
168 }
169 Ok(())
170 }
171
172 pub(crate) fn deserialize_property_pair<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
173 where
174 D: Deserializer<'de>,
175 T: Deserialize<'de>,
176 {
177 let properties = Vec::<T>::deserialize(deserializer)?;
179 Self::require_property_pair(properties.len()).map_err(serde::de::Error::custom)?;
180 Ok(properties)
181 }
182}