diff --git a/lib/rdf/dataset.ex b/lib/rdf/dataset.ex index 9e3ab47..81b8dfc 100644 --- a/lib/rdf/dataset.ex +++ b/lib/rdf/dataset.ex @@ -48,10 +48,12 @@ defmodule RDF.Dataset do ## Examples - RDF.Dataset.new({EX.S, EX.p, EX.O}) - RDF.Dataset.new(name: EX.GraphName) + RDF.Dataset.new(init: {EX.S, EX.p, EX.O}) + + RDF.Dataset.new({EX.S, EX.p, EX.O}) + """ @spec new(input | keyword) :: t def new(data_or_options) @@ -59,7 +61,8 @@ defmodule RDF.Dataset do def new(data_or_options) when is_list(data_or_options) and length(data_or_options) != 0 do if Keyword.keyword?(data_or_options) do - new([], data_or_options) + {data, options} = Keyword.pop(data_or_options, :init) + new(data, options) else new(data_or_options, []) end @@ -75,6 +78,9 @@ defmodule RDF.Dataset do Available options: - `name`: the name of the dataset to be created + - `init`: some data with which the dataset should be initialized; the data can be + provided in any form accepted by `add/3` and above that also with a function returning + the initialization data in any of these forms """ @spec new(input, keyword) :: t @@ -87,9 +93,13 @@ defmodule RDF.Dataset do def new(data, options) do %__MODULE__{} |> new(options) - |> add(data) + |> init(data) end + defp init(dataset, nil), do: dataset + defp init(dataset, fun) when is_function(fun), do: add(dataset, fun.()) + defp init(dataset, data), do: add(dataset, data) + @doc """ Returns the dataset name IRI of `dataset`. """ diff --git a/lib/rdf/diff.ex b/lib/rdf/diff.ex index f98eb6f..9676fbd 100644 --- a/lib/rdf/diff.ex +++ b/lib/rdf/diff.ex @@ -35,7 +35,7 @@ defmodule RDF.Diff do defp coerce_graph(%Description{} = description), do: if(Enum.empty?(description), do: Graph.new(), else: Graph.new(description)) - defp coerce_graph(data), do: Graph.new(data) + defp coerce_graph(data), do: Graph.new(init: data) @doc """ Computes a diff between two `RDF.Graph`s or `RDF.Description`s. diff --git a/lib/rdf/graph.ex b/lib/rdf/graph.ex index 566ac86..8748684 100644 --- a/lib/rdf/graph.ex +++ b/lib/rdf/graph.ex @@ -56,17 +56,19 @@ defmodule RDF.Graph do @doc """ Creates an `RDF.Graph`. - If a keyword list is given an empty graph is created. + If a keyword list with options is given an empty graph is created. Otherwise an unnamed graph initialized with the given data is created. See `new/2` for available arguments and the different ways to provide data. ## Examples - RDF.Graph.new({EX.S, EX.p, EX.O}) - RDF.Graph.new(name: EX.GraphName) + RDF.Graph.new(init: {EX.S, EX.p, EX.O}) + + RDF.Graph.new({EX.S, EX.p, EX.O}) + """ @spec new(input | keyword) :: t def new(data_or_options) @@ -74,7 +76,8 @@ defmodule RDF.Graph do def new(data_or_options) when is_list(data_or_options) and length(data_or_options) != 0 do if Keyword.keyword?(data_or_options) do - new([], data_or_options) + {data, options} = Keyword.pop(data_or_options, :init) + new(data, options) else new(data_or_options, []) end @@ -99,6 +102,9 @@ defmodule RDF.Graph do and will be used for example when serializing in a format with prefix support - `base_iri`: a base IRI which should be stored alongside the graph and will be used for example when serializing in a format with base IRI support + - `init`: some data with which the graph should be initialized; the data can be + provided in any form accepted by `add/3` and above that also with a function returning + the initialization data in any of these forms ## Examples @@ -121,11 +127,15 @@ defmodule RDF.Graph do end def new(data, options) do - %__MODULE__{} + new() |> new(options) - |> add(data) + |> init(data) end + defp init(graph, nil), do: graph + defp init(graph, fun) when is_function(fun), do: add(graph, fun.()) + defp init(graph, data), do: add(graph, data) + @doc """ Removes all triples from `graph`. diff --git a/test/unit/dataset_test.exs b/test/unit/dataset_test.exs index 0a56eec..55dd0e7 100644 --- a/test/unit/dataset_test.exs +++ b/test/unit/dataset_test.exs @@ -150,6 +150,53 @@ defmodule RDF.DatasetTest do {EX.Subject, EX.predicate(), EX.Object, EX.GraphName} ) end + + @tag skip: "This case is currently not supported, since it's indistinguishable from Keywords" + test "creating a dataset with a list of subject-predications pairs" do + ds = + Dataset.new([ + {EX.S1, + [ + {EX.P1, EX.O1}, + %{EX.P2 => [EX.O2]} + ]} + ]) + + assert dataset_includes_statement?(ds, {EX.S1, EX.P1, EX.O1}) + assert dataset_includes_statement?(ds, {EX.S1, EX.P2, EX.O2}) + end + + test "with init data" do + ds = + Dataset.new( + init: [ + {EX.S1, + [ + {EX.P1, EX.O1}, + %{EX.P2 => [EX.O2]} + ]} + ] + ) + + assert unnamed_dataset?(ds) + assert dataset_includes_statement?(ds, {EX.S1, EX.P1, EX.O1}) + assert dataset_includes_statement?(ds, {EX.S1, EX.P2, EX.O2}) + + ds = + Dataset.new( + name: EX.Dataset, + init: {EX.S, EX.p(), EX.O} + ) + + assert named_dataset?(ds, RDF.iri(EX.Dataset)) + assert dataset_includes_statement?(ds, {EX.S, EX.p(), EX.O}) + end + + test "with an initializer function" do + ds = Dataset.new(init: fn -> {EX.S, EX.p(), EX.O} end) + assert unnamed_dataset?(ds) + assert dataset_includes_statement?(ds, {EX.S, EX.p(), EX.O}) + end end test "name/1" do diff --git a/test/unit/graph_test.exs b/test/unit/graph_test.exs index 59afe2b..dcba210 100644 --- a/test/unit/graph_test.exs +++ b/test/unit/graph_test.exs @@ -156,6 +156,53 @@ defmodule RDF.GraphTest do g = Graph.new(Graph.new(prefixes: %{ex: XSD, rdfs: RDFS}), prefixes: prefix_map) assert g.prefixes == PrefixMap.new(ex: EX, rdfs: RDFS) end + + @tag skip: "This case is currently not supported, since it's indistinguishable from Keywords" + test "creating a graph with a list of subject-predications pairs" do + g = + Graph.new([ + {EX.S1, + [ + {EX.P1, EX.O1}, + %{EX.P2 => [EX.O2]} + ]} + ]) + + assert graph_includes_statement?(g, {EX.S1, EX.P1, EX.O1}) + assert graph_includes_statement?(g, {EX.S1, EX.P2, EX.O2}) + end + + test "with init data" do + g = + Graph.new( + init: [ + {EX.S1, + [ + {EX.P1, EX.O1}, + %{EX.P2 => [EX.O2]} + ]} + ] + ) + + assert unnamed_graph?(g) + assert graph_includes_statement?(g, {EX.S1, EX.P1, EX.O1}) + assert graph_includes_statement?(g, {EX.S1, EX.P2, EX.O2}) + + g = + Graph.new( + name: EX.Graph, + init: {EX.S, EX.p(), EX.O} + ) + + assert named_graph?(g, RDF.iri(EX.Graph)) + assert graph_includes_statement?(g, {EX.S, EX.p(), EX.O}) + end + + test "with an initializer function" do + g = Graph.new(init: fn -> {EX.S, EX.p(), EX.O} end) + assert unnamed_graph?(g) + assert graph_includes_statement?(g, {EX.S, EX.p(), EX.O}) + end end test "clear/1" do