(*********************************************************************************)
(*                OCaml-RDF                                                      *)
(*                                                                               *)
(*    Copyright (C) 2012-2024 Institut National de Recherche en Informatique     *)
(*    et en Automatique. All rights reserved.                                    *)
(*                                                                               *)
(*    This program is free software; you can redistribute it and/or modify       *)
(*    it under the terms of the GNU Lesser General Public License version        *)
(*    3 as published by the Free Software Foundation.                            *)
(*                                                                               *)
(*    This program is distributed in the hope that it will be useful,            *)
(*    but WITHOUT ANY WARRANTY; without even the implied warranty of             *)
(*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *)
(*    GNU General Public License for more details.                               *)
(*                                                                               *)
(*    You should have received a copy of the GNU General Public License          *)
(*    along with this program; if not, write to the Free Software                *)
(*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                   *)
(*    02111-1307  USA                                                            *)
(*                                                                               *)
(*    Contact: Maxence.Guesdon@inria.fr                                          *)
(*                                                                               *)
(*********************************************************************************)

(** Datasets.

A dataset is composed of:
- a default graph,
- a set of named graphs,
- a function to get a graph by its name,
- a function to add a graph.
*)

type name = [ `I of Iri.t | `B of Term.blank_id ]
val compare_name : name -> name -> int
val string_of_name : name -> string
val pp_name : Format.formatter -> name -> unit
val term_of_name : name -> Term.term

module NameMap : Map.S with type key = name
module NameSet : Set.S with type elt = name

(** A dataset.*)
type dataset = {
  default : Graph.graph; (** The default graph. *)
  named : unit -> NameSet.t; (** The set of named graphs. *)
  get_named : ?add:bool -> name -> Graph.graph option;
    (** The function to get a graph by its name, if present.
       It not, then if [add] is [true] and the [add] field provides
       a function to add a graph, a new graph is created, added
       to the dataset and returned. If name is a blank id, base IRI
       of created graph is an empty IRI, else it is the [name].*)
  add : (?name:name -> Graph.graph -> Graph.graph) option
  (** Add a graph to dataset, if dataset allows it. Use the returned
      graph to add triples in the dataset, because if a graph for the
      same name already existed in the dataset, triples of the given
      graph are added to the existing graph.
      If optional parameter [name] is not provided, the base IRI of
      graph is used.
  *)
}

(** [simple_dataset graph] returns a dataset with [graph] as default graph.
  @param named can be used to specify named graphs. The [get_named] function
  is created from this closed list of named graphs and raise {!Could_not_retrieve_graph}
  in case a required graph is not part of the list. *)
val simple_dataset :
  ?named:(name * Graph.graph) list -> Graph.graph -> dataset

(** [dataset graph] returns a dataset with [graph] as default graph.
  @param named is used to specify the sef of named graphs, but it
  does not create a get_named function.
  @param get_named is the function to retrieve graph by name.
  @param add is a function used to add graph to dataset. If [get_named] is not
  provided, [add] argument is ignored.
*)
val dataset :
  ?add:(?name:name -> Graph.graph -> Graph.graph) ->
  ?get_named:(?add:bool -> name -> Graph.graph option) ->
    ?named:(unit -> NameSet.t) -> Graph.graph -> dataset

(** [mem_dataset g] create a new in-memory dataset with given graph [g]
  as default graph. [named], [get_named] and [add] functions are implemented
  to fulfill {!type:dataset} API.*)
val mem_dataset : Graph.graph -> dataset

(** [merge_to_default dataset] add triples of all named graphs
  to [dataset.default]. *)
val merge_to_default : dataset -> unit

(** [graphs dataset] returns the list of [(optional name, graph)] from
     [dataset]. *)
val graphs : dataset -> (name option * Graph.graph) list

(** [iter f dataset] calls [f] for each graph in the dataset,
  with optional name and graph as argument. *)
val iter : (name option -> Graph.graph -> unit) -> dataset -> unit

(** [fold f acc dataset] folds on dataset's graphs with [f] called
  with optional name and graph as argument. *)
val fold : ('a -> name option -> Graph.graph -> 'a) -> 'a -> dataset -> 'a

(** Differences when checking if two datasets are isomorphic. *)
type diff =
| Cardinals of int * int
| Missing_graph of name
| Graph_diff of name option * Graph.diff

val string_of_diff : diff -> string
val pp_diff : Format.formatter -> diff -> unit

(** Return [None] when the two given datasets are isomorphic or the
       first difference. *)
val isomorphic_diff : ?ignore_blanks:bool -> dataset -> dataset -> diff option

