@ -464,7 +464,7 @@ impl Dataset {
/// let file = "<http://example.com> <http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
/// let file = "<http://example.com> <http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
///
///
/// let mut store = Dataset::new();
/// let mut store = Dataset::new();
/// store.load(file, DatasetFormat::NQuads,None)?;
/// store.load(file, DatasetFormat::NQuads, None)?;
///
///
/// let mut buffer = Vec::new();
/// let mut buffer = Vec::new();
/// store.dump(&mut buffer, DatasetFormat::NQuads)?;
/// store.dump(&mut buffer, DatasetFormat::NQuads)?;
@ -558,7 +558,31 @@ impl Dataset {
/// Applies on the dataset the canonicalization process described in
/// Applies on the dataset 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)
/// [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)
///
///
/// Warning: This implementation worst-case complexity is in O(b!) with b the number of blank nodes in the input graphs.
/// Usage example ([Dataset isomorphim](https://www.w3.org/TR/rdf11-concepts/#dfn-dataset-isomorphism)):
/// ```
/// use oxigraph::io::DatasetFormat;
/// use oxigraph::model::Dataset;
///
/// let file = "GRAPH _:a1 { <http://example.com> <http://example.com> [ <http://example.com/p> <http://example.com/o> ] . }".as_bytes();
///
/// let mut dataset1 = Dataset::new();
/// dataset1.load(file, DatasetFormat::TriG, None)?;
/// let mut dataset2 = Dataset::new();
/// dataset2.load(file, DatasetFormat::TriG, None)?;
///
/// assert_ne!(dataset1, dataset2);
/// dataset1.canonicalize();
/// dataset2.canonicalize();
/// assert_eq!(dataset1, dataset2);
/// # Result::<_,Box<dyn std::error::Error>>::Ok(())
/// ```
///
/// Warning 1: 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.
/// 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 dataset.
pub fn canonicalize ( & mut self ) {
pub fn canonicalize ( & mut self ) {
let bnodes = self . blank_nodes ( ) ;
let bnodes = self . blank_nodes ( ) ;
let ( hash , partition ) =
let ( hash , partition ) =
@ -1122,15 +1146,15 @@ impl<'a> GraphView<'a> {
/// Usage example:
/// Usage example:
/// ```
/// ```
/// use oxigraph::io::GraphFormat;
/// use oxigraph::io::GraphFormat;
/// use oxigraph::model::Graph;
/// use oxigraph::model::*;
///
/// let file = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
///
///
/// let mut store = Graph::new();
/// let mut dataset = Dataset::new();
/// store.load(file, GraphFormat::NTriples,None)?;
/// let ex = NamedNodeRef::new("http://example.com")?;
/// dataset.insert(QuadRef::new(ex, ex, ex, ex));
///
///
/// let file = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
/// let mut buffer = Vec::new();
/// let mut buffer = Vec::new();
/// store .dump(&mut buffer, GraphFormat::NTriples)?;
/// dataset.graph(ex) .dump(&mut buffer, GraphFormat::NTriples)?;
/// assert_eq!(file, buffer.as_slice());
/// assert_eq!(file, buffer.as_slice());
/// # Result::<_,Box<dyn std::error::Error>>::Ok(())
/// # Result::<_,Box<dyn std::error::Error>>::Ok(())
/// ```
/// ```
@ -1281,13 +1305,14 @@ impl<'a> GraphViewMut<'a> {
/// use oxigraph::model::*;
/// use oxigraph::model::*;
/// use oxigraph::io::GraphFormat;
/// use oxigraph::io::GraphFormat;
///
///
/// let mut graph = Graph::new();
/// let mut dataset = Dataset::new();
/// let mut graph = dataset.graph_mut(NamedNodeRef::new("http://example.com")?);
///
///
/// // insertion
/// // insertion
/// let file = b"<http://example.com> <http://example.com> <http://example.com> .";
/// let file = b"<http://example.com> <http://example.com> <http://example.com> .";
/// graph.load(file.as_ref(), GraphFormat::NTriples, None)?;
/// graph.load(file.as_ref(), GraphFormat::NTriples, None)?;
///
///
/// // we inspect the store contents
/// // we inspect the dataset contents
/// let ex = NamedNodeRef::new("http://example.com")?;
/// let ex = NamedNodeRef::new("http://example.com")?;
/// assert!(graph.contains(TripleRef::new(ex, ex, ex)));
/// assert!(graph.contains(TripleRef::new(ex, ex, ex)));
/// # Result::<_,Box<dyn std::error::Error>>::Ok(())
/// # Result::<_,Box<dyn std::error::Error>>::Ok(())
@ -1425,15 +1450,17 @@ impl<'a> GraphViewMut<'a> {
/// Usage example:
/// Usage example:
/// ```
/// ```
/// use oxigraph::io::GraphFormat;
/// use oxigraph::io::GraphFormat;
/// use oxigraph::model::Graph;
/// use oxigraph::model::*;
///
///
/// let file = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
/// let mut dataset = Dataset::new();
/// let mut graph = dataset.graph_mut(NamedNodeRef::new("http://example.com")?);
///
///
/// let mut store = Graph::new() ;
/// let ex = NamedNodeRef::new("http://example.com")? ;
/// store.load(file, GraphFormat::NTriples,None)? ;
/// graph.insert(TripleRef::new(ex, ex, ex)) ;
///
///
/// let file = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();
/// let mut buffer = Vec::new();
/// let mut buffer = Vec::new();
/// store .dump(&mut buffer, GraphFormat::NTriples)?;
/// graph .dump(&mut buffer, GraphFormat::NTriples)?;
/// assert_eq!(file, buffer.as_slice());
/// assert_eq!(file, buffer.as_slice());
/// # Result::<_,Box<dyn std::error::Error>>::Ok(())
/// # Result::<_,Box<dyn std::error::Error>>::Ok(())
/// ```
/// ```