1use super::*;
3use crate::dataset::{DTerm, Dataset, MutableDataset, SetDataset};
4use crate::quad::Quad;
5use crate::term::{
6 matcher::{Any, GraphNameMatcher},
7 GraphName,
8};
9
10#[repr(transparent)]
14#[derive(Clone, Copy, Debug)]
15pub struct UnionGraph<T: Dataset>(T);
16
17impl<T: Dataset> UnionGraph<T> {
18 pub fn new(wrapped: T) -> Self {
20 UnionGraph(wrapped)
21 }
22
23 pub fn unwrap(self) -> T {
25 self.0
26 }
27}
28
29impl<T: Dataset> Graph for UnionGraph<T> {
30 type Triple<'x> = [DTerm<'x, T>; 3] where Self: 'x;
31 type Error = T::Error;
32
33 fn triples(&self) -> GTripleSource<Self> {
34 Box::new(
35 self.0
36 .quads()
37 .map(|r| r.map(Quad::into_triple)),
39 )
40 }
41
42 fn triples_matching<'s, S, P, O>(&'s self, sm: S, pm: P, om: O) -> GTripleSource<'s, Self>
43 where
44 S: TermMatcher + 's,
45 P: TermMatcher + 's,
46 O: TermMatcher + 's,
47 {
48 Box::new(
49 self.0
50 .quads_matching(sm, pm, om, Any)
51 .map(|r| r.map(Quad::into_triple)),
53 )
54 }
55
56 fn subjects(&self) -> GTermSource<Self> {
57 self.0.subjects()
58 }
59
60 fn predicates(&self) -> GTermSource<Self> {
61 self.0.predicates()
62 }
63
64 fn objects(&self) -> GTermSource<Self> {
65 self.0.objects()
66 }
67
68 fn iris(&self) -> GTermSource<Self> {
69 self.0.iris()
70 }
71
72 fn blank_nodes(&self) -> GTermSource<Self> {
73 self.0.blank_nodes()
74 }
75
76 fn literals(&self) -> GTermSource<Self> {
77 self.0.literals()
78 }
79
80 fn quoted_triples<'s>(&'s self) -> GTermSource<'s, Self>
81 where
82 GTerm<'s, Self>: Clone,
83 {
84 self.0.quoted_triples()
85 }
86
87 fn variables(&self) -> GTermSource<Self> {
88 self.0.variables()
89 }
90}
91
92#[derive(Clone, Copy, Debug)]
98pub struct PartialUnionGraph<D: Dataset, M: GraphNameMatcher> {
99 d: D,
100 m: M,
101}
102
103impl<D: Dataset, M: GraphNameMatcher + Copy> PartialUnionGraph<D, M> {
104 pub fn new(d: D, m: M) -> Self {
107 PartialUnionGraph { d, m }
108 }
109
110 pub fn unwrap(self) -> (D, M) {
112 (self.d, self.m)
113 }
114}
115
116impl<D: Dataset, M: GraphNameMatcher + Copy> Graph for PartialUnionGraph<D, M> {
117 type Triple<'x> = [DTerm<'x, D>; 3] where Self: 'x;
118 type Error = D::Error;
119
120 fn triples(&self) -> GTripleSource<Self> {
121 Box::new(
122 self.d
123 .quads_matching(Any, Any, Any, self.m)
124 .map(|r| r.map(Quad::into_triple)),
126 )
127 }
128
129 fn triples_matching<'s, S, P, O>(&'s self, sm: S, pm: P, om: O) -> GTripleSource<'s, Self>
130 where
131 S: TermMatcher + 's,
132 P: TermMatcher + 's,
133 O: TermMatcher + 's,
134 {
135 Box::new(
136 self.d
137 .quads_matching(sm, pm, om, self.m)
138 .map(|r| r.map(Quad::into_triple)),
140 )
141 }
142}
143
144#[derive(Clone, Copy, Debug)]
154pub struct DatasetGraph<D: Dataset, G: Term> {
155 d: D,
156 g: GraphName<G>,
157}
158
159impl<D: Dataset, G: Term> DatasetGraph<D, G> {
160 pub fn new(d: D, g: GraphName<G>) -> Self {
163 DatasetGraph { d, g }
164 }
165
166 pub fn unwrap(self) -> (D, GraphName<G>) {
168 (self.d, self.g)
169 }
170
171 fn g(&self) -> GraphName<G::BorrowTerm<'_>> {
172 self.g.as_ref().map(|gn| gn.borrow_term())
173 }
174
175 fn gd(&mut self) -> (Option<G::BorrowTerm<'_>>, &mut D) {
176 (self.g.as_ref().map(|gn| gn.borrow_term()), &mut self.d)
177 }
178}
179
180impl<D: Dataset, G: Term> Graph for DatasetGraph<D, G> {
181 type Triple<'x> = [DTerm<'x, D>; 3] where Self: 'x;
182 type Error = D::Error;
183
184 fn triples(&self) -> GTripleSource<Self> {
185 Box::new(
186 self.d
187 .quads_matching(Any, Any, Any, [self.g()])
188 .map(|r| r.map(Quad::into_triple)),
190 )
191 }
192
193 fn triples_matching<'s, S, P, O>(&'s self, sm: S, pm: P, om: O) -> GTripleSource<'s, Self>
194 where
195 S: TermMatcher + 's,
196 P: TermMatcher + 's,
197 O: TermMatcher + 's,
198 {
199 Box::new(
200 self.d
201 .quads_matching(sm, pm, om, [self.g()])
202 .map(|r| r.map(Quad::into_triple)),
204 )
205 }
206}
207
208impl<D: SetDataset, G: Term> SetGraph for DatasetGraph<D, G> {}
209
210impl<D: MutableDataset, G: Term> MutableGraph for DatasetGraph<D, G> {
211 type MutationError = D::MutationError;
212
213 fn insert<TS, TP, TO>(&mut self, s: TS, p: TP, o: TO) -> MgResult<Self, bool>
214 where
215 TS: Term,
216 TP: Term,
217 TO: Term,
218 {
219 let (g, d) = self.gd();
220 d.insert(s, p, o, g)
221 }
222
223 fn remove<TS, TP, TO>(&mut self, s: TS, p: TP, o: TO) -> MgResult<Self, bool>
224 where
225 TS: Term,
226 TP: Term,
227 TO: Term,
228 {
229 let (g, d) = self.gd();
230 d.remove(s, p, o, g)
231 }
232}
233
234#[cfg(test)]
235mod test {
236 use super::*;
237 use crate::quad::Spog;
238 use crate::term::{graph_name_eq, FromTerm};
239 use sophia_iri::Iri;
240 use std::collections::BTreeSet;
241
242 static G1: Iri<&'static str> = Iri::new_unchecked_const("http://example.com/g1");
243 static G2: Iri<&'static str> = Iri::new_unchecked_const("http://example.com/g2");
244 static G3: Iri<&'static str> = Iri::new_unchecked_const("http://example.com/g3");
245
246 type MyTerm = SimpleTerm<'static>;
247 type MyQuad = Spog<MyTerm>;
248 type MyDS = BTreeSet<MyQuad>;
249
250 #[derive(Clone, Copy, Debug)]
251 struct GM;
252 impl GraphNameMatcher for GM {
253 type Term = MyTerm;
254
255 fn matches<T2: Term + ?Sized>(&self, graph_name: GraphName<&T2>) -> bool {
256 graph_name_eq(graph_name.map(|gn| gn.borrow_term()), Some(G1))
257 || graph_name_eq(graph_name.map(|gn| gn.borrow_term()), Some(G2))
258 }
259 }
260
261 type MyUG = UnionGraph<MyDS>;
262 fn collect_union_graph<T: TripleSource>(mut ts: T) -> Result<MyUG, T::Error> {
263 let mut ds = MyDS::new();
264 ts.for_each_triple(|t| {
265 let [s, p, o] = t.spo();
266 ds.insert_quad(([s, p, o], Some(s))).unwrap();
267 })?;
268 Ok(ds.into_union_graph())
269 }
270 crate::test_immutable_graph_impl!(union_graph, MyUG, true, true, collect_union_graph);
271
272 type MyPUG = PartialUnionGraph<MyDS, GM>;
273 fn collect_partial_union_graph<T: TripleSource>(mut ts: T) -> Result<MyPUG, T::Error> {
274 let g1: GraphName<MyTerm> = Some(G1.into_term());
275 let g2: GraphName<MyTerm> = Some(G2.into_term());
276 let g3: GraphName<MyTerm> = Some(G3.into_term());
277 let mut ds = MyDS::new();
278 let mut b = true;
279 ts.for_each_triple(|t| {
280 let [s, p, o] = t.spo();
281 if b {
282 ds.insert_quad(([s, p, o].map(MyTerm::from_term), g1.clone()))
283 .unwrap();
284 ds.insert_quad(([o, p, s].map(MyTerm::from_term), g3.clone()))
285 .unwrap();
286 } else {
287 ds.insert_quad(([s, p, o].map(MyTerm::from_term), g2.clone()))
288 .unwrap();
289 }
290 b = !b;
291 })?;
292 Ok(PartialUnionGraph::new(ds, GM))
293 }
294 crate::test_immutable_graph_impl!(
295 partial_union_graph,
296 MyPUG,
297 true,
298 true,
299 collect_partial_union_graph
300 );
301
302 type MyDG = DatasetGraph<MyDS, MyTerm>;
303 fn collect_dataset_graph<T: TripleSource>(mut ts: T) -> Result<MyDG, T::Error> {
304 let g1: GraphName<MyTerm> = Some(G1.into_term());
305 let g2: GraphName<MyTerm> = Some(G2.into_term());
306 let mut ds = MyDS::new();
307 ts.for_each_triple(|t| {
308 let [s, p, o] = t.spo();
309 ds.insert_quad(([s, p, o].map(MyTerm::from_term), g1.clone()))
310 .unwrap();
311 ds.insert_quad(([o, p, s].map(MyTerm::from_term), g2.clone()))
312 .unwrap();
313 })?;
314 Ok(DatasetGraph::new(ds, g1))
315 }
316 crate::test_graph_impl!(dataset_graph, MyDG, true, true, collect_dataset_graph);
317
318 #[allow(dead_code)] fn check_trait_impls() {
320 let mut ds = MyDS::new();
321 let g1: Option<MyTerm> = Some(G1.into_term());
322
323 for _ in ds.graph(g1.clone()).triples() {}
325
326 let mut gm = ds.graph_mut(g1);
327 for _ in gm.triples() {}
329 gm.remove_triple([1, 2, 3]).unwrap();
331
332 for _ in ds.partial_union_graph(GM).triples() {}
334
335 for _ in ds.union_graph().triples() {}
337
338 for _ in ds.into_union_graph().triples() {}
340 }
341}