oxrdf/
graph.rs

1//! [In-memory implementation](Graph) of [RDF graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph).
2//!
3//! Usage example:
4//! ```
5//! use oxrdf::*;
6//!
7//! let mut graph = Graph::default();
8//!
9//! // insertion
10//! let ex = NamedNodeRef::new("http://example.com")?;
11//! let triple = TripleRef::new(ex, ex, ex);
12//! graph.insert(triple);
13//!
14//! // simple filter
15//! let results: Vec<_> = graph.triples_for_subject(ex).collect();
16//! assert_eq!(vec![triple], results);
17//!
18//! // Print
19//! assert_eq!(
20//!     graph.to_string(),
21//!     "<http://example.com> <http://example.com> <http://example.com> .\n"
22//! );
23//! # Result::<_, Box<dyn std::error::Error>>::Ok(())
24//! ```
25//!
26//! See also [`Dataset`] if you want to get support of multiple RDF graphs at the same time.
27
28pub use crate::dataset::CanonicalizationAlgorithm;
29use crate::dataset::*;
30use crate::*;
31use std::fmt;
32
33/// An in-memory [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph).
34///
35/// It can accommodate a fairly large number of triples (in the few millions).
36///
37/// <div class="warning">It interns the string and does not do any garbage collection yet:
38/// if you insert and remove a lot of different terms, memory will grow without any reduction.</div>
39///
40/// Usage example:
41/// ```
42/// use oxrdf::*;
43///
44/// let mut graph = Graph::default();
45///
46/// // insertion
47/// let ex = NamedNodeRef::new("http://example.com")?;
48/// let triple = TripleRef::new(ex, ex, ex);
49/// graph.insert(triple);
50///
51/// // simple filter
52/// let results: Vec<_> = graph.triples_for_subject(ex).collect();
53/// assert_eq!(vec![triple], results);
54/// # Result::<_, Box<dyn std::error::Error>>::Ok(())
55/// ```
56#[derive(Debug, Default, Clone)]
57pub struct Graph {
58    dataset: Dataset,
59}
60
61impl Graph {
62    /// Creates a new graph.
63    pub fn new() -> Self {
64        Self::default()
65    }
66
67    fn graph(&self) -> GraphView<'_> {
68        self.dataset.graph(GraphNameRef::DefaultGraph)
69    }
70
71    fn graph_mut(&mut self) -> GraphViewMut<'_> {
72        self.dataset.graph_mut(GraphNameRef::DefaultGraph)
73    }
74
75    /// Returns all the triples contained by the graph.
76    pub fn iter(&self) -> Iter<'_> {
77        Iter {
78            inner: self.graph().iter(),
79        }
80    }
81
82    pub fn triples_for_subject<'a, 'b>(
83        &'a self,
84        subject: impl Into<SubjectRef<'b>>,
85    ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
86        self.graph()
87            .triples_for_interned_subject(self.dataset.encoded_subject(subject))
88    }
89
90    pub fn objects_for_subject_predicate<'a, 'b>(
91        &'a self,
92        subject: impl Into<SubjectRef<'b>>,
93        predicate: impl Into<NamedNodeRef<'b>>,
94    ) -> impl Iterator<Item = TermRef<'a>> + 'a {
95        self.graph().objects_for_interned_subject_predicate(
96            self.dataset.encoded_subject(subject),
97            self.dataset.encoded_named_node(predicate),
98        )
99    }
100
101    pub fn object_for_subject_predicate<'a, 'b>(
102        &'a self,
103        subject: impl Into<SubjectRef<'b>>,
104        predicate: impl Into<NamedNodeRef<'b>>,
105    ) -> Option<TermRef<'a>> {
106        self.graph()
107            .objects_for_subject_predicate(subject, predicate)
108            .next()
109    }
110
111    pub fn predicates_for_subject_object<'a, 'b>(
112        &'a self,
113        subject: impl Into<SubjectRef<'b>>,
114        object: impl Into<TermRef<'b>>,
115    ) -> impl Iterator<Item = NamedNodeRef<'a>> + 'a {
116        self.graph().predicates_for_interned_subject_object(
117            self.dataset.encoded_subject(subject),
118            self.dataset.encoded_term(object),
119        )
120    }
121
122    pub fn triples_for_predicate<'a, 'b>(
123        &'a self,
124        predicate: impl Into<NamedNodeRef<'b>>,
125    ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
126        self.graph()
127            .triples_for_interned_predicate(self.dataset.encoded_named_node(predicate))
128    }
129
130    pub fn subjects_for_predicate_object<'a, 'b>(
131        &'a self,
132        predicate: impl Into<NamedNodeRef<'b>>,
133        object: impl Into<TermRef<'b>>,
134    ) -> impl Iterator<Item = SubjectRef<'a>> + 'a {
135        self.graph().subjects_for_interned_predicate_object(
136            self.dataset.encoded_named_node(predicate),
137            self.dataset.encoded_term(object),
138        )
139    }
140
141    pub fn subject_for_predicate_object<'a, 'b>(
142        &'a self,
143        predicate: impl Into<NamedNodeRef<'b>>,
144        object: impl Into<TermRef<'b>>,
145    ) -> Option<SubjectRef<'a>> {
146        self.graph().subject_for_predicate_object(predicate, object)
147    }
148
149    pub fn triples_for_object<'a, 'b>(
150        &'a self,
151        object: impl Into<TermRef<'b>>,
152    ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
153        self.graph()
154            .triples_for_interned_object(self.dataset.encoded_term(object))
155    }
156
157    /// Checks if the graph contains the given triple.
158    pub fn contains<'a>(&self, triple: impl Into<TripleRef<'a>>) -> bool {
159        self.graph().contains(triple)
160    }
161
162    /// Returns the number of triples in this graph.
163    pub fn len(&self) -> usize {
164        self.dataset.len()
165    }
166
167    /// Checks if this graph contains a triple.
168    pub fn is_empty(&self) -> bool {
169        self.dataset.is_empty()
170    }
171
172    /// Adds a triple to the graph.
173    pub fn insert<'a>(&mut self, triple: impl Into<TripleRef<'a>>) -> bool {
174        self.graph_mut().insert(triple)
175    }
176
177    /// Removes a concrete triple from the graph.
178    pub fn remove<'a>(&mut self, triple: impl Into<TripleRef<'a>>) -> bool {
179        self.graph_mut().remove(triple)
180    }
181
182    /// Clears the graph.
183    pub fn clear(&mut self) {
184        self.dataset.clear()
185    }
186
187    /// Canonicalizes the dataset by renaming blank nodes.
188    ///
189    /// Usage example ([Graph isomorphism](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-isomorphism)):
190    /// ```
191    /// use oxrdf::graph::CanonicalizationAlgorithm;
192    /// use oxrdf::*;
193    ///
194    /// let iri = NamedNodeRef::new("http://example.com")?;
195    ///
196    /// let mut graph1 = Graph::new();
197    /// let bnode1 = BlankNode::default();
198    /// graph1.insert(TripleRef::new(iri, iri, &bnode1));
199    /// graph1.insert(TripleRef::new(&bnode1, iri, iri));
200    ///
201    /// let mut graph2 = Graph::new();
202    /// let bnode2 = BlankNode::default();
203    /// graph2.insert(TripleRef::new(iri, iri, &bnode2));
204    /// graph2.insert(TripleRef::new(&bnode2, iri, iri));
205    ///
206    /// assert_ne!(graph1, graph2);
207    /// graph1.canonicalize(CanonicalizationAlgorithm::Unstable);
208    /// graph2.canonicalize(CanonicalizationAlgorithm::Unstable);
209    /// assert_eq!(graph1, graph2);
210    /// # Result::<_, Box<dyn std::error::Error>>::Ok(())
211    /// ```
212    ///
213    /// <div class="warning">Blank node ids depends on the current shape of the graph. Adding a new quad might change the ids of a lot of blank nodes.
214    /// Hence, this canonization might not be suitable for diffs.</div>
215    ///
216    /// <div class="warning">This implementation worst-case complexity is in *O(b!)* with *b* the number of blank nodes in the input dataset.</div>
217    pub fn canonicalize(&mut self, algorithm: CanonicalizationAlgorithm) {
218        self.dataset.canonicalize(algorithm)
219    }
220}
221
222impl PartialEq for Graph {
223    fn eq(&self, other: &Self) -> bool {
224        self.dataset == other.dataset
225    }
226}
227
228impl Eq for Graph {}
229
230impl<'a> IntoIterator for &'a Graph {
231    type Item = TripleRef<'a>;
232    type IntoIter = Iter<'a>;
233
234    fn into_iter(self) -> Self::IntoIter {
235        self.iter()
236    }
237}
238
239impl FromIterator<Triple> for Graph {
240    fn from_iter<I: IntoIterator<Item = Triple>>(iter: I) -> Self {
241        let mut g = Self::new();
242        g.extend(iter);
243        g
244    }
245}
246
247impl<'a, T: Into<TripleRef<'a>>> FromIterator<T> for Graph {
248    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
249        let mut g = Self::new();
250        g.extend(iter);
251        g
252    }
253}
254
255impl Extend<Triple> for Graph {
256    fn extend<I: IntoIterator<Item = Triple>>(&mut self, iter: I) {
257        self.graph_mut().extend(iter)
258    }
259}
260
261impl<'a, T: Into<TripleRef<'a>>> Extend<T> for Graph {
262    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
263        self.graph_mut().extend(iter)
264    }
265}
266
267impl fmt::Display for Graph {
268    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269        self.graph().fmt(f)
270    }
271}
272
273/// Iterator returned by [`Graph::iter`].
274pub struct Iter<'a> {
275    inner: GraphViewIter<'a>,
276}
277
278impl<'a> Iterator for Iter<'a> {
279    type Item = TripleRef<'a>;
280
281    fn next(&mut self) -> Option<Self::Item> {
282        self.inner.next()
283    }
284}