use std::collections::HashSet;
use std::marker::PhantomData;
use resiter::filter::*;
use resiter::map::*;
use crate::dataset::adapter::DatasetGraph;
use crate::error::*;
use crate::quad::stream::*;
use crate::quad::*;
use crate::term::matcher::*;
use crate::term::*;
use super::*;
use crate::graph::insert_if_absent;
pub type DTerm<'a, D> = Term<<<D as Dataset<'a>>::Quad as Quad<'a>>::TermData>;
pub type DResult<'a, D, T> = std::result::Result<T, <D as Dataset<'a>>::Error>;
pub type DQuadSource<'a, D> = Box<Iterator<Item = DResult<'a, D, <D as Dataset<'a>>::Quad>> + 'a>;
pub type DResultTermSet<'a, D> = DResult<'a, D, HashSet<DTerm<'a, D>>>;
pub trait Dataset<'a> {
type Quad: Quad<'a>;
type Error: CoercibleWith<Error> + CoercibleWith<Never>;
fn quads(&'a self) -> DQuadSource<'a, Self>;
fn quads_with_s<T>(&'a self, s: &'a Term<T>) -> DQuadSource<'a, Self>
where
T: TermData,
{
Box::new(self.quads().filter_ok(move |q| q.s() == s))
}
fn quads_with_p<T>(&'a self, p: &'a Term<T>) -> DQuadSource<'a, Self>
where
T: TermData,
{
Box::new(self.quads().filter_ok(move |q| q.p() == p))
}
fn quads_with_o<T>(&'a self, o: &'a Term<T>) -> DQuadSource<'a, Self>
where
T: TermData,
{
Box::new(self.quads().filter_ok(move |q| q.o() == o))
}
fn quads_with_g<T>(&'a self, g: Option<&'a Term<T>>) -> DQuadSource<'a, Self>
where
T: TermData,
{
Box::new(self.quads().filter_ok(move |q| same_graph_name(q.g(), g)))
}
fn quads_with_sp<T, U>(&'a self, s: &'a Term<T>, p: &'a Term<U>) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
{
Box::new(self.quads_with_s(s).filter_ok(move |q| q.p() == p))
}
fn quads_with_so<T, U>(&'a self, s: &'a Term<T>, o: &'a Term<U>) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
{
Box::new(self.quads_with_s(s).filter_ok(move |q| q.o() == o))
}
fn quads_with_sg<T, U>(
&'a self,
s: &'a Term<T>,
g: Option<&'a Term<U>>,
) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
{
Box::new(self.quads_with_g(g).filter_ok(move |q| q.s() == s))
}
fn quads_with_po<T, U>(&'a self, p: &'a Term<T>, o: &'a Term<U>) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
{
Box::new(self.quads_with_p(p).filter_ok(move |q| q.o() == o))
}
fn quads_with_pg<T, U>(
&'a self,
p: &'a Term<T>,
g: Option<&'a Term<U>>,
) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
{
Box::new(self.quads_with_g(g).filter_ok(move |q| q.p() == p))
}
fn quads_with_og<T, U>(
&'a self,
o: &'a Term<T>,
g: Option<&'a Term<U>>,
) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
{
Box::new(self.quads_with_g(g).filter_ok(move |q| q.o() == o))
}
fn quads_with_spo<T, U, V>(
&'a self,
s: &'a Term<T>,
p: &'a Term<U>,
o: &'a Term<V>,
) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
V: TermData,
{
Box::new(self.quads_with_sp(s, p).filter_ok(move |q| q.o() == o))
}
fn quads_with_spg<T, U, V>(
&'a self,
s: &'a Term<T>,
p: &'a Term<U>,
g: Option<&'a Term<V>>,
) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
V: TermData,
{
Box::new(self.quads_with_sg(s, g).filter_ok(move |q| q.p() == p))
}
fn quads_with_sog<T, U, V>(
&'a self,
s: &'a Term<T>,
o: &'a Term<U>,
g: Option<&'a Term<V>>,
) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
V: TermData,
{
Box::new(self.quads_with_sg(s, g).filter_ok(move |q| q.o() == o))
}
fn quads_with_pog<T, U, V>(
&'a self,
p: &'a Term<T>,
o: &'a Term<U>,
g: Option<&'a Term<V>>,
) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
V: TermData,
{
Box::new(self.quads_with_pg(p, g).filter_ok(move |q| q.o() == o))
}
fn quads_with_spog<T, U, V, W>(
&'a self,
s: &'a Term<T>,
p: &'a Term<U>,
o: &'a Term<V>,
g: Option<&'a Term<W>>,
) -> DQuadSource<'a, Self>
where
T: TermData,
U: TermData,
V: TermData,
W: TermData,
{
Box::new(self.quads_with_spg(s, p, g).filter_ok(move |q| q.o() == o))
}
fn contains<T, U, V, W>(
&'a self,
s: &'a Term<T>,
p: &'a Term<U>,
o: &'a Term<V>,
g: Option<&'a Term<W>>,
) -> DResult<'a, Self, bool>
where
T: TermData,
U: TermData,
V: TermData,
W: TermData,
{
match self.quads_with_spog(s, p, o, g).next() {
None => Ok(false),
Some(Ok(_)) => Ok(true),
Some(Err(err)) => Err(err),
}
}
fn quads_matching<S, P, O, G>(
&'a self,
ms: &'a S,
mp: &'a P,
mo: &'a O,
mg: &'a G,
) -> DQuadSource<'a, Self>
where
S: TermMatcher + ?Sized,
P: TermMatcher + ?Sized,
O: TermMatcher + ?Sized,
G: GraphNameMatcher + ?Sized,
{
match (
&ms.constant(),
&mp.constant(),
&mo.constant(),
&mg.constant(),
) {
(None, None, None, None) => Box::from(self.quads().filter_ok(move |q| {
ms.matches(q.s()) && mp.matches(q.p()) && mo.matches(q.o()) && mg.matches(q.g())
})),
(Some(s), None, None, None) => {
Box::from(self.quads_with_s(s).filter_ok(move |q| {
mp.matches(q.p()) && mo.matches(q.o()) && mg.matches(q.g())
}))
}
(None, Some(p), None, None) => {
Box::from(self.quads_with_p(p).filter_ok(move |q| {
ms.matches(q.s()) && mo.matches(q.o()) && mg.matches(q.g())
}))
}
(None, None, Some(o), None) => {
Box::from(self.quads_with_o(o).filter_ok(move |q| {
ms.matches(q.s()) && mp.matches(q.p()) && mg.matches(q.g())
}))
}
(None, None, None, Some(g)) => {
Box::from(self.quads_with_g(*g).filter_ok(move |q| {
ms.matches(q.s()) && mp.matches(q.p()) && mo.matches(q.o())
}))
}
(Some(s), Some(p), None, None) => Box::from(
self.quads_with_sp(s, p)
.filter_ok(move |q| mo.matches(q.o()) && mg.matches(q.g())),
),
(Some(s), None, Some(o), None) => Box::from(
self.quads_with_so(s, o)
.filter_ok(move |q| mp.matches(q.p()) && mg.matches(q.g())),
),
(Some(s), None, None, Some(g)) => Box::from(
self.quads_with_sg(s, *g)
.filter_ok(move |q| mp.matches(q.p()) && mo.matches(q.o())),
),
(None, Some(p), Some(o), None) => Box::from(
self.quads_with_po(p, o)
.filter_ok(move |q| ms.matches(q.s()) && mg.matches(q.g())),
),
(None, Some(p), None, Some(g)) => Box::from(
self.quads_with_pg(p, *g)
.filter_ok(move |q| ms.matches(q.s()) && mo.matches(q.o())),
),
(None, None, Some(o), Some(g)) => Box::from(
self.quads_with_og(o, *g)
.filter_ok(move |q| ms.matches(q.s()) && mp.matches(q.p())),
),
(Some(s), Some(p), Some(o), None) => Box::from(
self.quads_with_spo(s, p, o)
.filter_ok(move |q| mg.matches(q.g())),
),
(Some(s), Some(p), None, Some(g)) => Box::from(
self.quads_with_spg(s, p, *g)
.filter_ok(move |q| mo.matches(q.o())),
),
(Some(s), None, Some(o), Some(g)) => Box::from(
self.quads_with_sog(s, o, *g)
.filter_ok(move |q| mp.matches(q.p())),
),
(None, Some(p), Some(o), Some(g)) => Box::from(
self.quads_with_pog(p, o, *g)
.filter_ok(move |q| ms.matches(q.s())),
),
(Some(s), Some(p), Some(o), Some(g)) => self.quads_with_spog(s, p, o, *g),
}
}
fn subjects(&'a self) -> DResultTermSet<'a, Self> {
let mut res = std::collections::HashSet::new();
for q in self.quads() {
insert_if_absent(&mut res, q?.s());
}
Ok(res)
}
fn predicates(&'a self) -> DResultTermSet<'a, Self> {
let mut res = std::collections::HashSet::new();
for q in self.quads() {
insert_if_absent(&mut res, q?.p());
}
Ok(res)
}
fn objects(&'a self) -> DResultTermSet<'a, Self> {
let mut res = std::collections::HashSet::new();
for q in self.quads() {
insert_if_absent(&mut res, q?.o());
}
Ok(res)
}
fn graph_names(&'a self) -> DResultTermSet<'a, Self> {
let mut res = std::collections::HashSet::new();
for q in self.quads() {
let q = q?;
let name = q.g();
if let Some(name) = name {
insert_if_absent(&mut res, name);
}
}
Ok(res)
}
fn iris(&'a self) -> DResultTermSet<'a, Self> {
let mut res = std::collections::HashSet::new();
for q in self.quads() {
let q = q?;
let (s, p, o) = (q.s(), q.p(), q.o());
if let Iri(_) = s {
insert_if_absent(&mut res, s)
}
if let Iri(_) = p {
insert_if_absent(&mut res, p)
}
if let Iri(_) = o {
insert_if_absent(&mut res, o)
}
if let Some(gn) = q.g() {
if let Iri(_) = gn {
insert_if_absent(&mut res, &gn)
}
}
}
Ok(res)
}
fn bnodes(&'a self) -> DResultTermSet<'a, Self> {
let mut res = std::collections::HashSet::new();
for q in self.quads() {
let q = q?;
let (s, p, o) = (q.s(), q.p(), q.o());
if let BNode(_) = s {
insert_if_absent(&mut res, s)
}
if let BNode(_) = p {
insert_if_absent(&mut res, p)
}
if let BNode(_) = o {
insert_if_absent(&mut res, o)
}
if let Some(gn) = q.g() {
if let BNode(_) = gn {
insert_if_absent(&mut res, &gn)
}
}
}
Ok(res)
}
fn literals(&'a self) -> DResultTermSet<'a, Self> {
let mut res = std::collections::HashSet::new();
for q in self.quads() {
let q = q?;
let (s, p, o) = (q.s(), q.p(), q.o());
if let Literal(_, _) = s {
insert_if_absent(&mut res, s)
}
if let Literal(_, _) = p {
insert_if_absent(&mut res, p)
}
if let Literal(_, _) = o {
insert_if_absent(&mut res, o)
}
if let Some(gn) = q.g() {
if let Literal(_, _) = gn {
insert_if_absent(&mut res, &gn)
}
}
}
Ok(res)
}
fn variables(&'a self) -> DResultTermSet<'a, Self> {
let mut res = std::collections::HashSet::new();
for q in self.quads() {
let q = q?;
let (s, p, o) = (q.s(), q.p(), q.o());
if let Variable(_) = s {
insert_if_absent(&mut res, s)
}
if let Variable(_) = p {
insert_if_absent(&mut res, p)
}
if let Variable(_) = o {
insert_if_absent(&mut res, o)
}
if let Some(gn) = q.g() {
if let Variable(_) = gn {
insert_if_absent(&mut res, &gn)
}
}
}
Ok(res)
}
fn graph<T>(&self, graph_name: Option<&Term<T>>) -> DatasetGraph<Self, &Self, Option<BoxTerm>>
where
T: TermData,
{
DatasetGraph {
dataset: self,
gmatcher: graph_name.map(|n| n.into()),
_phantom: PhantomData,
}
}
fn graph_mut<T>(
&mut self,
graph_name: Option<&Term<T>>,
) -> DatasetGraph<Self, &mut Self, Option<BoxTerm>>
where
T: TermData,
{
DatasetGraph {
dataset: self,
gmatcher: graph_name.map(|n| n.into()),
_phantom: PhantomData,
}
}
fn union_graph<T>(&'a self, gmatcher: T) -> DatasetGraph<Self, &Self, T>
where
T: GraphNameMatcher,
{
DatasetGraph {
dataset: self,
gmatcher,
_phantom: PhantomData,
}
}
}
pub type MDResult<D, T> = std::result::Result<T, <D as MutableDataset>::MutationError>;
pub trait MutableDataset: for<'x> Dataset<'x> {
type MutationError: CoercibleWith<Error> + CoercibleWith<Never>;
fn insert<T, U, V, W>(
&mut self,
s: &Term<T>,
p: &Term<U>,
o: &Term<V>,
g: Option<&Term<W>>,
) -> MDResult<Self, bool>
where
T: TermData,
U: TermData,
V: TermData,
W: TermData;
fn remove<T, U, V, W>(
&mut self,
s: &Term<T>,
p: &Term<U>,
o: &Term<V>,
g: Option<&Term<W>>,
) -> MDResult<Self, bool>
where
T: TermData,
U: TermData,
V: TermData,
W: TermData;
#[inline]
fn inserter(&mut self) -> Inserter<Self> {
Inserter::new(self)
}
#[inline]
fn insert_all<'a, TS>(
&mut self,
src: &mut TS,
) -> CoercedResult<usize, TS::Error, <Self as MutableDataset>::MutationError>
where
TS: QuadSource<'a>,
TS::Error: CoercibleWith<<Self as MutableDataset>::MutationError>,
{
src.in_sink(&mut self.inserter())
}
#[inline]
fn remover(&mut self) -> Remover<Self> {
Remover::new(self)
}
#[inline]
fn remove_all<'a, TS>(
&mut self,
src: &mut TS,
) -> CoercedResult<usize, TS::Error, <Self as MutableDataset>::MutationError>
where
TS: QuadSource<'a>,
TS::Error: CoercibleWith<<Self as MutableDataset>::MutationError>,
{
src.in_sink(&mut self.remover())
}
fn remove_matching<S, P, O, G>(
&mut self,
ms: &S,
mp: &P,
mo: &O,
mg: &G,
) -> MDResult<Self, usize>
where
S: TermMatcher + ?Sized,
P: TermMatcher + ?Sized,
O: TermMatcher + ?Sized,
G: GraphNameMatcher + ?Sized,
for<'a> <Self as Dataset<'a>>::Error: Into<Self::MutationError>,
Never: CoercibleWith<Self::MutationError>,
Self::MutationError: From<CoercedError<Never, Self::MutationError>>,
{
let to_remove: Vec<_> = self
.quads_matching(ms, mp, mo, mg)
.map_ok(|q| {
(
[
BoxTerm::from(q.s()),
BoxTerm::from(q.p()),
BoxTerm::from(q.o()),
],
q.g().map(BoxTerm::from),
)
})
.collect::<std::result::Result<_, _>>()
.map_err(Into::into)?;
let mut to_remove = to_remove.into_iter().as_quad_source();
Ok(self.remove_all(&mut to_remove)?)
}
fn retain<S, P, O, G>(&mut self, ms: &S, mp: &P, mo: &O, mg: &G) -> MDResult<Self, ()>
where
S: TermMatcher + ?Sized,
P: TermMatcher + ?Sized,
O: TermMatcher + ?Sized,
G: GraphNameMatcher + ?Sized,
for<'a> <Self as Dataset<'a>>::Error: Into<Self::MutationError>,
Never: CoercibleWith<Self::MutationError>,
Self::MutationError: From<CoercedError<Never, Self::MutationError>>,
{
let to_remove: Vec<_> = self
.quads()
.filter_ok(|q| {
!(ms.matches(q.s()) && mp.matches(q.p()) && mo.matches(q.o()) && mg.matches(q.g()))
})
.map_ok(|q| {
(
[
BoxTerm::from(q.s()),
BoxTerm::from(q.p()),
BoxTerm::from(q.o()),
],
q.g().map(BoxTerm::from),
)
})
.collect::<std::result::Result<_, _>>()
.map_err(Into::into)?;
let mut to_remove = to_remove.into_iter().as_quad_source();
self.remove_all(&mut to_remove)?;
Ok(())
}
}
pub trait SetDataset {}
#[cfg(test)]
mod test {
}