owl_structural_model/
axiom.rs1use 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#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
14pub enum Axiom {
15 Declaration {
17 entity: Entity,
19 annotations: AxiomAnnotations,
21 },
22 SubClassOf {
24 sub_class: ClassExpression,
26 super_class: ClassExpression,
28 annotations: AxiomAnnotations,
30 },
31 EquivalentClasses {
33 classes: Vec<ClassExpression>,
35 annotations: AxiomAnnotations,
37 },
38 DisjointClasses {
40 classes: Vec<ClassExpression>,
42 annotations: AxiomAnnotations,
44 },
45 ObjectPropertyDomain {
47 property: ObjectPropertyExpression,
49 domain: ClassExpression,
51 annotations: AxiomAnnotations,
53 },
54 AnnotationAssertion {
56 property: Iri<String>,
58 subject: AnnotationSubject,
60 value: AnnotationValue,
62 annotations: AxiomAnnotations,
64 },
65}
66
67impl Axiom {
68 #[must_use]
70 pub fn declaration(entity: Entity) -> Self {
71 Self::Declaration {
72 entity,
73 annotations: AxiomAnnotations::empty(),
74 }
75 }
76
77 #[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 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 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}