Skip to main content

fukurow_lite/
model.rs

1//! OWL Lite データモデル
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashSet;
5
6/// OWL IRI wrapper for type safety
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
8pub struct OwlIri(pub String);
9
10impl OwlIri {
11    pub fn new(s: String) -> Self {
12        Self(s)
13    }
14
15    pub fn as_str(&self) -> &str {
16        &self.0
17    }
18}
19
20impl std::fmt::Display for OwlIri {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        write!(f, "{}", self.0)
23    }
24}
25
26/// OWL Class
27#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
28pub enum Class {
29    /// Named class
30    Named(OwlIri),
31    /// owl:Thing (⊤)
32    Thing,
33    /// owl:Nothing (⊥)
34    Nothing,
35}
36
37/// OWL Property
38#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
39pub enum Property {
40    /// Object property
41    Object(OwlIri),
42    /// Data property
43    Data(OwlIri),
44}
45
46/// OWL Individual
47#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
48pub struct Individual(pub OwlIri);
49
50/// OWL Axiom (OWL Lite subset)
51#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
52pub enum Axiom {
53    /// SubClassOf(C1 C2)
54    SubClassOf(Class, Class),
55
56    /// EquivalentClasses(C1 ... Cn)
57    EquivalentClasses(Vec<Class>),
58
59    /// DisjointClasses(C1 ... Cn)
60    DisjointClasses(Vec<Class>),
61
62    /// SubPropertyOf(P1 P2)
63    SubPropertyOf(Property, Property),
64
65    /// EquivalentProperties(P1 ... Pn)
66    EquivalentProperties(Vec<Property>),
67
68    /// ObjectPropertyDomain(P C)
69    ObjectPropertyDomain(Property, Class),
70
71    /// ObjectPropertyRange(P C)
72    ObjectPropertyRange(Property, Class),
73
74    /// FunctionalProperty(P)
75    FunctionalProperty(Property),
76
77    /// InverseFunctionalProperty(P)
78    InverseFunctionalProperty(Property),
79
80    /// TransitiveProperty(P)
81    TransitiveProperty(Property),
82
83    /// SymmetricProperty(P)
84    SymmetricProperty(Property),
85
86    /// SameIndividual(i1 ... in)
87    SameIndividual(Vec<Individual>),
88
89    /// DifferentIndividuals(i1 ... in)
90    DifferentIndividuals(Vec<Individual>),
91
92    /// ClassAssertion(C i)
93    ClassAssertion(Class, Individual),
94
95    /// ObjectPropertyAssertion(P i1 i2)
96    ObjectPropertyAssertion(Property, Individual, Individual),
97
98    /// NegativeObjectPropertyAssertion(P i1 i2)
99    NegativeObjectPropertyAssertion(Property, Individual, Individual),
100}
101
102/// OWL Ontology
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct Ontology {
105    /// Ontology IRI
106    pub iri: Option<OwlIri>,
107
108    /// All axioms in the ontology
109    pub axioms: Vec<Axiom>,
110
111    /// All classes mentioned in the ontology
112    pub classes: HashSet<Class>,
113
114    /// All properties mentioned in the ontology
115    pub properties: HashSet<Property>,
116
117    /// All individuals mentioned in the ontology
118    pub individuals: HashSet<Individual>,
119}
120
121impl Ontology {
122    pub fn new() -> Self {
123        Self {
124            iri: None,
125            axioms: Vec::new(),
126            classes: HashSet::new(),
127            properties: HashSet::new(),
128            individuals: HashSet::new(),
129        }
130    }
131
132    pub fn with_iri(iri: OwlIri) -> Self {
133        Self {
134            iri: Some(iri),
135            axioms: Vec::new(),
136            classes: HashSet::new(),
137            properties: HashSet::new(),
138            individuals: HashSet::new(),
139        }
140    }
141
142    pub fn add_axiom(&mut self, axiom: Axiom) {
143        // Extract classes, properties, and individuals from the axiom
144        match &axiom {
145            Axiom::SubClassOf(c1, c2) => {
146                self.classes.insert(c1.clone());
147                self.classes.insert(c2.clone());
148            }
149            Axiom::EquivalentClasses(classes) => {
150                self.classes.extend(classes.iter().cloned());
151            }
152            Axiom::DisjointClasses(classes) => {
153                self.classes.extend(classes.iter().cloned());
154            }
155            Axiom::SubPropertyOf(p1, p2) => {
156                self.properties.insert(p1.clone());
157                self.properties.insert(p2.clone());
158            }
159            Axiom::EquivalentProperties(properties) => {
160                self.properties.extend(properties.iter().cloned());
161            }
162            Axiom::ObjectPropertyDomain(p, c) => {
163                self.properties.insert(p.clone());
164                self.classes.insert(c.clone());
165            }
166            Axiom::ObjectPropertyRange(p, c) => {
167                self.properties.insert(p.clone());
168                self.classes.insert(c.clone());
169            }
170            Axiom::FunctionalProperty(p) |
171            Axiom::InverseFunctionalProperty(p) |
172            Axiom::TransitiveProperty(p) |
173            Axiom::SymmetricProperty(p) => {
174                self.properties.insert(p.clone());
175            }
176            Axiom::SameIndividual(individuals) => {
177                self.individuals.extend(individuals.iter().cloned());
178            }
179            Axiom::DifferentIndividuals(individuals) => {
180                self.individuals.extend(individuals.iter().cloned());
181            }
182            Axiom::ClassAssertion(c, i) => {
183                self.classes.insert(c.clone());
184                self.individuals.insert(i.clone());
185            }
186            Axiom::ObjectPropertyAssertion(p, i1, i2) |
187            Axiom::NegativeObjectPropertyAssertion(p, i1, i2) => {
188                self.properties.insert(p.clone());
189                self.individuals.insert(i1.clone());
190                self.individuals.insert(i2.clone());
191            }
192        }
193
194        self.axioms.push(axiom);
195    }
196}