json_ld_serialization/expanded/
node.rs

1use iref::Iri;
2use json_ld_core::{object::node::Multiset, Indexed, Node, Object};
3use linked_data::{CowRdfTerm, LinkedDataResource};
4use rdf_types::{
5	interpretation::{
6		ReverseBlankIdInterpretation, ReverseIriInterpretation, ReverseLiteralInterpretation,
7	},
8	vocabulary::{IriVocabulary, IriVocabularyMut},
9	Interpretation, Term, Vocabulary, RDF_TYPE,
10};
11use std::hash::Hash;
12
13use crate::Error;
14
15use super::{
16	graph::SerializeGraph,
17	property::{SerializeProperty, SerializeReverseProperty},
18};
19
20/// Serialize the given Linked-Data value into a JSON-LD node object using a
21/// custom vocabulary and interpretation.
22pub fn serialize_node_with<I, V, T>(
23	vocabulary: &mut V,
24	interpretation: &mut I,
25	value: &T,
26) -> Result<Node<V::Iri, V::BlankId>, Error>
27where
28	V: Vocabulary + IriVocabularyMut,
29	V::Iri: Clone + Eq + Hash,
30	V::BlankId: Clone + Eq + Hash,
31	I: ReverseIriInterpretation<Iri = V::Iri>
32		+ ReverseBlankIdInterpretation<BlankId = V::BlankId>
33		+ ReverseLiteralInterpretation<Literal = V::Literal>,
34	T: ?Sized + LinkedDataResource<I, V> + linked_data::LinkedDataSubject<I, V>,
35{
36	let id = match value
37		.lexical_representation(vocabulary, interpretation)
38		.map(CowRdfTerm::into_owned)
39	{
40		Some(Term::Literal(_)) => return Err(Error::InvalidNode),
41		Some(Term::Id(id)) => Some(json_ld_core::Id::Valid(id)),
42		None => None,
43	};
44
45	let serializer = SerializeNode::new(vocabulary, interpretation, id);
46
47	value.visit_subject(serializer)
48}
49
50pub struct SerializeNode<'a, I, V: Vocabulary> {
51	vocabulary: &'a mut V,
52	interpretation: &'a mut I,
53	result: Node<V::Iri, V::BlankId>,
54}
55
56impl<'a, I, V: Vocabulary> SerializeNode<'a, I, V> {
57	pub fn new(
58		vocabulary: &'a mut V,
59		interpretation: &'a mut I,
60		id: Option<json_ld_core::Id<V::Iri, V::BlankId>>,
61	) -> Self {
62		let result = match id {
63			Some(id) => Node::with_id(id),
64			None => Node::new(),
65		};
66
67		Self {
68			vocabulary,
69			interpretation,
70			result,
71		}
72	}
73}
74
75impl<'a, I: Interpretation, V: Vocabulary> linked_data::SubjectVisitor<I, V>
76	for SerializeNode<'a, I, V>
77where
78	V: IriVocabularyMut,
79	V::Iri: Clone + Eq + Hash,
80	V::BlankId: Clone + Eq + Hash,
81	I: ReverseIriInterpretation<Iri = V::Iri>
82		+ ReverseBlankIdInterpretation<BlankId = V::BlankId>
83		+ ReverseLiteralInterpretation<Literal = V::Literal>,
84{
85	type Ok = Node<V::Iri, V::BlankId>;
86	type Error = Error;
87
88	fn predicate<L, T>(&mut self, predicate: &L, value: &T) -> Result<(), Self::Error>
89	where
90		L: ?Sized + LinkedDataResource<I, V>,
91		T: ?Sized + linked_data::LinkedDataPredicateObjects<I, V>,
92	{
93		let prop = match predicate
94			.lexical_representation(self.vocabulary, self.interpretation)
95			.map(CowRdfTerm::into_owned)
96		{
97			Some(Term::Id(id)) => json_ld_core::Id::Valid(id),
98			_ => return Err(Error::InvalidPredicate),
99		};
100
101		let serializer = SerializeProperty::new(self.vocabulary, self.interpretation);
102
103		let objects = value.visit_objects(serializer)?;
104
105		if is_iri(self.vocabulary, &prop, RDF_TYPE) {
106			let mut non_iri_objects = Multiset::new();
107
108			for obj in objects {
109				match into_type_value(obj) {
110					Ok(ty) => self.result.types_mut_or_default().push(ty),
111					Err(obj) => {
112						non_iri_objects.insert(obj);
113					}
114				}
115			}
116
117			if !non_iri_objects.is_empty() {
118				self.result.properties_mut().set(prop, non_iri_objects);
119			}
120		} else {
121			self.result.properties_mut().set(prop, objects);
122		}
123
124		Ok(())
125	}
126
127	fn reverse_predicate<L, T>(&mut self, predicate: &L, value: &T) -> Result<(), Self::Error>
128	where
129		L: ?Sized + LinkedDataResource<I, V>,
130		T: ?Sized + linked_data::LinkedDataPredicateObjects<I, V>,
131	{
132		let prop = match predicate
133			.lexical_representation(self.vocabulary, self.interpretation)
134			.map(CowRdfTerm::into_owned)
135		{
136			Some(Term::Id(id)) => json_ld_core::Id::Valid(id),
137			_ => return Err(Error::InvalidPredicate),
138		};
139
140		let serializer = SerializeReverseProperty::new(self.vocabulary, self.interpretation);
141
142		let objects = value.visit_objects(serializer)?;
143		self.result
144			.reverse_properties_mut_or_default()
145			.set(prop, objects);
146
147		Ok(())
148	}
149
150	fn include<T>(&mut self, value: &T) -> Result<(), Self::Error>
151	where
152		T: ?Sized + LinkedDataResource<I, V> + linked_data::LinkedDataSubject<I, V>,
153	{
154		let node = serialize_node_with(self.vocabulary, self.interpretation, value)?;
155
156		self.result
157			.included_mut_or_default()
158			.insert(Indexed::none(node));
159		Ok(())
160	}
161
162	fn graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
163	where
164		T: ?Sized + linked_data::LinkedDataGraph<I, V>,
165	{
166		let serializer = SerializeGraph::new(self.vocabulary, self.interpretation);
167
168		let graph = value.visit_graph(serializer)?;
169		self.result.graph = Some(graph);
170		Ok(())
171	}
172
173	fn end(self) -> Result<Self::Ok, Self::Error> {
174		Ok(self.result)
175	}
176}
177
178pub(crate) fn into_type_value<I, B>(
179	obj: Indexed<Object<I, B>>,
180) -> Result<json_ld_core::Id<I, B>, Indexed<Object<I, B>>> {
181	match obj.index() {
182		Some(_) => Err(obj),
183		None => match obj.into_inner() {
184			Object::Node(node) => {
185				if node.is_empty() && node.id.is_some() {
186					Ok(node.id.unwrap())
187				} else {
188					Err(Indexed::none(Object::Node(node)))
189				}
190			}
191			obj => Err(Indexed::none(obj)),
192		},
193	}
194}
195
196pub(crate) fn is_iri<V, B>(vocabulary: &V, id: &json_ld_core::Id<V::Iri, B>, iri: &Iri) -> bool
197where
198	V: IriVocabulary,
199{
200	match id {
201		json_ld_core::Id::Valid(rdf_types::Id::Iri(i)) => match vocabulary.iri(i) {
202			Some(i) => i == iri,
203			None => false,
204		},
205		_ => false,
206	}
207}