Fork of https://github.com/oxigraph/oxigraph.git for the purpose of NextGraph project
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
278 lines
8.2 KiB
278 lines
8.2 KiB
//! [In-memory implementation](super::Graph) of [RDF graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-graph).
|
|
//!
|
|
//! Usage example:
|
|
//! ```
|
|
//! use oxrdf::*;
|
|
//!
|
|
//! let mut graph = Graph::default();
|
|
//!
|
|
//! // insertion
|
|
//! let ex = NamedNodeRef::new("http://example.com")?;
|
|
//! let triple = TripleRef::new(ex, ex, ex);
|
|
//! graph.insert(triple);
|
|
//!
|
|
//! // simple filter
|
|
//! let results: Vec<_> = graph.triples_for_subject(ex).collect();
|
|
//! assert_eq!(vec![triple], results);
|
|
//! # Result::<_,Box<dyn std::error::Error>>::Ok(())
|
|
//! ```
|
|
//!
|
|
//! See also [`Dataset`](super::Dataset) if you want to get support of multiple RDF graphs at the same time.
|
|
|
|
use crate::dataset::*;
|
|
use crate::*;
|
|
use std::fmt;
|
|
|
|
/// An in-memory [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-graph).
|
|
///
|
|
/// It can accommodate a fairly large number of triples (in the few millions).
|
|
/// Beware: it interns the string and does not do any garbage collection yet:
|
|
/// if you insert and remove a lot of different terms, memory will grow without any reduction.
|
|
///
|
|
/// Usage example:
|
|
/// ```
|
|
/// use oxrdf::*;
|
|
///
|
|
/// let mut graph = Graph::default();
|
|
///
|
|
/// // insertion
|
|
/// let ex = NamedNodeRef::new("http://example.com")?;
|
|
/// let triple = TripleRef::new(ex, ex, ex);
|
|
/// graph.insert(triple);
|
|
///
|
|
/// // simple filter
|
|
/// let results: Vec<_> = graph.triples_for_subject(ex).collect();
|
|
/// assert_eq!(vec![triple], results);
|
|
/// # Result::<_,Box<dyn std::error::Error>>::Ok(())
|
|
/// ```
|
|
#[derive(Debug, Default)]
|
|
pub struct Graph {
|
|
dataset: Dataset,
|
|
}
|
|
|
|
impl Graph {
|
|
/// Creates a new graph.
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
fn graph(&self) -> GraphView<'_> {
|
|
self.dataset.graph(GraphNameRef::DefaultGraph)
|
|
}
|
|
|
|
fn graph_mut(&mut self) -> GraphViewMut<'_> {
|
|
self.dataset.graph_mut(GraphNameRef::DefaultGraph)
|
|
}
|
|
|
|
/// Returns all the triples contained by the graph.
|
|
pub fn iter(&self) -> Iter<'_> {
|
|
Iter {
|
|
inner: self.graph().iter(),
|
|
}
|
|
}
|
|
|
|
pub fn triples_for_subject<'a, 'b>(
|
|
&'a self,
|
|
subject: impl Into<SubjectRef<'b>>,
|
|
) -> impl Iterator<Item = TripleRef<'a>> + 'a {
|
|
self.graph()
|
|
.triples_for_interned_subject(self.dataset.encoded_subject(subject))
|
|
}
|
|
|
|
pub fn objects_for_subject_predicate<'a, 'b>(
|
|
&'a self,
|
|
subject: impl Into<SubjectRef<'b>>,
|
|
predicate: impl Into<NamedNodeRef<'b>>,
|
|
) -> impl Iterator<Item = TermRef<'a>> + 'a {
|
|
self.graph().objects_for_interned_subject_predicate(
|
|
self.dataset.encoded_subject(subject),
|
|
self.dataset.encoded_named_node(predicate),
|
|
)
|
|
}
|
|
|
|
pub fn object_for_subject_predicate<'a, 'b>(
|
|
&'a self,
|
|
subject: impl Into<SubjectRef<'b>>,
|
|
predicate: impl Into<NamedNodeRef<'b>>,
|
|
) -> Option<TermRef<'a>> {
|
|
self.graph()
|
|
.objects_for_subject_predicate(subject, predicate)
|
|
.next()
|
|
}
|
|
|
|
pub fn predicates_for_subject_object<'a, 'b>(
|
|
&'a self,
|
|
subject: impl Into<SubjectRef<'b>>,
|
|
object: impl Into<TermRef<'b>>,
|
|
) -> impl Iterator<Item = NamedNodeRef<'a>> + 'a {
|
|
self.graph().predicates_for_interned_subject_object(
|
|
self.dataset.encoded_subject(subject),
|
|
self.dataset.encoded_term(object),
|
|
)
|
|
}
|
|
|
|
pub fn triples_for_predicate<'a, 'b>(
|
|
&'a self,
|
|
predicate: impl Into<NamedNodeRef<'b>>,
|
|
) -> impl Iterator<Item = TripleRef<'a>> + 'a {
|
|
self.graph()
|
|
.triples_for_interned_predicate(self.dataset.encoded_named_node(predicate))
|
|
}
|
|
|
|
pub fn subjects_for_predicate_object<'a, 'b>(
|
|
&'a self,
|
|
predicate: impl Into<NamedNodeRef<'b>>,
|
|
object: impl Into<TermRef<'b>>,
|
|
) -> impl Iterator<Item = SubjectRef<'a>> + 'a {
|
|
self.graph().subjects_for_interned_predicate_object(
|
|
self.dataset.encoded_named_node(predicate),
|
|
self.dataset.encoded_term(object),
|
|
)
|
|
}
|
|
|
|
pub fn subject_for_predicate_object<'a, 'b>(
|
|
&'a self,
|
|
predicate: impl Into<NamedNodeRef<'b>>,
|
|
object: impl Into<TermRef<'b>>,
|
|
) -> Option<SubjectRef<'a>> {
|
|
self.graph().subject_for_predicate_object(predicate, object)
|
|
}
|
|
|
|
pub fn triples_for_object<'a, 'b>(
|
|
&'a self,
|
|
object: impl Into<TermRef<'b>>,
|
|
) -> impl Iterator<Item = TripleRef<'a>> + 'a {
|
|
self.graph()
|
|
.triples_for_interned_object(self.dataset.encoded_term(object))
|
|
}
|
|
|
|
/// Checks if the graph contains the given triple.
|
|
pub fn contains<'a>(&self, triple: impl Into<TripleRef<'a>>) -> bool {
|
|
self.graph().contains(triple)
|
|
}
|
|
|
|
/// Returns the number of triples in this graph.
|
|
pub fn len(&self) -> usize {
|
|
self.dataset.len()
|
|
}
|
|
|
|
/// Checks if this graph contains a triple.
|
|
pub fn is_empty(&self) -> bool {
|
|
self.dataset.is_empty()
|
|
}
|
|
|
|
/// Adds a triple to the graph.
|
|
pub fn insert<'a>(&mut self, triple: impl Into<TripleRef<'a>>) -> bool {
|
|
self.graph_mut().insert(triple)
|
|
}
|
|
|
|
/// Removes a concrete triple from the graph.
|
|
pub fn remove<'a>(&mut self, triple: impl Into<TripleRef<'a>>) -> bool {
|
|
self.graph_mut().remove(triple)
|
|
}
|
|
|
|
/// Clears the graph.
|
|
pub fn clear(&mut self) {
|
|
self.dataset.clear()
|
|
}
|
|
|
|
/// Applies on the graph the canonicalization process described in
|
|
/// [Canonical Forms for Isomorphic and Equivalent RDF Graphs: Algorithms for Leaning and Labelling Blank Nodes, Aidan Hogan, 2017](http://aidanhogan.com/docs/rdf-canonicalisation.pdf).
|
|
///
|
|
/// Usage example ([Graph isomorphism](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-isomorphism)):
|
|
/// ```
|
|
/// use oxrdf::*;
|
|
///
|
|
/// let iri = NamedNodeRef::new("http://example.com")?;
|
|
///
|
|
/// let mut graph1 = Graph::new();
|
|
/// let bnode1 = BlankNode::default();
|
|
/// graph1.insert(TripleRef::new(iri, iri, &bnode1));
|
|
/// graph1.insert(TripleRef::new(&bnode1, iri, iri));
|
|
///
|
|
/// let mut graph2 = Graph::new();
|
|
/// let bnode2 = BlankNode::default();
|
|
/// graph2.insert(TripleRef::new(iri, iri, &bnode2));
|
|
/// graph2.insert(TripleRef::new(&bnode2, iri, iri));
|
|
///
|
|
/// assert_ne!(graph1, graph2);
|
|
/// graph1.canonicalize();
|
|
/// graph2.canonicalize();
|
|
/// assert_eq!(graph1, graph2);
|
|
/// # Result::<_,Box<dyn std::error::Error>>::Ok(())
|
|
/// ```
|
|
///
|
|
/// Warning 1: Blank node ids depends on the current shape of the graph. Adding a new triple might change the ids of a lot of blank nodes.
|
|
/// Hence, this canonization might not be suitable for diffs.
|
|
///
|
|
/// Warning 2: The canonicalization algorithm is not stable and canonical blank node Ids might change between Oxigraph version.
|
|
///
|
|
/// Warning 3: This implementation worst-case complexity is in *O(b!)* with *b* the number of blank nodes in the input graph.
|
|
pub fn canonicalize(&mut self) {
|
|
self.dataset.canonicalize()
|
|
}
|
|
}
|
|
|
|
impl PartialEq for Graph {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.dataset == other.dataset
|
|
}
|
|
}
|
|
|
|
impl Eq for Graph {}
|
|
|
|
impl<'a> IntoIterator for &'a Graph {
|
|
type Item = TripleRef<'a>;
|
|
type IntoIter = Iter<'a>;
|
|
|
|
fn into_iter(self) -> Iter<'a> {
|
|
self.iter()
|
|
}
|
|
}
|
|
|
|
impl FromIterator<Triple> for Graph {
|
|
fn from_iter<I: IntoIterator<Item = Triple>>(iter: I) -> Self {
|
|
let mut g = Self::new();
|
|
g.extend(iter);
|
|
g
|
|
}
|
|
}
|
|
|
|
impl<'a, T: Into<TripleRef<'a>>> FromIterator<T> for Graph {
|
|
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
|
let mut g = Self::new();
|
|
g.extend(iter);
|
|
g
|
|
}
|
|
}
|
|
|
|
impl Extend<Triple> for Graph {
|
|
fn extend<I: IntoIterator<Item = Triple>>(&mut self, iter: I) {
|
|
self.graph_mut().extend(iter)
|
|
}
|
|
}
|
|
|
|
impl<'a, T: Into<TripleRef<'a>>> Extend<T> for Graph {
|
|
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
|
self.graph_mut().extend(iter)
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Graph {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
self.graph().fmt(f)
|
|
}
|
|
}
|
|
|
|
/// Iterator returned by [`Graph::iter`].
|
|
pub struct Iter<'a> {
|
|
inner: GraphViewIter<'a>,
|
|
}
|
|
|
|
impl<'a> Iterator for Iter<'a> {
|
|
type Item = TripleRef<'a>;
|
|
|
|
fn next(&mut self) -> Option<TripleRef<'a>> {
|
|
self.inner.next()
|
|
}
|
|
}
|
|
|