Skip to main content

linked_data_next/
subject.rs

1use iref::{Iri, IriBuf};
2use rdf_types::{
3	BlankId, BlankIdBuf, Id, Interpretation, Vocabulary,
4	dataset::PatternMatchingDataset,
5	interpretation::{
6		ReverseBlankIdInterpretation, ReverseIdInterpretation, ReverseIriInterpretation,
7	},
8};
9use std::collections::HashSet;
10use std::hash::Hash;
11
12use crate::{
13	Context, FromLinkedDataError, LinkedDataGraph, LinkedDataPredicateObjects, LinkedDataResource,
14};
15
16/// Serialize a Linked-Data node.
17pub trait LinkedDataSubject<I: Interpretation = (), V: Vocabulary = ()> {
18	fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
19	where
20		S: SubjectVisitor<I, V>;
21}
22
23impl<I: Interpretation, V: Vocabulary> LinkedDataSubject<I, V> for () {
24	fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
25	where
26		S: SubjectVisitor<I, V>,
27	{
28		serializer.end()
29	}
30}
31
32impl<I: Interpretation, V: Vocabulary, T: ?Sized + LinkedDataSubject<I, V>> LinkedDataSubject<I, V>
33	for &T
34{
35	fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36	where
37		S: SubjectVisitor<I, V>,
38	{
39		T::visit_subject(self, serializer)
40	}
41}
42
43impl<I: Interpretation, V: Vocabulary, T: ?Sized + LinkedDataSubject<I, V>> LinkedDataSubject<I, V>
44	for Box<T>
45{
46	fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47	where
48		S: SubjectVisitor<I, V>,
49	{
50		T::visit_subject(self, serializer)
51	}
52}
53
54impl<I: Interpretation, V: Vocabulary> LinkedDataSubject<I, V> for Iri {
55	fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
56	where
57		S: SubjectVisitor<I, V>,
58	{
59		serializer.end()
60	}
61}
62
63impl<I: Interpretation, V: Vocabulary> LinkedDataSubject<I, V> for IriBuf {
64	fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65	where
66		S: SubjectVisitor<I, V>,
67	{
68		serializer.end()
69	}
70}
71
72impl<I: Interpretation, V: Vocabulary> LinkedDataSubject<I, V> for BlankId {
73	fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
74	where
75		S: SubjectVisitor<I, V>,
76	{
77		serializer.end()
78	}
79}
80
81impl<I: Interpretation, V: Vocabulary> LinkedDataSubject<I, V> for BlankIdBuf {
82	fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
83	where
84		S: SubjectVisitor<I, V>,
85	{
86		serializer.end()
87	}
88}
89
90impl<I: Interpretation, V: Vocabulary, T, B> LinkedDataSubject<I, V> for Id<T, B>
91where
92	T: LinkedDataSubject<I, V>,
93	B: LinkedDataSubject<I, V>,
94{
95	fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
96	where
97		S: SubjectVisitor<I, V>,
98	{
99		match self {
100			Self::Iri(i) => i.visit_subject(serializer),
101			Self::Blank(b) => b.visit_subject(serializer),
102		}
103	}
104}
105
106pub trait SubjectVisitor<I: Interpretation, V: Vocabulary> {
107	type Ok;
108	type Error;
109
110	/// Visit a predicate of the graph.
111	fn predicate<L, T>(&mut self, predicate: &L, objects: &T) -> Result<(), Self::Error>
112	where
113		L: ?Sized + LinkedDataResource<I, V>,
114		T: ?Sized + LinkedDataPredicateObjects<I, V>;
115
116	/// Visit a reverse predicate of the graph.
117	fn reverse_predicate<L, T>(&mut self, predicate: &L, subjects: &T) -> Result<(), Self::Error>
118	where
119		L: ?Sized + LinkedDataResource<I, V>,
120		T: ?Sized + LinkedDataPredicateObjects<I, V>;
121
122	fn graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
123	where
124		T: ?Sized + LinkedDataGraph<I, V>;
125
126	fn include<T>(&mut self, value: &T) -> Result<(), Self::Error>
127	where
128		T: ?Sized + LinkedDataResource<I, V> + LinkedDataSubject<I, V>;
129
130	fn end(self) -> Result<Self::Ok, Self::Error>;
131}
132
133impl<I: Interpretation, V: Vocabulary, S: SubjectVisitor<I, V>> SubjectVisitor<I, V> for &mut S {
134	type Ok = ();
135	type Error = S::Error;
136
137	fn predicate<L, T>(&mut self, predicate: &L, objects: &T) -> Result<(), Self::Error>
138	where
139		L: ?Sized + LinkedDataResource<I, V>,
140		T: ?Sized + LinkedDataPredicateObjects<I, V>,
141	{
142		S::predicate(self, predicate, objects)
143	}
144
145	fn reverse_predicate<L, T>(&mut self, predicate: &L, subjects: &T) -> Result<(), Self::Error>
146	where
147		L: ?Sized + LinkedDataResource<I, V>,
148		T: ?Sized + LinkedDataPredicateObjects<I, V>,
149	{
150		S::reverse_predicate(self, predicate, subjects)
151	}
152
153	fn graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
154	where
155		T: ?Sized + LinkedDataGraph<I, V>,
156	{
157		S::graph(self, value)
158	}
159
160	fn include<T>(&mut self, value: &T) -> Result<(), Self::Error>
161	where
162		T: ?Sized + LinkedDataResource<I, V> + LinkedDataSubject<I, V>,
163	{
164		S::include(self, value)
165	}
166
167	fn end(self) -> Result<Self::Ok, Self::Error> {
168		Ok(())
169	}
170}
171
172pub trait LinkedDataDeserializeSubject<I: Interpretation = (), V: Vocabulary = ()>: Sized {
173	fn deserialize_subject_in<D>(
174		vocabulary: &V,
175		interpretation: &I,
176		dataset: &D,
177		graph: Option<&I::Resource>,
178		resource: &I::Resource,
179		context: Context<I>,
180	) -> Result<Self, FromLinkedDataError>
181	where
182		D: PatternMatchingDataset<Resource = I::Resource>;
183
184	fn deserialize_subject<D>(
185		vocabulary: &V,
186		interpretation: &I,
187		dataset: &D,
188		graph: Option<&I::Resource>,
189		resource: &I::Resource,
190	) -> Result<Self, FromLinkedDataError>
191	where
192		D: PatternMatchingDataset<Resource = I::Resource>,
193	{
194		Self::deserialize_subject_in(
195			vocabulary,
196			interpretation,
197			dataset,
198			graph,
199			resource,
200			Context::default(),
201		)
202	}
203
204	fn deserialize_subjects_in<D>(
205		vocabulary: &V,
206		interpretation: &I,
207		dataset: &D,
208		graph: Option<&I::Resource>,
209		resources: impl IntoIterator<Item = I::Resource>,
210		context: Context<I>,
211	) -> Result<Vec<Self>, FromLinkedDataError>
212	where
213		D: PatternMatchingDataset<Resource = I::Resource>,
214	{
215		resources
216			.into_iter()
217			.map(|resource| {
218				Self::deserialize_subject_in(
219					vocabulary,
220					interpretation,
221					dataset,
222					graph,
223					&resource,
224					context,
225				)
226			})
227			.collect::<Result<Vec<_>, _>>()
228	}
229
230	fn deserialize_subjects<D>(
231		vocabulary: &V,
232		interpretation: &I,
233		dataset: &D,
234		graph: Option<&I::Resource>,
235		resources: impl IntoIterator<Item = I::Resource>,
236	) -> Result<Vec<Self>, FromLinkedDataError>
237	where
238		D: PatternMatchingDataset<Resource = I::Resource>,
239	{
240		Self::deserialize_subjects_in(
241			vocabulary,
242			interpretation,
243			dataset,
244			graph,
245			resources,
246			Context::default(),
247		)
248	}
249}
250
251impl<I: Interpretation, V: Vocabulary> LinkedDataDeserializeSubject<I, V> for IriBuf
252where
253	I: ReverseIriInterpretation<Iri = V::Iri>,
254{
255	fn deserialize_subject_in<D>(
256		vocabulary: &V,
257		interpretation: &I,
258		_dataset: &D,
259		_graph: Option<&I::Resource>,
260		resource: &I::Resource,
261		context: Context<I>,
262	) -> Result<Self, FromLinkedDataError>
263	where
264		D: PatternMatchingDataset<Resource = I::Resource>,
265	{
266		match interpretation.iris_of(resource).next() {
267			Some(i) => {
268				let iri = vocabulary.iri(i).unwrap();
269				Ok(iri.to_owned())
270			}
271			None => Err(FromLinkedDataError::InvalidSubject {
272				context: context.into_iris(vocabulary, interpretation),
273				subject: None,
274			}),
275		}
276	}
277}
278
279impl<I: Interpretation, V: Vocabulary> LinkedDataDeserializeSubject<I, V> for BlankIdBuf
280where
281	I: ReverseIriInterpretation<Iri = V::Iri> + ReverseBlankIdInterpretation<BlankId = V::BlankId>,
282{
283	fn deserialize_subject_in<D>(
284		vocabulary: &V,
285		interpretation: &I,
286		_dataset: &D,
287		_graph: Option<&I::Resource>,
288		resource: &I::Resource,
289		context: Context<I>,
290	) -> Result<Self, FromLinkedDataError>
291	where
292		D: PatternMatchingDataset<Resource = I::Resource>,
293	{
294		match interpretation.blank_ids_of(resource).next() {
295			Some(b) => {
296				let blank_id = vocabulary.blank_id(b).unwrap();
297				Ok(blank_id.to_owned())
298			}
299			None => Err(FromLinkedDataError::InvalidSubject {
300				context: context.into_iris(vocabulary, interpretation),
301				subject: interpretation
302					.iris_of(resource)
303					.next()
304					.map(|i| vocabulary.iri(i).unwrap().to_owned()),
305			}),
306		}
307	}
308}
309
310impl<I: Interpretation, V: Vocabulary> LinkedDataDeserializeSubject<I, V> for Id
311where
312	I: ReverseIdInterpretation<Iri = V::Iri, BlankId = V::BlankId>,
313{
314	fn deserialize_subject_in<D>(
315		vocabulary: &V,
316		interpretation: &I,
317		_dataset: &D,
318		_graph: Option<&I::Resource>,
319		resource: &I::Resource,
320		context: Context<I>,
321	) -> Result<Self, FromLinkedDataError>
322	where
323		D: PatternMatchingDataset<Resource = I::Resource>,
324	{
325		match interpretation.ids_of(resource).next() {
326			Some(Id::Iri(i)) => {
327				let iri = vocabulary.iri(i).unwrap();
328				Ok(Id::Iri(iri.to_owned()))
329			}
330			Some(Id::Blank(b)) => {
331				let blank_id = vocabulary.blank_id(b).unwrap();
332				Ok(Id::Blank(blank_id.to_owned()))
333			}
334			None => Err(FromLinkedDataError::InvalidSubject {
335				context: context.into_iris(vocabulary, interpretation),
336				subject: None,
337			}),
338		}
339	}
340}
341
342impl<I: Interpretation, V: Vocabulary, T: LinkedDataDeserializeSubject<I, V>>
343	LinkedDataDeserializeSubject<I, V> for Box<T>
344{
345	fn deserialize_subject_in<D>(
346		vocabulary: &V,
347		interpretation: &I,
348		dataset: &D,
349		graph: Option<&I::Resource>,
350		resource: &I::Resource,
351		context: Context<I>,
352	) -> Result<Self, FromLinkedDataError>
353	where
354		D: PatternMatchingDataset<Resource = I::Resource>,
355	{
356		T::deserialize_subject_in(
357			vocabulary,
358			interpretation,
359			dataset,
360			graph,
361			resource,
362			context,
363		)
364		.map(Box::new)
365	}
366}
367
368impl<I: Interpretation, V: Vocabulary, T: LinkedDataDeserializeSubject<I, V>>
369	LinkedDataDeserializeSubject<I, V> for HashSet<T>
370where
371	T: Hash + Eq,
372{
373	fn deserialize_subject_in<D>(
374		vocabulary: &V,
375		interpretation: &I,
376		dataset: &D,
377		graph: Option<&I::Resource>,
378		resource: &I::Resource,
379		context: Context<I>,
380	) -> Result<Self, FromLinkedDataError>
381	where
382		D: PatternMatchingDataset<Resource = I::Resource>,
383	{
384		T::deserialize_subject_in(
385			vocabulary,
386			interpretation,
387			dataset,
388			graph,
389			resource,
390			context,
391		)
392		.map(|value| HashSet::from([value]))
393	}
394}