From ade35fded6d511b082326d33deffe852fcf52a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Haudebourg?= Date: Wed, 18 Oct 2023 13:57:43 +0200 Subject: [PATCH] Add `interpretation::WithVocabulary` Add `vocabulary: V` type parameter to `InterpretationMut`. Remove `Namespace` trait. Change return type of `Generator::next` to `Id`. --- src/generator.rs | 41 +++---- src/interpretation.rs | 19 ++-- src/interpretation/indexed.rs | 4 +- src/interpretation/with_generator.rs | 155 +++++++++++++++++++++++++++ src/lib.rs | 11 +- src/vocabulary.rs | 7 +- 6 files changed, 196 insertions(+), 41 deletions(-) create mode 100644 src/interpretation/with_generator.rs diff --git a/src/generator.rs b/src/generator.rs index e0c8dae..c1e4ac0 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -1,14 +1,15 @@ use crate::{ - vocabulary, BlankIdBuf, BlankIdVocabularyMut, Id, Namespace, Vocabulary, VocabularyMut, + vocabulary, BlankIdBuf, BlankIdVocabulary, BlankIdVocabularyMut, Id, IriVocabulary, Vocabulary, + VocabularyMut, }; #[cfg(feature = "meta")] use locspan::Meta; /// Subject identifier generator. -pub trait Generator { - /// Generates the next fresh identifier in the given namespace. - fn next(&mut self, namespace: &mut N) -> N::Id; +pub trait Generator { + /// Generates the next fresh node identifier in the given vocabulary. + fn next(&mut self, vocabulary: &mut V) -> Id; #[cfg(feature = "meta")] /// Generates identifiers annotated with the given metadata. @@ -35,22 +36,24 @@ pub trait Generator { } } -impl<'a, N: Namespace, G: Generator> Generator for &'a mut G { - fn next(&mut self, namespace: &mut N) -> N::Id { - (*self).next(namespace) +impl<'a, V: IriVocabulary + BlankIdVocabulary, G: Generator> Generator for &'a mut G { + fn next(&mut self, vocabulary: &mut V) -> Id { + (*self).next(vocabulary) } } #[cfg(feature = "meta")] /// Subject identifier generator, with metadata. -pub trait MetaGenerator { - fn next(&mut self, namespace: &mut N) -> Meta; +pub trait MetaGenerator { + fn next(&mut self, vocabulary: &mut V) -> Meta, M>; } #[cfg(feature = "meta")] -impl<'a, N: Namespace, M, G: MetaGenerator> MetaGenerator for &'a mut G { - fn next(&mut self, namespace: &mut N) -> Meta { - (*self).next(namespace) +impl<'a, V: IriVocabulary + BlankIdVocabulary, M, G: MetaGenerator> MetaGenerator + for &'a mut G +{ + fn next(&mut self, vocabulary: &mut V) -> Meta, M> { + (*self).next(vocabulary) } } @@ -72,16 +75,18 @@ impl WithMetadata { } #[cfg(feature = "meta")] -impl, M> Generator for WithMetadata { - fn next(&mut self, namespace: &mut N) -> N::Id { - self.generator.next(namespace) +impl, M> Generator for WithMetadata { + fn next(&mut self, vocabulary: &mut V) -> Id { + self.generator.next(vocabulary) } } #[cfg(feature = "meta")] -impl, M: Clone> MetaGenerator for WithMetadata { - fn next(&mut self, namespace: &mut N) -> Meta { - Meta(self.generator.next(namespace), self.metadata.clone()) +impl, M: Clone> MetaGenerator + for WithMetadata +{ + fn next(&mut self, vocabulary: &mut V) -> Meta, M> { + Meta(self.generator.next(vocabulary), self.metadata.clone()) } } diff --git a/src/interpretation.rs b/src/interpretation.rs index 3c5db89..7bc9746 100644 --- a/src/interpretation.rs +++ b/src/interpretation.rs @@ -4,13 +4,15 @@ use langtag::LanguageTagBuf; use crate::{ literal, BlankId, BlankIdBuf, BlankIdVocabulary, BlankIdVocabularyMut, Generator, Id, IriVocabulary, IriVocabularyMut, LanguageTagVocabularyMut, Literal, LiteralVocabulary, - LiteralVocabularyMut, Namespace, Quad, Term, + LiteralVocabularyMut, Quad, Term, }; mod indexed; mod none; +mod with_generator; pub use indexed::*; +pub use with_generator::WithGenerator; pub type UninterpretedIdRef<'a, I> = Id<&'a ::Iri, &'a ::BlankId>; @@ -206,9 +208,9 @@ impl + LiteralInterpretation } /// Mutable RDF resource interpretation. -pub trait InterpretationMut: Interpretation { +pub trait InterpretationMut: Interpretation { /// Creates a new resource. - fn new_resource(&mut self) -> Self::Resource; + fn new_resource(&mut self, vocabulary: &mut V) -> Self::Resource; } /// Mutable IRI interpretation. @@ -889,14 +891,15 @@ pub trait ReverseTermInterpretationMut: /// Generates and assign a node identifier for all the resources that don't /// have any term, using the given generator. - fn generate_ids>>( + fn generate_ids( &mut self, - namespace: &mut N, - generator: &mut impl Generator, + vocabulary: &mut V, + generator: &mut impl Generator, ) where - Self: TraversableInterpretation + ReverseTermInterpretationMut, + Self: TraversableInterpretation + + ReverseTermInterpretationMut, { - self.assign_terms(|i, r| (!i.has_term(r)).then(|| Term::Id(generator.next(namespace)))) + self.assign_terms(|i, r| (!i.has_term(r)).then(|| Term::Id(generator.next(vocabulary)))) } } diff --git a/src/interpretation/indexed.rs b/src/interpretation/indexed.rs index 16be6d0..fa8a540 100644 --- a/src/interpretation/indexed.rs +++ b/src/interpretation/indexed.rs @@ -100,8 +100,8 @@ impl TraversableInterpretation for Indexed { } } -impl InterpretationMut for Indexed { - fn new_resource(&mut self) -> Self::Resource { +impl InterpretationMut for Indexed { + fn new_resource(&mut self, _vocabulary: &mut V) -> Self::Resource { self.resources.insert().0 } } diff --git a/src/interpretation/with_generator.rs b/src/interpretation/with_generator.rs new file mode 100644 index 0000000..1c241ad --- /dev/null +++ b/src/interpretation/with_generator.rs @@ -0,0 +1,155 @@ +use crate::{ + BlankIdInterpretation, BlankIdInterpretationMut, BlankIdVocabulary, Generator, Id, + Interpretation, InterpretationMut, IriInterpretation, IriInterpretationMut, IriVocabulary, + LiteralInterpretation, LiteralInterpretationMut, ReverseBlankIdInterpretation, + ReverseBlankIdInterpretationMut, ReverseIriInterpretation, ReverseIriInterpretationMut, + ReverseLiteralInterpretation, ReverseLiteralInterpretationMut, +}; + +/// Combines any RDF interpretation with a node id generator to make it +/// implement `InterpretationMut`. +/// +/// # Use cases +/// +/// ## `()` does not implement `InterpretationMut` +/// +/// The transparent interpretation (the unit type `()`) does not implement +/// `InterpretationMut` because the `new_resource` method would require the +/// creation of a fresh, unused, blank node identifier, which the transparent +/// interpretation cannot create without a node id generator. +/// +/// ## Resources returned by `InterpretationMut::new_resource` have no lexical representation +/// +/// Interpreted resources are not required to have a lexical representation. +/// This is most probably the case for new resources returned by +/// `InterpretationMut::new_resource`. You can use `WithGenerator` to pair the +/// interpretation with a node id generator so that `new_resource` will assign +/// a lexical representation to new resources (a fresh blank node id for +/// instance). +pub struct WithGenerator<'a, I, G> { + interpretation: &'a mut I, + generator: G, +} + +impl<'a, I, G> WithGenerator<'a, I, G> { + pub fn new(interpretation: &'a mut I, generator: G) -> Self { + Self { + interpretation, + generator, + } + } +} + +impl<'a, I: Interpretation, G> Interpretation for WithGenerator<'a, I, G> { + type Resource = I::Resource; +} + +impl<'a, V: IriVocabulary + BlankIdVocabulary, I, G: Generator> InterpretationMut + for WithGenerator<'a, I, G> +where + I: IriInterpretationMut + BlankIdInterpretationMut, +{ + fn new_resource(&mut self, vocabulary: &mut V) -> Self::Resource { + match self.generator.next(vocabulary) { + Id::Iri(i) => self.interpretation.interpret_iri(i), + Id::Blank(b) => self.interpretation.interpret_blank_id(b), + } + } +} + +impl<'a, Iri, I: IriInterpretation, G> IriInterpretation for WithGenerator<'a, I, G> { + fn iri_interpretation(&self, iri: &Iri) -> Option { + self.interpretation.iri_interpretation(iri) + } +} + +impl<'a, Iri, I: IriInterpretationMut, G> IriInterpretationMut + for WithGenerator<'a, I, G> +{ + fn interpret_iri(&mut self, iri: Iri) -> Self::Resource { + self.interpretation.interpret_iri(iri) + } +} + +impl<'i, I: ReverseIriInterpretation, G> ReverseIriInterpretation for WithGenerator<'i, I, G> { + type Iri = I::Iri; + type Iris<'a> = I::Iris<'a> where Self: 'a; + + fn iris_of<'a>(&'a self, id: &'a Self::Resource) -> Self::Iris<'a> { + self.interpretation.iris_of(id) + } +} + +impl<'i, I: ReverseIriInterpretationMut, G> ReverseIriInterpretationMut + for WithGenerator<'i, I, G> +{ + fn assign_iri(&mut self, id: Self::Resource, iri: Self::Iri) -> bool { + self.interpretation.assign_iri(id, iri) + } +} + +impl<'a, B, I: BlankIdInterpretation, G> BlankIdInterpretation for WithGenerator<'a, I, G> { + fn blank_id_interpretation(&self, blank_id: &B) -> Option { + self.interpretation.blank_id_interpretation(blank_id) + } +} + +impl<'a, B, I: BlankIdInterpretationMut, G> BlankIdInterpretationMut + for WithGenerator<'a, I, G> +{ + fn interpret_blank_id(&mut self, blank_id: B) -> Self::Resource { + self.interpretation.interpret_blank_id(blank_id) + } +} + +impl<'i, I: ReverseBlankIdInterpretation, G> ReverseBlankIdInterpretation + for WithGenerator<'i, I, G> +{ + type BlankId = I::BlankId; + type BlankIds<'a> = I::BlankIds<'a> where Self: 'a; + + fn blank_ids_of<'a>(&'a self, id: &'a Self::Resource) -> Self::BlankIds<'a> { + self.interpretation.blank_ids_of(id) + } +} + +impl<'i, I: ReverseBlankIdInterpretationMut, G> ReverseBlankIdInterpretationMut + for WithGenerator<'i, I, G> +{ + fn assign_blank_id(&mut self, id: Self::Resource, blank_id: Self::BlankId) -> bool { + self.interpretation.assign_blank_id(id, blank_id) + } +} + +impl<'a, L, I: LiteralInterpretation, G> LiteralInterpretation for WithGenerator<'a, I, G> { + fn literal_interpretation(&self, literal: &L) -> Option { + self.interpretation.literal_interpretation(literal) + } +} + +impl<'a, L, I: LiteralInterpretationMut, G> LiteralInterpretationMut + for WithGenerator<'a, I, G> +{ + fn interpret_literal(&mut self, literal: L) -> Self::Resource { + self.interpretation.interpret_literal(literal) + } +} + +impl<'i, I: ReverseLiteralInterpretation, G> ReverseLiteralInterpretation + for WithGenerator<'i, I, G> +{ + type Literal = I::Literal; + type Literals<'a> = I::Literals<'a> where Self: 'a; + + fn literals_of<'a>(&'a self, id: &'a Self::Resource) -> Self::Literals<'a> { + self.interpretation.literals_of(id) + } +} + +impl<'i, I: ReverseLiteralInterpretationMut, G> ReverseLiteralInterpretationMut + for WithGenerator<'i, I, G> +{ + fn assign_literal(&mut self, resource: Self::Resource, literal: Self::Literal) -> bool { + self.interpretation.assign_literal(resource, literal) + } +} diff --git a/src/lib.rs b/src/lib.rs index 1e236b4..3357790 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,8 +29,10 @@ pub use interpretation::{ Interpret, Interpretation, InterpretationMut, IriInterpretation, IriInterpretationMut, LexicalIdInterpretation, LexicalIdInterpretationMut, LexicalTermInterpretation, LexicalTermInterpretationMut, LiteralInterpretation, LiteralInterpretationMut, - ReverseIdInterpretation, ReverseLiteralInterpretation, ReverseTermInterpretation, - ReverseTermInterpretationMut, TermInterpretation, TermInterpretationMut, + ReverseBlankIdInterpretation, ReverseBlankIdInterpretationMut, ReverseIdInterpretation, + ReverseIriInterpretation, ReverseIriInterpretationMut, ReverseLiteralInterpretation, + ReverseLiteralInterpretationMut, ReverseTermInterpretation, ReverseTermInterpretationMut, + TermInterpretation, TermInterpretationMut, }; use iref::Iri; pub use literal::{ @@ -52,8 +54,3 @@ pub const XSD_STRING: &Iri = static_iref::iri!("http://www.w3.org/2001/XMLSchema #[cfg(feature = "meta")] pub use generator::MetaGenerator; - -/// Node identifier namespace. -pub trait Namespace { - type Id; -} diff --git a/src/vocabulary.rs b/src/vocabulary.rs index 21664c3..2cef54f 100644 --- a/src/vocabulary.rs +++ b/src/vocabulary.rs @@ -1,4 +1,4 @@ -use crate::{BlankId, BlankIdBuf, Id, Literal, Namespace}; +use crate::{BlankId, BlankIdBuf, Literal}; use iref::{Iri, IriBuf}; mod indexed; @@ -38,11 +38,6 @@ impl Namespace for V { - type Id = Id; -} - impl< V: IriVocabularyMut + BlankIdVocabularyMut + LiteralVocabularyMut + LanguageTagVocabularyMut, > VocabularyMut for V