1use crate::model::{Graph, GraphName, NamedNode, Quad, Triple};
21use crate::{OxirsError, Result};
22use std::collections::HashMap;
23
24pub use crate::model::GraphName as GraphNameKey;
28
29#[derive(Debug, Clone)]
59pub struct NamedGraphManager {
60 default_graph: Graph,
61 named_graphs: HashMap<GraphName, Graph>,
62}
63
64impl NamedGraphManager {
65 pub fn new() -> Self {
67 NamedGraphManager {
68 default_graph: Graph::new(),
69 named_graphs: HashMap::new(),
70 }
71 }
72
73 pub fn with_capacity(named_graph_capacity: usize) -> Self {
75 NamedGraphManager {
76 default_graph: Graph::new(),
77 named_graphs: HashMap::with_capacity(named_graph_capacity),
78 }
79 }
80
81 pub fn default_graph(&self) -> &Graph {
85 &self.default_graph
86 }
87
88 pub fn default_graph_mut(&mut self) -> &mut Graph {
90 &mut self.default_graph
91 }
92
93 pub fn add_named_graph(&mut self, name: GraphName) -> bool {
100 if name.is_default_graph() {
101 return false;
102 }
103 if self.named_graphs.contains_key(&name) {
104 return false;
105 }
106 self.named_graphs.insert(name, Graph::new());
107 true
108 }
109
110 pub fn remove_named_graph(&mut self, name: &GraphName) -> Option<Graph> {
116 if name.is_default_graph() {
117 let mut old = Graph::new();
118 std::mem::swap(&mut old, &mut self.default_graph);
119 Some(old)
120 } else {
121 self.named_graphs.remove(name)
122 }
123 }
124
125 pub fn get_named_graph(&self, name: &GraphName) -> Option<&Graph> {
130 if name.is_default_graph() {
131 Some(&self.default_graph)
132 } else {
133 self.named_graphs.get(name)
134 }
135 }
136
137 pub fn get_or_create_named_graph_mut(&mut self, name: &GraphName) -> &mut Graph {
140 if name.is_default_graph() {
141 &mut self.default_graph
142 } else {
143 self.named_graphs.entry(name.clone()).or_default()
144 }
145 }
146
147 pub fn get_named_graph_mut(&mut self, name: &GraphName) -> Option<&mut Graph> {
152 if name.is_default_graph() {
153 Some(&mut self.default_graph)
154 } else {
155 self.named_graphs.get_mut(name)
156 }
157 }
158
159 pub fn contains_named_graph(&self, name: &GraphName) -> bool {
161 if name.is_default_graph() {
162 true } else {
164 self.named_graphs.contains_key(name)
165 }
166 }
167
168 pub fn list_named_graphs(&self) -> impl Iterator<Item = &GraphName> {
170 self.named_graphs.keys()
171 }
172
173 pub fn graph_count(&self) -> usize {
175 self.named_graphs.len()
176 }
177
178 pub fn total_graph_count(&self) -> usize {
180 self.named_graphs.len() + 1
181 }
182
183 pub fn insert_triple(&mut self, graph: &GraphName, triple: Triple) -> Result<bool> {
190 let target = self.get_or_create_named_graph_mut(graph);
191 Ok(target.insert(triple))
192 }
193
194 pub fn remove_triple(&mut self, graph: &GraphName, triple: &Triple) -> Result<bool> {
199 let target = self
200 .get_named_graph_mut(graph)
201 .ok_or_else(|| OxirsError::Store(format!("Graph does not exist: {graph}")))?;
202 Ok(target.remove(triple))
203 }
204
205 pub fn contains_triple(&self, graph: &GraphName, triple: &Triple) -> bool {
207 self.get_named_graph(graph)
208 .is_some_and(|g| g.contains(triple))
209 }
210
211 pub fn triples_in_graph(&self, graph: &GraphName) -> Vec<Triple> {
215 match self.get_named_graph(graph) {
216 Some(g) => g.iter().cloned().collect(),
217 None => vec![],
218 }
219 }
220
221 pub fn triple_count_in(&self, graph: &GraphName) -> usize {
223 self.get_named_graph(graph).map_or(0, Graph::len)
224 }
225
226 pub fn triple_count(&self) -> usize {
228 let named_count: usize = self.named_graphs.values().map(Graph::len).sum();
229 named_count + self.default_graph.len()
230 }
231
232 pub fn clear_graph(&mut self, graph: &GraphName) -> Result<usize> {
236 let target = self
237 .get_named_graph_mut(graph)
238 .ok_or_else(|| OxirsError::Store(format!("Graph does not exist: {graph}")))?;
239 let count = target.len();
240 target.clear();
241 Ok(count)
242 }
243
244 pub fn drop_graph(&mut self, graph: &GraphName) -> bool {
249 if graph.is_default_graph() {
250 let was_empty = self.default_graph.is_empty();
251 self.default_graph.clear();
252 !was_empty
253 } else {
254 self.named_graphs.remove(graph).is_some()
255 }
256 }
257
258 pub fn union_graph(&self) -> Graph {
265 let mut union = self.default_graph.clone();
266 for graph in self.named_graphs.values() {
267 for triple in graph.iter() {
268 union.insert(triple.clone());
269 }
270 }
271 union
272 }
273
274 pub fn union_of_named_graphs(&self) -> Graph {
278 let mut union = Graph::new();
279 for graph in self.named_graphs.values() {
280 for triple in graph.iter() {
281 union.insert(triple.clone());
282 }
283 }
284 union
285 }
286
287 pub fn insert_quad(&mut self, quad: Quad) -> Result<bool> {
291 let triple = quad.to_triple();
292 let graph_name = quad.graph_name().clone();
293 self.insert_triple(&graph_name, triple)
294 }
295
296 pub fn iter_quads(&self) -> impl Iterator<Item = Quad> + '_ {
298 let default_quads = self
299 .default_graph
300 .iter()
301 .map(|t| Quad::from_triple(t.clone()));
302 let named_quads = self.named_graphs.iter().flat_map(|(name, graph)| {
303 let name = name.clone();
304 graph
305 .iter()
306 .map(move |t| Quad::from_triple_in_graph(t.clone(), name.clone()))
307 });
308 default_quads.chain(named_quads)
309 }
310
311 pub fn statistics(&self) -> GraphStatistics {
315 let named_triple_counts: HashMap<GraphName, usize> = self
316 .named_graphs
317 .iter()
318 .map(|(name, g)| (name.clone(), g.len()))
319 .collect();
320
321 let largest_graph = self
322 .named_graphs
323 .iter()
324 .max_by_key(|(_, g)| g.len())
325 .map(|(n, _)| n.clone());
326
327 GraphStatistics {
328 named_graph_count: self.named_graphs.len(),
329 default_graph_triple_count: self.default_graph.len(),
330 named_triple_counts,
331 total_triple_count: self.triple_count(),
332 largest_named_graph: largest_graph,
333 }
334 }
335
336 pub fn bulk_insert<I>(&mut self, graph: &GraphName, triples: I) -> usize
342 where
343 I: IntoIterator<Item = Triple>,
344 {
345 let target = self.get_or_create_named_graph_mut(graph);
346 let before = target.len();
347 target.extend(triples);
348 target.len() - before
349 }
350
351 pub fn copy_graph(&mut self, source: &GraphName, destination: &GraphName) -> Result<usize> {
356 let source_triples: Vec<Triple> = match self.get_named_graph(source) {
358 Some(g) => g.iter().cloned().collect(),
359 None => {
360 return Err(OxirsError::Store(format!(
361 "Source graph does not exist: {source}"
362 )))
363 }
364 };
365 Ok(self.bulk_insert(destination, source_triples))
366 }
367
368 pub fn move_graph(&mut self, source: &GraphName, destination: &GraphName) -> Result<usize> {
373 let source_triples: Vec<Triple> = {
375 let src = self.get_named_graph_mut(source).ok_or_else(|| {
376 OxirsError::Store(format!("Source graph does not exist: {source}"))
377 })?;
378 let triples: Vec<_> = src.iter().cloned().collect();
379 src.clear();
380 triples
381 };
382 Ok(self.bulk_insert(destination, source_triples))
383 }
384}
385
386impl Default for NamedGraphManager {
387 fn default() -> Self {
388 Self::new()
389 }
390}
391
392#[derive(Debug, Clone)]
396pub struct GraphStatistics {
397 pub named_graph_count: usize,
399 pub default_graph_triple_count: usize,
401 pub named_triple_counts: HashMap<GraphName, usize>,
403 pub total_triple_count: usize,
405 pub largest_named_graph: Option<GraphName>,
407}
408
409impl GraphStatistics {
410 pub fn average_named_graph_size(&self) -> f64 {
412 if self.named_graph_count == 0 {
413 return 0.0;
414 }
415 let total: usize = self.named_triple_counts.values().sum();
416 total as f64 / self.named_graph_count as f64
417 }
418
419 pub fn is_empty(&self) -> bool {
421 self.total_triple_count == 0
422 }
423}
424
425pub struct NamedGraphIterator {
429 inner: std::vec::IntoIter<(GraphName, Graph)>,
430}
431
432impl NamedGraphIterator {
433 pub fn from_manager(manager: NamedGraphManager) -> Self {
435 let pairs: Vec<(GraphName, Graph)> = manager.named_graphs.into_iter().collect();
436 NamedGraphIterator {
437 inner: pairs.into_iter(),
438 }
439 }
440}
441
442impl Iterator for NamedGraphIterator {
443 type Item = (GraphName, Graph);
444
445 fn next(&mut self) -> Option<Self::Item> {
446 self.inner.next()
447 }
448
449 fn size_hint(&self) -> (usize, Option<usize>) {
450 self.inner.size_hint()
451 }
452}
453
454impl ExactSizeIterator for NamedGraphIterator {}
455
456pub trait GraphStore {
463 fn add_triple(&mut self, graph: &GraphName, triple: Triple) -> Result<bool>;
467
468 fn remove_triple(&mut self, graph: &GraphName, triple: &Triple) -> Result<bool>;
472
473 fn contains_triple(&self, graph: &GraphName, triple: &Triple) -> Result<bool>;
475
476 fn triples_in_graph(&self, graph: &GraphName) -> Result<Vec<Triple>>;
478
479 fn clear_graph(&mut self, graph: &GraphName) -> Result<usize>;
483
484 fn drop_graph(&mut self, graph: &GraphName) -> Result<bool>;
488}
489
490impl GraphStore for NamedGraphManager {
492 fn add_triple(&mut self, graph: &GraphName, triple: Triple) -> Result<bool> {
493 self.insert_triple(graph, triple)
494 }
495
496 fn remove_triple(&mut self, graph: &GraphName, triple: &Triple) -> Result<bool> {
497 self.remove_triple(graph, triple)
498 }
499
500 fn contains_triple(&self, graph: &GraphName, triple: &Triple) -> Result<bool> {
501 Ok(self.contains_triple(graph, triple))
502 }
503
504 fn triples_in_graph(&self, graph: &GraphName) -> Result<Vec<Triple>> {
505 Ok(self.triples_in_graph(graph))
506 }
507
508 fn clear_graph(&mut self, graph: &GraphName) -> Result<usize> {
509 self.clear_graph(graph)
510 }
511
512 fn drop_graph(&mut self, graph: &GraphName) -> Result<bool> {
513 Ok(self.drop_graph(graph))
514 }
515}
516
517pub fn graph_name_from_iri(iri: &str) -> Result<GraphName> {
523 let node = NamedNode::new(iri).map_err(|e| OxirsError::Parse(e.to_string()))?;
524 Ok(GraphName::NamedNode(node))
525}
526
527pub fn default_graph_name() -> GraphName {
529 GraphName::DefaultGraph
530}
531
532#[cfg(test)]
535mod tests {
536 use super::*;
537 use crate::model::{Literal, NamedNode, Triple};
538
539 fn iri(s: &str) -> NamedNode {
542 NamedNode::new(s).expect("valid IRI")
543 }
544
545 fn graph_key(s: &str) -> GraphName {
546 GraphName::NamedNode(iri(s))
547 }
548
549 fn triple(s: &str, p: &str, o: &str) -> Triple {
550 Triple::new(iri(s), iri(p), Literal::new(o))
551 }
552
553 #[test]
556 fn test_new_manager_is_empty() {
557 let mgr = NamedGraphManager::new();
558 assert_eq!(mgr.graph_count(), 0);
559 assert_eq!(mgr.triple_count(), 0);
560 }
561
562 #[test]
563 fn test_default_manager_is_empty() {
564 let mgr = NamedGraphManager::default();
565 assert_eq!(mgr.graph_count(), 0);
566 }
567
568 #[test]
569 fn test_with_capacity_starts_empty() {
570 let mgr = NamedGraphManager::with_capacity(32);
571 assert_eq!(mgr.graph_count(), 0);
572 assert!(mgr.triple_count() == 0);
573 }
574
575 #[test]
576 fn test_total_graph_count_includes_default() {
577 let mgr = NamedGraphManager::new();
578 assert_eq!(mgr.total_graph_count(), 1); }
580
581 #[test]
584 fn test_add_named_graph_returns_true_on_creation() {
585 let mut mgr = NamedGraphManager::new();
586 let key = graph_key("http://example.org/g1");
587 assert!(mgr.add_named_graph(key));
588 }
589
590 #[test]
591 fn test_add_named_graph_returns_false_if_already_exists() {
592 let mut mgr = NamedGraphManager::new();
593 let key = graph_key("http://example.org/g1");
594 mgr.add_named_graph(key.clone());
595 assert!(!mgr.add_named_graph(key));
596 }
597
598 #[test]
599 fn test_add_named_graph_increments_count() {
600 let mut mgr = NamedGraphManager::new();
601 mgr.add_named_graph(graph_key("http://example.org/g1"));
602 assert_eq!(mgr.graph_count(), 1);
603 }
604
605 #[test]
606 fn test_add_default_graph_key_is_noop() {
607 let mut mgr = NamedGraphManager::new();
608 let result = mgr.add_named_graph(GraphName::DefaultGraph);
609 assert!(!result);
610 assert_eq!(mgr.graph_count(), 0);
611 }
612
613 #[test]
614 fn test_add_multiple_named_graphs() {
615 let mut mgr = NamedGraphManager::new();
616 for i in 0..5 {
617 mgr.add_named_graph(graph_key(&format!("http://example.org/g{i}")));
618 }
619 assert_eq!(mgr.graph_count(), 5);
620 assert_eq!(mgr.total_graph_count(), 6);
621 }
622
623 #[test]
626 fn test_contains_named_graph_true_after_add() {
627 let mut mgr = NamedGraphManager::new();
628 let key = graph_key("http://example.org/g1");
629 mgr.add_named_graph(key.clone());
630 assert!(mgr.contains_named_graph(&key));
631 }
632
633 #[test]
634 fn test_contains_named_graph_false_before_add() {
635 let mgr = NamedGraphManager::new();
636 assert!(!mgr.contains_named_graph(&graph_key("http://example.org/missing")));
637 }
638
639 #[test]
640 fn test_contains_default_graph_always_true() {
641 let mgr = NamedGraphManager::new();
642 assert!(mgr.contains_named_graph(&GraphName::DefaultGraph));
643 }
644
645 #[test]
648 fn test_get_named_graph_returns_some_after_add() {
649 let mut mgr = NamedGraphManager::new();
650 let key = graph_key("http://example.org/g1");
651 mgr.add_named_graph(key.clone());
652 assert!(mgr.get_named_graph(&key).is_some());
653 }
654
655 #[test]
656 fn test_get_named_graph_returns_none_if_absent() {
657 let mgr = NamedGraphManager::new();
658 assert!(mgr
659 .get_named_graph(&graph_key("http://example.org/absent"))
660 .is_none());
661 }
662
663 #[test]
664 fn test_get_default_graph_always_some() {
665 let mgr = NamedGraphManager::new();
666 assert!(mgr.get_named_graph(&GraphName::DefaultGraph).is_some());
667 }
668
669 #[test]
672 fn test_remove_named_graph_returns_some_if_existed() {
673 let mut mgr = NamedGraphManager::new();
674 let key = graph_key("http://example.org/g1");
675 mgr.add_named_graph(key.clone());
676 assert!(mgr.remove_named_graph(&key).is_some());
677 }
678
679 #[test]
680 fn test_remove_named_graph_returns_none_if_absent() {
681 let mut mgr = NamedGraphManager::new();
682 assert!(mgr
683 .remove_named_graph(&graph_key("http://example.org/absent"))
684 .is_none());
685 }
686
687 #[test]
688 fn test_remove_named_graph_decrements_count() {
689 let mut mgr = NamedGraphManager::new();
690 let key = graph_key("http://example.org/g1");
691 mgr.add_named_graph(key.clone());
692 mgr.remove_named_graph(&key);
693 assert_eq!(mgr.graph_count(), 0);
694 }
695
696 #[test]
697 fn test_remove_default_graph_clears_contents() {
698 let mut mgr = NamedGraphManager::new();
699 let t = triple("http://example.org/s", "http://example.org/p", "hello");
700 mgr.insert_triple(&GraphName::DefaultGraph, t)
701 .expect("operation should succeed");
702 assert_eq!(mgr.default_graph().len(), 1);
703 let removed = mgr.remove_named_graph(&GraphName::DefaultGraph);
704 assert!(removed.is_some());
705 assert_eq!(mgr.default_graph().len(), 0);
706 }
707
708 #[test]
711 fn test_insert_triple_returns_true_on_new() {
712 let mut mgr = NamedGraphManager::new();
713 let key = graph_key("http://example.org/g1");
714 let t = triple("http://s.org/s", "http://p.org/p", "o");
715 assert!(mgr
716 .insert_triple(&key, t)
717 .expect("operation should succeed"));
718 }
719
720 #[test]
721 fn test_insert_triple_returns_false_on_duplicate() {
722 let mut mgr = NamedGraphManager::new();
723 let key = graph_key("http://example.org/g1");
724 let t = triple("http://s.org/s", "http://p.org/p", "o");
725 mgr.insert_triple(&key, t.clone())
726 .expect("triple insert should succeed");
727 assert!(!mgr
728 .insert_triple(&key, t)
729 .expect("operation should succeed"));
730 }
731
732 #[test]
733 fn test_insert_triple_auto_creates_graph() {
734 let mut mgr = NamedGraphManager::new();
735 let key = graph_key("http://example.org/g1");
736 let t = triple("http://s.org/s", "http://p.org/p", "o");
737 assert!(!mgr.contains_named_graph(&key));
738 mgr.insert_triple(&key, t)
739 .expect("operation should succeed");
740 assert!(mgr.contains_named_graph(&key));
741 }
742
743 #[test]
744 fn test_contains_triple_true_after_insert() {
745 let mut mgr = NamedGraphManager::new();
746 let key = graph_key("http://example.org/g1");
747 let t = triple("http://s.org/s", "http://p.org/p", "o");
748 mgr.insert_triple(&key, t.clone())
749 .expect("triple insert should succeed");
750 assert!(mgr.contains_triple(&key, &t));
751 }
752
753 #[test]
754 fn test_contains_triple_false_in_wrong_graph() {
755 let mut mgr = NamedGraphManager::new();
756 let key1 = graph_key("http://example.org/g1");
757 let key2 = graph_key("http://example.org/g2");
758 let t = triple("http://s.org/s", "http://p.org/p", "o");
759 mgr.insert_triple(&key1, t.clone())
760 .expect("triple insert should succeed");
761 assert!(!mgr.contains_triple(&key2, &t));
762 }
763
764 #[test]
765 fn test_triple_count_in_named_graph() {
766 let mut mgr = NamedGraphManager::new();
767 let key = graph_key("http://example.org/g1");
768 for i in 0..7 {
769 let t = triple(&format!("http://s.org/s{i}"), "http://p.org/p", "o");
770 mgr.insert_triple(&key, t)
771 .expect("operation should succeed");
772 }
773 assert_eq!(mgr.triple_count_in(&key), 7);
774 }
775
776 #[test]
777 fn test_triple_count_total_across_graphs() {
778 let mut mgr = NamedGraphManager::new();
779 for g in 0..3 {
780 let key = graph_key(&format!("http://example.org/g{g}"));
781 for i in 0..4 {
782 let t = triple(&format!("http://s.org/s{i}"), "http://p.org/p", "o");
783 mgr.insert_triple(&key, t)
784 .expect("operation should succeed");
785 }
786 }
787 assert_eq!(mgr.triple_count(), 12);
788 }
789
790 #[test]
793 fn test_remove_triple_returns_true_if_present() {
794 let mut mgr = NamedGraphManager::new();
795 let key = graph_key("http://example.org/g1");
796 let t = triple("http://s.org/s", "http://p.org/p", "o");
797 mgr.insert_triple(&key, t.clone())
798 .expect("triple insert should succeed");
799 assert!(mgr
800 .remove_triple(&key, &t)
801 .expect("operation should succeed"));
802 }
803
804 #[test]
805 fn test_remove_triple_returns_false_if_absent() {
806 let mut mgr = NamedGraphManager::new();
807 let key = graph_key("http://example.org/g1");
808 mgr.add_named_graph(key.clone());
809 let t = triple("http://s.org/s", "http://p.org/p", "o");
810 assert!(!mgr
811 .remove_triple(&key, &t)
812 .expect("operation should succeed"));
813 }
814
815 #[test]
816 fn test_remove_triple_from_nonexistent_graph_is_error() {
817 let mut mgr = NamedGraphManager::new();
818 let key = graph_key("http://example.org/absent");
819 let t = triple("http://s.org/s", "http://p.org/p", "o");
820 assert!(mgr.remove_triple(&key, &t).is_err());
821 }
822
823 #[test]
824 fn test_remove_triple_decrements_count() {
825 let mut mgr = NamedGraphManager::new();
826 let key = graph_key("http://example.org/g1");
827 let t = triple("http://s.org/s", "http://p.org/p", "o");
828 mgr.insert_triple(&key, t.clone())
829 .expect("triple insert should succeed");
830 mgr.remove_triple(&key, &t)
831 .expect("operation should succeed");
832 assert_eq!(mgr.triple_count_in(&key), 0);
833 }
834
835 #[test]
838 fn test_triples_in_graph_returns_all() {
839 let mut mgr = NamedGraphManager::new();
840 let key = graph_key("http://example.org/g1");
841 let t1 = triple("http://s.org/s1", "http://p.org/p", "o1");
842 let t2 = triple("http://s.org/s2", "http://p.org/p", "o2");
843 mgr.insert_triple(&key, t1.clone())
844 .expect("triple insert should succeed");
845 mgr.insert_triple(&key, t2.clone())
846 .expect("triple insert should succeed");
847 let triples = mgr.triples_in_graph(&key);
848 assert_eq!(triples.len(), 2);
849 assert!(triples.contains(&t1));
850 assert!(triples.contains(&t2));
851 }
852
853 #[test]
854 fn test_triples_in_nonexistent_graph_is_empty() {
855 let mgr = NamedGraphManager::new();
856 assert!(mgr
857 .triples_in_graph(&graph_key("http://example.org/absent"))
858 .is_empty());
859 }
860
861 #[test]
864 fn test_clear_graph_removes_all_triples() {
865 let mut mgr = NamedGraphManager::new();
866 let key = graph_key("http://example.org/g1");
867 let t = triple("http://s.org/s", "http://p.org/p", "o");
868 mgr.insert_triple(&key, t)
869 .expect("operation should succeed");
870 let cleared = mgr.clear_graph(&key).expect("operation should succeed");
871 assert_eq!(cleared, 1);
872 assert_eq!(mgr.triple_count_in(&key), 0);
873 }
874
875 #[test]
876 fn test_clear_graph_keeps_graph_entry() {
877 let mut mgr = NamedGraphManager::new();
878 let key = graph_key("http://example.org/g1");
879 mgr.add_named_graph(key.clone());
880 mgr.clear_graph(&key).expect("operation should succeed");
881 assert!(mgr.contains_named_graph(&key));
882 }
883
884 #[test]
885 fn test_clear_nonexistent_graph_is_error() {
886 let mut mgr = NamedGraphManager::new();
887 let key = graph_key("http://example.org/absent");
888 assert!(mgr.clear_graph(&key).is_err());
889 }
890
891 #[test]
894 fn test_drop_graph_removes_graph_entry() {
895 let mut mgr = NamedGraphManager::new();
896 let key = graph_key("http://example.org/g1");
897 mgr.add_named_graph(key.clone());
898 assert!(mgr.drop_graph(&key));
899 assert!(!mgr.contains_named_graph(&key));
900 }
901
902 #[test]
903 fn test_drop_graph_returns_false_if_absent() {
904 let mut mgr = NamedGraphManager::new();
905 assert!(!mgr.drop_graph(&graph_key("http://example.org/absent")));
906 }
907
908 #[test]
909 fn test_drop_default_graph_clears_triples() {
910 let mut mgr = NamedGraphManager::new();
911 let t = triple("http://s.org/s", "http://p.org/p", "o");
912 mgr.insert_triple(&GraphName::DefaultGraph, t)
913 .expect("operation should succeed");
914 let result = mgr.drop_graph(&GraphName::DefaultGraph);
915 assert!(result);
916 assert_eq!(mgr.default_graph().len(), 0);
917 }
918
919 #[test]
922 fn test_union_graph_merges_all_triples() {
923 let mut mgr = NamedGraphManager::new();
924 let k1 = graph_key("http://example.org/g1");
925 let k2 = graph_key("http://example.org/g2");
926 let t1 = triple("http://s.org/s1", "http://p.org/p", "o1");
927 let t2 = triple("http://s.org/s2", "http://p.org/p", "o2");
928 mgr.insert_triple(&k1, t1.clone())
929 .expect("triple insert should succeed");
930 mgr.insert_triple(&k2, t2.clone())
931 .expect("triple insert should succeed");
932 let union = mgr.union_graph();
933 assert!(union.contains(&t1));
934 assert!(union.contains(&t2));
935 assert_eq!(union.len(), 2);
936 }
937
938 #[test]
939 fn test_union_graph_includes_default_graph() {
940 let mut mgr = NamedGraphManager::new();
941 let t = triple("http://s.org/s", "http://p.org/p", "o");
942 mgr.insert_triple(&GraphName::DefaultGraph, t.clone())
943 .expect("operation should succeed");
944 let union = mgr.union_graph();
945 assert!(union.contains(&t));
946 }
947
948 #[test]
949 fn test_union_graph_deduplicates() {
950 let mut mgr = NamedGraphManager::new();
951 let k1 = graph_key("http://example.org/g1");
952 let k2 = graph_key("http://example.org/g2");
953 let t = triple("http://s.org/s", "http://p.org/p", "o");
954 mgr.insert_triple(&k1, t.clone())
955 .expect("triple insert should succeed");
956 mgr.insert_triple(&k2, t.clone())
957 .expect("triple insert should succeed");
958 let union = mgr.union_graph();
959 assert_eq!(union.len(), 1);
960 }
961
962 #[test]
963 fn test_union_of_named_graphs_excludes_default() {
964 let mut mgr = NamedGraphManager::new();
965 let k1 = graph_key("http://example.org/g1");
966 let t_named = triple("http://s.org/named", "http://p.org/p", "o");
967 let t_default = triple("http://s.org/default", "http://p.org/p", "o");
968 mgr.insert_triple(&k1, t_named.clone())
969 .expect("triple insert should succeed");
970 mgr.insert_triple(&GraphName::DefaultGraph, t_default.clone())
971 .expect("operation should succeed");
972 let union = mgr.union_of_named_graphs();
973 assert!(union.contains(&t_named));
974 assert!(!union.contains(&t_default));
975 }
976
977 #[test]
980 fn test_list_named_graphs_empty_when_none() {
981 let mgr = NamedGraphManager::new();
982 assert_eq!(mgr.list_named_graphs().count(), 0);
983 }
984
985 #[test]
986 fn test_list_named_graphs_returns_correct_count() {
987 let mut mgr = NamedGraphManager::new();
988 for i in 0..4 {
989 mgr.add_named_graph(graph_key(&format!("http://example.org/g{i}")));
990 }
991 assert_eq!(mgr.list_named_graphs().count(), 4);
992 }
993
994 #[test]
995 fn test_list_named_graphs_contains_added_keys() {
996 let mut mgr = NamedGraphManager::new();
997 let key = graph_key("http://example.org/myGraph");
998 mgr.add_named_graph(key.clone());
999 let names: Vec<_> = mgr.list_named_graphs().collect();
1000 assert!(names.contains(&&key));
1001 }
1002
1003 #[test]
1006 fn test_bulk_insert_returns_inserted_count() {
1007 let mut mgr = NamedGraphManager::new();
1008 let key = graph_key("http://example.org/g1");
1009 let triples: Vec<Triple> = (0..5)
1010 .map(|i| triple(&format!("http://s.org/s{i}"), "http://p.org/p", "o"))
1011 .collect();
1012 let count = mgr.bulk_insert(&key, triples);
1013 assert_eq!(count, 5);
1014 }
1015
1016 #[test]
1017 fn test_bulk_insert_deduplicates() {
1018 let mut mgr = NamedGraphManager::new();
1019 let key = graph_key("http://example.org/g1");
1020 let t = triple("http://s.org/s", "http://p.org/p", "o");
1021 mgr.bulk_insert(&key, vec![t.clone(), t]);
1022 assert_eq!(mgr.triple_count_in(&key), 1);
1023 }
1024
1025 #[test]
1026 fn test_copy_graph_copies_all_triples() {
1027 let mut mgr = NamedGraphManager::new();
1028 let src = graph_key("http://example.org/src");
1029 let dst = graph_key("http://example.org/dst");
1030 let t = triple("http://s.org/s", "http://p.org/p", "o");
1031 mgr.insert_triple(&src, t.clone())
1032 .expect("triple insert should succeed");
1033 mgr.copy_graph(&src, &dst)
1034 .expect("operation should succeed");
1035 assert!(mgr.contains_triple(&dst, &t));
1036 assert!(mgr.contains_triple(&src, &t)); }
1038
1039 #[test]
1040 fn test_copy_nonexistent_graph_is_error() {
1041 let mut mgr = NamedGraphManager::new();
1042 let src = graph_key("http://example.org/absent");
1043 let dst = graph_key("http://example.org/dst");
1044 assert!(mgr.copy_graph(&src, &dst).is_err());
1045 }
1046
1047 #[test]
1048 fn test_move_graph_empties_source() {
1049 let mut mgr = NamedGraphManager::new();
1050 let src = graph_key("http://example.org/src");
1051 let dst = graph_key("http://example.org/dst");
1052 let t = triple("http://s.org/s", "http://p.org/p", "o");
1053 mgr.insert_triple(&src, t.clone())
1054 .expect("triple insert should succeed");
1055 mgr.move_graph(&src, &dst)
1056 .expect("operation should succeed");
1057 assert_eq!(mgr.triple_count_in(&src), 0);
1058 assert!(mgr.contains_triple(&dst, &t));
1059 }
1060
1061 #[test]
1062 fn test_move_nonexistent_graph_is_error() {
1063 let mut mgr = NamedGraphManager::new();
1064 let src = graph_key("http://example.org/absent");
1065 let dst = graph_key("http://example.org/dst");
1066 assert!(mgr.move_graph(&src, &dst).is_err());
1067 }
1068
1069 #[test]
1072 fn test_insert_quad_into_named_graph() {
1073 let mut mgr = NamedGraphManager::new();
1074 let graph_node = iri("http://example.org/g1");
1075 let quad = Quad::new(
1076 iri("http://s.org/s"),
1077 iri("http://p.org/p"),
1078 Literal::new("o"),
1079 graph_node,
1080 );
1081 mgr.insert_quad(quad).expect("operation should succeed");
1082 assert_eq!(mgr.triple_count(), 1);
1083 }
1084
1085 #[test]
1086 fn test_insert_quad_into_default_graph() {
1087 let mut mgr = NamedGraphManager::new();
1088 let quad = Quad::new_default_graph(
1089 iri("http://s.org/s"),
1090 iri("http://p.org/p"),
1091 Literal::new("o"),
1092 );
1093 mgr.insert_quad(quad).expect("operation should succeed");
1094 assert_eq!(mgr.default_graph().len(), 1);
1095 }
1096
1097 #[test]
1100 fn test_iter_quads_covers_all_graphs() {
1101 let mut mgr = NamedGraphManager::new();
1102 let k1 = graph_key("http://example.org/g1");
1103 let k2 = graph_key("http://example.org/g2");
1104 mgr.insert_triple(&k1, triple("http://s.org/s1", "http://p.org/p", "o"))
1105 .expect("operation should succeed");
1106 mgr.insert_triple(&k2, triple("http://s.org/s2", "http://p.org/p", "o"))
1107 .expect("operation should succeed");
1108 mgr.insert_triple(
1109 &GraphName::DefaultGraph,
1110 triple("http://s.org/s3", "http://p.org/p", "o"),
1111 )
1112 .expect("operation should succeed");
1113 let count = mgr.iter_quads().count();
1114 assert_eq!(count, 3);
1115 }
1116
1117 #[test]
1120 fn test_statistics_empty_dataset() {
1121 let mgr = NamedGraphManager::new();
1122 let stats = mgr.statistics();
1123 assert_eq!(stats.named_graph_count, 0);
1124 assert_eq!(stats.total_triple_count, 0);
1125 assert!(stats.is_empty());
1126 }
1127
1128 #[test]
1129 fn test_statistics_named_graph_count() {
1130 let mut mgr = NamedGraphManager::new();
1131 for i in 0..3 {
1132 mgr.add_named_graph(graph_key(&format!("http://example.org/g{i}")));
1133 }
1134 assert_eq!(mgr.statistics().named_graph_count, 3);
1135 }
1136
1137 #[test]
1138 fn test_statistics_total_triple_count() {
1139 let mut mgr = NamedGraphManager::new();
1140 let key = graph_key("http://example.org/g1");
1141 for i in 0..6 {
1142 mgr.insert_triple(
1143 &key,
1144 triple(&format!("http://s.org/s{i}"), "http://p.org/p", "o"),
1145 )
1146 .expect("operation should succeed");
1147 }
1148 assert_eq!(mgr.statistics().total_triple_count, 6);
1149 }
1150
1151 #[test]
1152 fn test_statistics_largest_named_graph() {
1153 let mut mgr = NamedGraphManager::new();
1154 let big = graph_key("http://example.org/big");
1155 let small = graph_key("http://example.org/small");
1156 for i in 0..10 {
1157 mgr.insert_triple(
1158 &big,
1159 triple(&format!("http://s.org/s{i}"), "http://p.org/p", "o"),
1160 )
1161 .expect("operation should succeed");
1162 }
1163 mgr.insert_triple(&small, triple("http://s.org/s", "http://p.org/p", "o"))
1164 .expect("operation should succeed");
1165 let stats = mgr.statistics();
1166 assert_eq!(stats.largest_named_graph, Some(big));
1167 }
1168
1169 #[test]
1170 fn test_statistics_average_size_zero_when_no_named_graphs() {
1171 let mgr = NamedGraphManager::new();
1172 assert_eq!(mgr.statistics().average_named_graph_size(), 0.0);
1173 }
1174
1175 #[test]
1176 fn test_statistics_average_named_graph_size() {
1177 let mut mgr = NamedGraphManager::new();
1178 let k1 = graph_key("http://example.org/g1");
1179 let k2 = graph_key("http://example.org/g2");
1180 for i in 0..4 {
1181 mgr.insert_triple(
1182 &k1,
1183 triple(&format!("http://s.org/s{i}"), "http://p.org/p", "o"),
1184 )
1185 .expect("operation should succeed");
1186 }
1187 for i in 0..2 {
1188 mgr.insert_triple(
1189 &k2,
1190 triple(&format!("http://s.org/s{i}"), "http://p.org/p", "x"),
1191 )
1192 .expect("operation should succeed");
1193 }
1194 assert!((mgr.statistics().average_named_graph_size() - 3.0).abs() < 1e-10);
1196 }
1197
1198 #[test]
1201 fn test_named_graph_iterator_yields_all_graphs() {
1202 let mut mgr = NamedGraphManager::new();
1203 for i in 0..4 {
1204 mgr.add_named_graph(graph_key(&format!("http://example.org/g{i}")));
1205 }
1206 let iter = NamedGraphIterator::from_manager(mgr);
1207 assert_eq!(iter.count(), 4);
1208 }
1209
1210 #[test]
1211 fn test_named_graph_iterator_size_hint() {
1212 let mut mgr = NamedGraphManager::new();
1213 for i in 0..3 {
1214 mgr.add_named_graph(graph_key(&format!("http://example.org/g{i}")));
1215 }
1216 let iter = NamedGraphIterator::from_manager(mgr);
1217 let (lower, upper) = iter.size_hint();
1218 assert_eq!(lower, 3);
1219 assert_eq!(upper, Some(3));
1220 }
1221
1222 #[test]
1225 fn test_graph_store_add_triple() {
1226 let mut store: Box<dyn GraphStore> = Box::new(NamedGraphManager::new());
1227 let key = graph_key("http://example.org/g1");
1228 let t = triple("http://s.org/s", "http://p.org/p", "o");
1229 assert!(store
1230 .add_triple(&key, t)
1231 .expect("store operation should succeed"));
1232 }
1233
1234 #[test]
1235 fn test_graph_store_contains_triple() {
1236 let mut store = NamedGraphManager::new();
1237 let key = graph_key("http://example.org/g1");
1238 let t = triple("http://s.org/s", "http://p.org/p", "o");
1239 GraphStore::add_triple(&mut store, &key, t.clone()).expect("add triple should succeed");
1240 assert!(GraphStore::contains_triple(&store, &key, &t)
1241 .expect("GraphStore operation should succeed"));
1242 }
1243
1244 #[test]
1245 fn test_graph_store_remove_triple() {
1246 let mut store = NamedGraphManager::new();
1247 let key = graph_key("http://example.org/g1");
1248 let t = triple("http://s.org/s", "http://p.org/p", "o");
1249 GraphStore::add_triple(&mut store, &key, t.clone()).expect("add triple should succeed");
1250 assert!(GraphStore::remove_triple(&mut store, &key, &t)
1251 .expect("GraphStore operation should succeed"));
1252 }
1253
1254 #[test]
1255 fn test_graph_store_triples_in_graph() {
1256 let mut store = NamedGraphManager::new();
1257 let key = graph_key("http://example.org/g1");
1258 let t = triple("http://s.org/s", "http://p.org/p", "o");
1259 GraphStore::add_triple(&mut store, &key, t.clone()).expect("add triple should succeed");
1260 let triples = GraphStore::triples_in_graph(&store, &key)
1261 .expect("GraphStore operation should succeed");
1262 assert_eq!(triples.len(), 1);
1263 assert!(triples.contains(&t));
1264 }
1265
1266 #[test]
1267 fn test_graph_store_clear_graph() {
1268 let mut store = NamedGraphManager::new();
1269 let key = graph_key("http://example.org/g1");
1270 let t = triple("http://s.org/s", "http://p.org/p", "o");
1271 GraphStore::add_triple(&mut store, &key, t).expect("GraphStore operation should succeed");
1272 let cleared =
1273 GraphStore::clear_graph(&mut store, &key).expect("GraphStore operation should succeed");
1274 assert_eq!(cleared, 1);
1275 }
1276
1277 #[test]
1278 fn test_graph_store_drop_graph() {
1279 let mut store = NamedGraphManager::new();
1280 let key = graph_key("http://example.org/g1");
1281 store.add_named_graph(key.clone());
1282 assert!(
1283 GraphStore::drop_graph(&mut store, &key).expect("GraphStore operation should succeed")
1284 );
1285 }
1286
1287 #[test]
1290 fn test_graph_name_from_iri_valid() {
1291 let key = graph_name_from_iri("http://example.org/g1");
1292 assert!(key.is_ok());
1293 assert!(matches!(
1294 key.expect("key should be valid"),
1295 GraphName::NamedNode(_)
1296 ));
1297 }
1298
1299 #[test]
1300 fn test_graph_name_from_iri_invalid() {
1301 let key = graph_name_from_iri("not a valid IRI!!!");
1302 assert!(key.is_err());
1303 }
1304
1305 #[test]
1306 fn test_default_graph_name_is_default() {
1307 let key = default_graph_name();
1308 assert!(key.is_default_graph());
1309 }
1310}