linked_data_next/
resource.rs

1use educe::Educe;
2use iref::{Iri, IriBuf};
3use rdf_types::{
4	interpretation::ReverseTermInterpretation,
5	vocabulary::{BlankIdVocabularyMut, IriVocabularyMut},
6	BlankId, BlankIdBuf, Id, Interpretation, Term, Vocabulary,
7};
8use std::fmt;
9
10use crate::{AsRdfLiteral, CowRdfTerm};
11
12/// Resource interpretation.
13#[derive(Educe)]
14#[educe(Debug(bound = "I::Resource: fmt::Debug, V::Iri: fmt::Debug, V::BlankId: fmt::Debug"))]
15pub enum ResourceInterpretation<'a, I: Interpretation, V: Vocabulary> {
16	/// Interpreted resource.
17	Interpreted(&'a I::Resource),
18
19	/// Uninterpreted resource with the given optional lexical representation.
20	///
21	/// It can be used to give an actual interpretation to the resource, bound
22	/// to its lexical representation.
23	Uninterpreted(Option<CowRdfTerm<'a, V>>),
24}
25
26impl<'a, I: Interpretation, V: Vocabulary> ResourceInterpretation<'a, I, V> {
27	pub fn as_interpreted(&self) -> Option<&'a I::Resource> {
28		match self {
29			Self::Interpreted(i) => Some(i),
30			_ => None,
31		}
32	}
33
34	pub fn as_uninterpreted(&self) -> Option<&CowRdfTerm<'a, V>> {
35		match self {
36			Self::Uninterpreted(t) => t.as_ref(),
37			_ => None,
38		}
39	}
40
41	pub fn into_lexical_representation(
42		self,
43		vocabulary: &'a V,
44		interpretation: &'a I,
45	) -> Option<CowRdfTerm<'a, V>>
46	where
47		I: ReverseTermInterpretation<Iri = V::Iri, BlankId = V::BlankId, Literal = V::Literal>,
48	{
49		match self {
50			Self::Interpreted(r) => {
51				if let Some(i) = interpretation.iris_of(r).next() {
52					return Some(CowRdfTerm::Borrowed(Term::Id(Id::Iri(i))));
53				}
54
55				if let Some(l) = interpretation.literals_of(r).next() {
56					let l = vocabulary.literal(l).unwrap();
57					let term = match l.value.as_rdf_literal(vocabulary, l.type_) {
58						crate::CowRdfLiteral::Borrowed(l) => CowRdfTerm::Borrowed(Term::Literal(l)),
59						crate::CowRdfLiteral::Owned(l) => CowRdfTerm::Owned(Term::Literal(l)),
60					};
61
62					return Some(term);
63				}
64
65				if let Some(b) = interpretation.blank_ids_of(r).next() {
66					return Some(CowRdfTerm::Borrowed(Term::Id(Id::Blank(b))));
67				}
68
69				None
70			}
71			Self::Uninterpreted(t) => t,
72		}
73	}
74}
75
76/// Type that can have an interpretation bound to the given lifetime.
77pub trait LinkedDataResourceRef<'a, I: Interpretation = (), V: Vocabulary = ()> {
78	fn interpretation_ref(
79		&self,
80		vocabulary: &mut V,
81		interpretation: &mut I,
82	) -> ResourceInterpretation<'a, I, V>;
83}
84
85/// Type that can have an interpretation.
86pub trait LinkedDataResource<I: Interpretation = (), V: Vocabulary = ()> {
87	fn interpretation(
88		&self,
89		vocabulary: &mut V,
90		interpretation: &mut I,
91	) -> ResourceInterpretation<I, V>;
92
93	fn lexical_representation<'a>(
94		&'a self,
95		vocabulary: &'a mut V,
96		interpretation: &'a mut I,
97	) -> Option<CowRdfTerm<'a, V>>
98	where
99		I: ReverseTermInterpretation<Iri = V::Iri, BlankId = V::BlankId, Literal = V::Literal>,
100	{
101		self.interpretation(vocabulary, interpretation)
102			.into_lexical_representation(vocabulary, interpretation)
103	}
104
105	fn reference_interpretation(
106		&self,
107		vocabulary: &mut V,
108		interpretation: &mut I,
109	) -> ResourceInterpretation<I, V> {
110		self.interpretation(vocabulary, interpretation)
111	}
112}
113
114impl<I: Interpretation, V: Vocabulary, T: ?Sized + LinkedDataResource<I, V>>
115	LinkedDataResource<I, V> for &T
116{
117	fn interpretation(
118		&self,
119		vocabulary: &mut V,
120		interpretation: &mut I,
121	) -> ResourceInterpretation<I, V> {
122		T::interpretation(self, vocabulary, interpretation)
123	}
124}
125
126impl<I: Interpretation, V: Vocabulary, T: ?Sized + LinkedDataResource<I, V>>
127	LinkedDataResource<I, V> for Box<T>
128{
129	fn interpretation(
130		&self,
131		vocabulary: &mut V,
132		interpretation: &mut I,
133	) -> ResourceInterpretation<I, V> {
134		T::interpretation(self, vocabulary, interpretation)
135	}
136}
137
138impl<I: Interpretation, V: Vocabulary> LinkedDataResource<I, V> for () {
139	fn interpretation(
140		&self,
141		_vocabulary: &mut V,
142		_interpretation: &mut I,
143	) -> ResourceInterpretation<I, V> {
144		ResourceInterpretation::Uninterpreted(None)
145	}
146}
147
148/// Anonymous lexical representation.
149///
150/// This type implements the `LexicalRepresentation` trait, producing a blank
151/// node identifier.
152pub struct Anonymous;
153
154impl<I: Interpretation, V: Vocabulary> LinkedDataResource<I, V> for Anonymous {
155	fn interpretation(
156		&self,
157		_vocabulary: &mut V,
158		_interpretation: &mut I,
159	) -> ResourceInterpretation<I, V> {
160		ResourceInterpretation::Uninterpreted(None)
161	}
162}
163
164impl<V: Vocabulary + IriVocabularyMut, I: Interpretation> LinkedDataResource<I, V> for Iri {
165	fn interpretation(
166		&self,
167		vocabulary: &mut V,
168		_interpretation: &mut I,
169	) -> ResourceInterpretation<I, V> {
170		ResourceInterpretation::Uninterpreted(Some(CowRdfTerm::Owned(Term::Id(Id::Iri(
171			vocabulary.insert(self),
172		)))))
173	}
174}
175
176impl<V: Vocabulary + IriVocabularyMut, I: Interpretation> LinkedDataResource<I, V> for IriBuf {
177	fn interpretation(
178		&self,
179		vocabulary: &mut V,
180		_interpretation: &mut I,
181	) -> ResourceInterpretation<I, V> {
182		ResourceInterpretation::Uninterpreted(Some(CowRdfTerm::Owned(Term::Id(Id::Iri(
183			vocabulary.insert(self),
184		)))))
185	}
186}
187
188impl<V: Vocabulary + BlankIdVocabularyMut, I: Interpretation> LinkedDataResource<I, V> for BlankId {
189	fn interpretation(
190		&self,
191		vocabulary: &mut V,
192		_interpretation: &mut I,
193	) -> ResourceInterpretation<I, V> {
194		ResourceInterpretation::Uninterpreted(Some(CowRdfTerm::Owned(Term::Id(Id::Blank(
195			vocabulary.insert_blank_id(self),
196		)))))
197	}
198}
199
200impl<V: Vocabulary + BlankIdVocabularyMut, I: Interpretation> LinkedDataResource<I, V>
201	for BlankIdBuf
202{
203	fn interpretation(
204		&self,
205		vocabulary: &mut V,
206		_interpretation: &mut I,
207	) -> ResourceInterpretation<I, V> {
208		ResourceInterpretation::Uninterpreted(Some(CowRdfTerm::Owned(Term::Id(Id::Blank(
209			vocabulary.insert_blank_id(self),
210		)))))
211	}
212}
213
214impl<
215		V: Vocabulary,
216		I: Interpretation,
217		T: LinkedDataResource<I, V>,
218		B: LinkedDataResource<I, V>,
219	> LinkedDataResource<I, V> for Id<T, B>
220{
221	fn interpretation(
222		&self,
223		vocabulary: &mut V,
224		interpretation: &mut I,
225	) -> ResourceInterpretation<I, V> {
226		match self {
227			Self::Iri(i) => i.reference_interpretation(vocabulary, interpretation),
228			Self::Blank(b) => b.reference_interpretation(vocabulary, interpretation),
229		}
230	}
231}
232
233impl<
234		V: Vocabulary,
235		I: Interpretation,
236		T: LinkedDataResource<I, V>,
237		B: LinkedDataResource<I, V>,
238		L: LinkedDataResource<I, V>,
239	> LinkedDataResource<I, V> for Term<Id<T, B>, L>
240{
241	fn interpretation(
242		&self,
243		vocabulary: &mut V,
244		interpretation: &mut I,
245	) -> ResourceInterpretation<I, V> {
246		match self {
247			Self::Id(id) => id.reference_interpretation(vocabulary, interpretation),
248			Self::Literal(l) => l.interpretation(vocabulary, interpretation),
249		}
250	}
251}
252
253impl<V: Vocabulary, I: Interpretation> LinkedDataResource<I, V> for rdf_types::Literal<V::Iri> {
254	fn interpretation(
255		&self,
256		_vocabulary: &mut V,
257		_interpretation: &mut I,
258	) -> ResourceInterpretation<I, V> {
259		ResourceInterpretation::Uninterpreted(Some(CowRdfTerm::Borrowed(Term::Literal(
260			crate::RdfLiteralRef::Any(self.value.as_ref(), self.type_.as_ref()),
261		))))
262	}
263}
264
265impl<I: Interpretation, V: Vocabulary, T: LinkedDataResource<I, V>> LinkedDataResource<I, V>
266	for Option<T>
267{
268	fn interpretation(
269		&self,
270		vocabulary: &mut V,
271		interpretation: &mut I,
272	) -> ResourceInterpretation<I, V> {
273		match self {
274			Some(t) => t.interpretation(vocabulary, interpretation),
275			None => ResourceInterpretation::Uninterpreted(None),
276		}
277	}
278}