#[cfg(feature = "source_browser")]
pub mod browser;
pub mod local;
pub mod remote;
use crate::prelude::*;
use iref::InvalidIri;
use taganak_core::{
default_graph_view,
graphs::{either_graph::{EitherGraph3, EitherGraph4, EitherGraph5}, GraphView},
terms::Iri,
};
use futures::Stream;
use taganak_orm::GraphORM;
pub trait GraphConfig: Clone {
type Graph: ConfigurableGraph<Config = Self>;
fn into_graph(self) -> Result<Self::Graph, SourceError>
where
Self: Sized,
{
Self::Graph::from_config(self)
}
}
pub trait ConfigurableGraph: Graph {
type Config: GraphConfig<Graph = Self>;
fn from_config(config: Self::Config) -> Result<Self, SourceError>
where
Self: Sized;
}
#[derive(Clone, Debug, PartialEq, Eq, GraphORM, Hash)]
#[rdf(
prefix(ns = "sdk", iri = "http://sdk.taganak.net/vocab/taganak#"),
rdf_type = "sdk:GraphConfigs"
)]
pub enum GraphConfigs {
#[cfg(feature = "source_local_file")]
#[rdf(proxy(rdf_type = "sdk:LocalFileSourceGraphConfig"))]
LocalFile(self::local::persistent::local_file::LocalFileSourceGraphConfig),
#[cfg(feature = "source_graph_store_http")]
#[rdf(proxy(rdf_type = "sdk:GraphStoreHttpSourceGraphConfig"))]
GraphStoreHttp(self::remote::graph_store_http::GraphStoreHttpSourceGraphConfig),
#[cfg(feature = "source_indexeddb")]
#[rdf(proxy(rdf_type = "sdk:IndexedDbSourceGraphConfig"))]
IndexedDb(self::browser::indexeddb::IndexedDbSourceGraphConfig),
#[rdf(proxy(rdf_type = "sdk:DummyGraphConfig"))]
Dummy,
#[cfg(feature = "source_fidibats")]
#[rdf(proxy(rdf_type = "sdk:FidibatsSourceGraphConfig"))]
Fidibats(self::local::persistent::fidibats::FidibatsSourceGraphConfig)
}
impl GraphConfig for GraphConfigs {
type Graph = ConfigurableGraphs;
}
#[cfg(feature = "source_local_file")]
type LocalFileSourceGraph = self::local::persistent::local_file::LocalFileSourceGraph;
#[cfg(not(feature = "source_local_file"))]
type LocalFileSourceGraph = ();
#[cfg(feature = "source_graph_store_http")]
type GraphStoreHttpSourceGraph = self::remote::graph_store_http::GraphStoreHttpSourceGraph;
#[cfg(not(feature = "source_graph_store_http"))]
type GraphStoreHttpSourceGraph = ();
#[cfg(feature = "source_indexeddb")]
type IndexedDbSourceGraph = self::browser::indexeddb::IndexedDbSourceGraph;
#[cfg(not(feature = "source_indexeddb"))]
type IndexedDbSourceGraph = ();
#[cfg(feature = "source_fidibats")]
type FidibatsSourceGrah = self::local::persistent::fidibats::FidibatsSourceGraph;
#[cfg(not(feature = "source_fidibats"))]
type FidibatsSourceGrah = ();
type ConfigEither =
EitherGraph5<LocalFileSourceGraph, GraphStoreHttpSourceGraph, IndexedDbSourceGraph, FidibatsSourceGrah, ()>;
#[derive(Debug)]
pub struct ConfigurableGraphs(ConfigEither);
#[derive(Debug, thiserror::Error)]
pub enum FromGraphError {
#[error("the requested subject is lacking any type")]
NoType,
#[error("the requested subject is not a valid GraphConfigs type {0:?}")]
NotGraph(Arc<Term>),
#[error(
"the requested subject has no <http://sdk.taganak.net/vocab/taganak#SourceIri> predicate"
)]
NoSourceIri,
#[error("the source iri is invalid: `{_0}`")]
InvalidSourceIri(
#[source]
#[from]
InvalidIri<String>,
),
#[error(transparent)]
InvalidGrahIri(#[from] FromIriError),
#[error("the source iri of the provided subject is no literal")]
SourceIriNotLiteral,
#[cfg(feature = "source_graph_store_http")]
#[error(transparent)]
InvalidHttpSourceGraphConfig(#[from] remote::graph_store_http::FromGraphError),
#[cfg(feature = "source_local_file")]
#[error(transparent)]
InvalidLocalFileConfig(#[from] local::persistent::local_file::FromGraphError),
#[error(transparent)]
GraphErr(#[from] GraphError),
}
#[derive(Debug, thiserror::Error)]
pub enum FromIriError {
#[error("Invalid scheme {_0:?}")]
InvalidScheme(iref::iri::SchemeBuf),
}
impl GraphConfigs {
pub fn from_iri(iri: Iri) -> Result<Self, FromIriError> {
let scheme = iri.scheme();
Ok(match scheme.as_str() {
#[cfg(feature = "source_local_file")]
"file" => Self::LocalFile(
self::local::persistent::local_file::LocalFileSourceGraphConfig::new(
iri,
None,
None,
false,
),
),
#[cfg(feature = "source_graph_store_http")]
"http" | "https" => Self::GraphStoreHttp(
self::remote::graph_store_http::GraphStoreHttpSourceGraphConfig::new(iri),
),
#[cfg(feature = "source_indexeddb")]
"indexeddb" => Self::IndexedDb(
self::browser::indexeddb::IndexedDbSourceGraphConfig::new(iri),
),
#[cfg(feature = "source_fidibats")]
"file+fidibats" => Self::Fidibats(self::local::persistent::fidibats::FidibatsSourceGraphConfig::from_iri(iri).unwrap()),
_ => return Err(FromIriError::InvalidScheme(scheme.to_owned())),
})
}
}
impl ConfigurableGraph for ConfigurableGraphs {
type Config = GraphConfigs;
fn from_config(config: Self::Config) -> Result<Self, SourceError> {
match config {
#[cfg(feature = "source_local_file")]
GraphConfigs::LocalFile(c) => Ok(Self(EitherGraph5::N1(
self::local::persistent::local_file::LocalFileSourceGraph::from_config(c)?,
))),
#[cfg(feature = "source_graph_store_http")]
GraphConfigs::GraphStoreHttp(c) => Ok(Self(EitherGraph5::N2(
self::remote::graph_store_http::GraphStoreHttpSourceGraph::from_config(c)?,
))),
#[cfg(feature = "source_indexeddb")]
GraphConfigs::IndexedDb(c) => Ok(Self(EitherGraph5::N3(
self::browser::indexeddb::IndexedDbSourceGraph::from_config(c)?,
))),
#[cfg(feature = "source_fidibats")]
GraphConfigs::Fidibats(c) => Ok(Self(EitherGraph5::N4(self::local::persistent::fidibats::FidibatsSourceGraph::from_config(c)?))),
_ => unreachable!(),
}
}
}
impl Graph for ConfigurableGraphs {
type View<'g> = <ConfigEither as Graph>::View<'g>
where
Self: 'g;
fn view(&self) -> impl core::future::Future<Output = Self::View<'_>> + Send {
self.0.view()
}
fn add(
&mut self,
triple: Arc<Triple>,
) -> impl core::future::Future<Output = Result<(), GraphError>> + Send {
self.0.add(triple)
}
fn remove(
&mut self,
triple: TripleRef<'_>,
) -> impl core::future::Future<Output = Result<(), GraphError>> + Send {
self.0.remove(triple)
}
fn merge<G>(
&mut self,
source_graph: G,
) -> impl core::future::Future<Output = Result<(), GraphError>> + Send
where
G: GraphView,
{
self.0.merge(source_graph)
}
fn merge_stream<S, E>(
&mut self,
stream: S,
) -> impl core::future::Future<Output = Result<(), GraphError>> + Send
where
S: Stream<Item = Result<Arc<Triple>, E>> + Unpin + Send,
GraphError: From<E>,
E: Send,
{
self.0.merge_stream(stream)
}
}