use super::indexed::ForIndex;
use super::set::SetOntology;
use crate::{
model::*,
visitor::{entity::IRIExtract, Walk},
};
use std::{
cell::RefCell,
collections::{BTreeMap, BTreeSet},
rc::Rc,
sync::Arc,
};
use super::axiom_mapped::AxiomMappedIndex;
use super::declaration_mapped::DeclarationMappedIndex;
use super::indexed::{FourIndexedOntology, OntologyIndex};
use super::set::SetIndex;
use std::collections::HashSet;
#[derive(Debug, Default, Eq, PartialEq)]
pub struct IRIMappedIndex<A, AA> {
irindex: RefCell<BTreeMap<IRI<A>, BTreeSet<AA>>>,
}
impl<A: ForIRI, AA: ForIndex<A>> IRIMappedIndex<A, AA> {
pub fn new() -> IRIMappedIndex<A, AA> {
IRIMappedIndex {
irindex: RefCell::new(BTreeMap::new()),
}
}
fn aa_to_iris(&self, ax: &AnnotatedAxiom<A>) -> HashSet<IRI<A>> {
let mut w = Walk::new(IRIExtract::default());
w.annotated_axiom(ax);
w.into_visit().into_vec().into_iter().collect()
}
fn axioms_as_ptr(&self, iri: &IRI<A>) -> *mut BTreeMap<IRI<A>, BTreeSet<AA>> {
self.irindex
.borrow_mut()
.entry(iri.clone())
.or_insert_with(BTreeSet::new);
self.irindex.as_ptr()
}
fn set_for_iri(&self, iri: &IRI<A>) -> Option<&BTreeSet<AA>> {
unsafe { (*self.irindex.as_ptr()).get(iri) }
}
fn mut_set_for_iri(&mut self, iri: &IRI<A>) -> &mut BTreeSet<AA> {
unsafe { (*self.axioms_as_ptr(iri)).get_mut(iri).unwrap() }
}
pub fn axiom_for_iri(&self, iri: &IRI<A>) -> impl Iterator<Item = &AnnotatedAxiom<A>> {
self.set_for_iri(iri)
.into_iter()
.flat_map(|hs| hs.iter())
.map(|rc| rc.borrow())
}
pub fn axiom(&self, iri: &IRI<A>) -> impl Iterator<Item = &Axiom<A>> {
self.axiom_for_iri(iri).map(|ann| &ann.axiom)
}
}
impl<A: ForIRI, AA: ForIndex<A>> OntologyIndex<A, AA> for IRIMappedIndex<A, AA> {
fn index_insert(&mut self, ax: AA) -> bool {
let iris = self.aa_to_iris(ax.borrow());
if !iris.is_empty() {
for iri in iris.iter() {
self.mut_set_for_iri(iri).insert(ax.clone());
}
true
} else {
false
}
}
fn index_take(&mut self, ax: &AnnotatedAxiom<A>) -> Option<AnnotatedAxiom<A>> {
let iris = self.aa_to_iris(ax);
if !iris.is_empty() {
let iri = iris.iter().next();
if let Some(iri) = iri {
self.mut_set_for_iri(iri).take(ax).map(|aax| aax.unwrap())
} else {
None
}
} else {
None
}
}
fn index_remove(&mut self, ax: &AnnotatedAxiom<A>) -> bool {
if let Some(iri) = self.aa_to_iris(ax).iter().next() {
self.mut_set_for_iri(&iri.clone()).remove(ax)
} else {
false
}
}
}
#[allow(clippy::type_complexity)]
pub struct IRIMappedOntology<A: ForIRI, AA: ForIndex<A>>(
FourIndexedOntology<
A,
AA,
SetIndex<A, AA>,
IRIMappedIndex<A, AA>,
AxiomMappedIndex<A, AA>,
DeclarationMappedIndex<A, AA>,
>,
);
pub type RcIRIMappedOntology = IRIMappedOntology<RcStr, Rc<AnnotatedAxiom<RcStr>>>;
pub type ArcIRIMappedOntology = IRIMappedOntology<ArcStr, Arc<AnnotatedAxiom<ArcStr>>>;
impl<A: ForIRI, AA: ForIndex<A>> Ontology<A> for IRIMappedOntology<A, AA> {
fn id(&self) -> &OntologyID<A> {
self.0.id()
}
fn mut_id(&mut self) -> &mut OntologyID<A> {
self.0.mut_id()
}
fn doc_iri(&self) -> &Option<IRI<A>> {
self.0.doc_iri()
}
fn mut_doc_iri(&mut self) -> &mut Option<IRI<A>> {
self.0.mut_doc_iri()
}
}
impl<A: ForIRI, AA: ForIndex<A>> MutableOntology<A> for IRIMappedOntology<A, AA> {
fn insert<IAA>(&mut self, ax: IAA) -> bool
where
IAA: Into<AnnotatedAxiom<A>>,
{
self.0.insert(ax)
}
fn take(&mut self, ax: &AnnotatedAxiom<A>) -> Option<AnnotatedAxiom<A>> {
self.0.take(ax)
}
}
impl<A: ForIRI, AA: ForIndex<A>> IRIMappedOntology<A, AA> {
pub fn default() -> IRIMappedOntology<A, AA> {
IRIMappedOntology(FourIndexedOntology::new(
SetIndex::new(),
IRIMappedIndex::new(),
AxiomMappedIndex::new(),
DeclarationMappedIndex::new(),
Default::default(),
))
}
pub fn axiom_for_iri(&mut self, iri: &IRI<A>) -> impl Iterator<Item = &AnnotatedAxiom<A>> {
self.0.j().axiom_for_iri(iri)
}
pub fn axiom_for_kind(&mut self, axkind: AxiomKind) -> impl Iterator<Item = &AnnotatedAxiom<A>> {
self.0.k().axiom_for_kind(axkind)
}
pub fn update_axiom(&mut self, ax: &AnnotatedAxiom<A>, new_ax: AnnotatedAxiom<A>) -> bool {
self.take(ax);
self.insert(new_ax)
}
pub fn iter(&self) -> std::vec::IntoIter<&AnnotatedAxiom<A>> {
self.0.i().into_iter()
}
}
impl RcIRIMappedOntology {
pub fn new_rc() -> Self {
IRIMappedOntology::default()
}
}
impl ArcIRIMappedOntology {
pub fn new_arc() -> Self {
IRIMappedOntology::default()
}
}
impl<A: ForIRI, AA: ForIndex<A>> IntoIterator for IRIMappedOntology<A, AA> {
type Item = AnnotatedAxiom<A>;
type IntoIter = std::vec::IntoIter<AnnotatedAxiom<A>>;
fn into_iter(self) -> Self::IntoIter {
self.0.index().0.into_iter()
}
}
impl<A: ForIRI, AA: ForIndex<A>> From<SetOntology<A>> for IRIMappedOntology<A, AA> {
fn from(mut so: SetOntology<A>) -> IRIMappedOntology<A, AA> {
let mut imo = IRIMappedOntology::default();
std::mem::swap(imo.mut_id(), so.mut_id());
for ax in so {
imo.insert(ax);
}
imo
}
}
impl<A: ForIRI, AA: ForIndex<A>> From<IRIMappedOntology<A, AA>> for SetOntology<A> {
fn from(mut imo: IRIMappedOntology<A, AA>) -> SetOntology<A> {
SetOntology::from_index(imo.mut_id().clone(), imo.0.index().0)
}
}
#[cfg(test)]
mod test {
use super::IRIMappedOntology;
use crate::model::*;
#[test]
fn test_ontology_cons() {
let _ = IRIMappedOntology::new_arc();
assert!(true);
}
#[test]
fn test_ontology_iter_empty() {
let mut it = IRIMappedOntology::new_arc().into_iter();
assert_eq!(it.next(), None);
assert_eq!(it.next(), None);
}
#[test]
fn test_ontology_into_iter() {
let build = Build::new();
let mut o = IRIMappedOntology::new_rc();
let decl1 = DeclareClass(build.class("http://www.example.com#a"));
let decl2 = DeclareClass(build.class("http://www.example.com#b"));
let decl3 = DeclareClass(build.class("http://www.example.com#c"));
let disj1 = DisjointClasses(vec![
ClassExpression::Class(build.class("http://www.example.com#a")),
ClassExpression::Class(build.class("http://www.example.com#b")),
]);
let disj2 = DisjointClasses(vec![
ClassExpression::Class(build.class("http://www.example.com#b")),
ClassExpression::Class(build.class("http://www.example.com#c")),
]);
o.insert(disj1.clone());
o.insert(disj2.clone());
o.insert(decl1.clone());
o.insert(decl2.clone());
o.insert(decl3.clone());
let mut v: Vec<_> = o.into_iter().collect();
v.sort();
assert_eq!(
v,
[
AnnotatedAxiom::from(Axiom::DeclareClass(decl1)),
AnnotatedAxiom::from(Axiom::DeclareClass(decl2)),
AnnotatedAxiom::from(Axiom::DeclareClass(decl3)),
AnnotatedAxiom::from(Axiom::DisjointClasses(disj1)),
AnnotatedAxiom::from(Axiom::DisjointClasses(disj2)),
]
);
}
#[test]
fn test_ontology_into_iter_empty() {
let o = IRIMappedOntology::new_arc();
let mut it = o.into_iter();
assert_eq!(it.next(), None);
assert_eq!(it.next(), None);
}
#[test]
fn test_ontology_iter() {
let build = Build::new();
let mut o = IRIMappedOntology::new_rc();
let decl1 = DeclareClass(build.class("http://www.example.com#a"));
let decl2 = DeclareClass(build.class("http://www.example.com#b"));
let decl3 = DeclareClass(build.class("http://www.example.com#c"));
let disj1 = DisjointClasses(vec![
ClassExpression::Class(build.class("http://www.example.com#a")),
ClassExpression::Class(build.class("http://www.example.com#b")),
]);
let disj2 = DisjointClasses(vec![
ClassExpression::Class(build.class("http://www.example.com#b")),
ClassExpression::Class(build.class("http://www.example.com#c")),
]);
o.insert(disj1.clone());
o.insert(disj2.clone());
o.insert(decl1.clone());
o.insert(decl2.clone());
o.insert(decl3.clone());
let mut v: Vec<_> = o.iter().collect();
v.sort();
assert_eq!(
v,
[
&AnnotatedAxiom::from(Axiom::DeclareClass(decl1)),
&AnnotatedAxiom::from(Axiom::DeclareClass(decl2)),
&AnnotatedAxiom::from(Axiom::DeclareClass(decl3)),
&AnnotatedAxiom::from(Axiom::DisjointClasses(disj1)),
&AnnotatedAxiom::from(Axiom::DisjointClasses(disj2)),
]
);
}
}