Limit and unify the forms of input on RDF.Graph functions
This commit is contained in:
parent
20a69964c7
commit
a8c71df20b
6 changed files with 250 additions and 195 deletions
|
@ -237,8 +237,6 @@ defmodule RDF do
|
|||
defdelegate graph(), to: Graph, as: :new
|
||||
defdelegate graph(arg), to: Graph, as: :new
|
||||
defdelegate graph(arg1, arg2), to: Graph, as: :new
|
||||
defdelegate graph(arg1, arg2, arg3), to: Graph, as: :new
|
||||
defdelegate graph(arg1, arg2, arg3, arg4), to: Graph, as: :new
|
||||
|
||||
defdelegate dataset(), to: Dataset, as: :new
|
||||
defdelegate dataset(arg), to: Dataset, as: :new
|
||||
|
|
|
@ -309,7 +309,7 @@ defmodule RDF.Dataset do
|
|||
|
||||
new_graphs =
|
||||
graphs
|
||||
|> Map.put(graph_context, Graph.put(graph, subject, predications))
|
||||
|> Map.put(graph_context, Graph.put(graph, {subject, predications}))
|
||||
|
||||
%__MODULE__{name: name, graphs: new_graphs}
|
||||
end
|
||||
|
|
252
lib/rdf/graph.ex
252
lib/rdf/graph.ex
|
@ -14,6 +14,7 @@ defmodule RDF.Graph do
|
|||
@behaviour Access
|
||||
|
||||
import RDF.Statement
|
||||
import RDF.Utils
|
||||
alias RDF.{Description, IRI, PrefixMap, Statement}
|
||||
|
||||
@type graph_description :: %{Statement.subject() => Description.t()}
|
||||
|
@ -25,8 +26,21 @@ defmodule RDF.Graph do
|
|||
base_iri: IRI.t() | nil
|
||||
}
|
||||
|
||||
@type input :: Statement.t() | Description.t() | t
|
||||
|
||||
@type input ::
|
||||
Statement.coercible_t()
|
||||
| {
|
||||
Statement.coercible_subject(),
|
||||
Description.input()
|
||||
}
|
||||
| Description.t()
|
||||
| t
|
||||
| %{
|
||||
Statement.coercible_subject() => %{
|
||||
Statement.coercible_predicate() =>
|
||||
Statement.coercible_object() | [Statement.coercible_object()]
|
||||
}
|
||||
}
|
||||
| list(input)
|
||||
@type update_description_fun :: (Description.t() -> Description.t())
|
||||
|
||||
@type get_and_update_description_fun :: (Description.t() -> {Description.t(), input} | :pop)
|
||||
|
@ -54,7 +68,7 @@ defmodule RDF.Graph do
|
|||
RDF.Graph.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)
|
||||
|
@ -74,8 +88,8 @@ defmodule RDF.Graph do
|
|||
The initial RDF triples can be provided
|
||||
|
||||
- as a single statement tuple
|
||||
- an `RDF.Description`
|
||||
- an `RDF.Graph`
|
||||
- a `RDF.Description`
|
||||
- a `RDF.Graph`
|
||||
- or a list with any combination of the former
|
||||
|
||||
Available options:
|
||||
|
@ -97,7 +111,7 @@ defmodule RDF.Graph do
|
|||
RDF.Graph.new({EX.S, EX.p, EX.O}, name: EX.GraphName, base_iri: EX.base)
|
||||
|
||||
"""
|
||||
@spec new(input | [input], keyword) :: t
|
||||
@spec new(input, keyword) :: t
|
||||
def new(data, options)
|
||||
|
||||
def new(%__MODULE__{} = graph, options) do
|
||||
|
@ -112,26 +126,12 @@ defmodule RDF.Graph do
|
|||
|> add(data)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates an `RDF.Graph` with initial triples.
|
||||
|
||||
See `new/2` for available arguments.
|
||||
"""
|
||||
@spec new(
|
||||
Statement.coercible_subject(),
|
||||
Statement.coercible_predicate(),
|
||||
Statement.coercible_object() | [Statement.coercible_object()],
|
||||
keyword
|
||||
) :: t
|
||||
def new(subject, predicate, objects, options \\ []),
|
||||
do: new([], options) |> add(subject, predicate, objects)
|
||||
|
||||
@doc """
|
||||
Removes all triples from `graph`.
|
||||
|
||||
This function is useful for getting an empty graph based on the settings of
|
||||
another graph, as this function keeps graph name name, base IRI and default
|
||||
prefixes as they are and just removes the triples.
|
||||
another graph, as this function keeps graph name, base IRI and default prefixes
|
||||
as they are and just removes the triples.
|
||||
"""
|
||||
@spec clear(t) :: t
|
||||
def clear(%__MODULE__{} = graph) do
|
||||
|
@ -140,42 +140,35 @@ defmodule RDF.Graph do
|
|||
|
||||
@doc """
|
||||
Adds triples to a `RDF.Graph`.
|
||||
"""
|
||||
@spec add(
|
||||
t,
|
||||
Statement.coercible_subject(),
|
||||
Statement.coercible_predicate(),
|
||||
Statement.coercible_object() | [Statement.coercible_object()]
|
||||
) :: t
|
||||
def add(%__MODULE__{} = graph, subject, predicate, objects),
|
||||
do: add(graph, {subject, predicate, objects})
|
||||
|
||||
@doc """
|
||||
Adds triples to a `RDF.Graph`.
|
||||
The `input` can be provided
|
||||
|
||||
- as a single statement tuple
|
||||
- a `RDF.Description`
|
||||
- a `RDF.Graph`
|
||||
- or a list with any combination of the former
|
||||
|
||||
|
||||
When the statements to be added are given as another `RDF.Graph`,
|
||||
the graph name must not match graph name of the graph to which the statements
|
||||
are added. As opposed to that `RDF.Data.merge/2` will produce a `RDF.Dataset`
|
||||
are added. As opposed to that, `RDF.Data.merge/2` will produce a `RDF.Dataset`
|
||||
containing both graphs.
|
||||
|
||||
Also when the statements to be added are given as another `RDF.Graph`, the
|
||||
prefixes of this graph will be added. In case of conflicting prefix mappings
|
||||
the original prefix from `graph` will be kept.
|
||||
"""
|
||||
@spec add(t, input | [input]) :: t
|
||||
def add(graph, triples)
|
||||
@spec add(t, input) :: t
|
||||
def add(graph, input)
|
||||
|
||||
def add(%__MODULE__{} = graph, {subject, _, _} = statement),
|
||||
do: do_add(graph, coerce_subject(subject), statement)
|
||||
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, triples) when is_list(triples) do
|
||||
Enum.reduce(triples, graph, fn triple, graph ->
|
||||
add(graph, triple)
|
||||
end)
|
||||
end
|
||||
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
|
||||
|
@ -198,17 +191,23 @@ 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)
|
||||
end
|
||||
|
||||
defp do_add(%__MODULE__{descriptions: descriptions} = graph, subject, statements) do
|
||||
%__MODULE__{
|
||||
graph
|
||||
| descriptions:
|
||||
Map.update(
|
||||
lazy_map_update(
|
||||
descriptions,
|
||||
subject,
|
||||
Description.new(subject) |> Description.add(statements),
|
||||
fn description ->
|
||||
Description.add(description, statements)
|
||||
end
|
||||
# when new: create and initialize description with statements
|
||||
fn -> Description.new(subject, init: statements) end,
|
||||
# when update: merge statements description
|
||||
fn description -> Description.add(description, statements) end
|
||||
)
|
||||
}
|
||||
end
|
||||
|
@ -222,14 +221,17 @@ defmodule RDF.Graph do
|
|||
|
||||
## Examples
|
||||
|
||||
iex> RDF.Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}]) |>
|
||||
...> RDF.Graph.put([{EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}])
|
||||
iex> RDF.Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}])
|
||||
...> |> RDF.Graph.put([{EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}])
|
||||
RDF.Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}])
|
||||
|
||||
"""
|
||||
@spec put(t, input | [input]) :: t
|
||||
@spec put(t, input) :: t
|
||||
def put(graph, statements)
|
||||
|
||||
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)
|
||||
|
||||
|
@ -254,92 +256,34 @@ defmodule RDF.Graph do
|
|||
|
||||
def put(%__MODULE__{} = graph, statements) when is_map(statements) do
|
||||
Enum.reduce(statements, graph, fn {subject, predications}, graph ->
|
||||
put(graph, subject, predications)
|
||||
put(graph, {subject, predications})
|
||||
end)
|
||||
end
|
||||
|
||||
def put(%__MODULE__{} = graph, statements) when is_list(statements) do
|
||||
put(graph, Enum.group_by(statements, &elem(&1, 0), fn {_, p, o} -> {p, o} end))
|
||||
put(
|
||||
graph,
|
||||
Enum.group_by(statements, &elem(&1, 0), fn
|
||||
{_, p, o} -> {p, o}
|
||||
{_, predications} -> predications
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Add statements to a `RDF.Graph`, overwriting all statements with the same subject and predicate.
|
||||
"""
|
||||
@spec put(
|
||||
t,
|
||||
Statement.coercible_subject(),
|
||||
Description.statements() | [Description.statements()]
|
||||
) :: t
|
||||
def put(graph, subject, predications)
|
||||
|
||||
def put(%__MODULE__{descriptions: descriptions} = graph, subject, predications)
|
||||
when is_list(predications) do
|
||||
with subject = coerce_subject(subject) do
|
||||
# TODO: Can we reduce this case also to do_put somehow? Only the initializer of Map.update differs ...
|
||||
defp do_put(%__MODULE__{descriptions: descriptions} = graph, subject, predications) do
|
||||
%__MODULE__{
|
||||
graph
|
||||
| descriptions:
|
||||
Map.update(
|
||||
lazy_map_update(
|
||||
descriptions,
|
||||
subject,
|
||||
Description.new(subject) |> Description.add(predications),
|
||||
fn current ->
|
||||
Description.put(current, predications)
|
||||
end
|
||||
# when new
|
||||
fn -> Description.new(subject, init: predications) end,
|
||||
# when updating
|
||||
fn current -> Description.put(current, predications) end
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def put(graph, subject, {_predicate, _objects} = predications),
|
||||
do: put(graph, subject, [predications])
|
||||
|
||||
defp do_put(%__MODULE__{descriptions: descriptions} = graph, subject, statements) do
|
||||
%__MODULE__{
|
||||
graph
|
||||
| descriptions:
|
||||
Map.update(
|
||||
descriptions,
|
||||
subject,
|
||||
Description.new(subject) |> Description.add(statements),
|
||||
fn current ->
|
||||
Description.put(current, statements)
|
||||
end
|
||||
)
|
||||
}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Add statements to a `RDF.Graph`, overwriting all statements with the same subject and predicate.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> RDF.Graph.new(EX.S, EX.P, EX.O1) |> RDF.Graph.put(EX.S, EX.P, EX.O2)
|
||||
RDF.Graph.new(EX.S, EX.P, EX.O2)
|
||||
iex> RDF.Graph.new(EX.S, EX.P1, EX.O1) |> RDF.Graph.put(EX.S, EX.P2, EX.O2)
|
||||
RDF.Graph.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}])
|
||||
|
||||
"""
|
||||
@spec put(
|
||||
t,
|
||||
Statement.coercible_subject(),
|
||||
Statement.coercible_predicate(),
|
||||
Statement.coercible_object() | [Statement.coercible_object()]
|
||||
) :: t
|
||||
def put(%__MODULE__{} = graph, subject, predicate, objects),
|
||||
do: put(graph, {subject, predicate, objects})
|
||||
|
||||
@doc """
|
||||
Deletes statements from a `RDF.Graph`.
|
||||
"""
|
||||
@spec delete(
|
||||
t,
|
||||
Statement.coercible_subject(),
|
||||
Statement.coercible_predicate(),
|
||||
Statement.coercible_object() | [Statement.coercible_object()]
|
||||
) :: t
|
||||
def delete(graph, subject, predicate, object),
|
||||
do: delete(graph, {subject, predicate, object})
|
||||
|
||||
@doc """
|
||||
Deletes statements from a `RDF.Graph`.
|
||||
|
@ -356,12 +300,15 @@ defmodule RDF.Graph do
|
|||
def delete(%__MODULE__{} = graph, {subject, _, _} = triple),
|
||||
do: do_delete(graph, coerce_subject(subject), triple)
|
||||
|
||||
def delete(graph, {subject, predications}),
|
||||
do: do_delete(graph, coerce_subject(subject), predications)
|
||||
|
||||
def delete(graph, {subject, predicate, object, _}),
|
||||
do: delete(graph, {subject, predicate, object})
|
||||
|
||||
def delete(%__MODULE__{} = graph, triples) when is_list(triples) do
|
||||
Enum.reduce(triples, graph, fn triple, graph ->
|
||||
delete(graph, triple)
|
||||
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)
|
||||
end
|
||||
|
||||
|
@ -375,8 +322,9 @@ defmodule RDF.Graph do
|
|||
end
|
||||
|
||||
defp do_delete(%__MODULE__{descriptions: descriptions} = graph, subject, statements) do
|
||||
with description when not is_nil(description) <- descriptions[subject],
|
||||
new_description = Description.delete(description, statements) do
|
||||
if description = descriptions[subject] do
|
||||
new_description = Description.delete(description, statements)
|
||||
|
||||
%__MODULE__{
|
||||
graph
|
||||
| descriptions:
|
||||
|
@ -387,7 +335,7 @@ defmodule RDF.Graph do
|
|||
end
|
||||
}
|
||||
else
|
||||
nil -> graph
|
||||
graph
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -448,7 +396,7 @@ defmodule RDF.Graph do
|
|||
@spec update(
|
||||
t,
|
||||
Statement.coercible_subject(),
|
||||
Description.statements() | [Description.statements()] | nil,
|
||||
Description.input() | nil,
|
||||
update_description_fun
|
||||
) :: t
|
||||
def update(graph = %__MODULE__{}, subject, initial \\ nil, fun) do
|
||||
|
@ -575,11 +523,11 @@ defmodule RDF.Graph do
|
|||
|
||||
## Examples
|
||||
|
||||
iex> RDF.Graph.new({EX.S, EX.P, EX.O}) |>
|
||||
...> RDF.Graph.get_and_update(EX.S, fn current_description ->
|
||||
iex> RDF.Graph.new({EX.S, EX.P, EX.O})
|
||||
...> |> RDF.Graph.get_and_update(EX.S, fn current_description ->
|
||||
...> {current_description, {EX.P, EX.NEW}}
|
||||
...> end)
|
||||
{RDF.Description.new({EX.S, EX.P, EX.O}), RDF.Graph.new({EX.S, EX.P, EX.NEW})}
|
||||
{RDF.Description.new(EX.S, init: {EX.P, EX.O}), RDF.Graph.new({EX.S, EX.P, EX.NEW})}
|
||||
|
||||
"""
|
||||
@impl Access
|
||||
|
@ -589,7 +537,7 @@ defmodule RDF.Graph do
|
|||
with subject = coerce_subject(subject) do
|
||||
case fun.(get(graph, subject)) do
|
||||
{old_description, new_description} ->
|
||||
{old_description, put(graph, subject, new_description)}
|
||||
{old_description, put(graph, {subject, new_description})}
|
||||
|
||||
:pop ->
|
||||
pop(graph, subject)
|
||||
|
@ -792,16 +740,34 @@ defmodule RDF.Graph do
|
|||
@doc """
|
||||
Checks if the given statement exists within a `RDF.Graph`.
|
||||
"""
|
||||
@spec include?(t, Statement.t()) :: boolean
|
||||
def include?(
|
||||
%__MODULE__{descriptions: descriptions},
|
||||
triple = {subject, _, _}
|
||||
) do
|
||||
with subject = coerce_subject(subject),
|
||||
%Description{} <- description = descriptions[subject] do
|
||||
Description.include?(description, triple)
|
||||
@spec include?(t, input) :: boolean
|
||||
def include?(%__MODULE__{} = graph, {subject, _, _} = triple),
|
||||
do: do_include?(graph, coerce_subject(subject), triple)
|
||||
|
||||
def include?(graph, {subject, predicate, object, _}),
|
||||
do: include?(graph, {subject, predicate, object})
|
||||
|
||||
def include?(graph, {subject, predications}),
|
||||
do: do_include?(graph, coerce_subject(subject), predications)
|
||||
|
||||
def include?(%__MODULE__{} = graph, %Description{subject: subject} = description),
|
||||
do: do_include?(graph, subject, description)
|
||||
|
||||
def include?(graph, %__MODULE__{} = other_graph) do
|
||||
other_graph
|
||||
|> descriptions()
|
||||
|> Enum.all?(&include?(graph, &1))
|
||||
end
|
||||
|
||||
def include?(graph, statements) when is_list(statements) or is_map(statements) do
|
||||
Enum.all?(statements, &include?(graph, &1))
|
||||
end
|
||||
|
||||
defp do_include?(%__MODULE__{descriptions: descriptions}, subject, statements) do
|
||||
if description = descriptions[subject] do
|
||||
Description.include?(description, statements)
|
||||
else
|
||||
_ -> false
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ defmodule RDF.Statement do
|
|||
@type term_mapping :: (qualified_term -> any | nil)
|
||||
|
||||
@type t :: Triple.t() | Quad.t()
|
||||
@type coercible_t :: Triple.coercible_t() | Quad.coercible_t()
|
||||
|
||||
@doc """
|
||||
Creates a `RDF.Statement` tuple with proper RDF values.
|
||||
|
|
16
lib/rdf/utils/utils.ex
Normal file
16
lib/rdf/utils/utils.ex
Normal file
|
@ -0,0 +1,16 @@
|
|||
defmodule RDF.Utils do
|
||||
@moduledoc false
|
||||
|
||||
def lazy_map_update(map, key, init_fun, fun) do
|
||||
case map do
|
||||
%{^key => value} ->
|
||||
Map.put(map, key, fun.(value))
|
||||
|
||||
%{} ->
|
||||
Map.put(map, key, init_fun.())
|
||||
|
||||
other ->
|
||||
:erlang.error({:badmap, other}, [map, key, init_fun, fun])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -32,20 +32,12 @@ defmodule RDF.GraphTest do
|
|||
g = Graph.new({EX.Subject, EX.predicate(), EX.Object})
|
||||
assert unnamed_graph?(g)
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object})
|
||||
|
||||
g = Graph.new(EX.Subject, EX.predicate(), EX.Object)
|
||||
assert unnamed_graph?(g)
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object})
|
||||
end
|
||||
|
||||
test "creating a named graph with an initial triple" do
|
||||
g = Graph.new({EX.Subject, EX.predicate(), EX.Object}, name: EX.GraphName)
|
||||
assert named_graph?(g, iri(EX.GraphName))
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object})
|
||||
|
||||
g = Graph.new(EX.Subject, EX.predicate(), EX.Object, name: EX.GraphName)
|
||||
assert named_graph?(g, iri(EX.GraphName))
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object})
|
||||
end
|
||||
|
||||
test "creating an unnamed graph with a list of initial triples" do
|
||||
|
@ -59,7 +51,7 @@ defmodule RDF.GraphTest do
|
|||
assert graph_includes_statement?(g, {EX.Subject1, EX.predicate1(), EX.Object1})
|
||||
assert graph_includes_statement?(g, {EX.Subject2, EX.predicate2(), EX.Object2})
|
||||
|
||||
g = Graph.new(EX.Subject, EX.predicate(), [EX.Object1, EX.Object2])
|
||||
g = Graph.new({EX.Subject, EX.predicate(), [EX.Object1, EX.Object2]})
|
||||
assert unnamed_graph?(g)
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object1})
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object2})
|
||||
|
@ -76,7 +68,7 @@ defmodule RDF.GraphTest do
|
|||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate1(), EX.Object1})
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate2(), EX.Object2})
|
||||
|
||||
g = Graph.new(EX.Subject, EX.predicate(), [EX.Object1, EX.Object2], name: EX.GraphName)
|
||||
g = Graph.new({EX.Subject, EX.predicate(), [EX.Object1, EX.Object2]}, name: EX.GraphName)
|
||||
assert named_graph?(g, iri(EX.GraphName))
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object1})
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object2})
|
||||
|
@ -107,17 +99,15 @@ defmodule RDF.GraphTest do
|
|||
|
||||
test "creating a named graph from another graph" do
|
||||
g =
|
||||
Graph.new(Graph.new({EX.Subject, EX.predicate(), EX.Object}),
|
||||
name: EX.GraphName
|
||||
)
|
||||
Graph.new({EX.Subject, EX.predicate(), EX.Object})
|
||||
|> Graph.new(name: EX.GraphName)
|
||||
|
||||
assert named_graph?(g, iri(EX.GraphName))
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object})
|
||||
|
||||
g =
|
||||
Graph.new(Graph.new({EX.Subject, EX.predicate(), EX.Object}, name: EX.OtherGraphName),
|
||||
name: EX.GraphName
|
||||
)
|
||||
Graph.new({EX.Subject, EX.predicate(), EX.Object}, name: EX.OtherGraphName)
|
||||
|> Graph.new(name: EX.GraphName)
|
||||
|
||||
assert named_graph?(g, iri(EX.GraphName))
|
||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object})
|
||||
|
@ -175,19 +165,13 @@ defmodule RDF.GraphTest do
|
|||
|> Graph.clear() == Graph.new(opts)
|
||||
end
|
||||
|
||||
describe "add" do
|
||||
describe "add/2" do
|
||||
test "a proper triple" do
|
||||
assert Graph.add(graph(), iri(EX.Subject), EX.predicate(), iri(EX.Object))
|
||||
|> graph_includes_statement?({EX.Subject, EX.predicate(), EX.Object})
|
||||
|
||||
assert Graph.add(graph(), {iri(EX.Subject), EX.predicate(), iri(EX.Object)})
|
||||
|> graph_includes_statement?({EX.Subject, EX.predicate(), EX.Object})
|
||||
end
|
||||
|
||||
test "a coercible triple" do
|
||||
assert Graph.add(graph(), "http://example.com/Subject", EX.predicate(), EX.Object)
|
||||
|> graph_includes_statement?({EX.Subject, EX.predicate(), EX.Object})
|
||||
|
||||
test "a coerced triple" do
|
||||
assert Graph.add(
|
||||
graph(),
|
||||
{"http://example.com/Subject", EX.predicate(), EX.Object}
|
||||
|
@ -196,7 +180,7 @@ defmodule RDF.GraphTest do
|
|||
end
|
||||
|
||||
test "a triple with multiple objects" do
|
||||
g = Graph.add(graph(), EX.Subject1, EX.predicate1(), [EX.Object1, EX.Object2])
|
||||
g = Graph.add(graph(), {EX.Subject1, EX.predicate1(), [EX.Object1, EX.Object2]})
|
||||
assert graph_includes_statement?(g, {EX.Subject1, EX.predicate1(), EX.Object1})
|
||||
assert graph_includes_statement?(g, {EX.Subject1, EX.predicate1(), EX.Object2})
|
||||
end
|
||||
|
@ -214,7 +198,23 @@ defmodule RDF.GraphTest do
|
|||
assert graph_includes_statement?(g, {EX.Subject3, EX.predicate3(), EX.Object3})
|
||||
end
|
||||
|
||||
test "a Description" do
|
||||
test "a graph map" do
|
||||
g =
|
||||
Graph.add(graph(), %{
|
||||
EX.Subject1 => [{EX.predicate1(), EX.Object1}, {EX.predicate2(), [EX.Object2]}],
|
||||
EX.Subject3 => %{EX.predicate3() => EX.Object3}
|
||||
})
|
||||
|
||||
assert graph_includes_statement?(g, {EX.Subject1, EX.predicate1(), EX.Object1})
|
||||
assert graph_includes_statement?(g, {EX.Subject1, EX.predicate2(), EX.Object2})
|
||||
assert graph_includes_statement?(g, {EX.Subject3, EX.predicate3(), EX.Object3})
|
||||
end
|
||||
|
||||
test "an empty map" do
|
||||
assert Graph.add(graph(), %{}) == graph()
|
||||
end
|
||||
|
||||
test "a description" do
|
||||
g =
|
||||
Graph.add(
|
||||
graph(),
|
||||
|
@ -235,7 +235,7 @@ defmodule RDF.GraphTest do
|
|||
assert graph_includes_statement?(g, {EX.Subject1, EX.predicate3(), EX.Object3})
|
||||
end
|
||||
|
||||
test "a list of Descriptions" do
|
||||
test "a list of descriptions" do
|
||||
g =
|
||||
Graph.add(graph(), [
|
||||
Description.new(EX.Subject1, init: {EX.predicate1(), EX.Object1}),
|
||||
|
@ -253,7 +253,7 @@ defmodule RDF.GraphTest do
|
|||
assert Graph.add(g, {EX.Subject, EX.predicate(), EX.Object}) == g
|
||||
end
|
||||
|
||||
test "a Graph" do
|
||||
test "a graph" do
|
||||
g =
|
||||
Graph.add(
|
||||
graph(),
|
||||
|
@ -311,7 +311,7 @@ defmodule RDF.GraphTest do
|
|||
test "preserves the name and prefixes when the data provided is not a graph" do
|
||||
graph =
|
||||
Graph.new(name: EX.GraphName, prefixes: %{ex: EX})
|
||||
|> Graph.add(EX.Subject, EX.predicate(), EX.Object)
|
||||
|> Graph.add({EX.Subject, EX.predicate(), EX.Object})
|
||||
|
||||
assert graph.name == RDF.iri(EX.GraphName)
|
||||
assert graph.prefixes == PrefixMap.new(ex: EX)
|
||||
|
@ -328,7 +328,7 @@ defmodule RDF.GraphTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "put" do
|
||||
describe "put/2" do
|
||||
test "a list of triples" do
|
||||
g =
|
||||
Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}])
|
||||
|
@ -347,7 +347,38 @@ defmodule RDF.GraphTest do
|
|||
assert graph_includes_statement?(g, {EX.S2, EX.P2, EX.O4})
|
||||
end
|
||||
|
||||
test "a Description" do
|
||||
test "a list subject-predications pairs" do
|
||||
g =
|
||||
Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}])
|
||||
|> RDF.Graph.put([
|
||||
{EX.S1,
|
||||
[
|
||||
{EX.P1, EX.O3},
|
||||
%{EX.P2 => [EX.O4]}
|
||||
]}
|
||||
])
|
||||
|
||||
assert Graph.triple_count(g) == 3
|
||||
assert graph_includes_statement?(g, {EX.S1, EX.P1, EX.O3})
|
||||
assert graph_includes_statement?(g, {EX.S1, EX.P2, EX.O4})
|
||||
assert graph_includes_statement?(g, {EX.S2, EX.P2, EX.O2})
|
||||
end
|
||||
|
||||
test "a map" do
|
||||
g =
|
||||
Graph.new([{EX.S1, EX.p1(), EX.O1}, {EX.S2, EX.p2(), EX.O2}])
|
||||
|> Graph.put(%{
|
||||
EX.S1 => [{EX.p1(), EX.O2}],
|
||||
EX.S2 => %{EX.p1() => EX.O2},
|
||||
EX.S3 => %{EX.p3() => EX.O3}
|
||||
})
|
||||
|
||||
assert graph_includes_statement?(g, {EX.S1, EX.p1(), EX.O2})
|
||||
assert graph_includes_statement?(g, {EX.S2, EX.p1(), EX.O2})
|
||||
assert graph_includes_statement?(g, {EX.S3, EX.p3(), EX.O3})
|
||||
end
|
||||
|
||||
test "a description" do
|
||||
g =
|
||||
Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}, {EX.S1, EX.P3, EX.O3}])
|
||||
|> RDF.Graph.put(
|
||||
|
@ -362,7 +393,7 @@ defmodule RDF.GraphTest do
|
|||
assert graph_includes_statement?(g, {EX.S2, EX.P2, EX.O2})
|
||||
end
|
||||
|
||||
test "a Graph" do
|
||||
test "a graph" do
|
||||
g =
|
||||
Graph.new([
|
||||
{EX.S1, EX.P1, EX.O1},
|
||||
|
@ -403,7 +434,7 @@ defmodule RDF.GraphTest do
|
|||
test "preserves the name, base_iri and prefixes" do
|
||||
graph =
|
||||
Graph.new(name: EX.GraphName, prefixes: %{ex: EX}, base_iri: EX.base())
|
||||
|> Graph.put(EX.Subject, EX.predicate(), EX.Object)
|
||||
|> Graph.put({EX.Subject, EX.predicate(), EX.Object})
|
||||
|
||||
assert graph.name == RDF.iri(EX.GraphName)
|
||||
assert graph.prefixes == PrefixMap.new(ex: EX)
|
||||
|
@ -411,7 +442,7 @@ defmodule RDF.GraphTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "delete" do
|
||||
describe "delete/2" do
|
||||
setup do
|
||||
{:ok,
|
||||
graph1: Graph.new({EX.S, EX.p(), EX.O}),
|
||||
|
@ -424,7 +455,7 @@ defmodule RDF.GraphTest do
|
|||
])}
|
||||
end
|
||||
|
||||
test "a single statement as a triple",
|
||||
test "a triple",
|
||||
%{graph1: graph1, graph2: graph2} do
|
||||
assert Graph.delete(Graph.new(), {EX.S, EX.p(), EX.O}) == Graph.new()
|
||||
assert Graph.delete(graph1, {EX.S, EX.p(), EX.O}) == Graph.new()
|
||||
|
@ -436,15 +467,13 @@ defmodule RDF.GraphTest do
|
|||
Graph.new({EX.S, EX.p(), EX.O2}, name: EX.Graph)
|
||||
end
|
||||
|
||||
test "multiple statements with a triple with multiple objects",
|
||||
%{graph1: graph1, graph2: graph2} do
|
||||
test "a triple with multiple objects", %{graph1: graph1, graph2: graph2} do
|
||||
assert Graph.delete(Graph.new(), {EX.S, EX.p(), [EX.O1, EX.O2]}) == Graph.new()
|
||||
assert Graph.delete(graph1, {EX.S, EX.p(), [EX.O, EX.O2]}) == Graph.new()
|
||||
assert Graph.delete(graph2, {EX.S, EX.p(), [EX.O1, EX.O2]}) == Graph.new(name: EX.Graph)
|
||||
end
|
||||
|
||||
test "multiple statements with a list of triples",
|
||||
%{graph1: graph1, graph2: graph2, graph3: graph3} do
|
||||
test "a list of triples", %{graph1: graph1, graph2: graph2, graph3: graph3} do
|
||||
assert Graph.delete(graph1, [{EX.S, EX.p(), EX.O}, {EX.S, EX.p(), EX.O2}]) == Graph.new()
|
||||
|
||||
assert Graph.delete(graph2, [{EX.S, EX.p(), EX.O1}, {EX.S, EX.p(), EX.O2}]) ==
|
||||
|
@ -457,7 +486,23 @@ defmodule RDF.GraphTest do
|
|||
]) == Graph.new({EX.S3, EX.p3(), ~L"bar"})
|
||||
end
|
||||
|
||||
test "multiple statements with a Description",
|
||||
test "a map", %{graph1: graph1, graph2: graph2, graph3: graph3} do
|
||||
assert Graph.delete(graph1, %{EX.S => {EX.p(), [EX.O, EX.O2]}}) == Graph.new()
|
||||
|
||||
assert Graph.delete(graph2, %{EX.S => {EX.p(), [EX.O1, EX.O2]}}) ==
|
||||
Graph.new(name: EX.Graph)
|
||||
|
||||
assert Graph.delete(
|
||||
graph3,
|
||||
%{
|
||||
EX.S1 => %{EX.p1() => [EX.O1, EX.O2]},
|
||||
EX.S2 => %{EX.p2() => EX.O3},
|
||||
EX.S3 => %{EX.p3() => ~B<foo>}
|
||||
}
|
||||
) == Graph.new({EX.S3, EX.p3(), ~L"bar"})
|
||||
end
|
||||
|
||||
test "a description",
|
||||
%{graph1: graph1, graph2: graph2, graph3: graph3} do
|
||||
assert Graph.delete(
|
||||
graph1,
|
||||
|
@ -476,7 +521,7 @@ defmodule RDF.GraphTest do
|
|||
])
|
||||
end
|
||||
|
||||
test "multiple statements with a Graph",
|
||||
test "a graph",
|
||||
%{graph1: graph1, graph2: graph2, graph3: graph3} do
|
||||
assert Graph.delete(graph1, graph2) == graph1
|
||||
assert Graph.delete(graph1, graph1) == Graph.new()
|
||||
|
@ -499,15 +544,15 @@ defmodule RDF.GraphTest do
|
|||
|
||||
test "preserves the name and prefixes" do
|
||||
graph =
|
||||
Graph.new(EX.Subject, EX.predicate(), EX.Object, name: EX.GraphName, prefixes: %{ex: EX})
|
||||
|> Graph.delete(EX.Subject, EX.predicate(), EX.Object)
|
||||
Graph.new({EX.Subject, EX.predicate(), EX.Object}, name: EX.GraphName, prefixes: %{ex: EX})
|
||||
|> Graph.delete({EX.Subject, EX.predicate(), EX.Object})
|
||||
|
||||
assert graph.name == RDF.iri(EX.GraphName)
|
||||
assert graph.prefixes == PrefixMap.new(ex: EX)
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_subjects" do
|
||||
describe "delete_subjects/2" do
|
||||
setup do
|
||||
{:ok,
|
||||
graph1: Graph.new({EX.S, EX.p(), [EX.O1, EX.O2]}, name: EX.Graph),
|
||||
|
@ -596,7 +641,7 @@ defmodule RDF.GraphTest do
|
|||
|
||||
assert Graph.new()
|
||||
|> Graph.update(EX.S, {EX.P, EX.O}, fun) ==
|
||||
Graph.new(EX.S, EX.P, EX.O)
|
||||
Graph.new({EX.S, EX.P, EX.O})
|
||||
|
||||
assert Graph.new()
|
||||
|> Graph.update(EX.S, fun) ==
|
||||
|
@ -626,6 +671,33 @@ defmodule RDF.GraphTest do
|
|||
assert Enum.count(graph.descriptions) == 1
|
||||
end
|
||||
|
||||
test "include?/2" do
|
||||
graph =
|
||||
Graph.new([
|
||||
{EX.S1, EX.p(), EX.O1},
|
||||
{EX.S2, EX.p(), EX.O2}
|
||||
])
|
||||
|
||||
assert Graph.include?(graph, {EX.S1, EX.p(), EX.O1})
|
||||
assert Graph.include?(graph, {EX.S1, EX.p(), EX.O1, EX.Graph})
|
||||
|
||||
assert Graph.include?(graph, [{EX.S1, EX.p(), EX.O1}])
|
||||
|
||||
assert Graph.include?(graph, [
|
||||
{EX.S1, EX.p(), EX.O1},
|
||||
{EX.S2, EX.p(), EX.O2}
|
||||
])
|
||||
|
||||
refute Graph.include?(graph, [
|
||||
{EX.S1, EX.p(), EX.O1},
|
||||
{EX.S2, EX.p(), EX.O3}
|
||||
])
|
||||
|
||||
assert Graph.include?(graph, EX.S1 |> EX.p(EX.O1))
|
||||
assert Graph.include?(graph, Graph.new(EX.S1 |> EX.p(EX.O1)))
|
||||
assert Graph.include?(graph, graph)
|
||||
end
|
||||
|
||||
test "values/1" do
|
||||
assert Graph.new() |> Graph.values() == %{}
|
||||
|
||||
|
@ -710,7 +782,8 @@ defmodule RDF.GraphTest do
|
|||
end
|
||||
|
||||
test "equal/2" do
|
||||
assert Graph.new({EX.S, EX.p(), EX.O}) |> Graph.equal?(Graph.new({EX.S, EX.p(), EX.O}))
|
||||
assert Graph.new({EX.S, EX.p(), EX.O})
|
||||
|> Graph.equal?(Graph.new({EX.S, EX.p(), EX.O}))
|
||||
|
||||
assert Graph.new({EX.S, EX.p(), EX.O}, name: EX.Graph1)
|
||||
|> Graph.equal?(Graph.new({EX.S, EX.p(), EX.O}, name: EX.Graph1))
|
||||
|
@ -721,7 +794,8 @@ defmodule RDF.GraphTest do
|
|||
assert Graph.new({EX.S, EX.p(), EX.O}, base_iri: EX.base())
|
||||
|> Graph.equal?(Graph.new({EX.S, EX.p(), EX.O}, base_iri: EX.other_base()))
|
||||
|
||||
refute Graph.new({EX.S, EX.p(), EX.O}) |> Graph.equal?(Graph.new({EX.S, EX.p(), EX.O2}))
|
||||
refute Graph.new({EX.S, EX.p(), EX.O})
|
||||
|> Graph.equal?(Graph.new({EX.S, EX.p(), EX.O2}))
|
||||
|
||||
refute Graph.new({EX.S, EX.p(), EX.O}, name: EX.Graph1)
|
||||
|> Graph.equal?(Graph.new({EX.S, EX.p(), EX.O}, name: EX.Graph2))
|
||||
|
|
Loading…
Reference in a new issue