Limit the forms of input on RDF.Description functions
This commit is contained in:
parent
3f6393a191
commit
e9432ef556
9 changed files with 611 additions and 573 deletions
|
@ -233,8 +233,6 @@ defmodule RDF do
|
||||||
defdelegate quad(tuple), to: Quad, as: :new
|
defdelegate quad(tuple), to: Quad, as: :new
|
||||||
|
|
||||||
defdelegate description(arg), to: Description, as: :new
|
defdelegate description(arg), to: Description, as: :new
|
||||||
defdelegate description(arg1, arg2), to: Description, as: :new
|
|
||||||
defdelegate description(arg1, arg2, arg3), to: Description, as: :new
|
|
||||||
|
|
||||||
defdelegate graph(), to: Graph, as: :new
|
defdelegate graph(), to: Graph, as: :new
|
||||||
defdelegate graph(arg), to: Graph, as: :new
|
defdelegate graph(arg), to: Graph, as: :new
|
||||||
|
|
|
@ -15,294 +15,154 @@ defmodule RDF.Description do
|
||||||
import RDF.Statement
|
import RDF.Statement
|
||||||
alias RDF.{Statement, Triple}
|
alias RDF.{Statement, Triple}
|
||||||
|
|
||||||
@type predications :: %{Statement.predicate() => %{Statement.object() => nil}}
|
@enforce_keys [:subject]
|
||||||
|
defstruct subject: nil, predications: %{}
|
||||||
@type statements ::
|
|
||||||
{Statement.coercible_predicate(),
|
|
||||||
Statement.coercible_object() | [Statement.coercible_predicate()]}
|
|
||||||
| Statement.t()
|
|
||||||
| predications
|
|
||||||
| t
|
|
||||||
|
|
||||||
@type t :: %__MODULE__{
|
@type t :: %__MODULE__{
|
||||||
subject: Statement.subject(),
|
subject: Statement.subject(),
|
||||||
predications: predications
|
predications: predications
|
||||||
}
|
}
|
||||||
|
|
||||||
@enforce_keys [:subject]
|
@type predications :: %{Statement.predicate() => %{Statement.object() => nil}}
|
||||||
defstruct subject: nil, predications: %{}
|
|
||||||
|
@type input ::
|
||||||
|
Triple.coercible_t()
|
||||||
|
| {Statement.coercible_predicate(),
|
||||||
|
Statement.coercible_object() | [Statement.coercible_object()]}
|
||||||
|
| %{
|
||||||
|
Statement.coercible_predicate() =>
|
||||||
|
Statement.coercible_object() | [Statement.coercible_object()]
|
||||||
|
}
|
||||||
|
| [
|
||||||
|
Triple.coercible_t()
|
||||||
|
| {Statement.coercible_predicate(),
|
||||||
|
Statement.coercible_object() | [Statement.coercible_object()]}
|
||||||
|
| t
|
||||||
|
]
|
||||||
|
| t
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Creates a new `RDF.Description` about the given subject with optional initial statements.
|
Creates an empty `RDF.Description` about the given subject.
|
||||||
|
|
||||||
When given a list of statements, the first one must contain a subject.
|
|
||||||
"""
|
"""
|
||||||
@spec new(Statement.coercible_subject() | statements | [statements]) :: t
|
@spec new(Statement.coercible_subject() | Triple.coercible_t() | t) :: t
|
||||||
def new(subject)
|
def new(subject)
|
||||||
|
def new(%__MODULE__{} = description), do: new(description.subject)
|
||||||
def new({subject, predicate, object}),
|
def new({subject, predicate, object}), do: new(subject) |> add({predicate, object})
|
||||||
do: new(subject) |> add(predicate, object)
|
def new(subject), do: %__MODULE__{subject: coerce_subject(subject)}
|
||||||
|
|
||||||
def new([statement | more_statements]),
|
|
||||||
do: new(statement) |> add(more_statements)
|
|
||||||
|
|
||||||
def new(%__MODULE__{} = description),
|
|
||||||
do: description
|
|
||||||
|
|
||||||
def new(subject),
|
|
||||||
do: %__MODULE__{subject: coerce_subject(subject)}
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Creates a new `RDF.Description` about the given subject with optional initial statements.
|
Add statements to a `RDF.Description`.
|
||||||
"""
|
|
||||||
@spec new(Statement.coercible_subject(), statements | [statements]) :: t
|
|
||||||
def new(subject, {predicate, objects}),
|
|
||||||
do: new(subject) |> add(predicate, objects)
|
|
||||||
|
|
||||||
def new(subject, statements) when is_list(statements),
|
|
||||||
do: new(subject) |> add(statements)
|
|
||||||
|
|
||||||
def new(subject, %__MODULE__{predications: predications}),
|
|
||||||
do: %__MODULE__{new(subject) | predications: predications}
|
|
||||||
|
|
||||||
def new(subject, predications = %{}),
|
|
||||||
do: new(subject) |> add(predications)
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Creates a new `RDF.Description` about the given subject with optional initial statements.
|
|
||||||
"""
|
|
||||||
@spec new(
|
|
||||||
Statement.coercible_subject() | statements | [statements],
|
|
||||||
Statement.coercible_predicate(),
|
|
||||||
Statement.coercible_object() | [Statement.coercible_object()]
|
|
||||||
) :: t
|
|
||||||
def new(%__MODULE__{} = description, predicate, objects),
|
|
||||||
do: add(description, predicate, objects)
|
|
||||||
|
|
||||||
def new(subject, predicate, objects),
|
|
||||||
do: new(subject) |> add(predicate, objects)
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Add objects to a predicate of a `RDF.Description`.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
iex> RDF.Description.add(RDF.Description.new({EX.S, EX.P1, EX.O1}), EX.P2, EX.O2)
|
|
||||||
RDF.Description.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}])
|
|
||||||
iex> RDF.Description.add(RDF.Description.new({EX.S, EX.P, EX.O1}), EX.P, [EX.O2, EX.O3])
|
|
||||||
RDF.Description.new([{EX.S, EX.P, EX.O1}, {EX.S, EX.P, EX.O2}, {EX.S, EX.P, EX.O3}])
|
|
||||||
"""
|
|
||||||
@spec add(
|
|
||||||
t,
|
|
||||||
Statement.coercible_predicate(),
|
|
||||||
Statement.coercible_object() | [Statement.coercible_object()]
|
|
||||||
) :: t
|
|
||||||
def add(description, predicate, objects)
|
|
||||||
|
|
||||||
def add(description, predicate, objects) when is_list(objects) do
|
|
||||||
Enum.reduce(objects, description, fn object, description ->
|
|
||||||
add(description, predicate, object)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add(%__MODULE__{subject: subject, predications: predications}, predicate, object) do
|
|
||||||
with triple_predicate = coerce_predicate(predicate),
|
|
||||||
triple_object = coerce_object(object),
|
|
||||||
new_predications =
|
|
||||||
Map.update(predications, triple_predicate, %{triple_object => nil}, fn objects ->
|
|
||||||
Map.put_new(objects, triple_object, nil)
|
|
||||||
end) do
|
|
||||||
%__MODULE__{subject: subject, predications: new_predications}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Adds statements to a `RDF.Description`.
|
|
||||||
|
|
||||||
Note: When the statements to be added are given as another `RDF.Description`,
|
Note: When the statements to be added are given as another `RDF.Description`,
|
||||||
the subject must not match subject of the description to which the statements
|
the subject must not match subject of the description to which the statements
|
||||||
are added. As opposed to that `RDF.Data.merge/2` will produce a `RDF.Graph`
|
are added. As opposed to that `RDF.Data.merge/2` will produce a `RDF.Graph`
|
||||||
containing both descriptions.
|
containing both descriptions.
|
||||||
"""
|
|
||||||
@spec add(t, statements | [statements]) :: t
|
|
||||||
def add(description, statements)
|
|
||||||
|
|
||||||
def add(description, {predicate, object}),
|
|
||||||
do: add(description, predicate, object)
|
|
||||||
|
|
||||||
def add(description = %__MODULE__{}, {subject, predicate, object}) do
|
|
||||||
if coerce_subject(subject) == description.subject,
|
|
||||||
do: add(description, predicate, object),
|
|
||||||
else: description
|
|
||||||
end
|
|
||||||
|
|
||||||
def add(description, {subject, predicate, object, _}),
|
|
||||||
do: add(description, {subject, predicate, object})
|
|
||||||
|
|
||||||
def add(description, statements) when is_list(statements) do
|
|
||||||
Enum.reduce(statements, description, fn statement, description ->
|
|
||||||
add(description, statement)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add(
|
|
||||||
%__MODULE__{subject: subject, predications: predications},
|
|
||||||
%__MODULE__{predications: other_predications}
|
|
||||||
) do
|
|
||||||
merged_predications =
|
|
||||||
Map.merge(predications, other_predications, fn _, objects, other_objects ->
|
|
||||||
Map.merge(objects, other_objects)
|
|
||||||
end)
|
|
||||||
|
|
||||||
%__MODULE__{subject: subject, predications: merged_predications}
|
|
||||||
end
|
|
||||||
|
|
||||||
def add(description = %__MODULE__{}, predications = %{}) do
|
|
||||||
Enum.reduce(predications, description, fn {predicate, objects}, description ->
|
|
||||||
add(description, predicate, objects)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Puts objects to a predicate of a `RDF.Description`, overwriting all existing objects.
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> RDF.Description.put(RDF.Description.new({EX.S, EX.P, EX.O1}), EX.P, EX.O2)
|
iex> RDF.Description.new({EX.S, EX.P1, EX.O1}) |> RDF.Description.add({EX.P2, EX.O2})
|
||||||
RDF.Description.new([{EX.S, EX.P, EX.O2}])
|
RDF.Description.new(EX.S) |> RDF.Description.add([{EX.P1, EX.O1}, {EX.P2, EX.O2}])
|
||||||
iex> RDF.Description.put(RDF.Description.new({EX.S, EX.P1, EX.O1}), EX.P2, EX.O2)
|
iex> RDF.Description.new({EX.S, EX.P, EX.O1}) |> RDF.Description.add({EX.P, [EX.O2, EX.O3]})
|
||||||
RDF.Description.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}])
|
RDF.Description.new(EX.S) |> RDF.Description.add([{EX.P, EX.O1}, {EX.P, EX.O2}, {EX.P, EX.O3}])
|
||||||
"""
|
|
||||||
@spec put(
|
|
||||||
t,
|
|
||||||
Statement.coercible_predicate(),
|
|
||||||
Statement.coercible_object() | [Statement.coercible_object()]
|
|
||||||
) :: t
|
|
||||||
def put(description, predicate, objects)
|
|
||||||
|
|
||||||
def put(%__MODULE__{subject: subject, predications: predications}, predicate, objects)
|
"""
|
||||||
when is_list(objects) do
|
@spec add(t, input, keyword) :: t
|
||||||
with triple_predicate = coerce_predicate(predicate),
|
def add(description, input, opts \\ [])
|
||||||
triple_objects =
|
|
||||||
Enum.reduce(objects, %{}, fn object, acc ->
|
# This implementation is actually unnecessary as the implementation with the is_map clause
|
||||||
Map.put_new(acc, coerce_object(object), nil)
|
# would work perfectly fine with RDF.Descriptions Enumerable implementation.
|
||||||
end),
|
# It exists only for performance reasons, since this version is roughly twice as fast.
|
||||||
do: %__MODULE__{
|
def add(%__MODULE__{} = description, %__MODULE__{} = input_description, _opts) do
|
||||||
subject: subject,
|
%__MODULE__{
|
||||||
predications: Map.put(predications, triple_predicate, triple_objects)
|
description
|
||||||
}
|
| predications:
|
||||||
|
Map.merge(
|
||||||
|
description.predications,
|
||||||
|
input_description.predications,
|
||||||
|
fn _predicate, objects, new_objects ->
|
||||||
|
Map.merge(objects, new_objects)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def put(%__MODULE__{} = description, predicate, object),
|
def add(description, predications, opts)
|
||||||
do: put(description, predicate, [object])
|
when is_map(predications) or is_list(predications) do
|
||||||
|
Enum.reduce(predications, description, fn
|
||||||
|
predications, description -> add(description, predications, opts)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add(%__MODULE__{} = description, {subject, predicate, objects}, opts) do
|
||||||
|
if coerce_subject(subject) == description.subject do
|
||||||
|
add(description, {predicate, objects}, opts)
|
||||||
|
else
|
||||||
|
description
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add(%__MODULE__{} = description, {predicate, objects}, _opts) do
|
||||||
|
normalized_objects =
|
||||||
|
objects
|
||||||
|
|> List.wrap()
|
||||||
|
|> Map.new(fn object -> {coerce_object(object), nil} end)
|
||||||
|
|
||||||
|
if Enum.empty?(normalized_objects) do
|
||||||
|
description
|
||||||
|
else
|
||||||
|
%__MODULE__{
|
||||||
|
description
|
||||||
|
| predications:
|
||||||
|
Map.update(
|
||||||
|
description.predications,
|
||||||
|
coerce_predicate(predicate),
|
||||||
|
normalized_objects,
|
||||||
|
fn objects ->
|
||||||
|
Map.merge(objects, normalized_objects)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Adds statements to a `RDF.Description` and overwrites all existing statements with already used predicates.
|
Adds statements to a `RDF.Description` and overwrites all existing statements with already used predicates.
|
||||||
|
|
||||||
|
Note: As it is a destructive function this function is more strict in its handling of
|
||||||
|
`RDF.Description`s than `add/3`. The subject of a `RDF.Description` to be put must
|
||||||
|
match.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> RDF.Description.put(RDF.Description.new({EX.S, EX.P, EX.O1}), {EX.P, EX.O2})
|
iex> RDF.Description.put(RDF.Description.new({EX.S, EX.P, EX.O1}), {EX.P, EX.O2})
|
||||||
RDF.Description.new([{EX.S, EX.P, EX.O2}])
|
RDF.Description.new({EX.S, EX.P, EX.O2})
|
||||||
iex> RDF.Description.new({EX.S, EX.P1, EX.O1}) |>
|
|
||||||
...> RDF.Description.put([{EX.P2, EX.O2}, {EX.S, EX.P2, EX.O3}, {EX.P1, EX.O4}])
|
|
||||||
RDF.Description.new([{EX.S, EX.P1, EX.O4}, {EX.S, EX.P2, EX.O2}, {EX.S, EX.P2, EX.O3}])
|
|
||||||
iex> RDF.Description.new({EX.S, EX.P, EX.O1}) |>
|
|
||||||
...> RDF.Description.put(RDF.Description.new(EX.S, EX.P, [EX.O1, EX.O2]))
|
|
||||||
RDF.Description.new([{EX.S, EX.P, EX.O1}, {EX.S, EX.P, EX.O2}])
|
|
||||||
iex> RDF.Description.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}]) |>
|
|
||||||
...> RDF.Description.put(%{EX.P2 => [EX.O3, EX.O4]})
|
|
||||||
RDF.Description.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O3}, {EX.S, EX.P2, EX.O4}])
|
|
||||||
"""
|
"""
|
||||||
@spec put(t, statements | [statements]) :: t
|
@spec put(t, input, keyword) :: t
|
||||||
def put(description, statements)
|
def put(description, input, opts \\ [])
|
||||||
|
|
||||||
def put(%__MODULE__{} = description, {predicate, object}),
|
|
||||||
do: put(description, predicate, object)
|
|
||||||
|
|
||||||
def put(%__MODULE__{} = description, {subject, predicate, object}) do
|
|
||||||
if coerce_subject(subject) == description.subject,
|
|
||||||
do: put(description, predicate, object),
|
|
||||||
else: description
|
|
||||||
end
|
|
||||||
|
|
||||||
def put(description, {subject, predicate, object, _}),
|
|
||||||
do: put(description, {subject, predicate, object})
|
|
||||||
|
|
||||||
def put(%__MODULE__{subject: subject} = description, statements) when is_list(statements) do
|
|
||||||
statements
|
|
||||||
|> Stream.map(fn
|
|
||||||
{p, o} ->
|
|
||||||
{coerce_predicate(p), o}
|
|
||||||
|
|
||||||
{^subject, p, o} ->
|
|
||||||
{coerce_predicate(p), o}
|
|
||||||
|
|
||||||
{s, p, o} ->
|
|
||||||
if coerce_subject(s) == subject,
|
|
||||||
do: {coerce_predicate(p), o}
|
|
||||||
|
|
||||||
bad ->
|
|
||||||
raise ArgumentError, "#{inspect(bad)} is not a valid statement"
|
|
||||||
end)
|
|
||||||
# filter nil values
|
|
||||||
|> Stream.filter(& &1)
|
|
||||||
|> Enum.group_by(&elem(&1, 0), &elem(&1, 1))
|
|
||||||
|> Enum.reduce(description, fn {predicate, objects}, description ->
|
|
||||||
put(description, predicate, objects)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def put(
|
def put(
|
||||||
%__MODULE__{subject: subject, predications: predications},
|
%__MODULE__{subject: subject} = description,
|
||||||
%__MODULE__{predications: other_predications}
|
%__MODULE__{subject: subject} = input,
|
||||||
|
_opts
|
||||||
) do
|
) do
|
||||||
merged_predications =
|
%__MODULE__{
|
||||||
Map.merge(predications, other_predications, fn _, _, other_objects -> other_objects end)
|
description
|
||||||
|
| predications:
|
||||||
%__MODULE__{subject: subject, predications: merged_predications}
|
Enum.reduce(
|
||||||
end
|
input.predications,
|
||||||
|
description.predications,
|
||||||
def put(description = %__MODULE__{}, predications = %{}) do
|
fn {predicate, objects}, predications ->
|
||||||
Enum.reduce(predications, description, fn {predicate, objects}, description ->
|
Map.put(predications, predicate, objects)
|
||||||
put(description, predicate, objects)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Deletes statements from a `RDF.Description`.
|
|
||||||
"""
|
|
||||||
@spec delete(
|
|
||||||
t,
|
|
||||||
Statement.coercible_predicate(),
|
|
||||||
Statement.coercible_object() | [Statement.coercible_object()]
|
|
||||||
) :: t
|
|
||||||
def delete(description, predicate, objects)
|
|
||||||
|
|
||||||
def delete(description, predicate, objects) when is_list(objects) do
|
|
||||||
Enum.reduce(objects, description, fn object, description ->
|
|
||||||
delete(description, predicate, object)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete(%__MODULE__{subject: subject, predications: predications} = descr, predicate, object) do
|
|
||||||
with triple_predicate = coerce_predicate(predicate),
|
|
||||||
triple_object = coerce_object(object) do
|
|
||||||
if (objects = predications[triple_predicate]) && Map.has_key?(objects, triple_object) do
|
|
||||||
%__MODULE__{
|
|
||||||
subject: subject,
|
|
||||||
predications:
|
|
||||||
if map_size(objects) == 1 do
|
|
||||||
Map.delete(predications, triple_predicate)
|
|
||||||
else
|
|
||||||
Map.update!(predications, triple_predicate, fn objects ->
|
|
||||||
Map.delete(objects, triple_object)
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
}
|
)
|
||||||
else
|
}
|
||||||
descr
|
end
|
||||||
end
|
|
||||||
end
|
def put(%__MODULE__{} = description, %__MODULE__{}, _opts), do: description
|
||||||
|
|
||||||
|
def put(%__MODULE__{} = description, input, opts) do
|
||||||
|
put(description, description.subject |> new() |> add(input), opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -313,37 +173,76 @@ defmodule RDF.Description do
|
||||||
are deleted. If you want to delete only a matching description subject, you can
|
are deleted. If you want to delete only a matching description subject, you can
|
||||||
use `RDF.Data.delete/2`.
|
use `RDF.Data.delete/2`.
|
||||||
"""
|
"""
|
||||||
@spec delete(t, statements | [statements]) :: t
|
@spec delete(t, input, keyword) :: t
|
||||||
def delete(description, statements)
|
def delete(description, input, opts \\ [])
|
||||||
|
|
||||||
def delete(desc = %__MODULE__{}, {predicate, object}),
|
# This implementation is actually unnecessary as the implementation with the is_map clause
|
||||||
do: delete(desc, predicate, object)
|
# would work perfectly fine with RDF.Descriptions Enumerable implementation.
|
||||||
|
# It exists only for performance reasons.
|
||||||
|
def delete(%__MODULE__{} = description, %__MODULE__{} = input_description, _opts) do
|
||||||
|
predications = description.predications
|
||||||
|
|
||||||
def delete(description = %__MODULE__{}, {subject, predicate, object}) do
|
%__MODULE__{
|
||||||
if coerce_subject(subject) == description.subject,
|
description
|
||||||
do: delete(description, predicate, object),
|
| predications:
|
||||||
else: description
|
Enum.reduce(
|
||||||
|
input_description.predications,
|
||||||
|
predications,
|
||||||
|
fn {predicate, objects}, predications ->
|
||||||
|
if current_objects = Map.get(description.predications, predicate) do
|
||||||
|
rest = Map.drop(current_objects, Map.keys(objects))
|
||||||
|
|
||||||
|
if Enum.empty?(rest) do
|
||||||
|
Map.delete(predications, predicate)
|
||||||
|
else
|
||||||
|
Map.put(predications, predicate, rest)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
predications
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete(description, {subject, predicate, object, _}),
|
def delete(description, predications, opts)
|
||||||
do: delete(description, {subject, predicate, object})
|
when is_map(predications) or is_list(predications) do
|
||||||
|
Enum.reduce(predications, description, fn
|
||||||
def delete(description, statements) when is_list(statements) do
|
predications, description -> delete(description, predications, opts)
|
||||||
Enum.reduce(statements, description, fn statement, description ->
|
|
||||||
delete(description, statement)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete(description = %__MODULE__{}, other_description = %__MODULE__{}) do
|
def delete(%__MODULE__{} = description, {subject, predicate, objects}, opts) do
|
||||||
Enum.reduce(other_description, description, fn {_, predicate, object}, description ->
|
if coerce_subject(subject) == description.subject do
|
||||||
delete(description, predicate, object)
|
delete(description, {predicate, objects}, opts)
|
||||||
end)
|
else
|
||||||
|
description
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete(description = %__MODULE__{}, predications = %{}) do
|
def delete(%__MODULE__{} = description, {predicate, objects}, _opts) do
|
||||||
Enum.reduce(predications, description, fn {predicate, objects}, description ->
|
predicate = coerce_predicate(predicate)
|
||||||
delete(description, predicate, objects)
|
|
||||||
end)
|
if current_objects = Map.get(description.predications, predicate) do
|
||||||
|
normalized_objects =
|
||||||
|
objects
|
||||||
|
|> List.wrap()
|
||||||
|
|> Enum.map(&coerce_object/1)
|
||||||
|
|
||||||
|
rest = Map.drop(current_objects, normalized_objects)
|
||||||
|
|
||||||
|
%__MODULE__{
|
||||||
|
description
|
||||||
|
| predications:
|
||||||
|
if Enum.empty?(rest) do
|
||||||
|
Map.delete(description.predications, predicate)
|
||||||
|
else
|
||||||
|
Map.put(description.predications, predicate, rest)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
else
|
||||||
|
description
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -360,9 +259,10 @@ defmodule RDF.Description do
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_predicates(%__MODULE__{subject: subject, predications: predications}, property) do
|
def delete_predicates(%__MODULE__{subject: subject, predications: predications}, property) do
|
||||||
with property = coerce_predicate(property) do
|
%__MODULE__{
|
||||||
%__MODULE__{subject: subject, predications: Map.delete(predications, property)}
|
subject: subject,
|
||||||
end
|
predications: Map.delete(predications, coerce_predicate(property))
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -372,10 +272,10 @@ defmodule RDF.Description do
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> RDF.Description.fetch(RDF.Description.new({EX.S, EX.p, EX.O}), EX.p)
|
iex> RDF.Description.new({EX.S, EX.p, EX.O}) |> RDF.Description.fetch(EX.p)
|
||||||
{:ok, [RDF.iri(EX.O)]}
|
{:ok, [RDF.iri(EX.O)]}
|
||||||
iex> RDF.Description.fetch(RDF.Description.new([{EX.S, EX.P, EX.O1},
|
iex> RDF.Description.new(EX.S) |> RDF.Description.add([{EX.P, EX.O1}, {EX.P, EX.O2}]) |>
|
||||||
...> {EX.S, EX.P, EX.O2}]), EX.P)
|
...> RDF.Description.fetch(EX.P)
|
||||||
{:ok, [RDF.iri(EX.O1), RDF.iri(EX.O2)]}
|
{:ok, [RDF.iri(EX.O1), RDF.iri(EX.O2)]}
|
||||||
iex> RDF.Description.fetch(RDF.Description.new(EX.S), EX.foo)
|
iex> RDF.Description.fetch(RDF.Description.new(EX.S), EX.foo)
|
||||||
:error
|
:error
|
||||||
|
@ -445,7 +345,7 @@ defmodule RDF.Description do
|
||||||
|
|
||||||
iex> RDF.Description.new({EX.S, EX.p, EX.O}) |>
|
iex> RDF.Description.new({EX.S, EX.p, EX.O}) |>
|
||||||
...> RDF.Description.update(EX.p, fn objects -> [EX.O2 | objects] end)
|
...> RDF.Description.update(EX.p, fn objects -> [EX.O2 | objects] end)
|
||||||
RDF.Description.new([{EX.S, EX.p, EX.O}, {EX.S, EX.p, EX.O2}])
|
RDF.Description.new(EX.S) |> RDF.Description.add([{EX.p, EX.O}, {EX.p, EX.O2}])
|
||||||
iex> RDF.Description.new(EX.S) |>
|
iex> RDF.Description.new(EX.S) |>
|
||||||
...> RDF.Description.update(EX.p, EX.O, fn _ -> EX.O2 end)
|
...> RDF.Description.update(EX.p, EX.O, fn _ -> EX.O2 end)
|
||||||
RDF.Description.new({EX.S, EX.p, EX.O})
|
RDF.Description.new({EX.S, EX.p, EX.O})
|
||||||
|
@ -463,7 +363,7 @@ defmodule RDF.Description do
|
||||||
case get(description, predicate) do
|
case get(description, predicate) do
|
||||||
nil ->
|
nil ->
|
||||||
if initial do
|
if initial do
|
||||||
put(description, predicate, initial)
|
put(description, {predicate, initial})
|
||||||
else
|
else
|
||||||
description
|
description
|
||||||
end
|
end
|
||||||
|
@ -474,7 +374,7 @@ defmodule RDF.Description do
|
||||||
|> List.wrap()
|
|> List.wrap()
|
||||||
|> case do
|
|> case do
|
||||||
[] -> delete_predicates(description, predicate)
|
[] -> delete_predicates(description, predicate)
|
||||||
objects -> put(description, predicate, objects)
|
objects -> put(description, {predicate, objects})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -500,7 +400,8 @@ defmodule RDF.Description do
|
||||||
...> {current_objects, EX.NEW}
|
...> {current_objects, EX.NEW}
|
||||||
...> end)
|
...> end)
|
||||||
{[RDF.iri(EX.O)], RDF.Description.new({EX.S, EX.P, EX.NEW})}
|
{[RDF.iri(EX.O)], RDF.Description.new({EX.S, EX.P, EX.NEW})}
|
||||||
iex> RDF.Description.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}]) |>
|
iex> RDF.Graph.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}]) |>
|
||||||
|
...> RDF.Graph.description(EX.S) |>
|
||||||
...> RDF.Description.get_and_update(EX.P1, fn _ -> :pop end)
|
...> RDF.Description.get_and_update(EX.P1, fn _ -> :pop end)
|
||||||
{[RDF.iri(EX.O1)], RDF.Description.new({EX.S, EX.P2, EX.O2})}
|
{[RDF.iri(EX.O1)], RDF.Description.new({EX.S, EX.P2, EX.O2})}
|
||||||
"""
|
"""
|
||||||
|
@ -511,14 +412,14 @@ defmodule RDF.Description do
|
||||||
([Statement.Object] -> {[Statement.Object], t} | :pop)
|
([Statement.Object] -> {[Statement.Object], t} | :pop)
|
||||||
) :: {[Statement.Object], t}
|
) :: {[Statement.Object], t}
|
||||||
def get_and_update(description = %__MODULE__{}, predicate, fun) do
|
def get_and_update(description = %__MODULE__{}, predicate, fun) do
|
||||||
with triple_predicate = coerce_predicate(predicate) do
|
triple_predicate = coerce_predicate(predicate)
|
||||||
case fun.(get(description, triple_predicate)) do
|
|
||||||
{objects_to_return, new_objects} ->
|
|
||||||
{objects_to_return, put(description, triple_predicate, new_objects)}
|
|
||||||
|
|
||||||
:pop ->
|
case fun.(get(description, triple_predicate)) do
|
||||||
pop(description, triple_predicate)
|
{objects_to_return, new_objects} ->
|
||||||
end
|
{objects_to_return, put(description, {triple_predicate, new_objects})}
|
||||||
|
|
||||||
|
:pop ->
|
||||||
|
pop(description, triple_predicate)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -572,10 +473,10 @@ defmodule RDF.Description do
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> RDF.Description.new([
|
iex> RDF.Description.new(EX.S1) |> RDF.Description.add([
|
||||||
...> {EX.S1, EX.p1, EX.O1},
|
...> {EX.p1, EX.O1},
|
||||||
...> {EX.p2, EX.O2},
|
...> {EX.p2, EX.O2},
|
||||||
...> {EX.p2, EX.O3}]) |>
|
...> {EX.p2, EX.O3}]) |>
|
||||||
...> RDF.Description.predicates
|
...> RDF.Description.predicates
|
||||||
MapSet.new([EX.p1, EX.p2])
|
MapSet.new([EX.p1, EX.p2])
|
||||||
"""
|
"""
|
||||||
|
@ -590,12 +491,12 @@ defmodule RDF.Description do
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> RDF.Description.new([
|
iex> RDF.Description.new(EX.S1) |> RDF.Description.add([
|
||||||
...> {EX.S1, EX.p1, EX.O1},
|
...> {EX.p1, EX.O1},
|
||||||
...> {EX.p2, EX.O2},
|
...> {EX.p2, EX.O2},
|
||||||
...> {EX.p3, EX.O2},
|
...> {EX.p3, EX.O2},
|
||||||
...> {EX.p4, RDF.bnode(:bnode)},
|
...> {EX.p4, RDF.bnode(:bnode)},
|
||||||
...> {EX.p3, "foo"}
|
...> {EX.p3, "foo"}
|
||||||
...> ]) |> RDF.Description.objects
|
...> ]) |> RDF.Description.objects
|
||||||
MapSet.new([RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode)])
|
MapSet.new([RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode)])
|
||||||
"""
|
"""
|
||||||
|
@ -622,12 +523,12 @@ defmodule RDF.Description do
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> RDF.Description.new([
|
iex> RDF.Description.new(EX.S1) |> RDF.Description.add([
|
||||||
...> {EX.S1, EX.p1, EX.O1},
|
...> {EX.p1, EX.O1},
|
||||||
...> {EX.p2, EX.O2},
|
...> {EX.p2, EX.O2},
|
||||||
...> {EX.p1, EX.O2},
|
...> {EX.p1, EX.O2},
|
||||||
...> {EX.p2, RDF.bnode(:bnode)},
|
...> {EX.p2, RDF.bnode(:bnode)},
|
||||||
...> {EX.p3, "foo"}
|
...> {EX.p3, "foo"}
|
||||||
...> ]) |> RDF.Description.resources
|
...> ]) |> RDF.Description.resources
|
||||||
MapSet.new([RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2, EX.p3])
|
MapSet.new([RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2, EX.p3])
|
||||||
"""
|
"""
|
||||||
|
@ -657,46 +558,42 @@ defmodule RDF.Description do
|
||||||
@doc """
|
@doc """
|
||||||
Checks if the given statement exists within a `RDF.Description`.
|
Checks if the given statement exists within a `RDF.Description`.
|
||||||
"""
|
"""
|
||||||
@spec include?(t, statements) :: boolean
|
@spec include?(t, input) :: boolean
|
||||||
def include?(description, statement)
|
def include?(description, input)
|
||||||
|
|
||||||
def include?(
|
def include?(description, predications) when is_map(predications) or is_list(predications) do
|
||||||
%__MODULE__{predications: predications},
|
Enum.all?(predications, fn predication -> include?(description, predication) end)
|
||||||
{predicate, object}
|
end
|
||||||
) do
|
|
||||||
with triple_predicate = coerce_predicate(predicate),
|
def include?(%__MODULE__{} = description, {subject, predicate, objects}) do
|
||||||
triple_object = coerce_object(object) do
|
coerce_subject(subject) == description.subject &&
|
||||||
predications
|
include?(description, {predicate, objects})
|
||||||
|> Map.get(triple_predicate, %{})
|
end
|
||||||
|> Map.has_key?(triple_object)
|
|
||||||
|
def include?(%__MODULE__{} = description, {predicate, objects}) do
|
||||||
|
if existing_objects = description.predications[coerce_predicate(predicate)] do
|
||||||
|
objects
|
||||||
|
|> List.wrap()
|
||||||
|
|> Enum.map(&coerce_object/1)
|
||||||
|
|> Enum.all?(fn object -> Map.has_key?(existing_objects, object) end)
|
||||||
|
else
|
||||||
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def include?(
|
|
||||||
desc = %__MODULE__{subject: desc_subject},
|
|
||||||
{subject, predicate, object}
|
|
||||||
) do
|
|
||||||
coerce_subject(subject) == desc_subject &&
|
|
||||||
include?(desc, {predicate, object})
|
|
||||||
end
|
|
||||||
|
|
||||||
def include?(%__MODULE__{}, _), do: false
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Checks if a `RDF.Description` has the given resource as subject.
|
Checks if a `RDF.Description` has the given resource as subject.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> RDF.Description.new(EX.S1, EX.p1, EX.O1) |> RDF.Description.describes?(EX.S1)
|
iex> RDF.Description.new({EX.S1, EX.p1, EX.O1}) |> RDF.Description.describes?(EX.S1)
|
||||||
true
|
true
|
||||||
iex> RDF.Description.new(EX.S1, EX.p1, EX.O1) |> RDF.Description.describes?(EX.S2)
|
iex> RDF.Description.new({EX.S1, EX.p1, EX.O1}) |> RDF.Description.describes?(EX.S2)
|
||||||
false
|
false
|
||||||
"""
|
"""
|
||||||
@spec describes?(t, Statement.subject()) :: boolean
|
@spec describes?(t, Statement.subject()) :: boolean
|
||||||
def describes?(%__MODULE__{subject: subject}, other_subject) do
|
def describes?(%__MODULE__{subject: subject}, other_subject) do
|
||||||
with other_subject = coerce_subject(other_subject) do
|
subject == coerce_subject(other_subject)
|
||||||
subject == other_subject
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
|
@ -47,7 +47,7 @@ defmodule RDF.Diff do
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> RDF.Diff.diff(
|
iex> RDF.Diff.diff(
|
||||||
...> RDF.description(EX.S1, EX.p1, [EX.O1, EX.O2]),
|
...> RDF.description({EX.S1, EX.p1, [EX.O1, EX.O2]}),
|
||||||
...> RDF.graph([
|
...> RDF.graph([
|
||||||
...> {EX.S1, EX.p1, [EX.O2, EX.O3]},
|
...> {EX.S1, EX.p1, [EX.O2, EX.O3]},
|
||||||
...> {EX.S2, EX.p2, EX.O4}
|
...> {EX.S2, EX.p2, EX.O4}
|
||||||
|
@ -81,7 +81,7 @@ defmodule RDF.Diff do
|
||||||
nil ->
|
nil ->
|
||||||
{
|
{
|
||||||
additions,
|
additions,
|
||||||
Description.add(deletions, property, original_objects)
|
Description.add(deletions, {property, original_objects})
|
||||||
}
|
}
|
||||||
|
|
||||||
new_objects ->
|
new_objects ->
|
||||||
|
@ -96,8 +96,8 @@ defmodule RDF.Diff do
|
||||||
end)
|
end)
|
||||||
|
|
||||||
{
|
{
|
||||||
Description.delete(additions, property, unchanged_objects),
|
Description.delete(additions, {property, unchanged_objects}),
|
||||||
Description.add(deletions, property, deleted_objects)
|
Description.add(deletions, {property, deleted_objects})
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -202,9 +202,14 @@ defmodule RDF.Graph do
|
||||||
%__MODULE__{
|
%__MODULE__{
|
||||||
graph
|
graph
|
||||||
| descriptions:
|
| descriptions:
|
||||||
Map.update(descriptions, subject, Description.new(statements), fn description ->
|
Map.update(
|
||||||
Description.add(description, statements)
|
descriptions,
|
||||||
end)
|
subject,
|
||||||
|
Description.new(subject) |> Description.add(statements),
|
||||||
|
fn description ->
|
||||||
|
Description.add(description, statements)
|
||||||
|
end
|
||||||
|
)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -277,7 +282,7 @@ defmodule RDF.Graph do
|
||||||
Map.update(
|
Map.update(
|
||||||
descriptions,
|
descriptions,
|
||||||
subject,
|
subject,
|
||||||
Description.new(subject, predications),
|
Description.new(subject) |> Description.add(predications),
|
||||||
fn current ->
|
fn current ->
|
||||||
Description.put(current, predications)
|
Description.put(current, predications)
|
||||||
end
|
end
|
||||||
|
@ -293,9 +298,14 @@ defmodule RDF.Graph do
|
||||||
%__MODULE__{
|
%__MODULE__{
|
||||||
graph
|
graph
|
||||||
| descriptions:
|
| descriptions:
|
||||||
Map.update(descriptions, subject, Description.new(statements), fn current ->
|
Map.update(
|
||||||
Description.put(current, statements)
|
descriptions,
|
||||||
end)
|
subject,
|
||||||
|
Description.new(subject) |> Description.add(statements),
|
||||||
|
fn current ->
|
||||||
|
Description.put(current, statements)
|
||||||
|
end
|
||||||
|
)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -420,15 +430,15 @@ defmodule RDF.Graph do
|
||||||
|
|
||||||
iex> RDF.Graph.new({EX.S, EX.p, EX.O}) |>
|
iex> RDF.Graph.new({EX.S, EX.p, EX.O}) |>
|
||||||
...> RDF.Graph.update(EX.S,
|
...> RDF.Graph.update(EX.S,
|
||||||
...> fn description -> Description.add(description, EX.p, EX.O2) end)
|
...> fn description -> Description.add(description, {EX.p, EX.O2}) end)
|
||||||
RDF.Graph.new([{EX.S, EX.p, EX.O}, {EX.S, EX.p, EX.O2}])
|
RDF.Graph.new([{EX.S, EX.p, EX.O}, {EX.S, EX.p, EX.O2}])
|
||||||
iex> RDF.Graph.new({EX.S, EX.p, EX.O}) |>
|
iex> RDF.Graph.new({EX.S, EX.p, EX.O}) |>
|
||||||
...> RDF.Graph.update(EX.S,
|
...> RDF.Graph.update(EX.S,
|
||||||
...> fn _ -> Description.new(EX.S2, EX.p2, EX.O2) end)
|
...> fn _ -> Description.new({EX.S2, EX.p2, EX.O2}) end)
|
||||||
RDF.Graph.new([{EX.S, EX.p2, EX.O2}])
|
RDF.Graph.new([{EX.S, EX.p2, EX.O2}])
|
||||||
iex> RDF.Graph.new() |>
|
iex> RDF.Graph.new() |>
|
||||||
...> RDF.Graph.update(EX.S, Description.new({EX.S, EX.p, EX.O}),
|
...> RDF.Graph.update(EX.S, Description.new({EX.S, EX.p, EX.O}),
|
||||||
...> fn description -> Description.add(description, EX.p, EX.O2) end)
|
...> fn description -> Description.add(description, {EX.p, EX.O2}) end)
|
||||||
RDF.Graph.new([{EX.S, EX.p, EX.O}])
|
RDF.Graph.new([{EX.S, EX.p, EX.O}])
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -444,7 +454,7 @@ defmodule RDF.Graph do
|
||||||
case get(graph, subject) do
|
case get(graph, subject) do
|
||||||
nil ->
|
nil ->
|
||||||
if initial do
|
if initial do
|
||||||
add(graph, Description.new(subject, initial))
|
add(graph, Description.new(subject) |> Description.add(initial))
|
||||||
else
|
else
|
||||||
graph
|
graph
|
||||||
end
|
end
|
||||||
|
@ -459,7 +469,7 @@ defmodule RDF.Graph do
|
||||||
new_description ->
|
new_description ->
|
||||||
graph
|
graph
|
||||||
|> delete_subjects(subject)
|
|> delete_subjects(subject)
|
||||||
|> add(Description.new(subject, new_description))
|
|> add(Description.new(subject) |> Description.add(new_description))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -566,7 +576,7 @@ defmodule RDF.Graph do
|
||||||
...> RDF.Graph.get_and_update(EX.S, fn current_description ->
|
...> RDF.Graph.get_and_update(EX.S, fn current_description ->
|
||||||
...> {current_description, {EX.P, EX.NEW}}
|
...> {current_description, {EX.P, EX.NEW}}
|
||||||
...> end)
|
...> end)
|
||||||
{RDF.Description.new(EX.S, EX.P, EX.O), RDF.Graph.new(EX.S, EX.P, EX.NEW)}
|
{RDF.Description.new({EX.S, EX.P, EX.O}), RDF.Graph.new({EX.S, EX.P, EX.NEW})}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@impl Access
|
@impl Access
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule RDF.Vocabulary.Namespace do
|
||||||
the `RDF.NS` module.
|
the `RDF.NS` module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
alias RDF.Description
|
||||||
alias RDF.Utils.ResourceClassifier
|
alias RDF.Utils.ResourceClassifier
|
||||||
|
|
||||||
@vocabs_dir "priv/vocabs"
|
@vocabs_dir "priv/vocabs"
|
||||||
|
@ -123,10 +124,20 @@ defmodule RDF.Vocabulary.Namespace do
|
||||||
end
|
end
|
||||||
|
|
||||||
def unquote(:"$handle_undefined_function")(term, [subject | objects]) do
|
def unquote(:"$handle_undefined_function")(term, [subject | objects]) do
|
||||||
|
objects =
|
||||||
|
case objects do
|
||||||
|
[objects] when is_list(objects) -> objects
|
||||||
|
_ -> objects
|
||||||
|
end
|
||||||
|
|
||||||
if MapSet.member?(@ignored_terms, term) do
|
if MapSet.member?(@ignored_terms, term) do
|
||||||
raise UndefinedFunctionError
|
raise UndefinedFunctionError
|
||||||
else
|
else
|
||||||
RDF.Description.new(subject, term_to_iri(@base_iri, term), objects)
|
case subject do
|
||||||
|
%Description{} -> subject
|
||||||
|
_ -> Description.new(subject)
|
||||||
|
end
|
||||||
|
|> Description.add({term_to_iri(@base_iri, term), objects})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -153,8 +164,15 @@ defmodule RDF.Vocabulary.Namespace do
|
||||||
def unquote(term)(), do: unquote(Macro.escape(iri))
|
def unquote(term)(), do: unquote(Macro.escape(iri))
|
||||||
|
|
||||||
@doc "`RDF.Description` builder for `#{unquote(term)}/0`"
|
@doc "`RDF.Description` builder for `#{unquote(term)}/0`"
|
||||||
|
def unquote(term)(subject, object)
|
||||||
|
|
||||||
|
def unquote(term)(%Description{} = subject, object) do
|
||||||
|
Description.add(subject, {unquote(Macro.escape(iri)), object})
|
||||||
|
end
|
||||||
|
|
||||||
def unquote(term)(subject, object) do
|
def unquote(term)(subject, object) do
|
||||||
RDF.Description.new(subject, unquote(Macro.escape(iri)), object)
|
Description.new(subject)
|
||||||
|
|> Description.add({unquote(Macro.escape(iri)), object})
|
||||||
end
|
end
|
||||||
|
|
||||||
# Is there a better way to support multiple objects via arguments?
|
# Is there a better way to support multiple objects via arguments?
|
||||||
|
@ -224,7 +242,7 @@ defmodule RDF.Vocabulary.Namespace do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp raw_rdf_data(%RDF.Description{} = rdf_data), do: rdf_data
|
defp raw_rdf_data(%Description{} = rdf_data), do: rdf_data
|
||||||
defp raw_rdf_data(%RDF.Graph{} = rdf_data), do: rdf_data
|
defp raw_rdf_data(%RDF.Graph{} = rdf_data), do: rdf_data
|
||||||
defp raw_rdf_data(%RDF.Dataset{} = rdf_data), do: rdf_data
|
defp raw_rdf_data(%RDF.Dataset{} = rdf_data), do: rdf_data
|
||||||
|
|
||||||
|
|
|
@ -325,7 +325,8 @@ defmodule RDF.DatasetTest do
|
||||||
ds =
|
ds =
|
||||||
Dataset.add(
|
Dataset.add(
|
||||||
dataset(),
|
dataset(),
|
||||||
Description.new(EX.Subject1, [
|
Description.new(EX.Subject1)
|
||||||
|
|> Description.add([
|
||||||
{EX.predicate1(), EX.Object1},
|
{EX.predicate1(), EX.Object1},
|
||||||
{EX.predicate2(), EX.Object2}
|
{EX.predicate2(), EX.Object2}
|
||||||
])
|
])
|
||||||
|
@ -339,7 +340,8 @@ defmodule RDF.DatasetTest do
|
||||||
ds =
|
ds =
|
||||||
Dataset.add(
|
Dataset.add(
|
||||||
dataset(),
|
dataset(),
|
||||||
Description.new(EX.Subject1, [
|
Description.new(EX.Subject1)
|
||||||
|
|> RDF.Description.add([
|
||||||
{EX.predicate1(), EX.Object1},
|
{EX.predicate1(), EX.Object1},
|
||||||
{EX.predicate2(), EX.Object2}
|
{EX.predicate2(), EX.Object2}
|
||||||
]),
|
]),
|
||||||
|
@ -707,7 +709,10 @@ defmodule RDF.DatasetTest do
|
||||||
test "a Description" do
|
test "a Description" do
|
||||||
ds =
|
ds =
|
||||||
Dataset.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}, {EX.S1, EX.P3, EX.O3}])
|
Dataset.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}, {EX.S1, EX.P3, EX.O3}])
|
||||||
|> RDF.Dataset.put(Description.new(EX.S1, [{EX.P3, EX.O4}, {EX.P2, bnode(:foo)}]))
|
|> RDF.Dataset.put(
|
||||||
|
Description.new(EX.S1)
|
||||||
|
|> Description.add([{EX.P3, EX.O4}, {EX.P2, bnode(:foo)}])
|
||||||
|
)
|
||||||
|
|
||||||
assert Dataset.statement_count(ds) == 4
|
assert Dataset.statement_count(ds) == 4
|
||||||
assert dataset_includes_statement?(ds, {EX.S1, EX.P1, EX.O1})
|
assert dataset_includes_statement?(ds, {EX.S1, EX.P1, EX.O1})
|
||||||
|
@ -823,15 +828,15 @@ defmodule RDF.DatasetTest do
|
||||||
|
|
||||||
test "multiple statements with a Description",
|
test "multiple statements with a Description",
|
||||||
%{dataset1: dataset1, dataset2: dataset2} do
|
%{dataset1: dataset1, dataset2: dataset2} do
|
||||||
assert Dataset.delete(dataset1, Description.new(EX.S1, EX.p1(), EX.O1)) == Dataset.new()
|
assert Dataset.delete(dataset1, Description.new({EX.S1, EX.p1(), EX.O1})) == Dataset.new()
|
||||||
|
|
||||||
assert Dataset.delete(dataset1, Description.new(EX.S1, EX.p1(), EX.O1), EX.Graph) ==
|
assert Dataset.delete(dataset1, Description.new({EX.S1, EX.p1(), EX.O1}), EX.Graph) ==
|
||||||
dataset1
|
dataset1
|
||||||
|
|
||||||
assert Dataset.delete(dataset2, Description.new(EX.S2, EX.p2(), EX.O2), EX.Graph) ==
|
assert Dataset.delete(dataset2, Description.new({EX.S2, EX.p2(), EX.O2}), EX.Graph) ==
|
||||||
dataset1
|
dataset1
|
||||||
|
|
||||||
assert Dataset.delete(dataset2, Description.new(EX.S1, EX.p1(), EX.O1)) ==
|
assert Dataset.delete(dataset2, Description.new({EX.S1, EX.p1(), EX.O1})) ==
|
||||||
Dataset.new({EX.S2, EX.p2(), EX.O2, EX.Graph})
|
Dataset.new({EX.S2, EX.p2(), EX.O2, EX.Graph})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -26,128 +26,61 @@ defmodule RDF.DescriptionTest do
|
||||||
assert description_of_subject(Description.new(bnode(:foo)), bnode(:foo))
|
assert description_of_subject(Description.new(bnode(:foo)), bnode(:foo))
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with a single initial triple" do
|
test "with another description" do
|
||||||
desc = Description.new({EX.Subject, EX.predicate(), EX.Object})
|
existing_description = description({EX.Subject, EX.predicate(), EX.Object})
|
||||||
assert description_of_subject(desc, iri(EX.Subject))
|
new_description = Description.new(existing_description)
|
||||||
assert description_includes_predication(desc, {EX.predicate(), iri(EX.Object)})
|
assert description_of_subject(new_description, iri(EX.Subject))
|
||||||
|
refute description_includes_predication(new_description, {EX.predicate(), iri(EX.Object)})
|
||||||
desc = Description.new(EX.Subject, EX.predicate(), 42)
|
|
||||||
assert description_of_subject(desc, iri(EX.Subject))
|
|
||||||
assert description_includes_predication(desc, {EX.predicate(), literal(42)})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "with a list of initial triples" do
|
|
||||||
desc =
|
|
||||||
Description.new([
|
|
||||||
{EX.Subject, EX.predicate1(), EX.Object1},
|
|
||||||
{EX.Subject, EX.predicate2(), EX.Object2}
|
|
||||||
])
|
|
||||||
|
|
||||||
assert description_of_subject(desc, iri(EX.Subject))
|
|
||||||
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
|
||||||
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
|
||||||
|
|
||||||
desc = Description.new(EX.Subject, EX.predicate(), [EX.Object, bnode(:foo), "bar"])
|
|
||||||
assert description_of_subject(desc, iri(EX.Subject))
|
|
||||||
assert description_includes_predication(desc, {EX.predicate(), iri(EX.Object)})
|
|
||||||
assert description_includes_predication(desc, {EX.predicate(), bnode(:foo)})
|
|
||||||
assert description_includes_predication(desc, {EX.predicate(), literal("bar")})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "from another description" do
|
|
||||||
desc1 = Description.new({EX.Other, EX.predicate(), EX.Object})
|
|
||||||
desc2 = Description.new(EX.Subject, desc1)
|
|
||||||
assert description_of_subject(desc2, iri(EX.Subject))
|
|
||||||
assert description_includes_predication(desc2, {EX.predicate(), iri(EX.Object)})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "from a map with coercible RDF term" do
|
|
||||||
desc = Description.new(EX.Subject, %{EX.Predicate => EX.Object})
|
|
||||||
assert description_of_subject(desc, iri(EX.Subject))
|
|
||||||
assert description_includes_predication(desc, {iri(EX.Predicate), iri(EX.Object)})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "with another description as subject, it performs and add " do
|
|
||||||
desc = Description.new({EX.S, EX.p(), EX.O})
|
|
||||||
|
|
||||||
assert Description.new(desc, EX.p2(), EX.O2) ==
|
|
||||||
Description.add(desc, EX.p2(), EX.O2)
|
|
||||||
|
|
||||||
assert Description.new(desc, EX.p(), [EX.O1, EX.O2]) ==
|
|
||||||
Description.add(desc, EX.p(), [EX.O1, EX.O2])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "add" do
|
describe "add/3" do
|
||||||
test "a predicate-object-pair of proper RDF terms" do
|
test "with a triple" do
|
||||||
assert Description.add(description(), EX.predicate(), iri(EX.Object))
|
assert Description.add(description(), {iri(EX.Subject), EX.predicate(), iri(EX.Object)})
|
||||||
|> description_includes_predication({EX.predicate(), iri(EX.Object)})
|
|> description_includes_predication({EX.predicate(), iri(EX.Object)})
|
||||||
|
|
||||||
|
assert Description.add(description(), {iri(EX.Subject), EX.predicate(), bnode(:foo)})
|
||||||
|
|> description_includes_predication({EX.predicate(), bnode(:foo)})
|
||||||
|
|
||||||
|
assert Description.add(description(), {iri(EX.Subject), EX.predicate(), literal(42)})
|
||||||
|
|> description_includes_predication({EX.predicate(), literal(42)})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with a predicate-object tuple" do
|
||||||
assert Description.add(description(), {EX.predicate(), iri(EX.Object)})
|
assert Description.add(description(), {EX.predicate(), iri(EX.Object)})
|
||||||
|> description_includes_predication({EX.predicate(), iri(EX.Object)})
|
|> description_includes_predication({EX.predicate(), iri(EX.Object)})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a predicate-object-pair of coercible RDF terms" do
|
test "with a predicate-object tuple and a list of objects" do
|
||||||
assert Description.add(description(), "http://example.com/predicate", iri(EX.Object))
|
desc = Description.add(description(), {EX.p(), [iri(EX.O1), iri(EX.O2)]})
|
||||||
|> description_includes_predication({EX.predicate(), iri(EX.Object)})
|
assert description_includes_predication(desc, {EX.p(), iri(EX.O1)})
|
||||||
|
assert description_includes_predication(desc, {EX.p(), iri(EX.O2)})
|
||||||
assert Description.add(
|
|
||||||
description(),
|
|
||||||
{"http://example.com/predicate", 42}
|
|
||||||
)
|
|
||||||
|> description_includes_predication({EX.predicate(), literal(42)})
|
|
||||||
|
|
||||||
assert Description.add(
|
|
||||||
description(),
|
|
||||||
{"http://example.com/predicate", true}
|
|
||||||
)
|
|
||||||
|> description_includes_predication({EX.predicate(), literal(true)})
|
|
||||||
|
|
||||||
assert Description.add(
|
|
||||||
description(),
|
|
||||||
{"http://example.com/predicate", bnode(:foo)}
|
|
||||||
)
|
|
||||||
|> description_includes_predication({EX.predicate(), bnode(:foo)})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a proper triple" do
|
test "with a list of predicate-object tuples" do
|
||||||
assert Description.add(
|
|
||||||
description(),
|
|
||||||
{iri(EX.Subject), EX.predicate(), iri(EX.Object)}
|
|
||||||
)
|
|
||||||
|> description_includes_predication({EX.predicate(), iri(EX.Object)})
|
|
||||||
|
|
||||||
assert Description.add(
|
|
||||||
description(),
|
|
||||||
{iri(EX.Subject), EX.predicate(), literal(42)}
|
|
||||||
)
|
|
||||||
|> description_includes_predication({EX.predicate(), literal(42)})
|
|
||||||
|
|
||||||
assert Description.add(
|
|
||||||
description(),
|
|
||||||
{iri(EX.Subject), EX.predicate(), bnode(:foo)}
|
|
||||||
)
|
|
||||||
|> description_includes_predication({EX.predicate(), bnode(:foo)})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "add ignores triples not about the subject of the Description struct" do
|
|
||||||
assert empty_description(
|
|
||||||
Description.add(description(), {EX.Other, EX.predicate(), iri(EX.Object)})
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a list of predicate-object-pairs" do
|
|
||||||
desc =
|
desc =
|
||||||
Description.add(
|
Description.add(description(), [
|
||||||
description(),
|
{EX.predicate(), EX.Object1},
|
||||||
[{EX.predicate(), EX.Object1}, {EX.predicate(), EX.Object2}]
|
{EX.predicate(), EX.Object2}
|
||||||
)
|
])
|
||||||
|
|
||||||
assert description_includes_predication(desc, {EX.predicate(), iri(EX.Object1)})
|
assert description_includes_predication(desc, {EX.predicate(), iri(EX.Object1)})
|
||||||
assert description_includes_predication(desc, {EX.predicate(), iri(EX.Object2)})
|
assert description_includes_predication(desc, {EX.predicate(), iri(EX.Object2)})
|
||||||
|
|
||||||
|
desc =
|
||||||
|
Description.add(description(), [
|
||||||
|
{EX.p1(), EX.O1},
|
||||||
|
{EX.p2(), [EX.O2, ~L"foo", "bar", 42]}
|
||||||
|
])
|
||||||
|
|
||||||
|
assert description_includes_predication(desc, {EX.p1(), iri(EX.O1)})
|
||||||
|
assert description_includes_predication(desc, {EX.p2(), iri(EX.O2)})
|
||||||
|
assert description_includes_predication(desc, {EX.p2(), ~L"foo"})
|
||||||
|
assert description_includes_predication(desc, {EX.p2(), ~L"bar"})
|
||||||
|
assert description_includes_predication(desc, {EX.p2(), RDF.literal(42)})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a list of triples" do
|
test "with a list of triples" do
|
||||||
desc =
|
desc =
|
||||||
Description.add(description(), [
|
Description.add(description(), [
|
||||||
{EX.Subject, EX.predicate1(), EX.Object1},
|
{EX.Subject, EX.predicate1(), EX.Object1},
|
||||||
|
@ -156,6 +89,16 @@ defmodule RDF.DescriptionTest do
|
||||||
|
|
||||||
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
||||||
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
||||||
|
|
||||||
|
desc =
|
||||||
|
Description.add(description(), [
|
||||||
|
{EX.Subject, EX.predicate1(), EX.Object1},
|
||||||
|
{EX.Subject, EX.predicate2(), [EX.Object2, EX.Object3]}
|
||||||
|
])
|
||||||
|
|
||||||
|
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object3)})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a list of mixed triples and predicate-object-pairs" do
|
test "a list of mixed triples and predicate-object-pairs" do
|
||||||
|
@ -172,24 +115,7 @@ defmodule RDF.DescriptionTest do
|
||||||
refute description_includes_predication(desc, {EX.predicate(), iri(EX.Object3)})
|
refute description_includes_predication(desc, {EX.predicate(), iri(EX.Object3)})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "another description" do
|
test "with a description map with coercible RDF terms" do
|
||||||
desc =
|
|
||||||
description([{EX.predicate1(), EX.Object1}, {EX.predicate2(), EX.Object2}])
|
|
||||||
|> Description.add(Description.new({EX.Other, EX.predicate3(), EX.Object3}))
|
|
||||||
|
|
||||||
assert description_of_subject(desc, iri(EX.Subject))
|
|
||||||
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
|
||||||
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
|
||||||
assert description_includes_predication(desc, {EX.predicate3(), iri(EX.Object3)})
|
|
||||||
|
|
||||||
desc = Description.add(desc, Description.new({EX.Other, EX.predicate1(), EX.Object4}))
|
|
||||||
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
|
||||||
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
|
||||||
assert description_includes_predication(desc, {EX.predicate3(), iri(EX.Object3)})
|
|
||||||
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object4)})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a map of predications with coercible RDF terms" do
|
|
||||||
desc =
|
desc =
|
||||||
description([{EX.predicate1(), EX.Object1}, {EX.predicate2(), EX.Object2}])
|
description([{EX.predicate1(), EX.Object1}, {EX.predicate2(), EX.Object2}])
|
||||||
|> Description.add(%{EX.predicate3() => EX.Object3})
|
|> Description.add(%{EX.predicate3() => EX.Object3})
|
||||||
|
@ -224,6 +150,38 @@ defmodule RDF.DescriptionTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "with an empty map" do
|
||||||
|
assert Description.add(description(), %{}) == description()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with empty object lists" do
|
||||||
|
assert Description.add(description(), {EX.p(), []}) == description()
|
||||||
|
assert Description.add(description(), %{EX.p() => []}) == description()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with another description" do
|
||||||
|
desc =
|
||||||
|
description([{EX.predicate1(), EX.Object1}, {EX.predicate2(), EX.Object2}])
|
||||||
|
|> Description.add(Description.new({EX.Other, EX.predicate3(), EX.Object3}))
|
||||||
|
|
||||||
|
assert description_of_subject(desc, iri(EX.Subject))
|
||||||
|
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate3(), iri(EX.Object3)})
|
||||||
|
|
||||||
|
desc = Description.add(desc, Description.new({EX.Other, EX.predicate1(), EX.Object4}))
|
||||||
|
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate3(), iri(EX.Object3)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object4)})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "triples with another subject are ignored" do
|
||||||
|
assert empty_description(
|
||||||
|
Description.add(description(), {EX.Other, EX.predicate(), iri(EX.Object)})
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
test "duplicates are ignored" do
|
test "duplicates are ignored" do
|
||||||
desc = Description.add(description(), {EX.predicate(), EX.Object})
|
desc = Description.add(description(), {EX.predicate(), EX.Object})
|
||||||
assert Description.add(desc, {EX.predicate(), EX.Object}) == desc
|
assert Description.add(desc, {EX.predicate(), EX.Object}) == desc
|
||||||
|
@ -233,6 +191,18 @@ defmodule RDF.DescriptionTest do
|
||||||
assert Description.add(desc, {EX.predicate(), literal(42)}) == desc
|
assert Description.add(desc, {EX.predicate(), literal(42)}) == desc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "coercion" do
|
||||||
|
assert Description.add(description(), {EX.Subject, EX.P, EX.O})
|
||||||
|
|> description_includes_predication({iri(EX.P), iri(EX.O)})
|
||||||
|
|
||||||
|
assert Description.add(description(), {"http://example.com/predicate", EX.Object})
|
||||||
|
|> description_includes_predication({EX.predicate(), iri(EX.Object)})
|
||||||
|
|
||||||
|
desc = Description.add(description(), {"http://example.com/predicate", [42, true]})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate(), literal(42)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate(), literal(true)})
|
||||||
|
end
|
||||||
|
|
||||||
test "non-coercible Triple elements are causing an error" do
|
test "non-coercible Triple elements are causing an error" do
|
||||||
assert_raise RDF.IRI.InvalidError, fn ->
|
assert_raise RDF.IRI.InvalidError, fn ->
|
||||||
Description.add(description(), {"not a IRI", iri(EX.Object)})
|
Description.add(description(), {"not a IRI", iri(EX.Object)})
|
||||||
|
@ -244,33 +214,116 @@ defmodule RDF.DescriptionTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "put/3" do
|
||||||
|
test "with a triple" do
|
||||||
|
assert Description.put(description(), {iri(EX.Subject), EX.predicate(), iri(EX.Object)})
|
||||||
|
|> description_includes_predication({EX.predicate(), iri(EX.Object)})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with a predicate-object tuple" do
|
||||||
|
desc = Description.put(description(), {EX.p(), [iri(EX.O1), iri(EX.O2)]})
|
||||||
|
assert description_includes_predication(desc, {EX.p(), iri(EX.O1)})
|
||||||
|
assert description_includes_predication(desc, {EX.p(), iri(EX.O2)})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with a list of predicate-object tuples" do
|
||||||
|
desc =
|
||||||
|
Description.put(description(), [
|
||||||
|
{EX.p1(), EX.O1},
|
||||||
|
{EX.p2(), [EX.O2]},
|
||||||
|
{EX.p2(), [~L"foo", "bar", 42]}
|
||||||
|
])
|
||||||
|
|
||||||
|
assert description_includes_predication(desc, {EX.p1(), iri(EX.O1)})
|
||||||
|
assert description_includes_predication(desc, {EX.p2(), iri(EX.O2)})
|
||||||
|
assert description_includes_predication(desc, {EX.p2(), ~L"foo"})
|
||||||
|
assert description_includes_predication(desc, {EX.p2(), ~L"bar"})
|
||||||
|
assert description_includes_predication(desc, {EX.p2(), RDF.literal(42)})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with a list of triples" do
|
||||||
|
desc =
|
||||||
|
Description.put(description(), [
|
||||||
|
{EX.Subject, EX.predicate1(), EX.Object1},
|
||||||
|
{EX.Subject, EX.predicate2(), [EX.Object2, EX.Object3]},
|
||||||
|
{EX.Subject, EX.predicate2(), [EX.Object4]}
|
||||||
|
])
|
||||||
|
|
||||||
|
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object3)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object4)})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with a description map with coercible RDF terms" do
|
||||||
|
desc =
|
||||||
|
description([{EX.predicate1(), EX.Object1}, {EX.predicate2(), EX.Object2}])
|
||||||
|
|> Description.put(%{
|
||||||
|
EX.predicate2() => [EX.Object3, 42],
|
||||||
|
EX.predicate3() => bnode(:foo)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert Description.count(desc) == 4
|
||||||
|
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object1)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object3)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), literal(42)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate3(), bnode(:foo)})
|
||||||
|
refute description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with an empty map" do
|
||||||
|
desc = description([{EX.predicate(), EX.Object}])
|
||||||
|
assert Description.put(desc, %{}) == desc
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with a description on the same subject" do
|
||||||
|
desc =
|
||||||
|
description([{EX.predicate1(), EX.Object1}, {EX.predicate2(), EX.Object2}])
|
||||||
|
|> Description.put(
|
||||||
|
description([
|
||||||
|
{EX.predicate1(), EX.Object4},
|
||||||
|
{EX.predicate3(), EX.Object3}
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
assert Description.count(desc) == 3
|
||||||
|
|
||||||
|
assert description_includes_predication(desc, {EX.predicate1(), iri(EX.Object4)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate2(), iri(EX.Object2)})
|
||||||
|
assert description_includes_predication(desc, {EX.predicate3(), iri(EX.Object3)})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with a description on another subject" do
|
||||||
|
desc = description([{EX.predicate1(), EX.Object1}, {EX.predicate2(), EX.Object2}])
|
||||||
|
|
||||||
|
assert Description.put(
|
||||||
|
desc,
|
||||||
|
Description.new({EX.Other, EX.predicate(), iri(EX.Object)})
|
||||||
|
) == desc
|
||||||
|
end
|
||||||
|
|
||||||
|
test "triples with another subject are ignored" do
|
||||||
|
assert empty_description(
|
||||||
|
Description.put(description(), {EX.Other, EX.predicate(), iri(EX.Object)})
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "delete" do
|
describe "delete" do
|
||||||
setup do
|
setup do
|
||||||
{:ok,
|
{:ok,
|
||||||
empty_description: Description.new(EX.S),
|
empty_description: Description.new(EX.S),
|
||||||
description1: Description.new(EX.S, EX.p(), EX.O),
|
description1: Description.new({EX.S, EX.p(), EX.O}),
|
||||||
description2: Description.new(EX.S, EX.p(), [EX.O1, EX.O2]),
|
description2: Description.new({EX.S, EX.p(), [EX.O1, EX.O2]}),
|
||||||
description3:
|
description3:
|
||||||
Description.new(EX.S, [
|
Description.new(EX.S)
|
||||||
|
|> Description.add([
|
||||||
{EX.p1(), [EX.O1, EX.O2]},
|
{EX.p1(), [EX.O1, EX.O2]},
|
||||||
{EX.p2(), EX.O3},
|
{EX.p2(), EX.O3},
|
||||||
{EX.p3(), [~B<foo>, ~L"bar"]}
|
{EX.p3(), [~B<foo>, ~L"bar"]}
|
||||||
])}
|
])}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a single statement as a predicate object",
|
|
||||||
%{
|
|
||||||
empty_description: empty_description,
|
|
||||||
description1: description1,
|
|
||||||
description2: description2
|
|
||||||
} do
|
|
||||||
assert Description.delete(empty_description, EX.p(), EX.O) == empty_description
|
|
||||||
assert Description.delete(description1, EX.p(), EX.O) == empty_description
|
|
||||||
|
|
||||||
assert Description.delete(description2, EX.p(), EX.O1) ==
|
|
||||||
Description.new(EX.S, EX.p(), EX.O2)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a single statement as a predicate-object tuple",
|
test "a single statement as a predicate-object tuple",
|
||||||
%{
|
%{
|
||||||
empty_description: empty_description,
|
empty_description: empty_description,
|
||||||
|
@ -281,7 +334,7 @@ defmodule RDF.DescriptionTest do
|
||||||
assert Description.delete(description1, {EX.p(), EX.O}) == empty_description
|
assert Description.delete(description1, {EX.p(), EX.O}) == empty_description
|
||||||
|
|
||||||
assert Description.delete(description2, {EX.p(), EX.O2}) ==
|
assert Description.delete(description2, {EX.p(), EX.O2}) ==
|
||||||
Description.new(EX.S, EX.p(), EX.O1)
|
Description.new({EX.S, EX.p(), EX.O1})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a single statement as a subject-predicate-object tuple and the proper description subject",
|
test "a single statement as a subject-predicate-object tuple and the proper description subject",
|
||||||
|
@ -294,7 +347,7 @@ defmodule RDF.DescriptionTest do
|
||||||
assert Description.delete(description1, {EX.S, EX.p(), EX.O}) == empty_description
|
assert Description.delete(description1, {EX.S, EX.p(), EX.O}) == empty_description
|
||||||
|
|
||||||
assert Description.delete(description2, {EX.S, EX.p(), EX.O2}) ==
|
assert Description.delete(description2, {EX.S, EX.p(), EX.O2}) ==
|
||||||
Description.new(EX.S, EX.p(), EX.O1)
|
Description.new({EX.S, EX.p(), EX.O1})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a single statement as a subject-predicate-object tuple and another description subject",
|
test "a single statement as a subject-predicate-object tuple and another description subject",
|
||||||
|
@ -328,7 +381,7 @@ defmodule RDF.DescriptionTest do
|
||||||
{EX.p1(), EX.O1},
|
{EX.p1(), EX.O1},
|
||||||
{EX.p2(), [EX.O2, EX.O3]},
|
{EX.p2(), [EX.O2, EX.O3]},
|
||||||
{EX.S, EX.p3(), [~B<foo>, ~L"bar"]}
|
{EX.S, EX.p3(), [~B<foo>, ~L"bar"]}
|
||||||
]) == Description.new(EX.S, EX.p1(), EX.O2)
|
]) == Description.new({EX.S, EX.p1(), EX.O2})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "multiple statements with a map of predications",
|
test "multiple statements with a map of predications",
|
||||||
|
@ -339,7 +392,7 @@ defmodule RDF.DescriptionTest do
|
||||||
EX.p1() => EX.O1,
|
EX.p1() => EX.O1,
|
||||||
EX.p2() => [EX.O2, EX.O3],
|
EX.p2() => [EX.O2, EX.O3],
|
||||||
EX.p3() => [~B<foo>, ~L"bar"]
|
EX.p3() => [~B<foo>, ~L"bar"]
|
||||||
}) == Description.new(EX.S, EX.p1(), EX.O2)
|
}) == Description.new({EX.S, EX.p1(), EX.O2})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "multiple statements with another description",
|
test "multiple statements with another description",
|
||||||
|
@ -352,12 +405,13 @@ defmodule RDF.DescriptionTest do
|
||||||
|
|
||||||
assert Description.delete(
|
assert Description.delete(
|
||||||
description3,
|
description3,
|
||||||
Description.new(EX.S, %{
|
Description.new(EX.S)
|
||||||
|
|> Description.add(%{
|
||||||
EX.p1() => EX.O1,
|
EX.p1() => EX.O1,
|
||||||
EX.p2() => [EX.O2, EX.O3],
|
EX.p2() => [EX.O2, EX.O3],
|
||||||
EX.p3() => [~B<foo>, ~L"bar"]
|
EX.p3() => [~B<foo>, ~L"bar"]
|
||||||
})
|
})
|
||||||
) == Description.new(EX.S, EX.p1(), EX.O2)
|
) == Description.new({EX.S, EX.p1(), EX.O2})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -365,9 +419,10 @@ defmodule RDF.DescriptionTest do
|
||||||
setup do
|
setup do
|
||||||
{:ok,
|
{:ok,
|
||||||
empty_description: Description.new(EX.S),
|
empty_description: Description.new(EX.S),
|
||||||
description1: Description.new(EX.S, EX.p(), [EX.O1, EX.O2]),
|
description1: Description.new({EX.S, EX.p(), [EX.O1, EX.O2]}),
|
||||||
description2:
|
description2:
|
||||||
Description.new(EX.S, [
|
Description.new(EX.S)
|
||||||
|
|> Description.add([
|
||||||
{EX.P1, [EX.O1, EX.O2]},
|
{EX.P1, [EX.O1, EX.O2]},
|
||||||
{EX.p2(), [~B<foo>, ~L"bar"]}
|
{EX.p2(), [~B<foo>, ~L"bar"]}
|
||||||
])}
|
])}
|
||||||
|
@ -382,7 +437,7 @@ defmodule RDF.DescriptionTest do
|
||||||
assert Description.delete_predicates(description1, EX.p()) == empty_description
|
assert Description.delete_predicates(description1, EX.p()) == empty_description
|
||||||
|
|
||||||
assert Description.delete_predicates(description2, EX.P1) ==
|
assert Description.delete_predicates(description2, EX.P1) ==
|
||||||
Description.new(EX.S, EX.p2(), [~B<foo>, ~L"bar"])
|
Description.new({EX.S, EX.p2(), [~B<foo>, ~L"bar"]})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a list of properties",
|
test "a list of properties",
|
||||||
|
@ -400,18 +455,18 @@ defmodule RDF.DescriptionTest do
|
||||||
|
|
||||||
describe "update/4" do
|
describe "update/4" do
|
||||||
test "list values returned from the update function become new coerced objects of the predicate" do
|
test "list values returned from the update function become new coerced objects of the predicate" do
|
||||||
assert Description.new(EX.S, EX.P, [EX.O1, EX.O2])
|
assert Description.new({EX.S, EX.P, [EX.O1, EX.O2]})
|
||||||
|> Description.update(
|
|> Description.update(
|
||||||
EX.P,
|
EX.P,
|
||||||
fn [_object | other] -> [EX.O3 | other] end
|
fn [_object | other] -> [EX.O3 | other] end
|
||||||
) ==
|
) ==
|
||||||
Description.new(EX.S, EX.P, [EX.O3, EX.O2])
|
Description.new({EX.S, EX.P, [EX.O3, EX.O2]})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "single values returned from the update function becomes new object of the predicate" do
|
test "single values returned from the update function becomes new object of the predicate" do
|
||||||
assert Description.new(EX.S, EX.P, [EX.O1, EX.O2])
|
assert Description.new({EX.S, EX.P, [EX.O1, EX.O2]})
|
||||||
|> Description.update(EX.P, fn _ -> EX.O3 end) ==
|
|> Description.update(EX.P, fn _ -> EX.O3 end) ==
|
||||||
Description.new(EX.S, EX.P, EX.O3)
|
Description.new({EX.S, EX.P, EX.O3})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returning an empty list or nil from the update function causes a removal of the predications" do
|
test "returning an empty list or nil from the update function causes a removal of the predications" do
|
||||||
|
@ -421,11 +476,11 @@ defmodule RDF.DescriptionTest do
|
||||||
|
|
||||||
assert description
|
assert description
|
||||||
|> Description.update(EX.p(), fn _ -> [] end) ==
|
|> Description.update(EX.p(), fn _ -> [] end) ==
|
||||||
Description.new(EX.S, {EX.p(), []})
|
Description.new(EX.S)
|
||||||
|
|
||||||
assert description
|
assert description
|
||||||
|> Description.update(EX.p(), fn _ -> nil end) ==
|
|> Description.update(EX.p(), fn _ -> nil end) ==
|
||||||
Description.new(EX.S, {EX.p(), []})
|
Description.new(EX.S)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "when the property is not present the initial object value is added for the predicate and the update function not called" do
|
test "when the property is not present the initial object value is added for the predicate and the update function not called" do
|
||||||
|
@ -433,7 +488,7 @@ defmodule RDF.DescriptionTest do
|
||||||
|
|
||||||
assert Description.new(EX.S)
|
assert Description.new(EX.S)
|
||||||
|> Description.update(EX.P, EX.O, fun) ==
|
|> Description.update(EX.P, EX.O, fun) ==
|
||||||
Description.new(EX.S, EX.P, EX.O)
|
Description.new({EX.S, EX.P, EX.O})
|
||||||
|
|
||||||
assert Description.new(EX.S)
|
assert Description.new(EX.S)
|
||||||
|> Description.update(EX.P, fun) ==
|
|> Description.update(EX.P, fun) ==
|
||||||
|
@ -449,20 +504,47 @@ defmodule RDF.DescriptionTest do
|
||||||
assert Enum.count(desc.predications) == 0
|
assert Enum.count(desc.predications) == 0
|
||||||
|
|
||||||
{{subject, predicate, _}, desc} =
|
{{subject, predicate, _}, desc} =
|
||||||
Description.new([{EX.S, EX.p(), EX.O1}, {EX.S, EX.p(), EX.O2}])
|
Description.new(EX.S)
|
||||||
|
|> Description.add([{EX.S, EX.p(), EX.O1}, {EX.S, EX.p(), EX.O2}])
|
||||||
|> Description.pop()
|
|> Description.pop()
|
||||||
|
|
||||||
assert {subject, predicate} == {iri(EX.S), iri(EX.p())}
|
assert {subject, predicate} == {iri(EX.S), iri(EX.p())}
|
||||||
assert Enum.count(desc.predications) == 1
|
assert Enum.count(desc.predications) == 1
|
||||||
|
|
||||||
{{subject, _, _}, desc} =
|
{{subject, _, _}, desc} =
|
||||||
Description.new([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
Description.new(EX.S)
|
||||||
|
|> Description.add([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
||||||
|> Description.pop()
|
|> Description.pop()
|
||||||
|
|
||||||
assert subject == iri(EX.S)
|
assert subject == iri(EX.S)
|
||||||
assert Enum.count(desc.predications) == 1
|
assert Enum.count(desc.predications) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "include?/2" do
|
||||||
|
desc =
|
||||||
|
Description.new(EX.S)
|
||||||
|
|> Description.add([
|
||||||
|
{EX.p1(), [EX.O1, EX.O2]},
|
||||||
|
{EX.p2(), EX.O3},
|
||||||
|
{EX.p3(), [~B<foo>, ~L"bar"]}
|
||||||
|
])
|
||||||
|
|
||||||
|
assert Description.include?(desc, {EX.p1(), EX.O2})
|
||||||
|
assert Description.include?(desc, {EX.p1(), [EX.O1, EX.O2]})
|
||||||
|
assert Description.include?(desc, [{EX.p1(), [EX.O1]}, {EX.p2(), EX.O3}])
|
||||||
|
assert Description.include?(desc, %{EX.p1() => [EX.O1, EX.O2], EX.p2() => EX.O3})
|
||||||
|
|
||||||
|
assert Description.include?(
|
||||||
|
desc,
|
||||||
|
Description.new(EX.S)
|
||||||
|
|> Description.add(%{EX.p1() => [EX.O1, EX.O2], EX.p2() => EX.O3})
|
||||||
|
)
|
||||||
|
|
||||||
|
refute Description.include?(desc, {EX.p4(), EX.O1})
|
||||||
|
refute Description.include?(desc, {EX.p1(), EX.O3})
|
||||||
|
refute Description.include?(desc, {EX.p1(), [EX.O1, EX.O3]})
|
||||||
|
end
|
||||||
|
|
||||||
test "values/1" do
|
test "values/1" do
|
||||||
assert Description.new(EX.s()) |> Description.values() == %{}
|
assert Description.new(EX.s()) |> Description.values() == %{}
|
||||||
|
|
||||||
|
@ -487,20 +569,24 @@ defmodule RDF.DescriptionTest do
|
||||||
|
|
||||||
describe "take/2" do
|
describe "take/2" do
|
||||||
test "with a non-empty property list" do
|
test "with a non-empty property list" do
|
||||||
assert Description.new([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
assert Description.new(EX.S)
|
||||||
|
|> Description.add([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
||||||
|> Description.take([EX.p2(), EX.p3()]) ==
|
|> Description.take([EX.p2(), EX.p3()]) ==
|
||||||
Description.new({EX.S, EX.p2(), EX.O2})
|
Description.new({EX.S, EX.p2(), EX.O2})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with an empty property list" do
|
test "with an empty property list" do
|
||||||
assert Description.new([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
assert Description.new(EX.S)
|
||||||
|
|> Description.add([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
||||||
|> Description.take([]) == Description.new(EX.S)
|
|> Description.take([]) == Description.new(EX.S)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with nil" do
|
test "with nil" do
|
||||||
assert Description.new([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
assert Description.new(EX.S)
|
||||||
|
|> Description.add([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
||||||
|> Description.take(nil) ==
|
|> Description.take(nil) ==
|
||||||
Description.new([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
Description.new(EX.S)
|
||||||
|
|> Description.add([{EX.S, EX.p1(), EX.O1}, {EX.S, EX.p2(), EX.O2}])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -516,7 +602,11 @@ defmodule RDF.DescriptionTest do
|
||||||
test "Enum.count" do
|
test "Enum.count" do
|
||||||
assert Enum.count(Description.new(EX.foo())) == 0
|
assert Enum.count(Description.new(EX.foo())) == 0
|
||||||
assert Enum.count(Description.new({EX.S, EX.p(), EX.O})) == 1
|
assert Enum.count(Description.new({EX.S, EX.p(), EX.O})) == 1
|
||||||
assert Enum.count(Description.new([{EX.S, EX.p(), EX.O1}, {EX.S, EX.p(), EX.O2}])) == 2
|
|
||||||
|
assert Enum.count(
|
||||||
|
Description.new(EX.S)
|
||||||
|
|> Description.add([{EX.S, EX.p(), EX.O1}, {EX.S, EX.p(), EX.O2}])
|
||||||
|
) == 2
|
||||||
end
|
end
|
||||||
|
|
||||||
test "Enum.member?" do
|
test "Enum.member?" do
|
||||||
|
@ -524,7 +614,8 @@ defmodule RDF.DescriptionTest do
|
||||||
assert Enum.member?(Description.new({EX.S, EX.p(), EX.O}), {EX.S, EX.p(), EX.O})
|
assert Enum.member?(Description.new({EX.S, EX.p(), EX.O}), {EX.S, EX.p(), EX.O})
|
||||||
|
|
||||||
desc =
|
desc =
|
||||||
Description.new([
|
Description.new(EX.Subject)
|
||||||
|
|> Description.add([
|
||||||
{EX.Subject, EX.predicate1(), EX.Object1},
|
{EX.Subject, EX.predicate1(), EX.Object1},
|
||||||
{EX.Subject, EX.predicate2(), EX.Object2},
|
{EX.Subject, EX.predicate2(), EX.Object2},
|
||||||
{EX.predicate2(), EX.Object3}
|
{EX.predicate2(), EX.Object3}
|
||||||
|
@ -538,7 +629,8 @@ defmodule RDF.DescriptionTest do
|
||||||
|
|
||||||
test "Enum.reduce" do
|
test "Enum.reduce" do
|
||||||
desc =
|
desc =
|
||||||
Description.new([
|
Description.new(EX.Subject)
|
||||||
|
|> Description.add([
|
||||||
{EX.Subject, EX.predicate1(), EX.Object1},
|
{EX.Subject, EX.predicate1(), EX.Object1},
|
||||||
{EX.Subject, EX.predicate2(), EX.Object2},
|
{EX.Subject, EX.predicate2(), EX.Object2},
|
||||||
{EX.predicate2(), EX.Object3}
|
{EX.predicate2(), EX.Object3}
|
||||||
|
@ -558,7 +650,8 @@ defmodule RDF.DescriptionTest do
|
||||||
EX.predicate2() => EX.Object2
|
EX.predicate2() => EX.Object2
|
||||||
}
|
}
|
||||||
|
|
||||||
assert Enum.into(map, Description.new(EX.Subject)) == Description.new(EX.Subject, map)
|
assert Enum.into(map, Description.new(EX.Subject)) ==
|
||||||
|
Description.new(EX.Subject) |> Description.add(map)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with a list of triples" do
|
test "with a list of triples" do
|
||||||
|
@ -567,7 +660,9 @@ defmodule RDF.DescriptionTest do
|
||||||
{EX.Subject, EX.predicate2(), EX.Object2}
|
{EX.Subject, EX.predicate2(), EX.Object2}
|
||||||
]
|
]
|
||||||
|
|
||||||
assert Enum.into(triples, Description.new(EX.Subject)) == Description.new(triples)
|
assert Enum.into(triples, Description.new(EX.Subject)) ==
|
||||||
|
Description.new(EX.Subject)
|
||||||
|
|> Description.add(triples)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with a list of predicate-object pairs" do
|
test "with a list of predicate-object pairs" do
|
||||||
|
@ -576,7 +671,9 @@ defmodule RDF.DescriptionTest do
|
||||||
{EX.predicate2(), EX.Object2}
|
{EX.predicate2(), EX.Object2}
|
||||||
]
|
]
|
||||||
|
|
||||||
assert Enum.into(pairs, Description.new(EX.Subject)) == Description.new(EX.Subject, pairs)
|
assert Enum.into(pairs, Description.new(EX.Subject)) ==
|
||||||
|
Description.new(EX.Subject)
|
||||||
|
|> Description.add(pairs)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with a list of lists" do
|
test "with a list of lists" do
|
||||||
|
@ -586,7 +683,8 @@ defmodule RDF.DescriptionTest do
|
||||||
]
|
]
|
||||||
|
|
||||||
assert Enum.into(lists, Description.new(EX.Subject)) ==
|
assert Enum.into(lists, Description.new(EX.Subject)) ==
|
||||||
Description.new(Enum.map(lists, &List.to_tuple/1))
|
Description.new(EX.Subject)
|
||||||
|
|> Description.add(Enum.map(lists, &List.to_tuple/1))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -594,23 +692,24 @@ defmodule RDF.DescriptionTest do
|
||||||
test "access with the [] operator" do
|
test "access with the [] operator" do
|
||||||
assert Description.new(EX.Subject)[EX.predicate()] == nil
|
assert Description.new(EX.Subject)[EX.predicate()] == nil
|
||||||
|
|
||||||
assert Description.new(EX.Subject, EX.predicate(), EX.Object)[EX.predicate()] == [
|
assert Description.new({EX.Subject, EX.predicate(), EX.Object})[EX.predicate()] == [
|
||||||
iri(EX.Object)
|
iri(EX.Object)
|
||||||
]
|
]
|
||||||
|
|
||||||
assert Description.new(EX.Subject, EX.Predicate, EX.Object)[EX.Predicate] == [
|
assert Description.new({EX.Subject, EX.Predicate, EX.Object})[EX.Predicate] == [
|
||||||
iri(EX.Object)
|
iri(EX.Object)
|
||||||
]
|
]
|
||||||
|
|
||||||
assert Description.new(EX.Subject, EX.predicate(), EX.Object)[
|
assert Description.new({EX.Subject, EX.predicate(), EX.Object})[
|
||||||
"http://example.com/predicate"
|
"http://example.com/predicate"
|
||||||
] == [iri(EX.Object)]
|
] == [iri(EX.Object)]
|
||||||
|
|
||||||
assert Description.new([
|
assert (Description.new(EX.Subject)
|
||||||
{EX.Subject, EX.predicate1(), EX.Object1},
|
|> Description.add([
|
||||||
{EX.Subject, EX.predicate1(), EX.Object2},
|
{EX.Subject, EX.predicate1(), EX.Object1},
|
||||||
{EX.Subject, EX.predicate2(), EX.Object3}
|
{EX.Subject, EX.predicate1(), EX.Object2},
|
||||||
])[EX.predicate1()] ==
|
{EX.Subject, EX.predicate2(), EX.Object3}
|
||||||
|
]))[EX.predicate1()] ==
|
||||||
[iri(EX.Object1), iri(EX.Object2)]
|
[iri(EX.Object1), iri(EX.Object2)]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -216,7 +216,8 @@ defmodule RDF.GraphTest do
|
||||||
g =
|
g =
|
||||||
Graph.add(
|
Graph.add(
|
||||||
graph(),
|
graph(),
|
||||||
Description.new(EX.Subject1, [
|
Description.new(EX.Subject1)
|
||||||
|
|> Description.add([
|
||||||
{EX.predicate1(), EX.Object1},
|
{EX.predicate1(), EX.Object1},
|
||||||
{EX.predicate2(), EX.Object2}
|
{EX.predicate2(), EX.Object2}
|
||||||
])
|
])
|
||||||
|
@ -346,7 +347,10 @@ defmodule RDF.GraphTest do
|
||||||
test "a Description" do
|
test "a Description" do
|
||||||
g =
|
g =
|
||||||
Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}, {EX.S1, EX.P3, EX.O3}])
|
Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}, {EX.S1, EX.P3, EX.O3}])
|
||||||
|> RDF.Graph.put(Description.new(EX.S1, [{EX.P3, EX.O4}, {EX.P2, bnode(:foo)}]))
|
|> RDF.Graph.put(
|
||||||
|
Description.new(EX.S1)
|
||||||
|
|> Description.add([{EX.P3, EX.O4}, {EX.P2, bnode(:foo)}])
|
||||||
|
)
|
||||||
|
|
||||||
assert Graph.triple_count(g) == 4
|
assert Graph.triple_count(g) == 4
|
||||||
assert graph_includes_statement?(g, {EX.S1, EX.P1, EX.O1})
|
assert graph_includes_statement?(g, {EX.S1, EX.P1, EX.O1})
|
||||||
|
@ -454,16 +458,14 @@ defmodule RDF.GraphTest do
|
||||||
%{graph1: graph1, graph2: graph2, graph3: graph3} do
|
%{graph1: graph1, graph2: graph2, graph3: graph3} do
|
||||||
assert Graph.delete(
|
assert Graph.delete(
|
||||||
graph1,
|
graph1,
|
||||||
Description.new(
|
Description.new(EX.S)
|
||||||
EX.S,
|
|> Description.add([{EX.p(), EX.O}, {EX.p2(), EX.O2}])
|
||||||
[{EX.p(), EX.O}, {EX.p2(), EX.O2}]
|
|
||||||
)
|
|
||||||
) == Graph.new()
|
) == Graph.new()
|
||||||
|
|
||||||
assert Graph.delete(graph2, Description.new(EX.S, EX.p(), [EX.O1, EX.O2])) ==
|
assert Graph.delete(graph2, Description.new({EX.S, EX.p(), [EX.O1, EX.O2]})) ==
|
||||||
Graph.new(name: EX.Graph)
|
Graph.new(name: EX.Graph)
|
||||||
|
|
||||||
assert Graph.delete(graph3, Description.new(EX.S3, EX.p3(), ~B<foo>)) ==
|
assert Graph.delete(graph3, Description.new({EX.S3, EX.p3(), ~B<foo>})) ==
|
||||||
Graph.new([
|
Graph.new([
|
||||||
{EX.S1, EX.p1(), [EX.O1, EX.O2]},
|
{EX.S1, EX.p1(), [EX.O1, EX.O2]},
|
||||||
{EX.S2, EX.p2(), EX.O3},
|
{EX.S2, EX.p2(), EX.O3},
|
||||||
|
@ -553,7 +555,9 @@ defmodule RDF.GraphTest do
|
||||||
])
|
])
|
||||||
|> Graph.update(
|
|> Graph.update(
|
||||||
EX.S2,
|
EX.S2,
|
||||||
fn ^old_description -> Description.new(EX.S3, new_description) end
|
fn ^old_description ->
|
||||||
|
Description.new(EX.S3) |> Description.add(new_description)
|
||||||
|
end
|
||||||
) ==
|
) ==
|
||||||
Graph.new([
|
Graph.new([
|
||||||
{EX.S1, EX.p1(), [EX.O1, EX.O2]},
|
{EX.S1, EX.p1(), [EX.O1, EX.O2]},
|
||||||
|
@ -575,7 +579,8 @@ defmodule RDF.GraphTest do
|
||||||
) ==
|
) ==
|
||||||
Graph.new([
|
Graph.new([
|
||||||
{EX.S1, EX.p1(), [EX.O1, EX.O2]},
|
{EX.S1, EX.p1(), [EX.O1, EX.O2]},
|
||||||
Description.new(EX.S2, new_description)
|
Description.new(EX.S2)
|
||||||
|
|> Description.add(new_description)
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -282,21 +282,21 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
assert Example.__ENV__() == ~I<http://example.com/ex#__ENV__>
|
assert Example.__ENV__() == ~I<http://example.com/ex#__ENV__>
|
||||||
assert Example.__CALLER__() == ~I<http://example.com/ex#__CALLER__>
|
assert Example.__CALLER__() == ~I<http://example.com/ex#__CALLER__>
|
||||||
|
|
||||||
assert Example.nil(EX.S, 1) == RDF.description(EX.S, Example.nil(), 1)
|
assert Example.nil(EX.S, 1) == RDF.description({EX.S, Example.nil(), 1})
|
||||||
assert Example.true(EX.S, 1) == RDF.description(EX.S, Example.true(), 1)
|
assert Example.true(EX.S, 1) == RDF.description({EX.S, Example.true(), 1})
|
||||||
assert Example.false(EX.S, 1) == RDF.description(EX.S, Example.false(), 1)
|
assert Example.false(EX.S, 1) == RDF.description({EX.S, Example.false(), 1})
|
||||||
assert Example.do(EX.S, 1) == RDF.description(EX.S, Example.do(), 1)
|
assert Example.do(EX.S, 1) == RDF.description({EX.S, Example.do(), 1})
|
||||||
assert Example.end(EX.S, 1) == RDF.description(EX.S, Example.end(), 1)
|
assert Example.end(EX.S, 1) == RDF.description({EX.S, Example.end(), 1})
|
||||||
assert Example.else(EX.S, 1) == RDF.description(EX.S, Example.else(), 1)
|
assert Example.else(EX.S, 1) == RDF.description({EX.S, Example.else(), 1})
|
||||||
assert Example.try(EX.S, 1) == RDF.description(EX.S, Example.try(), 1)
|
assert Example.try(EX.S, 1) == RDF.description({EX.S, Example.try(), 1})
|
||||||
assert Example.rescue(EX.S, 1) == RDF.description(EX.S, Example.rescue(), 1)
|
assert Example.rescue(EX.S, 1) == RDF.description({EX.S, Example.rescue(), 1})
|
||||||
assert Example.catch(EX.S, 1) == RDF.description(EX.S, Example.catch(), 1)
|
assert Example.catch(EX.S, 1) == RDF.description({EX.S, Example.catch(), 1})
|
||||||
assert Example.after(EX.S, 1) == RDF.description(EX.S, Example.after(), 1)
|
assert Example.after(EX.S, 1) == RDF.description({EX.S, Example.after(), 1})
|
||||||
assert Example.not(EX.S, 1) == RDF.description(EX.S, Example.not(), 1)
|
assert Example.not(EX.S, 1) == RDF.description({EX.S, Example.not(), 1})
|
||||||
assert Example.cond(EX.S, 1) == RDF.description(EX.S, Example.cond(), 1)
|
assert Example.cond(EX.S, 1) == RDF.description({EX.S, Example.cond(), 1})
|
||||||
assert Example.inbits(EX.S, 1) == RDF.description(EX.S, Example.inbits(), 1)
|
assert Example.inbits(EX.S, 1) == RDF.description({EX.S, Example.inbits(), 1})
|
||||||
assert Example.inlist(EX.S, 1) == RDF.description(EX.S, Example.inlist(), 1)
|
assert Example.inlist(EX.S, 1) == RDF.description({EX.S, Example.inlist(), 1})
|
||||||
assert Example.receive(EX.S, 1) == RDF.description(EX.S, Example.receive(), 1)
|
assert Example.receive(EX.S, 1) == RDF.description({EX.S, Example.receive(), 1})
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "defvocab with invalid terms" do
|
describe "defvocab with invalid terms" do
|
||||||
|
@ -885,7 +885,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
alias TestNS.EX
|
alias TestNS.EX
|
||||||
|
|
||||||
assert Example._foo() == ~I<http://example.com/ex#_foo>
|
assert Example._foo() == ~I<http://example.com/ex#_foo>
|
||||||
assert Example._foo(EX.S, 1) == RDF.description(EX.S, Example._foo(), 1)
|
assert Example._foo(EX.S, 1) == RDF.description({EX.S, Example._foo(), 1})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -966,7 +966,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
alias TestNS.{EX, EXS}
|
alias TestNS.{EX, EXS}
|
||||||
|
|
||||||
test "one statement with a strict property term" do
|
test "one statement with a strict property term" do
|
||||||
assert EXS.foo(EX.S, EX.O) == Description.new(EX.S, EXS.foo(), EX.O)
|
assert EXS.foo(EX.S, EX.O) == Description.new({EX.S, EXS.foo(), EX.O})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "multiple statements with strict property terms and one object" do
|
test "multiple statements with strict property terms and one object" do
|
||||||
|
@ -975,7 +975,8 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
|> EXS.foo(EX.O1)
|
|> EXS.foo(EX.O1)
|
||||||
|> EXS.bar(EX.O2)
|
|> EXS.bar(EX.O2)
|
||||||
|
|
||||||
assert description == Description.new(EX.S, [{EXS.foo(), EX.O1}, {EXS.bar(), EX.O2}])
|
assert description ==
|
||||||
|
Description.new(EX.S) |> Description.add([{EXS.foo(), EX.O1}, {EXS.bar(), EX.O2}])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "multiple statements with strict property terms and multiple objects in a list" do
|
test "multiple statements with strict property terms and multiple objects in a list" do
|
||||||
|
@ -985,7 +986,8 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
|> EXS.bar([EX.O3, EX.O4])
|
|> EXS.bar([EX.O3, EX.O4])
|
||||||
|
|
||||||
assert description ==
|
assert description ==
|
||||||
Description.new(EX.S, [
|
Description.new(EX.S)
|
||||||
|
|> Description.add([
|
||||||
{EXS.foo(), EX.O1},
|
{EXS.foo(), EX.O1},
|
||||||
{EXS.foo(), EX.O2},
|
{EXS.foo(), EX.O2},
|
||||||
{EXS.bar(), EX.O3},
|
{EXS.bar(), EX.O3},
|
||||||
|
@ -1000,7 +1002,8 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
|> EXS.bar(EX.O3, EX.O4, EX.O5)
|
|> EXS.bar(EX.O3, EX.O4, EX.O5)
|
||||||
|
|
||||||
assert description ==
|
assert description ==
|
||||||
Description.new(EX.S, [
|
Description.new(EX.S)
|
||||||
|
|> Description.add([
|
||||||
{EXS.foo(), EX.O1},
|
{EXS.foo(), EX.O1},
|
||||||
{EXS.foo(), EX.O2},
|
{EXS.foo(), EX.O2},
|
||||||
{EXS.bar(), EX.O3},
|
{EXS.bar(), EX.O3},
|
||||||
|
@ -1010,7 +1013,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "one statement with a non-strict property term" do
|
test "one statement with a non-strict property term" do
|
||||||
assert EX.p(EX.S, EX.O) == Description.new(EX.S, EX.p(), EX.O)
|
assert EX.p(EX.S, EX.O) == Description.new({EX.S, EX.p(), EX.O})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "multiple statements with non-strict property terms and one object" do
|
test "multiple statements with non-strict property terms and one object" do
|
||||||
|
@ -1019,7 +1022,8 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
|> EX.p1(EX.O1)
|
|> EX.p1(EX.O1)
|
||||||
|> EX.p2(EX.O2)
|
|> EX.p2(EX.O2)
|
||||||
|
|
||||||
assert description == Description.new(EX.S, [{EX.p1(), EX.O1}, {EX.p2(), EX.O2}])
|
assert description ==
|
||||||
|
Description.new(EX.S) |> Description.add([{EX.p1(), EX.O1}, {EX.p2(), EX.O2}])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "multiple statements with non-strict property terms and multiple objects in a list" do
|
test "multiple statements with non-strict property terms and multiple objects in a list" do
|
||||||
|
@ -1029,7 +1033,8 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
|> EX.p2([EX.O3, EX.O4])
|
|> EX.p2([EX.O3, EX.O4])
|
||||||
|
|
||||||
assert description ==
|
assert description ==
|
||||||
Description.new(EX.S, [
|
Description.new(EX.S)
|
||||||
|
|> Description.add([
|
||||||
{EX.p1(), EX.O1},
|
{EX.p1(), EX.O1},
|
||||||
{EX.p1(), EX.O2},
|
{EX.p1(), EX.O2},
|
||||||
{EX.p2(), EX.O3},
|
{EX.p2(), EX.O3},
|
||||||
|
@ -1044,7 +1049,8 @@ defmodule RDF.Vocabulary.NamespaceTest do
|
||||||
|> EX.p2(EX.O3, EX.O4)
|
|> EX.p2(EX.O3, EX.O4)
|
||||||
|
|
||||||
assert description ==
|
assert description ==
|
||||||
Description.new(EX.S, [
|
Description.new(EX.S)
|
||||||
|
|> Description.add([
|
||||||
{EX.p1(), EX.O1},
|
{EX.p1(), EX.O1},
|
||||||
{EX.p1(), EX.O2},
|
{EX.p1(), EX.O2},
|
||||||
{EX.p2(), EX.O3},
|
{EX.p2(), EX.O3},
|
||||||
|
|
Loading…
Reference in a new issue