Skip to main content

jsonld/processor/
remote_document.rs

1use super::{
2    CompactError,
3    CompactResult,
4    CompareResult,
5    ExpandError,
6    ExpandResult,
7    FlattenError,
8    FlattenResult,
9    JsonLdProcessor,
10    Options,
11    compact_expanded_full,
12};
13use crate::{
14    Context,
15    Flatten,
16    IntoDocumentResult,
17    Loader,
18    RemoteDocument,
19    RemoteDocumentReference,
20    context_processing::{self, Process},
21    expansion::{self, Expand},
22};
23use contextual::WithContext;
24use jsonld_core::{Document, RemoteContextReference};
25use rdfx::{LocalGenerator, vocabulary::VocabularyMut};
26use std::hash::Hash;
27
28impl<I> JsonLdProcessor<I> for RemoteDocument<I> {
29    async fn compare_full<N, L>(
30        &self,
31        other: &Self,
32        vocabulary: &mut N,
33        loader: &L,
34        options: Options<I>,
35        mut warnings: impl context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
36    ) -> CompareResult<L::Error>
37    where
38        N: VocabularyMut<Iri = I>,
39        I: Clone + Eq + Hash,
40        N::BlankId: Clone + Eq + Hash,
41        L: Loader,
42    {
43        if jsonld_syntax::Compare::compare(self.document(), other.document()) {
44            let a = JsonLdProcessor::expand_full(self, vocabulary, loader, options.clone(), &mut warnings).await?;
45            let b = JsonLdProcessor::expand_full(other, vocabulary, loader, options, &mut warnings).await?;
46            Ok(a == b)
47        } else {
48            Ok(false)
49        }
50    }
51
52    async fn expand_full<N, L>(
53        &self,
54        vocabulary: &mut N,
55        loader: &L,
56        mut options: Options<I>,
57        mut warnings: impl context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
58    ) -> ExpandResult<I, N::BlankId, L::Error>
59    where
60        N: VocabularyMut<Iri = I>,
61        I: Clone + Eq + Hash,
62        N::BlankId: Clone + Eq + Hash,
63        L: Loader,
64    {
65        let mut active_context = Context::new(options.base.clone().or_else(|| self.url().cloned()));
66
67        if let Some(expand_context) = options.expand_context.take() {
68            active_context = expand_context
69                .load_context_with(vocabulary, loader)
70                .await
71                .map_err(ExpandError::ContextLoading)?
72                .into_document()
73                .process_full(
74                    vocabulary,
75                    &active_context,
76                    loader,
77                    active_context.original_base_url().cloned(),
78                    options.context_processing_options(),
79                    &mut warnings,
80                )
81                .await
82                .map_err(ExpandError::ContextProcessing)?
83                .into_processed();
84        }
85
86        if let Some(context_url) = self.context_url() {
87            active_context = RemoteDocumentReference::Iri(context_url.clone())
88                .load_context_with(vocabulary, loader)
89                .await
90                .map_err(ExpandError::ContextLoading)?
91                .into_document()
92                .process_full(
93                    vocabulary,
94                    &active_context,
95                    loader,
96                    Some(context_url.clone()),
97                    options.context_processing_options(),
98                    &mut warnings,
99                )
100                .await
101                .map_err(ExpandError::ContextProcessing)?
102                .into_processed();
103        }
104
105        self.document()
106            .expand_full(
107                vocabulary,
108                active_context,
109                // `Options::base` overrides the document's own URL, matching
110                // its documentation and the initial-context base above.
111                options.base.as_ref().or(self.url()),
112                loader,
113                options.expansion_options(),
114                warnings,
115            )
116            .await
117            .map_err(ExpandError::Expansion)
118    }
119
120    async fn into_document_full<'a, N, L>(
121        self,
122        vocabulary: &'a mut N,
123        loader: &'a L,
124        options: Options<I>,
125        warnings: impl 'a + context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
126    ) -> IntoDocumentResult<I, N::BlankId, L::Error>
127    where
128        N: VocabularyMut<Iri = I>,
129        I: 'a + Clone + Eq + Hash,
130        N::BlankId: 'a + Clone + Eq + Hash,
131        L: Loader,
132    {
133        let expanded = JsonLdProcessor::expand_full(&self, vocabulary, loader, options, warnings).await?;
134        Ok(Document::new(self, expanded))
135    }
136
137    async fn compact_full<'a, N, L>(
138        &'a self,
139        vocabulary: &'a mut N,
140        context: RemoteContextReference<I>,
141        loader: &'a L,
142        options: Options<I>,
143        mut warnings: impl 'a + context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
144    ) -> CompactResult<L::Error>
145    where
146        N: VocabularyMut<Iri = I>,
147        I: Clone + Eq + Hash,
148        N::BlankId: 'a + Clone + Eq + Hash,
149        L: Loader,
150    {
151        let expanded_input = JsonLdProcessor::expand_full(self, vocabulary, loader, options.clone().unordered(), &mut warnings)
152            .await
153            .map_err(CompactError::Expand)?;
154
155        compact_expanded_full(&expanded_input, self.url(), vocabulary, context, loader, options, warnings).await
156    }
157
158    async fn flatten_full<'a, N, L>(
159        &'a self,
160        vocabulary: &'a mut N,
161        generator: &'a mut impl LocalGenerator,
162        context: Option<RemoteContextReference<I>>,
163        loader: &'a L,
164        options: Options<I>,
165        mut warnings: impl 'a + context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
166    ) -> FlattenResult<I, N::BlankId, L::Error>
167    where
168        N: VocabularyMut<Iri = I>,
169        I: Clone + Eq + Hash,
170        N::BlankId: 'a + Clone + Eq + Hash,
171        L: Loader,
172    {
173        let expanded_input = JsonLdProcessor::expand_full(self, vocabulary, loader, options.clone().unordered(), &mut warnings)
174            .await
175            .map_err(FlattenError::Expand)?;
176
177        let flattened_output = Flatten::flatten_with(expanded_input, vocabulary, generator, options.ordered)?;
178
179        match context {
180            Some(context) => compact_expanded_full(&flattened_output, self.url(), vocabulary, context, loader, options, warnings)
181                .await
182                .map_err(FlattenError::Compact),
183            None => Ok(jsonld_syntax::IntoJson::into_json(flattened_output.into_with(vocabulary))),
184        }
185    }
186}
187
188impl<I> JsonLdProcessor<I> for RemoteDocumentReference<I, jstrict::Value> {
189    async fn compare_full<N, L>(
190        &self,
191        other: &Self,
192        vocabulary: &mut N,
193        loader: &L,
194        options: Options<I>,
195        warnings: impl context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
196    ) -> CompareResult<L::Error>
197    where
198        N: VocabularyMut<Iri = I>,
199        I: Clone + Eq + Hash,
200        N::BlankId: Clone + Eq + Hash,
201        L: Loader,
202    {
203        let a = self.loaded_with(vocabulary, loader).await?;
204        let b = other.loaded_with(vocabulary, loader).await?;
205        JsonLdProcessor::compare_full(a.as_ref(), b.as_ref(), vocabulary, loader, options, warnings).await
206    }
207
208    async fn expand_full<N, L>(
209        &self,
210        vocabulary: &mut N,
211        loader: &L,
212        options: Options<I>,
213        warnings: impl context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
214    ) -> ExpandResult<I, N::BlankId, L::Error>
215    where
216        N: VocabularyMut<Iri = I>,
217        I: Clone + Eq + Hash,
218        N::BlankId: Clone + Eq + Hash,
219        L: Loader,
220    {
221        let doc = self.loaded_with(vocabulary, loader).await?;
222        JsonLdProcessor::expand_full(doc.as_ref(), vocabulary, loader, options, warnings).await
223    }
224
225    async fn into_document_full<'a, N, L>(
226        self,
227        vocabulary: &'a mut N,
228        loader: &'a L,
229        options: Options<I>,
230        warnings: impl 'a + context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
231    ) -> IntoDocumentResult<I, N::BlankId, L::Error>
232    where
233        N: VocabularyMut<Iri = I>,
234        I: 'a + Clone + Eq + Hash,
235        N::BlankId: 'a + Clone + Eq + Hash,
236        L: Loader,
237    {
238        let doc = self.load_with(vocabulary, loader).await?;
239        JsonLdProcessor::into_document_full(doc, vocabulary, loader, options, warnings).await
240    }
241
242    async fn compact_full<'a, N, L>(
243        &'a self,
244        vocabulary: &'a mut N,
245        context: RemoteContextReference<I>,
246        loader: &'a L,
247        options: Options<I>,
248        warnings: impl 'a + context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
249    ) -> CompactResult<L::Error>
250    where
251        N: VocabularyMut<Iri = I>,
252        I: Clone + Eq + Hash,
253        N::BlankId: 'a + Clone + Eq + Hash,
254        L: Loader,
255    {
256        let doc = self.loaded_with(vocabulary, loader).await?;
257        JsonLdProcessor::compact_full(doc.as_ref(), vocabulary, context, loader, options, warnings).await
258    }
259
260    async fn flatten_full<'a, N, L>(
261        &'a self,
262        vocabulary: &'a mut N,
263        generator: &'a mut impl LocalGenerator,
264        context: Option<RemoteContextReference<I>>,
265        loader: &'a L,
266        options: Options<I>,
267        warnings: impl 'a + context_processing::WarningHandler<N> + expansion::WarningHandler<N>,
268    ) -> FlattenResult<I, N::BlankId, L::Error>
269    where
270        N: VocabularyMut<Iri = I>,
271        I: Clone + Eq + Hash,
272        N::BlankId: 'a + Clone + Eq + Hash,
273        L: Loader,
274    {
275        let doc = self.loaded_with(vocabulary, loader).await?;
276        JsonLdProcessor::flatten_full(doc.as_ref(), vocabulary, generator, context, loader, options, warnings).await
277    }
278}