json_ld_serialization/expanded/
object.rs1use std::hash::Hash;
2
3use json_ld_core::{
4 object::{
5 node::{Included, Multiset, Properties, ReverseProperties},
6 Graph, List,
7 },
8 rdf::{RDF_FIRST, RDF_REST, RDF_TYPE},
9 Indexed, IndexedObject, Node, Object,
10};
11use linked_data::{CowRdfTerm, LinkedDataResource};
12use rdf_types::{
13 interpretation::{
14 ReverseBlankIdInterpretation, ReverseIriInterpretation, ReverseLiteralInterpretation,
15 },
16 vocabulary::IriVocabularyMut,
17 Id, Interpretation, Term, Vocabulary,
18};
19
20use crate::Error;
21
22use super::{
23 graph::SerializeGraph,
24 list::{SerializeListFirst, SerializeListRest},
25 node::{into_type_value, is_iri, SerializeNode},
26 property::{SerializeProperty, SerializeReverseProperty},
27 serialize_node_with,
28 value::literal_to_value,
29};
30
31pub fn serialize_object_with<I, V, T>(
34 vocabulary: &mut V,
35 interpretation: &mut I,
36 value: &T,
37) -> Result<Object<V::Iri, V::BlankId>, Error>
38where
39 V: Vocabulary + IriVocabularyMut,
40 V::Iri: Clone + Eq + Hash,
41 V::BlankId: Clone + Eq + Hash,
42 I: ReverseIriInterpretation<Iri = V::Iri>
43 + ReverseBlankIdInterpretation<BlankId = V::BlankId>
44 + ReverseLiteralInterpretation<Literal = V::Literal>,
45 T: ?Sized + LinkedDataResource<I, V> + linked_data::LinkedDataSubject<I, V>,
46{
47 match value
48 .lexical_representation(vocabulary, interpretation)
49 .map(CowRdfTerm::into_owned)
50 {
51 Some(Term::Literal(lit)) => {
52 let value = literal_to_value(vocabulary, lit);
53 Ok(Object::Value(value))
54 }
55 Some(Term::Id(id)) => {
56 let serializer = SerializeNode::new(
57 vocabulary,
58 interpretation,
59 Some(json_ld_core::Id::Valid(id)),
60 );
61
62 Ok(Object::node(value.visit_subject(serializer)?))
63 }
64 None => {
65 let serializer = SerializeObject::new(vocabulary, interpretation);
66
67 value.visit_subject(serializer)
68 }
69 }
70}
71
72pub struct SerializeObject<'a, I, V: Vocabulary> {
73 vocabulary: &'a mut V,
74 interpretation: &'a mut I,
75 types: Vec<json_ld_core::Id<V::Iri, V::BlankId>>,
76 properties: Properties<V::Iri, V::BlankId>,
77 reverse_properties: ReverseProperties<V::Iri, V::BlankId>,
78 included: Included<V::Iri, V::BlankId>,
79 graph: Option<Graph<V::Iri, V::BlankId>>,
80 first: Option<Object<V::Iri, V::BlankId>>,
81 rest: Option<Vec<IndexedObject<V::Iri, V::BlankId>>>,
82}
83
84impl<'a, I, V: Vocabulary> SerializeObject<'a, I, V> {
85 pub fn new(vocabulary: &'a mut V, interpretation: &'a mut I) -> Self {
86 Self {
87 vocabulary,
88 interpretation,
89 types: Vec::new(),
90 properties: Properties::new(),
91 reverse_properties: ReverseProperties::new(),
92 included: Included::new(),
93 graph: None,
94 first: None,
95 rest: None,
96 }
97 }
98}
99
100impl<'a, I: Interpretation, V: Vocabulary> linked_data::SubjectVisitor<I, V>
101 for SerializeObject<'a, I, V>
102where
103 V: IriVocabularyMut,
104 V::Iri: Clone + Eq + Hash,
105 V::BlankId: Clone + Eq + Hash,
106 I: ReverseIriInterpretation<Iri = V::Iri>
107 + ReverseBlankIdInterpretation<BlankId = V::BlankId>
108 + ReverseLiteralInterpretation<Literal = V::Literal>,
109{
110 type Ok = Object<V::Iri, V::BlankId>;
111 type Error = Error;
112
113 fn predicate<L, T>(&mut self, predicate: &L, value: &T) -> Result<(), Self::Error>
114 where
115 L: ?Sized + LinkedDataResource<I, V>,
116 T: ?Sized + linked_data::LinkedDataPredicateObjects<I, V>,
117 {
118 let prop = match predicate
119 .lexical_representation(self.vocabulary, self.interpretation)
120 .map(CowRdfTerm::into_owned)
121 {
122 Some(Term::Id(id)) => {
123 if let Id::Iri(iri) = &id {
124 let iri = self.vocabulary.iri(iri).unwrap();
125 if iri == RDF_FIRST {
126 let serializer =
127 SerializeListFirst::new(self.vocabulary, self.interpretation);
128 self.first = value.visit_objects(serializer)?;
129 } else if iri == RDF_REST {
130 let serializer =
131 SerializeListRest::new(self.vocabulary, self.interpretation);
132 self.rest = Some(value.visit_objects(serializer)?);
133 }
134 }
135
136 json_ld_core::Id::Valid(id)
137 }
138 _ => return Err(Error::InvalidPredicate),
139 };
140
141 let serializer = SerializeProperty::new(self.vocabulary, self.interpretation);
142
143 let objects = value.visit_objects(serializer)?;
144
145 if is_iri(self.vocabulary, &prop, RDF_TYPE) {
146 let mut non_iri_objects = Multiset::new();
147
148 for obj in objects {
149 match into_type_value(obj) {
150 Ok(ty) => self.types.push(ty),
151 Err(obj) => {
152 non_iri_objects.insert(obj);
153 }
154 }
155 }
156
157 if !non_iri_objects.is_empty() {
158 self.properties.set(prop, non_iri_objects);
159 }
160 } else {
161 self.properties.set(prop, objects);
162 }
163
164 Ok(())
165 }
166
167 fn reverse_predicate<L, T>(&mut self, predicate: &L, value: &T) -> Result<(), Self::Error>
168 where
169 L: ?Sized + LinkedDataResource<I, V>,
170 T: ?Sized + linked_data::LinkedDataPredicateObjects<I, V>,
171 {
172 let prop = match predicate
173 .lexical_representation(self.vocabulary, self.interpretation)
174 .map(CowRdfTerm::into_owned)
175 {
176 Some(Term::Id(id)) => json_ld_core::Id::Valid(id),
177 _ => return Err(Error::InvalidPredicate),
178 };
179
180 let serializer = SerializeReverseProperty::new(self.vocabulary, self.interpretation);
181
182 let objects = value.visit_objects(serializer)?;
183 self.reverse_properties.set(prop, objects);
184
185 Ok(())
186 }
187
188 fn include<T>(&mut self, value: &T) -> Result<(), Self::Error>
189 where
190 T: ?Sized + LinkedDataResource<I, V> + linked_data::LinkedDataSubject<I, V>,
191 {
192 let node = serialize_node_with(self.vocabulary, self.interpretation, value)?;
193 self.included.insert(Indexed::none(node));
194 Ok(())
195 }
196
197 fn graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
198 where
199 T: ?Sized + linked_data::LinkedDataGraph<I, V>,
200 {
201 let serializer = SerializeGraph::new(self.vocabulary, self.interpretation);
202 self.graph = Some(value.visit_graph(serializer)?);
203 Ok(())
204 }
205
206 fn end(mut self) -> Result<Self::Ok, Self::Error> {
207 if self.first.is_some()
208 && self.rest.is_some()
209 && self.types.is_empty()
210 && self.properties.is_empty()
211 && self.graph.is_none()
212 {
213 let mut items = self.rest.unwrap();
214 items.push(Indexed::none(self.first.unwrap()));
215 items.reverse();
216 Ok(Object::List(List::new(items)))
217 } else {
218 if let Some(item) = self.first {
219 let iri = self.vocabulary.insert(RDF_FIRST);
220 self.properties
221 .insert(json_ld_core::Id::Valid(Id::Iri(iri)), Indexed::none(item))
222 }
223
224 if let Some(rest) = self.rest {
225 let iri = self.vocabulary.insert(RDF_REST);
226 self.properties.insert(
227 json_ld_core::Id::Valid(Id::Iri(iri)),
228 Indexed::none(Object::List(List::new(rest))),
229 )
230 }
231
232 let mut node = Node::new();
233
234 if !self.types.is_empty() {
235 node.types = Some(self.types)
236 }
237
238 *node.properties_mut() = self.properties;
239
240 if !self.reverse_properties.is_empty() {
241 node.set_reverse_properties(Some(self.reverse_properties));
242 }
243
244 if !self.included.is_empty() {
245 node.set_included(Some(self.included));
246 }
247
248 node.graph = self.graph;
249
250 Ok(Object::node(node))
251 }
252 }
253}