use std::collections::HashSet;
use std::ops::{
Deref,
DerefMut
};
use futures::future::{BoxFuture, FutureExt};
use iref::{
Iri,
IriBuf
};
use json::JsonValue;
use crate::{
Error,
Id,
Indexed,
Object,
ContextMut,
context::{
self,
Loader
},
expansion
};
pub type ExpandedDocument<T> = HashSet<Indexed<Object<T>>>;
pub trait Document<T: Id> {
type LocalContext: context::Local<T>;
fn base_url(&self) -> Option<Iri>;
fn expand_with<'a, C: Send + Sync + ContextMut<T>, L: Send + Sync + Loader>(&'a self, base_url: Option<Iri>, context: &'a C, loader: &'a mut L, options: expansion::Options) -> BoxFuture<'a, Result<ExpandedDocument<T>, Error>> where
C::LocalContext: Send + Sync + From<L::Output> + From<Self::LocalContext>,
L::Output: Into<Self::LocalContext>,
T: 'a + Send + Sync;
fn expand<'a, C: Send + Sync + ContextMut<T>, L: Send + Sync + Loader>(&'a self, context: &'a C, loader: &'a mut L) -> BoxFuture<'a, Result<ExpandedDocument<T>, Error>> where
C::LocalContext: Send + Sync + From<L::Output> + From<Self::LocalContext>,
L::Output: Into<Self::LocalContext>,
T: 'a + Send + Sync
{
self.expand_with(self.base_url(), context, loader, expansion::Options::default())
}
}
impl<T: Id> Document<T> for JsonValue {
type LocalContext = JsonValue;
fn base_url(&self) -> Option<Iri> {
None
}
fn expand_with<'a, C: Send + Sync + ContextMut<T>, L: Send + Sync + Loader>(&'a self, base_url: Option<Iri>, context: &'a C, loader: &'a mut L, options: expansion::Options) -> BoxFuture<'a, Result<ExpandedDocument<T>, Error>> where
C::LocalContext: Send + Sync + From<L::Output> + From<JsonValue>,
L::Output: Into<JsonValue>,
T: 'a + Send + Sync
{
expansion::expand(context, self, base_url, loader, options).boxed()
}
}
#[derive(Clone)]
pub struct RemoteDocument<D = JsonValue> {
base_url: IriBuf,
doc: D,
}
impl<D> RemoteDocument<D> {
pub fn new(doc: D, base_url: Iri) -> RemoteDocument<D> {
RemoteDocument {
base_url: base_url.into(),
doc: doc
}
}
pub fn into_document(self) -> D {
self.doc
}
pub fn into_parts(self) -> (D, IriBuf) {
(self.doc, self.base_url)
}
}
impl<T: Id, D: Document<T>> Document<T> for RemoteDocument<D> {
type LocalContext = D::LocalContext;
fn base_url(&self) -> Option<Iri> {
Some(self.base_url.as_iri())
}
fn expand_with<'a, C: Send + Sync + ContextMut<T>, L: Send + Sync + Loader>(&'a self, base_url: Option<Iri>, context: &'a C, loader: &'a mut L, options: expansion::Options) -> BoxFuture<'a, Result<ExpandedDocument<T>, Error>> where
C::LocalContext: Send + Sync + From<L::Output> + From<Self::LocalContext>,
L::Output: Into<Self::LocalContext>,
T: 'a + Send + Sync
{
self.doc.expand_with(base_url, context, loader, options)
}
}
impl<D> Deref for RemoteDocument<D> {
type Target = D;
fn deref(&self) -> &D {
&self.doc
}
}
impl<D> DerefMut for RemoteDocument<D> {
fn deref_mut(&mut self) -> &mut D {
&mut self.doc
}
}