Limit and unify the forms of input on RDF.Dataset functions

This commit is contained in:
Marcel Otto 2020-09-28 17:39:31 +02:00
parent 2a44765631
commit 8b723286c5
4 changed files with 325 additions and 237 deletions

View file

@ -13,10 +13,13 @@ defmodule RDF.Dataset do
"""
defstruct name: nil, graphs: %{}
@behaviour Access
alias RDF.{Description, Graph, IRI, Statement}
import RDF.Statement
import RDF.Utils
@type graph_name :: IRI.t() | nil
@ -29,8 +32,6 @@ defmodule RDF.Dataset do
@type update_graph_fun :: (Graph.t() -> {Graph.t(), input} | :pop)
defstruct name: nil, graphs: %{}
@doc """
Creates an empty unnamed `RDF.Dataset`.
"""
@ -47,12 +48,12 @@ defmodule RDF.Dataset do
## Examples
RDF.Graph.new({EX.S, EX.p, EX.O})
RDF.Dataset.new({EX.S, EX.p, EX.O})
RDF.Graph.new(name: EX.GraphName)
RDF.Dataset.new(name: EX.GraphName)
"""
@spec new(input | [input] | keyword) :: t
@spec new(input | keyword) :: t
def new(data_or_options)
def new(data_or_options)
@ -69,20 +70,14 @@ defmodule RDF.Dataset do
@doc """
Creates an `RDF.Dataset` initialized with data.
The initial RDF triples can be provided
- as a single statement tuple
- an `RDF.Description`
- an `RDF.Graph`
- an `RDF.Dataset`
- or a list with any combination of the former
The initial RDF triples can be provided in any form accepted by `add/3`.
Available options:
- `name`: the name of the dataset to be created
"""
@spec new(input | [input], keyword) :: t
@spec new(input, keyword) :: t
def new(data, options)
def new(%__MODULE__{} = graph, options) do
@ -95,88 +90,63 @@ defmodule RDF.Dataset do
|> add(data)
end
defp destination_graph(opts, default \\ nil) do
opts
|> Keyword.get(:graph, default)
|> coerce_graph_name()
end
@doc """
Adds triples and quads to a `RDF.Dataset`.
The optional third `graph_context` argument allows to set a different
destination graph to which the statements are added, ignoring the graph context
of given quads or the name of given graphs.
The triples can be provided in any form accepted by `add/2`.
- as a single statement tuple
- an `RDF.Description`
- an `RDF.Graph`
- an `RDF.Dataset`
- or a list with any combination of the former
The `graph` option allows to set a different destination graph to which the
statements should be added, ignoring the graph context of given quads or the
name of given graphs.
"""
@spec add(t, input | [input], boolean | nil) :: t
def add(dataset, statements, graph_context \\ false)
@spec add(t, input, keyword) :: t
def add(dataset, statements, opts \\ [])
def add(dataset, statements, graph_context) when is_list(statements) do
with graph_context = graph_context && coerce_graph_name(graph_context) do
Enum.reduce(statements, dataset, fn statement, dataset ->
add(dataset, statement, graph_context)
end)
end
def add(dataset, {_, _, _, graph} = quad, opts),
do: do_add(dataset, destination_graph(opts, graph), quad)
def add(dataset, %Graph{} = graph, opts),
do: do_add(dataset, destination_graph(opts, graph.name), graph)
def add(%__MODULE__{} = dataset, %__MODULE__{} = other_dataset, opts) do
other_dataset
|> graphs()
|> Enum.reduce(dataset, &add(&2, &1, opts))
end
def add(dataset, {subject, predicate, objects}, false),
do: add(dataset, {subject, predicate, objects, nil})
def add(dataset, {subject, predicate, objects}, graph_context),
do: add(dataset, {subject, predicate, objects, graph_context})
def add(
%__MODULE__{name: name, graphs: graphs},
{subject, predicate, objects, graph_context},
false
) do
with graph_context = coerce_graph_name(graph_context) do
updated_graphs =
Map.update(
graphs,
graph_context,
Graph.new({subject, predicate, objects}, name: graph_context),
fn graph -> Graph.add(graph, {subject, predicate, objects}) end
)
%__MODULE__{name: name, graphs: updated_graphs}
end
def add(dataset, input, opts) when is_list(input) or is_map(input) do
Enum.reduce(input, dataset, &add(&2, &1, opts))
end
def add(%__MODULE__{} = dataset, {subject, predicate, objects, _}, graph_context),
do: add(dataset, {subject, predicate, objects, graph_context}, false)
def add(dataset, input, opts), do: do_add(dataset, destination_graph(opts), input)
def add(%__MODULE__{} = dataset, %Description{} = description, false),
do: add(dataset, description, nil)
def add(%__MODULE__{name: name, graphs: graphs}, %Description{} = description, graph_context) do
with graph_context = coerce_graph_name(graph_context) do
updated_graph =
Map.get(graphs, graph_context, Graph.new(name: graph_context))
|> Graph.add(description)
%__MODULE__{
name: name,
graphs: Map.put(graphs, graph_context, updated_graph)
}
end
end
def add(%__MODULE__{name: name, graphs: graphs}, %Graph{} = graph, false) do
defp do_add(dataset, graph_name, input) do
%__MODULE__{
name: name,
graphs:
Map.update(graphs, graph.name, graph, fn current ->
Graph.add(current, graph)
end)
dataset
| graphs:
lazy_map_update(
dataset.graphs,
graph_name,
# when new:
fn -> Graph.new(input, name: graph_name) end,
# when update:
fn graph -> Graph.add(graph, input) end
)
}
end
def add(%__MODULE__{} = dataset, %Graph{} = graph, graph_context),
do: add(dataset, %Graph{graph | name: coerce_graph_name(graph_context)}, false)
def add(%__MODULE__{} = dataset, %__MODULE__{} = other_dataset, graph_context) do
with graph_context = graph_context && coerce_graph_name(graph_context) do
Enum.reduce(graphs(other_dataset), dataset, fn graph, dataset ->
add(dataset, graph, graph_context)
end)
end
end
@doc """
Adds statements to a `RDF.Dataset` and overwrites all existing statements with the same subjects and predicates in the specified graph context.
@ -191,7 +161,7 @@ defmodule RDF.Dataset do
...> RDF.Dataset.put([{EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}])
RDF.Dataset.new([{EX.S1, EX.P1, EX.O1}, {EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}])
"""
@spec put(t, input | [input], Statement.coercible_graph_name() | boolean | nil) :: t
@spec put(t, input, Statement.coercible_graph_name() | boolean | nil) :: t
def put(dataset, statements, graph_context \\ false)
def put(%__MODULE__{} = dataset, {subject, predicate, objects}, false),
@ -318,71 +288,51 @@ defmodule RDF.Dataset do
@doc """
Deletes statements from a `RDF.Dataset`.
The optional third `graph_context` argument allows to set a different
destination graph from which the statements are deleted, ignoring the graph
context of given quads or the name of given graphs.
The `graph` option allows to set a different destination graph from which the
statements should be deleted, ignoring the graph context of given quads or the
name of given graphs.
Note: When the statements to be deleted are given as another `RDF.Dataset`,
the dataset name must not match dataset name of the dataset from which the statements
are deleted. If you want to delete only datasets with matching names, you can
use `RDF.Data.delete/2`.
"""
@spec delete(t, input | [input], Statement.coercible_graph_name() | boolean | nil) :: t
def delete(dataset, statements, graph_context \\ false)
@spec delete(t, input, keyword) :: t
def delete(dataset, statements, opts \\ [])
def delete(%__MODULE__{} = dataset, statements, graph_context) when is_list(statements) do
with graph_context = graph_context && coerce_graph_name(graph_context) do
Enum.reduce(statements, dataset, fn statement, dataset ->
delete(dataset, statement, graph_context)
end)
end
def delete(dataset, {_, _, _, graph} = quad, opts),
do: do_delete(dataset, destination_graph(opts, graph), quad)
def delete(dataset, %Graph{} = graph, opts),
do: do_delete(dataset, destination_graph(opts, graph.name), graph)
def delete(%__MODULE__{} = dataset, %__MODULE__{} = other_dataset, opts) do
other_dataset
|> graphs()
|> Enum.reduce(dataset, &delete(&2, &1, opts))
end
def delete(%__MODULE__{} = dataset, {_, _, _} = statement, false),
do: do_delete(dataset, nil, statement)
def delete(%__MODULE__{} = dataset, {_, _, _} = statement, graph_context),
do: do_delete(dataset, graph_context, statement)
def delete(%__MODULE__{} = dataset, {subject, predicate, objects, graph_context}, false),
do: do_delete(dataset, graph_context, {subject, predicate, objects})
def delete(%__MODULE__{} = dataset, {subject, predicate, objects, _}, graph_context),
do: do_delete(dataset, graph_context, {subject, predicate, objects})
def delete(%__MODULE__{} = dataset, %Description{} = description, false),
do: do_delete(dataset, nil, description)
def delete(%__MODULE__{} = dataset, %Description{} = description, graph_context),
do: do_delete(dataset, graph_context, description)
def delete(%__MODULE__{} = dataset, %RDF.Graph{name: name} = graph, false),
do: do_delete(dataset, name, graph)
def delete(%__MODULE__{} = dataset, %RDF.Graph{} = graph, graph_context),
do: do_delete(dataset, graph_context, graph)
def delete(%__MODULE__{} = dataset, %__MODULE__{graphs: graphs}, graph_context) do
Enum.reduce(graphs, dataset, fn {_, graph}, dataset ->
delete(dataset, graph, graph_context)
end)
def delete(dataset, input, opts) when is_list(input) or is_map(input) do
Enum.reduce(input, dataset, &delete(&2, &1, opts))
end
defp do_delete(%__MODULE__{name: name, graphs: graphs} = dataset, graph_context, statements) do
with graph_context = coerce_graph_name(graph_context),
graph when not is_nil(graph) <- graphs[graph_context],
new_graph = Graph.delete(graph, statements) do
def delete(dataset, input, opts), do: do_delete(dataset, destination_graph(opts), input)
defp do_delete(dataset, graph_name, input) do
if existing_graph = dataset.graphs[graph_name] do
new_graph = Graph.delete(existing_graph, input)
%__MODULE__{
name: name,
graphs:
if Enum.empty?(new_graph) do
Map.delete(graphs, graph_context)
else
Map.put(graphs, graph_context, new_graph)
end
dataset
| graphs:
if Enum.empty?(new_graph) do
Map.delete(dataset.graphs, graph_name)
else
Map.put(dataset.graphs, graph_name, new_graph)
end
}
else
nil -> dataset
dataset
end
end
@ -695,7 +645,11 @@ defmodule RDF.Dataset do
end
@doc """
Returns if a given statement is in a `RDF.Dataset`.
Checks if the given `input` statements exist within `dataset`.
The `graph` option allows to set a different destination graph in which the
statements should be checked, ignoring the graph context of given quads or the
name of given graphs.
## Examples
@ -706,21 +660,34 @@ defmodule RDF.Dataset do
...> RDF.Dataset.include?(dataset, {EX.S1, EX.p1, EX.O1, EX.Graph})
true
"""
@spec include?(t, Statement.t(), Statement.coercible_graph_name() | nil) :: boolean
def include?(dataset, statement, graph_context \\ nil)
@spec include?(t, input, keyword) :: boolean
def include?(dataset, input, opts \\ [])
def include?(%__MODULE__{graphs: graphs}, triple = {_, _, _}, graph_context) do
with graph_context = coerce_graph_name(graph_context) do
if graph = graphs[graph_context] do
Graph.include?(graph, triple)
else
false
end
end
def include?(dataset, {_, _, _, graph} = quad, opts),
do: do_include?(dataset, destination_graph(opts, graph), quad)
def include?(dataset, %Graph{} = graph, opts),
do: do_include?(dataset, destination_graph(opts, graph.name), graph)
def include?(%__MODULE__{} = dataset, %__MODULE__{} = other_dataset, opts) do
other_dataset
|> graphs()
|> Enum.all?(&include?(dataset, &1, opts))
end
def include?(%__MODULE__{} = dataset, {subject, predicate, object, graph_context}, _),
do: include?(dataset, {subject, predicate, object}, graph_context)
def include?(dataset, input, opts) when is_list(input) or is_map(input) do
Enum.all?(input, &include?(dataset, &1, opts))
end
def include?(dataset, input, opts), do: do_include?(dataset, destination_graph(opts), input)
defp do_include?(%__MODULE__{graphs: graphs}, graph_name, input) do
if graph = graphs[graph_name] do
Graph.include?(graph, input)
else
false
end
end
@doc """
Checks if a graph of a `RDF.Dataset` contains statements about the given resource.

View file

@ -10,14 +10,14 @@ defmodule RDF.Description do
- the `RDF.Data` protocol
"""
@enforce_keys [:subject]
defstruct subject: nil, predications: %{}
@behaviour Access
import RDF.Statement
alias RDF.{Statement, Triple}
@enforce_keys [:subject]
defstruct subject: nil, predications: %{}
@type t :: %__MODULE__{
subject: Statement.subject(),
predications: predications
@ -128,11 +128,8 @@ defmodule RDF.Description do
}
end
def add(description, predications, opts)
when is_map(predications) or is_list(predications) do
Enum.reduce(predications, description, fn
predications, description -> add(description, predications, opts)
end)
def add(description, input, opts) when is_map(input) or is_list(input) do
Enum.reduce(input, description, &add(&2, &1, opts))
end
def add(%__MODULE__{} = description, {subject, predicate, objects}, opts) do
@ -250,11 +247,8 @@ defmodule RDF.Description do
}
end
def delete(description, predications, opts)
when is_map(predications) or is_list(predications) do
Enum.reduce(predications, description, fn
predications, description -> delete(description, predications, opts)
end)
def delete(description, input, opts) when is_map(input) or is_list(input) do
Enum.reduce(input, description, &delete(&2, &1, opts))
end
def delete(%__MODULE__{} = description, {subject, predicate, objects}, opts) do
@ -603,7 +597,7 @@ defmodule RDF.Description do
end
@doc """
Checks if the given statement exists within a `RDF.Description`.
Checks if the given `input` statements exist within `description`.
"""
@spec include?(t, input) :: boolean
def include?(description, input)

View file

@ -11,14 +11,14 @@ defmodule RDF.Graph do
"""
defstruct name: nil, descriptions: %{}, prefixes: nil, base_iri: nil
@behaviour Access
import RDF.Statement
import RDF.Utils
alias RDF.{Description, IRI, PrefixMap, Statement}
defstruct name: nil, descriptions: %{}, prefixes: nil, base_iri: nil
@type graph_description :: %{Statement.subject() => Description.t()}
@type t :: %__MODULE__{
@ -175,15 +175,15 @@ defmodule RDF.Graph do
@spec add(t, input) :: t
def add(graph, input)
def add(graph, {subject, predications}),
do: do_add(graph, coerce_subject(subject), predications)
def add(%__MODULE__{} = graph, {subject, _, _} = triple),
do: do_add(graph, coerce_subject(subject), triple)
def add(graph, {subject, predicate, object, _}),
do: add(graph, {subject, predicate, object})
def add(graph, {subject, predications}),
do: do_add(graph, coerce_subject(subject), predications)
def add(%__MODULE__{} = graph, %Description{subject: subject} = description) do
if Description.count(description) > 0 do
do_add(graph, subject, description)
@ -205,10 +205,8 @@ defmodule RDF.Graph do
end
end
def add(graph, statements) when is_list(statements) or is_map(statements) do
Enum.reduce(statements, graph, fn triple, graph ->
add(graph, triple)
end)
def add(graph, input) when is_list(input) or is_map(input) do
Enum.reduce(input, graph, &add(&2, &1))
end
defp do_add(%__MODULE__{descriptions: descriptions} = graph, subject, statements) do
@ -241,13 +239,13 @@ defmodule RDF.Graph do
"""
@spec put(t, input) :: t
def put(graph, statements)
def put(graph, input)
def put(graph, {subject, predications}),
do: do_put(graph, coerce_subject(subject), predications)
def put(%__MODULE__{} = graph, {subject, _, _} = statement),
do: do_put(graph, coerce_subject(subject), statement)
def put(%__MODULE__{} = graph, {subject, _, _} = triple),
do: do_put(graph, coerce_subject(subject), triple)
def put(graph, {subject, predicate, object, _}),
do: put(graph, {subject, predicate, object})
@ -268,17 +266,17 @@ defmodule RDF.Graph do
end
end
def put(%__MODULE__{} = graph, statements) when is_map(statements) do
Enum.reduce(statements, graph, fn {subject, predications}, graph ->
def put(%__MODULE__{} = graph, input) when is_map(input) do
Enum.reduce(input, graph, fn {subject, predications}, graph ->
put(graph, {subject, predications})
end)
end
def put(%__MODULE__{} = graph, statements) when is_list(statements) do
def put(%__MODULE__{} = graph, input) when is_list(input) do
put(
graph,
Enum.group_by(
statements,
input,
fn
{subject, _} -> subject
{subject, _, _} -> subject
@ -318,7 +316,7 @@ defmodule RDF.Graph do
use `RDF.Data.delete/2`.
"""
@spec delete(t, input | [input]) :: t
@spec delete(t, input) :: t
def delete(graph, triples)
def delete(%__MODULE__{} = graph, {subject, _, _} = triple),
@ -330,10 +328,8 @@ defmodule RDF.Graph do
def delete(graph, {subject, predicate, object, _}),
do: delete(graph, {subject, predicate, object})
def delete(%__MODULE__{} = graph, statements) when is_list(statements) or is_map(statements) do
Enum.reduce(statements, graph, fn statement, graph ->
delete(graph, statement)
end)
def delete(%__MODULE__{} = graph, input) when is_list(input) or is_map(input) do
Enum.reduce(input, graph, &delete(&2, &1))
end
def delete(%__MODULE__{} = graph, %Description{subject: subject} = description),
@ -345,9 +341,9 @@ defmodule RDF.Graph do
end)
end
defp do_delete(%__MODULE__{descriptions: descriptions} = graph, subject, statements) do
defp do_delete(%__MODULE__{descriptions: descriptions} = graph, subject, input) do
if description = descriptions[subject] do
new_description = Description.delete(description, statements)
new_description = Description.delete(description, input)
%__MODULE__{
graph
@ -373,9 +369,7 @@ defmodule RDF.Graph do
def delete_subjects(graph, subjects)
def delete_subjects(%__MODULE__{} = graph, subjects) when is_list(subjects) do
Enum.reduce(subjects, graph, fn subject, graph ->
delete_subjects(graph, subject)
end)
Enum.reduce(subjects, graph, &delete_subjects(&2, &1))
end
def delete_subjects(%__MODULE__{descriptions: descriptions} = graph, subject) do
@ -762,9 +756,11 @@ defmodule RDF.Graph do
defdelegate statements(graph), to: RDF.Graph, as: :triples
@doc """
Checks if the given statement exists within a `RDF.Graph`.
Checks if the given `input` statements exist within `graph`.
"""
@spec include?(t, input) :: boolean
def include?(graph, input)
def include?(%__MODULE__{} = graph, {subject, _, _} = triple),
do: do_include?(graph, coerce_subject(subject), triple)
@ -787,9 +783,9 @@ defmodule RDF.Graph do
Enum.all?(statements, &include?(graph, &1))
end
defp do_include?(%__MODULE__{descriptions: descriptions}, subject, statements) do
defp do_include?(%__MODULE__{descriptions: descriptions}, subject, input) do
if description = descriptions[subject] do
Description.include?(description, statements)
Description.include?(description, input)
else
false
end

View file

@ -152,7 +152,7 @@ defmodule RDF.DatasetTest do
end
end
describe "add" do
describe "add/3" do
test "a proper triple is added to the default graph" do
assert Dataset.add(dataset(), {iri(EX.Subject), EX.predicate(), iri(EX.Object)})
|> dataset_includes_statement?({EX.Subject, EX.predicate(), EX.Object})
@ -190,11 +190,13 @@ defmodule RDF.DatasetTest do
|> dataset_includes_statement?({EX.Subject, EX.predicate(), EX.Object, EX.GraphName})
end
test "a quad and an overwriting graph context " do
assert Dataset.add(dataset(), {EX.Subject, EX.predicate(), EX.Object, EX.Graph}, EX.Other)
test "a quad and an overwriting graph context" do
assert Dataset.add(dataset(), {EX.Subject, EX.predicate(), EX.Object, EX.Graph},
graph: EX.Other
)
|> dataset_includes_statement?({EX.Subject, EX.predicate(), EX.Object, EX.Other})
assert Dataset.add(dataset(), {EX.Subject, EX.predicate(), EX.Object, EX.Graph}, nil)
assert Dataset.add(dataset(), {EX.Subject, EX.predicate(), EX.Object, EX.Graph}, graph: nil)
|> dataset_includes_statement?({EX.Subject, EX.predicate(), EX.Object})
end
@ -220,7 +222,7 @@ defmodule RDF.DatasetTest do
)
end
test "a list of triples without specification of the default context" do
test "a list of triples without an overwriting graph context" do
ds =
Dataset.add(dataset(), [
{EX.Subject1, EX.predicate1(), EX.Object1},
@ -233,7 +235,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject3, EX.predicate3(), EX.Object3})
end
test "a list of triples with specification of the default context" do
test "a list of triples with an overwriting graph context" do
ds =
Dataset.add(
dataset(),
@ -242,7 +244,7 @@ defmodule RDF.DatasetTest do
{EX.Subject1, EX.predicate2(), EX.Object2},
{EX.Subject3, EX.predicate3(), EX.Object3}
],
EX.Graph
graph: EX.Graph
)
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1, EX.Graph})
@ -257,7 +259,7 @@ defmodule RDF.DatasetTest do
{EX.Subject1, EX.predicate2(), EX.Object2},
{EX.Subject3, EX.predicate3(), EX.Object3}
],
nil
graph: nil
)
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1, nil})
@ -265,7 +267,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject3, EX.predicate3(), EX.Object3, nil})
end
test "a list of quads without specification of the default context" do
test "a list of quads without an overwriting graph context" do
ds =
Dataset.add(dataset(), [
{EX.Subject, EX.predicate1(), EX.Object1, EX.Graph1},
@ -278,7 +280,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate1(), EX.Object1, EX.Graph2})
end
test "a list of quads with specification of the default context" do
test "a list of quads with an overwriting graph context" do
ds =
Dataset.add(
dataset(),
@ -287,7 +289,7 @@ defmodule RDF.DatasetTest do
{EX.Subject, EX.predicate2(), EX.Object2, nil},
{EX.Subject, EX.predicate1(), EX.Object1, EX.Graph2}
],
EX.Graph
graph: EX.Graph
)
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate1(), EX.Object1, EX.Graph})
@ -302,7 +304,7 @@ defmodule RDF.DatasetTest do
{EX.Subject, EX.predicate2(), EX.Object2, nil},
{EX.Subject, EX.predicate1(), EX.Object1, EX.Graph2}
],
nil
graph: nil
)
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate1(), EX.Object1, nil})
@ -313,19 +315,77 @@ defmodule RDF.DatasetTest do
test "a list of mixed triples and quads" do
ds =
Dataset.add(dataset(), [
{EX.Subject1, EX.predicate1(), EX.Object1, EX.GraphName},
{EX.Subject3, EX.predicate3(), EX.Object3}
{EX.S1, EX.p1(), EX.O1, EX.Graph},
{EX.S3, EX.p3(), EX.O3}
])
assert dataset_includes_statement?(
ds,
{EX.Subject1, EX.predicate1(), EX.Object1, EX.GraphName}
)
assert dataset_includes_statement?(ds, {EX.S1, EX.p1(), EX.O1, EX.Graph})
assert dataset_includes_statement?(ds, {EX.S3, EX.p3(), EX.O3, nil})
ds =
Dataset.add(
dataset(),
[
{EX.S1, EX.p1(), EX.O1, EX.Graph},
{EX.S3, EX.p3(), EX.O3}
],
graph: EX.Graph2
)
assert dataset_includes_statement?(ds, {EX.S1, EX.p1(), EX.O1, EX.Graph2})
assert dataset_includes_statement?(ds, {EX.S3, EX.p3(), EX.O3, EX.Graph2})
end
test "a map without an overwriting graph context" do
ds =
Dataset.add(dataset(), %{
EX.Subject1 => %{
EX.predicate1() => EX.Object1,
EX.predicate2() => EX.Object2
},
EX.Subject3 => {EX.predicate3(), EX.Object3}
})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object2})
assert dataset_includes_statement?(ds, {EX.Subject3, EX.predicate3(), EX.Object3})
end
test "a map with an overwriting graph context" do
ds =
Dataset.add(
dataset(),
%{
EX.Subject1 => [
{EX.predicate2(), EX.Object2},
{EX.predicate1(), EX.Object1}
],
EX.Subject3 => %{EX.predicate3() => EX.Object3}
},
graph: EX.Graph
)
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1, EX.Graph})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object2, EX.Graph})
assert dataset_includes_statement?(ds, {EX.Subject3, EX.predicate3(), EX.Object3, EX.Graph})
ds =
Dataset.add(
dataset(),
[
{EX.Subject1, EX.predicate1(), EX.Object1},
{EX.Subject1, EX.predicate2(), EX.Object2},
{EX.Subject3, EX.predicate3(), EX.Object3}
],
graph: nil
)
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1, nil})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object2, nil})
assert dataset_includes_statement?(ds, {EX.Subject3, EX.predicate3(), EX.Object3, nil})
end
test "a Description without specification of the default context" do
test "a description without an overwriting graph context" do
ds =
Dataset.add(
dataset(),
@ -340,7 +400,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object2})
end
test "a Description with specification of the default context" do
test "a description with an overwriting graph context" do
ds =
Dataset.add(
dataset(),
@ -350,7 +410,7 @@ defmodule RDF.DatasetTest do
{EX.predicate2(), EX.Object2}
]
),
nil
graph: nil
)
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1})
@ -360,7 +420,7 @@ defmodule RDF.DatasetTest do
Dataset.add(
ds,
Description.new(EX.Subject1, init: {EX.predicate3(), EX.Object3}),
EX.Graph
graph: EX.Graph
)
assert Enum.count(ds) == 3
@ -369,7 +429,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate3(), EX.Object3, EX.Graph})
end
test "an unnamed Graph without specification of the default context" do
test "an unnamed graph without an overwriting graph context" do
ds =
Dataset.add(
dataset(),
@ -391,7 +451,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object3})
end
test "an unnamed Graph with specification of the default context" do
test "an unnamed graph with an overwriting graph context" do
ds =
Dataset.add(
dataset(),
@ -399,21 +459,21 @@ defmodule RDF.DatasetTest do
{EX.Subject1, EX.predicate1(), EX.Object1},
{EX.Subject1, EX.predicate2(), EX.Object2}
]),
nil
graph: nil
)
assert unnamed_graph?(Dataset.default_graph(ds))
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object2})
ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2(), EX.Object3}), nil)
ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2(), EX.Object3}), graph: nil)
assert unnamed_graph?(Dataset.default_graph(ds))
assert Enum.count(ds) == 3
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object2})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object3})
ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2(), EX.Object3}), EX.Graph)
ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2(), EX.Object3}), graph: EX.Graph)
assert unnamed_graph?(Dataset.default_graph(ds))
assert named_graph?(Dataset.graph(ds, EX.Graph), iri(EX.Graph))
assert Enum.count(ds) == 4
@ -423,7 +483,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object3, EX.Graph})
end
test "a named Graph without specification of the default context" do
test "a named graph without an overwriting graph context" do
ds =
Dataset.add(
dataset(),
@ -472,7 +532,7 @@ defmodule RDF.DatasetTest do
)
end
test "a named Graph with specification of the default context" do
test "a named graph with an overwriting graph context" do
ds =
Dataset.add(
dataset(),
@ -483,7 +543,7 @@ defmodule RDF.DatasetTest do
],
name: EX.Graph1
),
nil
graph: nil
)
refute Dataset.graph(ds, EX.Graph1)
@ -495,7 +555,7 @@ defmodule RDF.DatasetTest do
Dataset.add(
ds,
Graph.new({EX.Subject1, EX.predicate2(), EX.Object3}, name: EX.Graph2),
nil
graph: nil
)
refute Dataset.graph(ds, EX.Graph2)
@ -509,7 +569,7 @@ defmodule RDF.DatasetTest do
Dataset.add(
ds,
Graph.new({EX.Subject1, EX.predicate2(), EX.Object3}, name: EX.Graph3),
EX.Graph
graph: EX.Graph
)
assert named_graph?(Dataset.graph(ds, EX.Graph), iri(EX.Graph))
@ -520,7 +580,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object3, EX.Graph})
end
test "an unnamed Dataset" do
test "an unnamed dataset" do
ds =
Dataset.add(
dataset(),
@ -536,7 +596,10 @@ defmodule RDF.DatasetTest do
ds = Dataset.add(ds, Dataset.new({EX.Subject1, EX.predicate2(), EX.Object3}))
ds = Dataset.add(ds, Dataset.new({EX.Subject1, EX.predicate2(), EX.Object3, EX.Graph}))
ds = Dataset.add(ds, Dataset.new({EX.Subject1, EX.predicate2(), EX.Object4}), EX.Graph)
ds =
Dataset.add(ds, Dataset.new({EX.Subject1, EX.predicate2(), EX.Object4}), graph: EX.Graph)
assert ds.name == nil
assert Enum.count(ds) == 5
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1})
@ -546,7 +609,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object4, EX.Graph})
end
test "a named Dataset" do
test "a named dataset" do
ds =
Dataset.add(
named_dataset(),
@ -575,7 +638,7 @@ defmodule RDF.DatasetTest do
Dataset.add(
ds,
Dataset.new({EX.Subject1, EX.predicate2(), EX.Object4}, name: EX.DS2),
EX.Graph
graph: EX.Graph
)
assert ds.name == iri(EX.DatasetName)
@ -587,7 +650,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2(), EX.Object4, EX.Graph})
end
test "a list of Descriptions" do
test "a list of descriptions" do
ds =
Dataset.add(dataset(), [
Description.new(EX.Subject1, init: {EX.predicate1(), EX.Object1}),
@ -607,7 +670,7 @@ defmodule RDF.DatasetTest do
Description.new(EX.Subject2, init: {EX.predicate2(), EX.Object2}),
Description.new(EX.Subject1, init: {EX.predicate3(), EX.Object3})
],
EX.Graph
graph: EX.Graph
)
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1(), EX.Object1, EX.Graph})
@ -618,7 +681,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate3(), EX.Object3})
end
test "a list of Graphs" do
test "a list of graphs" do
ds =
Dataset.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}])
|> RDF.Dataset.add([
@ -653,6 +716,12 @@ defmodule RDF.DatasetTest do
assert_raise RDF.IRI.InvalidError, fn ->
Dataset.add(dataset(), {iri(EX.Subject), EX.predicate(), iri(EX.Object), "not a IRI"})
end
assert_raise RDF.IRI.InvalidError, fn ->
Dataset.add(dataset(), {iri(EX.Subject), EX.predicate(), iri(EX.Object)},
graph: "not a IRI"
)
end
end
end
@ -815,7 +884,7 @@ defmodule RDF.DatasetTest do
{EX.S3, EX.p3(), [~B<foo>, ~L"bar"], EX.Graph2}
])
assert Dataset.delete(dataset3, {EX.S2, EX.p2(), [EX.O1, EX.O2]}, EX.Graph1) ==
assert Dataset.delete(dataset3, {EX.S2, EX.p2(), [EX.O1, EX.O2]}, graph: EX.Graph1) ==
Dataset.new([
{EX.S1, EX.p1(), EX.O1},
{EX.S3, EX.p3(), [~B<foo>, ~L"bar"], EX.Graph2}
@ -837,22 +906,49 @@ defmodule RDF.DatasetTest do
]) == Dataset.new({EX.S3, EX.p3(), ~L"bar", EX.Graph2})
end
test "multiple statements with a Description",
test "multiple statements with a map",
%{dataset1: dataset1, dataset2: dataset2} do
assert Dataset.delete(dataset1, %{EX.S1 => {EX.p1(), EX.O1}}) ==
Dataset.new()
assert Dataset.delete(
dataset1,
%{EX.S1 => {EX.p1(), EX.O1}},
graph: EX.Graph
) ==
dataset1
assert Dataset.delete(
dataset2,
%{EX.S2 => %{EX.p2() => EX.O2}},
graph: EX.Graph
) ==
dataset1
assert Dataset.delete(dataset2, %{EX.S1 => %{EX.p1() => EX.O1}}) ==
Dataset.new({EX.S2, EX.p2(), EX.O2, EX.Graph})
end
test "multiple statements with a description",
%{dataset1: dataset1, dataset2: dataset2} do
assert Dataset.delete(dataset1, Description.new(EX.S1, init: {EX.p1(), EX.O1})) ==
Dataset.new()
assert Dataset.delete(dataset1, Description.new(EX.S1, init: {EX.p1(), EX.O1}), EX.Graph) ==
assert Dataset.delete(dataset1, Description.new(EX.S1, init: {EX.p1(), EX.O1}),
graph: EX.Graph
) ==
dataset1
assert Dataset.delete(dataset2, Description.new(EX.S2, init: {EX.p2(), EX.O2}), EX.Graph) ==
assert Dataset.delete(dataset2, Description.new(EX.S2, init: {EX.p2(), EX.O2}),
graph: EX.Graph
) ==
dataset1
assert Dataset.delete(dataset2, Description.new(EX.S1, init: {EX.p1(), EX.O1})) ==
Dataset.new({EX.S2, EX.p2(), EX.O2, EX.Graph})
end
test "multiple statements with a Graph",
test "multiple statements with a graph",
%{dataset1: dataset1, dataset2: dataset2, dataset3: dataset3} do
assert Dataset.delete(dataset1, Graph.new({EX.S1, EX.p1(), EX.O1})) == Dataset.new()
@ -865,8 +961,11 @@ defmodule RDF.DatasetTest do
assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2(), EX.O2}, name: EX.Graph)) ==
dataset1
assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2(), EX.O2}), EX.Graph) == dataset1
assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2(), EX.O2}), EX.Graph) == dataset1
assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2(), EX.O2}), graph: EX.Graph) ==
dataset1
assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2(), EX.O2}), graph: EX.Graph) ==
dataset1
assert Dataset.delete(
dataset3,
@ -898,7 +997,7 @@ defmodule RDF.DatasetTest do
{EX.S3, EX.p3(), [~L"bar"], EX.Graph2}
])
assert Dataset.delete(dataset3, Graph.new({EX.S3, EX.p3(), ~B<foo>}), EX.Graph2) ==
assert Dataset.delete(dataset3, Graph.new({EX.S3, EX.p3(), ~B<foo>}), graph: EX.Graph2) ==
Dataset.new([
{EX.S1, EX.p1(), EX.O1},
{EX.S2, EX.p2(), [EX.O1, EX.O2], EX.Graph1},
@ -906,7 +1005,7 @@ defmodule RDF.DatasetTest do
])
end
test "multiple statements with a Dataset",
test "multiple statements with a dataset",
%{dataset1: dataset1, dataset2: dataset2} do
assert Dataset.delete(dataset1, dataset1) == Dataset.new()
assert Dataset.delete(dataset1, dataset2) == Dataset.new()
@ -978,6 +1077,38 @@ defmodule RDF.DatasetTest do
assert Enum.count(dataset.graphs) == 1
end
test "include?/3" do
dataset =
Dataset.new([
{EX.S1, EX.p(), EX.O1},
{EX.S2, EX.p(), EX.O2, EX.Graph}
])
assert Dataset.include?(dataset, {EX.S1, EX.p(), EX.O1})
refute Dataset.include?(dataset, {EX.S2, EX.p(), EX.O2})
assert Dataset.include?(dataset, {EX.S2, EX.p(), EX.O2, EX.Graph})
assert Dataset.include?(dataset, {EX.S2, EX.p(), EX.O2}, graph: EX.Graph)
assert Dataset.include?(dataset, [{EX.S1, EX.p(), EX.O1}])
assert Dataset.include?(dataset, [{EX.S2, EX.p(), EX.O2}], graph: EX.Graph)
assert Dataset.include?(dataset, [
{EX.S1, EX.p(), EX.O1},
{EX.S2, EX.p(), EX.O2, EX.Graph}
])
refute Dataset.include?(dataset, [
{EX.S1, EX.p(), EX.O1},
{EX.S2, EX.p(), EX.O2}
])
assert Dataset.include?(dataset, EX.S1 |> EX.p(EX.O1))
refute Dataset.include?(dataset, EX.S2 |> EX.p(EX.O2))
assert Dataset.include?(dataset, EX.p(EX.S2, EX.O2), graph: EX.Graph)
assert Dataset.include?(dataset, Graph.new(EX.S1 |> EX.p(EX.O1)))
assert Dataset.include?(dataset, dataset)
end
test "values/1" do
assert Dataset.new() |> Dataset.values() == %{}