diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b52150d..385e8f1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,6 +15,12 @@ repos: entry: make pre-commit pass_filenames: false stages: [pre-commit, pre-push] + - id: Compile Benches + name: Compile Benches + language: system + entry: cargo bench --no-run --quiet + pass_filenames: false + stages: [pre-commit, pre-push] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: diff --git a/benches/io.rs b/benches/io.rs index 125e987..864192d 100644 --- a/benches/io.rs +++ b/benches/io.rs @@ -1,4 +1,6 @@ use criterion::{criterion_group, AxisScale, BenchmarkId, Criterion, PlotConfiguration}; +use horned_owl::model::RcStr; +use horned_owl::ontology::set::SetOntology; use std::fs::File; use std::io::BufReader; use std::time::Duration; @@ -20,7 +22,10 @@ fn io_read(c: &mut Criterion) { b.iter(|| { let f = File::open(format!("benches/ont/o{}.owx", n)).ok().unwrap(); let mut f = BufReader::new(f); - let _ = horned_owl::io::owx::reader::read(&mut f, Default::default()).ok(); + let _: (SetOntology, _) = + horned_owl::io::owx::reader::read(&mut f, Default::default()) + .ok() + .unwrap(); }) }); } diff --git a/benches/model.rs b/benches/model.rs index e250a50..9d18eb2 100644 --- a/benches/model.rs +++ b/benches/model.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use criterion::{criterion_group, AxisScale, BenchmarkId, Criterion, PlotConfiguration}; -use horned_owl::io::rdf::reader::RDFOntology; +use horned_owl::io::rdf::reader::ConcreteRDFOntology; use horned_owl::model::*; use horned_owl::ontology::component_mapped::ComponentMappedOntology; use horned_owl::ontology::declaration_mapped::DeclarationMappedIndex; @@ -237,7 +237,7 @@ fn food_to_vec() -> Vec { std::fs::read("./benches/ont/food.owl").unwrap() } -fn read_vec>(v: &Vec, b: Build) -> RDFOntology { +fn read_vec>(v: &Vec, b: Build) -> ConcreteRDFOntology { let mut c = Cursor::new(v.clone()); horned_owl::io::rdf::reader::read_with_build(&mut c, &b, Default::default()) .unwrap() @@ -253,21 +253,21 @@ fn food(c: &mut Criterion) { group.bench_function("food_rc_str_rc_comp", |b| { b.iter(|| { let b: Build = Build::new(); - let _: RDFOntology = read_vec(&food, b); + let _: ConcreteRDFOntology = read_vec(&food, b); }) }); group.bench_function("food_arc_str_arc_comp", |b| { b.iter(|| { let b: Build = Build::new(); - let _: RDFOntology = read_vec(&food, b); + let _: ConcreteRDFOntology = read_vec(&food, b); }) }); group.bench_function("food_string_direct_comp", |b| { b.iter(|| { let b: Build = Build::new(); - let _: RDFOntology> = read_vec(&food, b); + let _: ConcreteRDFOntology> = read_vec(&food, b); }) }); } diff --git a/horned-bin/src/bin/horned_unparsed.rs b/horned-bin/src/bin/horned_unparsed.rs index 5995962..f02ea97 100644 --- a/horned-bin/src/bin/horned_unparsed.rs +++ b/horned-bin/src/bin/horned_unparsed.rs @@ -7,7 +7,7 @@ use clap::ArgMatches; use horned_bin::config::{parser_app, parser_config}; use horned_owl::error::HornedError; -use horned_owl::io::rdf::reader::RDFOntology; +use horned_owl::io::rdf::reader::ConcreteRDFOntology; use horned_owl::model::{RcAnnotatedComponent, RcStr}; use std::{fs::File, io::BufReader, path::Path}; @@ -38,7 +38,7 @@ pub(crate) fn matcher(matches: &ArgMatches) -> Result<(), HornedError> { HornedError::CommandError("Command requires an INPUT argument".to_string()) })?; - let (_ont, incomplete): (RDFOntology, _) = + let (_ont, incomplete): (ConcreteRDFOntology, _) = horned_owl::io::rdf::reader::read( &mut BufReader::new(File::open(Path::new(input))?), parser_config(matches), diff --git a/src/io/mod.rs b/src/io/mod.rs index 450771b..d117a9e 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -7,7 +7,7 @@ pub mod rdf; use curie::PrefixMapping; -use self::rdf::reader::{IncompleteParse, RDFOntology}; +use self::rdf::reader::{ConcreteRDFOntology, IncompleteParse}; use crate::ontology::indexed::ForIndex; use crate::{ model::ForIRI, @@ -23,7 +23,7 @@ pub enum ResourceType { pub enum ParserOutput> { OFNParser(SetOntology, PrefixMapping), OWXParser(SetOntology, PrefixMapping), - RDFParser(RDFOntology, IncompleteParse), + RDFParser(ConcreteRDFOntology, IncompleteParse), } impl> ParserOutput { @@ -35,7 +35,7 @@ impl> ParserOutput { ParserOutput::OWXParser(sop.0, sop.1) } - pub fn rdf(rop: (RDFOntology, IncompleteParse)) -> ParserOutput { + pub fn rdf(rop: (ConcreteRDFOntology, IncompleteParse)) -> ParserOutput { ParserOutput::RDFParser(rop.0, rop.1) } } diff --git a/src/io/ofn/reader/from_pair.rs b/src/io/ofn/reader/from_pair.rs index ec737ed..a066ccf 100644 --- a/src/io/ofn/reader/from_pair.rs +++ b/src/io/ofn/reader/from_pair.rs @@ -1,4 +1,5 @@ use std::collections::BTreeSet; +use std::marker::PhantomData; use std::str::FromStr; use curie::Curie; @@ -8,7 +9,6 @@ use pest::iterators::Pair; use crate::error::HornedError; use crate::model::*; -use crate::ontology::set::SetOntology; use crate::vocab::{Facet, OWL2Datatype, OWL}; use super::Context; @@ -941,63 +941,62 @@ impl FromPair for ObjectPropertyExpression { } // --------------------------------------------------------------------------- +pub(crate) struct MutableOntologyWrapper + Ontology + Default>( + pub(crate) O, + PhantomData, +); -macro_rules! impl_ontology { - ($ty:ident) => { - impl FromPair for $ty { - const RULE: Rule = Rule::Ontology; - fn from_pair_unchecked(pair: Pair, ctx: &Context<'_, A>) -> Result { - debug_assert!(pair.as_rule() == Rule::Ontology); - let mut pairs = pair.into_inner(); - let mut pair = pairs.next().unwrap(); - - let mut ontology = $ty::default(); - let mut ontology_id = OntologyID::default(); - - // Parse ontology IRI and Version IRI if any - if pair.as_rule() == Rule::OntologyIRI { - let inner = pair.into_inner().next().unwrap(); - ontology_id.iri = Some(IRI::from_pair(inner, ctx)?); - pair = pairs.next().unwrap(); - if pair.as_rule() == Rule::VersionIRI { - let inner = pair.into_inner().next().unwrap(); - ontology_id.viri = Some(IRI::from_pair(inner, ctx)?); - pair = pairs.next().unwrap(); - } - } - ontology.insert(ontology_id); +impl + Ontology + Default> FromPair + for MutableOntologyWrapper +{ + const RULE: Rule = Rule::Ontology; + fn from_pair_unchecked(pair: Pair, ctx: &Context<'_, A>) -> Result { + debug_assert!(pair.as_rule() == Rule::Ontology); + let mut pairs = pair.into_inner(); + let mut pair = pairs.next().unwrap(); - // Process imports - for p in pair.into_inner() { - ontology.insert(Import::from_pair(p, ctx)?); - } + let mut ontology: O = Default::default(); + let mut ontology_id = OntologyID::default(); - // Process ontology annotations - for pair in pairs.next().unwrap().into_inner() { - ontology.insert(OntologyAnnotation::from_pair(pair, ctx)?); - } + // Parse ontology IRI and Version IRI if any + if pair.as_rule() == Rule::OntologyIRI { + let inner = pair.into_inner().next().unwrap(); + ontology_id.iri = Some(IRI::from_pair(inner, ctx)?); + pair = pairs.next().unwrap(); + if pair.as_rule() == Rule::VersionIRI { + let inner = pair.into_inner().next().unwrap(); + ontology_id.viri = Some(IRI::from_pair(inner, ctx)?); + pair = pairs.next().unwrap(); + } + } + ontology.insert(ontology_id); - // Process axioms, ignore SWRL rules - for pair in pairs.next().unwrap().into_inner() { - let inner = pair.into_inner().next().unwrap(); - match inner.as_rule() { - Rule::Axiom => { - ontology.insert(AnnotatedComponent::from_pair(inner, ctx)?); - } - rule => { - unreachable!("unexpected rule in Ontology::from_pair: {:?}", rule); - } - } - } + // Process imports + for p in pair.into_inner() { + ontology.insert(Import::from_pair(p, ctx)?); + } + + // Process ontology annotations + for pair in pairs.next().unwrap().into_inner() { + ontology.insert(OntologyAnnotation::from_pair(pair, ctx)?); + } - Ok(ontology) + // Process axioms, ignore SWRL rules + for pair in pairs.next().unwrap().into_inner() { + let inner = pair.into_inner().next().unwrap(); + match inner.as_rule() { + Rule::Axiom => { + ontology.insert(AnnotatedComponent::from_pair(inner, ctx)?); + } + rule => { + unreachable!("unexpected rule in Ontology::from_pair: {:?}", rule); + } } } - }; -} -impl_ontology!(SetOntology); -// impl_ontology!(AxiomMappedOntology); + Ok(MutableOntologyWrapper(ontology, Default::default())) + } +} // --------------------------------------------------------------------------- @@ -1035,17 +1034,18 @@ impl FromPair for PrefixMapping { // --------------------------------------------------------------------------- -impl FromPair for (O, PrefixMapping) +impl FromPair for (MutableOntologyWrapper, PrefixMapping) where A: ForIRI, - O: Ontology + FromPair, + O: Default + MutableOntology + Ontology, { const RULE: Rule = Rule::OntologyDocument; fn from_pair_unchecked(pair: Pair, ctx: &Context<'_, A>) -> Result { let mut pairs = pair.into_inner(); let prefixes = PrefixMapping::from_pair(pairs.next().unwrap(), ctx)?; let context = Context::new(ctx.build, &prefixes); - O::from_pair(pairs.next().unwrap(), &context).map(|ont| (ont, prefixes)) + MutableOntologyWrapper::from_pair(pairs.next().unwrap(), &context) + .map(|ont| (ont, prefixes)) } } @@ -1117,6 +1117,7 @@ mod tests { use super::*; use crate::io::ofn::reader::lexer::OwlFunctionalLexer; + use crate::ontology::set::SetOntology; use test_generator::test_resources; @@ -1244,8 +1245,10 @@ mod tests { .next() .unwrap(); - let doc: (SetOntology, PrefixMapping) = - FromPair::from_pair(pair, &Context::new(&build, &prefixes)).unwrap(); + let doc: ( + MutableOntologyWrapper<_, SetOntology>, + PrefixMapping, + ) = FromPair::from_pair(pair, &Context::new(&build, &prefixes)).unwrap(); assert_eq!( doc.1.mappings().collect::>(), expected.mappings().collect::>() @@ -1291,7 +1294,8 @@ mod tests { let build = Build::new(); let prefixes = PrefixMapping::default(); let ctx = Context::new(&build, &prefixes); - let item: (SetOntology>, _) = FromPair::from_pair(pair, &ctx).unwrap(); + let item: (MutableOntologyWrapper<_, SetOntology>>, _) = + FromPair::from_pair(pair, &ctx).unwrap(); let path = resource .replace("owl-functional", "owl-xml") @@ -1301,6 +1305,6 @@ mod tests { crate::io::owx::reader::read(&mut Cursor::new(&owx), Default::default()).unwrap(); // pretty_assertions::assert_eq!(item.1, expected.1); - pretty_assertions::assert_eq!(item.0, expected.0); + pretty_assertions::assert_eq!(item.0 .0, expected.0); } } diff --git a/src/io/ofn/reader/mod.rs b/src/io/ofn/reader/mod.rs index 3b9a933..96e6382 100644 --- a/src/io/ofn/reader/mod.rs +++ b/src/io/ofn/reader/mod.rs @@ -6,13 +6,14 @@ use crate::error::HornedError; use crate::io::ParserConfiguration; use crate::model::Build; use crate::model::ForIRI; -use crate::model::RcStr; -use crate::ontology::set::SetOntology; +use crate::model::MutableOntology; +use crate::model::Ontology; mod from_pair; mod lexer; use self::from_pair::FromPair; +use self::from_pair::MutableOntologyWrapper; use self::lexer::OwlFunctionalLexer; use self::lexer::Rule; @@ -27,18 +28,18 @@ impl<'a, A: ForIRI> Context<'a, A> { } } -pub fn read( +pub fn read + Ontology + Default, R: BufRead>( bufread: R, _config: ParserConfiguration, -) -> Result<(SetOntology, PrefixMapping), HornedError> { +) -> Result<(O, PrefixMapping), HornedError> { let b = Build::new(); read_with_build(bufread, &b) } -pub fn read_with_build( +pub fn read_with_build + Ontology + Default, R: BufRead>( mut bufread: R, build: &Build, -) -> Result<(SetOntology, PrefixMapping), HornedError> { +) -> Result<(O, PrefixMapping), HornedError> { let prefixes = PrefixMapping::default(); let ctx = Context::new(build, &prefixes); @@ -49,5 +50,7 @@ pub fn read_with_build( .next() .unwrap(); - FromPair::from_pair(pair, &ctx) + let wrapper: Result<(MutableOntologyWrapper, PrefixMapping), HornedError> = + FromPair::from_pair(pair, &ctx); + wrapper.map(|r| (r.0 .0, r.1)) } diff --git a/src/io/ofn/writer/mod.rs b/src/io/ofn/writer/mod.rs index b489f9e..82e5b00 100644 --- a/src/io/ofn/writer/mod.rs +++ b/src/io/ofn/writer/mod.rs @@ -104,12 +104,11 @@ mod test { let reader = std::fs::File::open(&resource) .map(std::io::BufReader::new) .unwrap(); - let (ont, prefixes) = crate::io::ofn::reader::read(reader, Default::default()).unwrap(); + let (ont, prefixes): (ComponentMappedOntology>, _) = + crate::io::ofn::reader::read(reader, Default::default()).unwrap(); - let component_mapped: ComponentMappedOntology> = - ont.clone().into(); let mut writer = Vec::new(); - crate::io::ofn::writer::write(&mut writer, &component_mapped, Some(&prefixes)).unwrap(); + crate::io::ofn::writer::write(&mut writer, &ont, Some(&prefixes)).unwrap(); let (ont2, prefixes2) = crate::io::ofn::reader::read(std::io::Cursor::new(&writer), Default::default()) diff --git a/src/io/owx/reader.rs b/src/io/owx/reader.rs index 9c1ee13..d8846a3 100644 --- a/src/io/owx/reader.rs +++ b/src/io/owx/reader.rs @@ -9,7 +9,7 @@ use crate::model::*; use crate::vocab::Facet; use crate::vocab::Namespace::*; use crate::vocab::OWL2Datatype; -use crate::{ontology::set::SetOntology, vocab::OWL}; +use crate::vocab::OWL; use std::borrow::Cow; use std::collections::BTreeSet; @@ -28,23 +28,22 @@ where build: &'a Build, mapping: PrefixMapping, reader: NsReader, - // buf: Vec, } -pub fn read( +pub fn read + Default, R: BufRead>( bufread: &mut R, _config: ParserConfiguration, -) -> Result<(SetOntology, PrefixMapping), HornedError> { +) -> Result<(O, PrefixMapping), HornedError> { let b = Build::new(); read_with_build(bufread, &b) } -pub fn read_with_build( +pub fn read_with_build + Default, R: BufRead>( bufread: R, build: &Build, -) -> Result<(SetOntology, PrefixMapping), HornedError> { +) -> Result<(O, PrefixMapping), HornedError> { let reader: NsReader = NsReader::from_reader(bufread); - let mut ont = SetOntology::new(); + let mut ont: O = Default::default(); let mapping = PrefixMapping::default(); let mut buf = Vec::new(); @@ -52,7 +51,6 @@ pub fn read_with_build( reader, build, mapping, - // buf: Vec::new(), }; loop { @@ -1363,10 +1361,11 @@ pub mod test { ComponentMappedOntology, PrefixMapping, ) { - let r = read(bufread, ParserConfiguration::default()); + let b = Build::new(); + let r = read_with_build(bufread, &b); assert!(r.is_ok(), "Expected ontology, got failure:{:?}", r.err()); let (o, m) = r.ok().unwrap(); - (o.into(), m) + (o, m) } #[test] diff --git a/src/io/owx/writer.rs b/src/io/owx/writer.rs index 879573e..9c20787 100644 --- a/src/io/owx/writer.rs +++ b/src/io/owx/writer.rs @@ -990,7 +990,7 @@ mod test { let r = read(bufread, ParserConfiguration::default()); assert!(r.is_ok(), "Expected ontology, got failure:{:?}", r.err()); let (o, m) = r.ok().unwrap(); - (o.into(), m) + (o, m) } #[test] diff --git a/src/io/rdf/closure_reader.rs b/src/io/rdf/closure_reader.rs index 09097d1..7f5f67d 100644 --- a/src/io/rdf/closure_reader.rs +++ b/src/io/rdf/closure_reader.rs @@ -1,35 +1,38 @@ use crate::error::HornedError; use crate::io::rdf::reader::parser_with_build; use crate::io::rdf::reader::OntologyParser; +use crate::io::rdf::reader::RDFOntology; use crate::io::IncompleteParse; use crate::io::ParserConfiguration; -use crate::io::RDFOntology; use crate::model::Build; use crate::model::DocIRI; use crate::model::ForIRI; -use crate::model::MutableOntology; use crate::model::IRI; use crate::ontology::indexed::ForIndex; +use crate::ontology::set::SetIndex; use crate::resolve::path_to_file_iri; use crate::resolve::resolve_iri; use std::collections::HashMap; +use std::marker::PhantomData; use std::path::PathBuf; -pub struct ClosureOntologyParser<'a, A: ForIRI, AA: ForIndex> { - op: HashMap, OntologyParser<'a, A, AA>>, +pub struct ClosureOntologyParser<'a, A: ForIRI, AA: ForIndex, O: RDFOntology> { + op: HashMap, OntologyParser<'a, A, AA, O>>, import_map: HashMap, Vec>>, b: &'a Build, config: ParserConfiguration, + p: PhantomData, } -impl<'a, A: ForIRI, AA: ForIndex> ClosureOntologyParser<'a, A, AA> { +impl<'a, A: ForIRI, AA: ForIndex, O: RDFOntology> ClosureOntologyParser<'a, A, AA, O> { pub fn new(b: &'a Build, config: ParserConfiguration) -> Self { ClosureOntologyParser { b, import_map: HashMap::new(), op: HashMap::new(), config, + p: Default::default(), } } @@ -87,17 +90,19 @@ impl<'a, A: ForIRI, AA: ForIndex> ClosureOntologyParser<'a, A, AA> { let mut p = parser_with_build(&mut s.as_bytes(), self.b, self.config); let imports = p.parse_imports().unwrap(); p.parse_declarations()?; - let o = p.mut_ontology_ref(); + let o: &mut O = p.mut_ontology_ref(); o.insert(DocIRI(new_doc_iri.clone())); - let mut res = if let Some(declared_iri) = o.i().the_ontology_id_or_default().iri { + let si: &SetIndex = o.as_ref(); + + let mut res = if let Some(declared_iri) = si.the_ontology_id_or_default().iri { vec![declared_iri] } else { vec![] }; - if let Some(declared_iri) = o.i().the_ontology_id_or_default().iri { + if let Some(declared_iri) = si.the_ontology_id_or_default().iri { self.import_map .insert(declared_iri.clone(), imports.clone()); self.op.insert(declared_iri, p); @@ -136,12 +141,12 @@ impl<'a, A: ForIRI, AA: ForIndex> ClosureOntologyParser<'a, A, AA> { } // Return ontology in potentially incompletely parsed state - pub fn as_ontology_vec(self) -> Vec> { + pub fn as_ontology_vec(self) -> Vec { todo!() } // Return ontology in potentially incompletely parsed state - pub fn as_ontology_vec_and_incomplete(self) -> Vec<(RDFOntology, IncompleteParse)> { + pub fn as_ontology_vec_and_incomplete(self) -> Vec<(O, IncompleteParse)> { self.op .into_values() .map(|op| op.as_ontology_and_incomplete().unwrap()) @@ -151,10 +156,10 @@ impl<'a, A: ForIRI, AA: ForIndex> ClosureOntologyParser<'a, A, AA> { // Parse the ontology at IRI, resolving any knowledge from imports necessary #[allow(clippy::type_complexity)] -pub fn read>( +pub fn read, O: RDFOntology>( iri: &IRI, config: ParserConfiguration, -) -> Result<(RDFOntology, IncompleteParse), HornedError> { +) -> Result<(O, IncompleteParse), HornedError> { // Do parse, then full parse of first, drop the rest let b = Build::new(); let mut c = ClosureOntologyParser::new(&b, config); @@ -170,11 +175,11 @@ pub fn read>( } #[allow(clippy::type_complexity)] -pub fn read_closure>( +pub fn read_closure, O: RDFOntology>( b: &Build, iri: &IRI, config: ParserConfiguration, -) -> Result, IncompleteParse)>, HornedError> { +) -> Result)>, HornedError> { // Do parse, then full parse, then result the results let mut c = ClosureOntologyParser::new(b, config); c.parse_iri(iri, None)?; @@ -189,7 +194,7 @@ pub fn read_closure>( #[cfg(test)] mod test { use crate::io::rdf::closure_reader::*; - use crate::io::rdf::reader::RcRDFOntology; + use crate::io::rdf::reader::ConcreteRcRDFOntology; use crate::ontology::set::SetOntology; use std::path::Path; @@ -199,7 +204,7 @@ mod test { let b = Build::new_rc(); let iri = path_to_file_iri(&b, path); - let (_, ic): (RcRDFOntology, _) = read(&iri, Default::default()).unwrap(); + let (_, ic): (ConcreteRcRDFOntology, _) = read(&iri, Default::default()).unwrap(); assert!(ic.is_complete()); } @@ -211,7 +216,8 @@ mod test { let b = Build::new_rc(); let iri = path_to_file_iri(&b, path); - let v: Vec<(RcRDFOntology, _)> = read_closure(&b, &iri, Default::default()).unwrap(); + let v: Vec<(ConcreteRcRDFOntology, _)> = + read_closure(&b, &iri, Default::default()).unwrap(); let v: Vec> = v .into_iter() .map(|(rdfo, ic)| { diff --git a/src/io/rdf/reader.rs b/src/io/rdf/reader.rs index ee76ca8..3767471 100644 --- a/src/io/rdf/reader.rs +++ b/src/io/rdf/reader.rs @@ -25,10 +25,10 @@ use crate::{ vocab::RDFS as VRDFS, }; -use std::io::BufRead; use std::io::Cursor; use std::{collections::BTreeSet, convert::TryFrom}; use std::{collections::HashMap, convert::TryInto}; +use std::{io::BufRead, marker::PhantomData}; type RioTerm<'a> = ::rio_api::model::Term<'a>; @@ -235,9 +235,27 @@ macro_rules! d { }; } +pub trait RDFOntology>: + AsRef> + + AsRef> + + AsRef> + + Default + + MutableOntology +{ +} + +impl, T: ?Sized> RDFOntology for T where + T: AsRef> + + AsRef> + + AsRef> + + Default + + MutableOntology +{ +} + #[derive(Debug)] #[allow(clippy::type_complexity)] -pub struct RDFOntology>( +pub struct ConcreteRDFOntology>( ThreeIndexedOntology< A, AA, @@ -247,9 +265,15 @@ pub struct RDFOntology>( >, ); -pub type RcRDFOntology = RDFOntology; +impl> Default for ConcreteRDFOntology { + fn default() -> Self { + Self(Default::default()) + } +} + +pub type ConcreteRcRDFOntology = ConcreteRDFOntology; -impl> RDFOntology { +impl> ConcreteRDFOntology { pub fn i(&self) -> &SetIndex { self.0.i() } @@ -273,9 +297,9 @@ impl> RDFOntology { } } -impl> Ontology for RDFOntology {} +impl> Ontology for ConcreteRDFOntology {} -impl> MutableOntology for RDFOntology { +impl> MutableOntology for ConcreteRDFOntology { fn insert(&mut self, cmp: IAA) -> bool where IAA: Into>, @@ -288,19 +312,41 @@ impl> MutableOntology for RDFOntology { } } -impl> From> for SetOntology { - fn from(rdfo: RDFOntology) -> SetOntology { +impl> From> for SetOntology { + fn from(rdfo: ConcreteRDFOntology) -> SetOntology { rdfo.index().0.into() } } -impl> From> for ComponentMappedOntology { - fn from(rdfo: RDFOntology) -> ComponentMappedOntology { +impl> From> + for ComponentMappedOntology +{ + fn from(rdfo: ConcreteRDFOntology) -> ComponentMappedOntology { let so: SetOntology<_> = rdfo.into(); so.into() } } +impl> AsRef> + for ConcreteRDFOntology +{ + fn as_ref(&self) -> &DeclarationMappedIndex { + self.j() + } +} + +impl> AsRef> for ConcreteRDFOntology { + fn as_ref(&self) -> &LogicallyEqualIndex { + self.k() + } +} + +impl> AsRef> for ConcreteRDFOntology { + fn as_ref(&self) -> &SetIndex { + self.i() + } +} + #[derive(Debug)] enum OntologyParserState { New, @@ -373,8 +419,8 @@ impl std::ops::DerefMut for VPosTriple { } #[derive(Debug)] -pub struct OntologyParser<'a, A: ForIRI, AA: ForIndex> { - o: RDFOntology, +pub struct OntologyParser<'a, A: ForIRI, AA: ForIndex, O: RDFOntology> { + o: O, b: &'a Build, config: ParserConfiguration, @@ -392,20 +438,17 @@ pub struct OntologyParser<'a, A: ForIRI, AA: ForIndex> { state: OntologyParserState, error: Result<(), HornedError>, + p: PhantomData, } -impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { +impl<'a, A: ForIRI, AA: ForIndex, O: RDFOntology> OntologyParser<'a, A, AA, O> { pub fn new( b: &'a Build, triple: Vec>, config: ParserConfiguration, - ) -> OntologyParser<'a, A, AA> { + ) -> OntologyParser<'a, A, AA, O> { OntologyParser { - o: RDFOntology(ThreeIndexedOntology::new( - SetIndex::new(), - DeclarationMappedIndex::new(), - LogicallyEqualIndex::new(), - )), + o: d!(), b, config, @@ -421,6 +464,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { variable: d!(), state: OntologyParserState::New, error: Ok(()), + p: d!(), } } @@ -428,7 +472,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { b: &'a Build, bufread: &'b mut R, config: ParserConfiguration, - ) -> OntologyParser<'a, A, AA> { + ) -> OntologyParser<'a, A, AA, O> { let mut parser = rio_xml::RdfXmlParser::new(bufread, None); let mut triples = vec![]; let last_pos = std::cell::Cell::new(0); @@ -449,7 +493,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { b: &'a Build, iri: &IRI, config: ParserConfiguration, - ) -> OntologyParser<'a, A, AA> { + ) -> OntologyParser<'a, A, AA, O> { OntologyParser::from_bufread( b, &mut Cursor::new(strict_resolve_iri(iri).expect("the IRI should resolve successfully")), @@ -631,7 +675,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { fn merge>>(&mut self, cmp: IAA) { let cmp = cmp.into(); - update_or_insert_logically_equal_component(&mut self.o.0, cmp); + update_or_insert_logically_equal_component(&mut self.o, cmp); } fn axiom_annotations(&mut self) { @@ -820,37 +864,25 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } } - fn fetch_sope( - &mut self, - t: &Term, - ic: &[&RDFOntology], - ) -> Option> { + fn fetch_sope(&mut self, t: &Term, ic: &[&O]) -> Option> { Some(self.fetch_ope(t, ic)?.into()) } - fn fetch_ope( - &mut self, - t: &Term, - ic: &[&RDFOntology], - ) -> Option> { + fn fetch_ope(&mut self, t: &Term, ic: &[&O]) -> Option> { match self.find_property_kind(t, ic)? { PropertyExpression::ObjectPropertyExpression(ope) => Some(ope), _ => None, } } - fn fetch_ap( - &mut self, - t: &Term, - ic: &[&RDFOntology], - ) -> Option> { + fn fetch_ap(&mut self, t: &Term, ic: &[&O]) -> Option> { match self.find_property_kind(t, ic)? { PropertyExpression::AnnotationProperty(ap) => Some(ap), _ => None, } } - fn fetch_dp(&mut self, t: &Term, ic: &[&RDFOntology]) -> Option> { + fn fetch_dp(&mut self, t: &Term, ic: &[&O]) -> Option> { match self.find_property_kind(t, ic)? { PropertyExpression::DataProperty(dp) => Some(dp), _ => None, @@ -955,7 +987,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } #[allow(clippy::wrong_self_convention)] - fn to_iargument(&mut self, t: &Term, ic: &[&RDFOntology]) -> Option> { + fn to_iargument(&mut self, t: &Term, ic: &[&O]) -> Option> { match t { Term::BNode(bn) => Some(IArgument::Individual( AnonymousIndividual(bn.0.clone()).into(), @@ -985,11 +1017,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } } - fn find_term_kind( - &mut self, - term: &Term, - ic: &[&RDFOntology], - ) -> Option { + fn find_term_kind(&mut self, term: &Term, ic: &[&O]) -> Option { match term { Term::Iri(iri) if crate::vocab::is_xsd_datatype(iri) => { Some(NamedOWLEntityKind::Datatype) @@ -1002,24 +1030,16 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } } - fn find_declaration_kind( - &mut self, - iri: &IRI, - ic: &[&RDFOntology], - ) -> Option { + fn find_declaration_kind(&mut self, iri: &IRI, ic: &[&O]) -> Option { [&self.o] .iter() .chain(ic.iter()) - .map(|o| o.0.j().declaration_kind(iri)) + .map(|o| >>::as_ref(o).declaration_kind(iri)) .find(|d| d.is_some()) .flatten() } - fn find_property_kind( - &mut self, - term: &Term, - ic: &[&RDFOntology], - ) -> Option> { + fn find_property_kind(&mut self, term: &Term, ic: &[&O]) -> Option> { match term { Term::OWL(vowl) => { let iri = self.b.iri(vowl.as_ref()); @@ -1042,7 +1062,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } } - fn class_expressions(&mut self, ic: &[&RDFOntology]) -> Result<(), HornedError> { + fn class_expressions(&mut self, ic: &[&O]) -> Result<(), HornedError> { let class_expression_len = self.class_expression.len(); for (this_bnode, v) in std::mem::take(&mut self.bnode) { // rustfmt breaks this (putting the triples all on one @@ -1313,7 +1333,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { Ok(()) } - fn axioms(&mut self, ic: &[&RDFOntology]) -> Result<(), HornedError> { + fn axioms(&mut self, ic: &[&O]) -> Result<(), HornedError> { let mut single_bnodes = vec![]; for (this_bnode, v) in std::mem::take(&mut self.bnode) { @@ -1692,7 +1712,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { Ok(()) } - fn swrl(&mut self, ic: &[&RDFOntology]) -> Result<(), HornedError> { + fn swrl(&mut self, ic: &[&O]) -> Result<(), HornedError> { // identify variables first for triple in std::mem::take(&mut self.simple) { match &triple.0 { @@ -1824,9 +1844,9 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } fn simple_annotations(&mut self, parse_all: bool) { - let ont_id = self.o.i().the_ontology_id_or_default(); + let ont_id = >>::as_ref(&self.o).the_ontology_id_or_default(); for triple in std::mem::take(&mut self.simple) { - let firi = |s: &mut OntologyParser<_, _>, t, iri: &IRI<_>| { + let firi = |s: &mut OntologyParser<_, _, _>, t, iri: &IRI<_>| { let ann = s.ann_map.remove(t).unwrap_or_default(); s.merge(AnnotatedComponent { component: AnnotationAssertion { @@ -1851,7 +1871,8 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } [Term::Iri(iri), Term::Iri(ap), _] if parse_all - || (self.o.0).j().is_annotation_property(ap) + || >>::as_ref(&self.o) + .is_annotation_property(ap) || is_annotation_builtin(ap.as_ref()) => { firi(self, &triple.0, iri) @@ -1862,7 +1883,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } } for (k, v) in std::mem::take(&mut self.bnode) { - let fbnode = |s: &mut OntologyParser<_, _>, t, ind: &BNode| { + let fbnode = |s: &mut OntologyParser<_, _, _>, t, ind: &BNode| { let ann = s.ann_map.remove(t).unwrap_or_default(); let ind: AnonymousIndividual = s.b.anon(ind.0.clone()); s.merge(AnnotatedComponent { @@ -1881,7 +1902,8 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } [triple @ [Term::BNode(ind), Term::Iri(ap), _]] if parse_all - || (self.o.0).j().is_annotation_property(ap) + || >>::as_ref(&self.o) + .is_annotation_property(ap) || is_annotation_builtin(ap) => { fbnode(self, triple, ind) @@ -1987,7 +2009,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { /// ic is a Vec of references to the import closure. These RDF /// ontologies do not need to be completely parsed, but will be /// relied on to resolve declarations. - pub fn finish_parse(&mut self, ic: &[&RDFOntology]) -> Result<(), HornedError> { + pub fn finish_parse(&mut self, ic: &[&O]) -> Result<(), HornedError> { // Table 10 self.simple_annotations(false); @@ -2012,7 +2034,7 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { Ok(()) } - pub fn parse(mut self) -> Result<(RDFOntology, IncompleteParse), HornedError> { + pub fn parse(mut self) -> Result<(O, IncompleteParse), HornedError> { if self.error.is_err() { return Err(self.error.unwrap_err()); } @@ -2036,24 +2058,22 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } } - pub fn ontology_ref(&self) -> &RDFOntology { + pub fn ontology_ref(&self) -> &O { &self.o } - pub fn mut_ontology_ref(&mut self) -> &mut RDFOntology { + pub fn mut_ontology_ref(&mut self) -> &mut O { &mut self.o } /// Consume the parser and return an Ontology. - pub fn as_ontology(self) -> Result, HornedError> { + pub fn as_ontology(self) -> Result { self.error.and(Ok(self.o)) } /// Consume the parser and return an Ontology and any data /// structures that have not been fully parsed - pub fn as_ontology_and_incomplete( - mut self, - ) -> Result<(RDFOntology, IncompleteParse), HornedError> { + pub fn as_ontology_and_incomplete(mut self) -> Result<(O, IncompleteParse), HornedError> { if self.error.is_err() { return Err(self.error.unwrap_err()); } @@ -2090,11 +2110,11 @@ impl<'a, A: ForIRI, AA: ForIndex> OntologyParser<'a, A, AA> { } } -pub fn parser_with_build<'b, A: ForIRI, AA: ForIndex, R: BufRead>( +pub fn parser_with_build<'b, A: ForIRI, AA: ForIndex, O: RDFOntology, R: BufRead>( bufread: &mut R, build: &'b Build, config: ParserConfiguration, -) -> OntologyParser<'b, A, AA> { +) -> OntologyParser<'b, A, AA, O> { OntologyParser::from_bufread(build, bufread, config) } @@ -2102,7 +2122,7 @@ pub fn read_with_build, R: BufRead>( bufread: &mut R, build: &Build, config: ParserConfiguration, -) -> Result<(RDFOntology, IncompleteParse), HornedError> { +) -> Result<(ConcreteRDFOntology, IncompleteParse), HornedError> { parser_with_build(bufread, build, config).parse() } @@ -2111,7 +2131,7 @@ pub fn read( config: ParserConfiguration, ) -> Result< ( - RDFOntology, + ConcreteRDFOntology, IncompleteParse, ), HornedError, @@ -2133,7 +2153,9 @@ mod test { use pretty_assertions::assert_eq; use test_generator::test_resources; - fn read_ok(bufread: &mut R) -> RDFOntology>> { + fn read_ok( + bufread: &mut R, + ) -> ConcreteRDFOntology>> { let r = read(bufread, Default::default()); if let Err(e) = r { @@ -2274,11 +2296,12 @@ mod test { #[test] fn import_with_partial_parse() { let b = Build::new_rc(); - let mut p: OntologyParser<_, Rc>> = parser_with_build( - &mut slurp_rdfont("import").as_bytes(), - &b, - Default::default(), - ); + let mut p: OntologyParser<_, Rc>, ConcreteRDFOntology<_, _>> = + parser_with_build( + &mut slurp_rdfont("import").as_bytes(), + &b, + Default::default(), + ); let _ = p.parse_imports(); let rdfont = p.as_ontology().unwrap(); @@ -2291,11 +2314,12 @@ mod test { fn declaration_with_partial_parse() { let b = Build::new_rc(); - let mut p: OntologyParser<_, Rc>> = parser_with_build( - &mut slurp_rdfont("class").as_bytes(), - &b, - Default::default(), - ); + let mut p: OntologyParser<_, Rc>, ConcreteRDFOntology<_, _>> = + parser_with_build( + &mut slurp_rdfont("class").as_bytes(), + &b, + Default::default(), + ); let _ = p.parse_declarations(); let rdfont = p.as_ontology().unwrap(); @@ -2307,11 +2331,12 @@ mod test { #[test] fn import_property_in_bits() -> Result<(), HornedError> { let b = Build::new_rc(); - let p: OntologyParser<_, Rc>> = parser_with_build( - &mut slurp_rdfont("withimport/other-property").as_bytes(), - &b, - Default::default(), - ); + let p: OntologyParser<_, Rc>, ConcreteRDFOntology<_, _>> = + parser_with_build( + &mut slurp_rdfont("withimport/other-property").as_bytes(), + &b, + Default::default(), + ); let (family_other, incomplete) = p.parse()?; assert!(incomplete.is_complete()); diff --git a/src/model.rs b/src/model.rs index b655baa..348bbc2 100644 --- a/src/model.rs +++ b/src/model.rs @@ -2044,7 +2044,7 @@ pub enum DArgument { pub trait Ontology {} /// Add or remove axioms to an `MutableOntology` -pub trait MutableOntology { +pub trait MutableOntology: Ontology { /// Insert an axiom into the ontology. /// /// # Examples diff --git a/src/ontology/component_mapped.rs b/src/ontology/component_mapped.rs index a7b2e9a..1043ed4 100644 --- a/src/ontology/component_mapped.rs +++ b/src/ontology/component_mapped.rs @@ -292,6 +292,8 @@ impl> Default for ComponentMappedOntology { } } +impl> Ontology for ComponentMappedOntology {} + impl> MutableOntology for ComponentMappedOntology { fn insert(&mut self, cmp: IAA) -> bool where diff --git a/src/ontology/logically_equal.rs b/src/ontology/logically_equal.rs index dab0b50..e3b6908 100644 --- a/src/ontology/logically_equal.rs +++ b/src/ontology/logically_equal.rs @@ -7,9 +7,15 @@ use std::collections::HashMap; use std::convert::AsRef; use std::rc::Rc; -#[derive(Debug, Default)] +#[derive(Debug)] pub struct LogicallyEqualIndex(HashMap, AA>); +impl> Default for LogicallyEqualIndex { + fn default() -> Self { + LogicallyEqualIndex(HashMap::new()) + } +} + impl> LogicallyEqualIndex { pub fn new() -> Self { LogicallyEqualIndex(HashMap::new()) diff --git a/src/visitor/mutable.rs b/src/visitor/mutable.rs index 03a99df..76c5c11 100644 --- a/src/visitor/mutable.rs +++ b/src/visitor/mutable.rs @@ -813,24 +813,8 @@ impl> WalkMut { mod test { use super::*; - use crate::io::owx::reader::read; - use crate::io::ParserConfiguration; + use crate::io::owx::reader::test::read_ok; use crate::model::Build; - use crate::ontology::component_mapped::ComponentMappedOntology; - use curie::PrefixMapping; - use std::io::BufRead; - - pub fn read_ok( - bufread: &mut R, - ) -> ( - ComponentMappedOntology, - PrefixMapping, - ) { - let r = read(bufread, ParserConfiguration::default()); - assert!(r.is_ok(), "Expected ontology, got failure:{:?}", r.err()); - let (o, m) = r.ok().unwrap(); - (o.into(), m) - } struct LabeltoFred; impl VisitMut for LabeltoFred {