Add :init option to RDF.Graph.new/2 and RDF.Dataset.new/2

This commit is contained in:
Marcel Otto 2020-10-07 16:08:22 +02:00
parent 8325ba9988
commit 71292b721c
5 changed files with 125 additions and 11 deletions

View file

@ -48,10 +48,12 @@ defmodule RDF.Dataset do
## Examples ## Examples
RDF.Dataset.new({EX.S, EX.p, EX.O})
RDF.Dataset.new(name: EX.GraphName) 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 @spec new(input | keyword) :: t
def new(data_or_options) def new(data_or_options)
@ -59,7 +61,8 @@ defmodule RDF.Dataset do
def new(data_or_options) def new(data_or_options)
when is_list(data_or_options) and length(data_or_options) != 0 do when is_list(data_or_options) and length(data_or_options) != 0 do
if Keyword.keyword?(data_or_options) do if Keyword.keyword?(data_or_options) do
new([], data_or_options) {data, options} = Keyword.pop(data_or_options, :init)
new(data, options)
else else
new(data_or_options, []) new(data_or_options, [])
end end
@ -75,6 +78,9 @@ defmodule RDF.Dataset do
Available options: Available options:
- `name`: the name of the dataset to be created - `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 @spec new(input, keyword) :: t
@ -87,9 +93,13 @@ defmodule RDF.Dataset do
def new(data, options) do def new(data, options) do
%__MODULE__{} %__MODULE__{}
|> new(options) |> new(options)
|> add(data) |> init(data)
end 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 """ @doc """
Returns the dataset name IRI of `dataset`. Returns the dataset name IRI of `dataset`.
""" """

View file

@ -35,7 +35,7 @@ defmodule RDF.Diff do
defp coerce_graph(%Description{} = description), defp coerce_graph(%Description{} = description),
do: if(Enum.empty?(description), do: Graph.new(), else: Graph.new(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 """ @doc """
Computes a diff between two `RDF.Graph`s or `RDF.Description`s. Computes a diff between two `RDF.Graph`s or `RDF.Description`s.

View file

@ -56,17 +56,19 @@ defmodule RDF.Graph do
@doc """ @doc """
Creates an `RDF.Graph`. 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. Otherwise an unnamed graph initialized with the given data is created.
See `new/2` for available arguments and the different ways to provide data. See `new/2` for available arguments and the different ways to provide data.
## Examples ## Examples
RDF.Graph.new({EX.S, EX.p, EX.O})
RDF.Graph.new(name: EX.GraphName) 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 @spec new(input | keyword) :: t
def new(data_or_options) def new(data_or_options)
@ -74,7 +76,8 @@ defmodule RDF.Graph do
def new(data_or_options) def new(data_or_options)
when is_list(data_or_options) and length(data_or_options) != 0 do when is_list(data_or_options) and length(data_or_options) != 0 do
if Keyword.keyword?(data_or_options) do if Keyword.keyword?(data_or_options) do
new([], data_or_options) {data, options} = Keyword.pop(data_or_options, :init)
new(data, options)
else else
new(data_or_options, []) new(data_or_options, [])
end end
@ -99,6 +102,9 @@ defmodule RDF.Graph do
and will be used for example when serializing in a format with prefix support 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 - `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 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 ## Examples
@ -121,11 +127,15 @@ defmodule RDF.Graph do
end end
def new(data, options) do def new(data, options) do
%__MODULE__{} new()
|> new(options) |> new(options)
|> add(data) |> init(data)
end 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 """ @doc """
Removes all triples from `graph`. Removes all triples from `graph`.

View file

@ -150,6 +150,53 @@ defmodule RDF.DatasetTest do
{EX.Subject, EX.predicate(), EX.Object, EX.GraphName} {EX.Subject, EX.predicate(), EX.Object, EX.GraphName}
) )
end 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 end
test "name/1" do test "name/1" do

View file

@ -156,6 +156,53 @@ defmodule RDF.GraphTest do
g = Graph.new(Graph.new(prefixes: %{ex: XSD, rdfs: RDFS}), prefixes: prefix_map) g = Graph.new(Graph.new(prefixes: %{ex: XSD, rdfs: RDFS}), prefixes: prefix_map)
assert g.prefixes == PrefixMap.new(ex: EX, rdfs: RDFS) assert g.prefixes == PrefixMap.new(ex: EX, rdfs: RDFS)
end 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 end
test "clear/1" do test "clear/1" do