use serde::{Deserialize, Serialize};
use std::collections::HashSet;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
pub struct OwlIri(pub String);
impl OwlIri {
pub fn new(s: String) -> Self {
Self(s)
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl std::fmt::Display for OwlIri {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Class {
Named(OwlIri),
Thing,
Nothing,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Property {
Object(OwlIri),
Data(OwlIri),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Individual(pub OwlIri);
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Axiom {
SubClassOf(Class, Class),
EquivalentClasses(Vec<Class>),
DisjointClasses(Vec<Class>),
SubPropertyOf(Property, Property),
EquivalentProperties(Vec<Property>),
ObjectPropertyDomain(Property, Class),
ObjectPropertyRange(Property, Class),
FunctionalProperty(Property),
InverseFunctionalProperty(Property),
TransitiveProperty(Property),
SymmetricProperty(Property),
SameIndividual(Vec<Individual>),
DifferentIndividuals(Vec<Individual>),
ClassAssertion(Class, Individual),
ObjectPropertyAssertion(Property, Individual, Individual),
NegativeObjectPropertyAssertion(Property, Individual, Individual),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Ontology {
pub iri: Option<OwlIri>,
pub axioms: Vec<Axiom>,
pub classes: HashSet<Class>,
pub properties: HashSet<Property>,
pub individuals: HashSet<Individual>,
}
impl Ontology {
pub fn new() -> Self {
Self {
iri: None,
axioms: Vec::new(),
classes: HashSet::new(),
properties: HashSet::new(),
individuals: HashSet::new(),
}
}
pub fn with_iri(iri: OwlIri) -> Self {
Self {
iri: Some(iri),
axioms: Vec::new(),
classes: HashSet::new(),
properties: HashSet::new(),
individuals: HashSet::new(),
}
}
pub fn add_axiom(&mut self, axiom: Axiom) {
match &axiom {
Axiom::SubClassOf(c1, c2) => {
self.classes.insert(c1.clone());
self.classes.insert(c2.clone());
}
Axiom::EquivalentClasses(classes) => {
self.classes.extend(classes.iter().cloned());
}
Axiom::DisjointClasses(classes) => {
self.classes.extend(classes.iter().cloned());
}
Axiom::SubPropertyOf(p1, p2) => {
self.properties.insert(p1.clone());
self.properties.insert(p2.clone());
}
Axiom::EquivalentProperties(properties) => {
self.properties.extend(properties.iter().cloned());
}
Axiom::ObjectPropertyDomain(p, c) => {
self.properties.insert(p.clone());
self.classes.insert(c.clone());
}
Axiom::ObjectPropertyRange(p, c) => {
self.properties.insert(p.clone());
self.classes.insert(c.clone());
}
Axiom::FunctionalProperty(p) |
Axiom::InverseFunctionalProperty(p) |
Axiom::TransitiveProperty(p) |
Axiom::SymmetricProperty(p) => {
self.properties.insert(p.clone());
}
Axiom::SameIndividual(individuals) => {
self.individuals.extend(individuals.iter().cloned());
}
Axiom::DifferentIndividuals(individuals) => {
self.individuals.extend(individuals.iter().cloned());
}
Axiom::ClassAssertion(c, i) => {
self.classes.insert(c.clone());
self.individuals.insert(i.clone());
}
Axiom::ObjectPropertyAssertion(p, i1, i2) |
Axiom::NegativeObjectPropertyAssertion(p, i1, i2) => {
self.properties.insert(p.clone());
self.individuals.insert(i1.clone());
self.individuals.insert(i2.clone());
}
}
self.axioms.push(axiom);
}
}