Skip to main content

jsonld_serialization/expanded/
node.rs

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