Fix graph addition of triples with an empty object list
This commit is contained in:
parent
8dcd949d24
commit
ca724d0300
4 changed files with 44 additions and 31 deletions
|
@ -16,6 +16,12 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
|
||||||
- The inspect string of `RDF.Description` now includes the subject separately, so
|
- The inspect string of `RDF.Description` now includes the subject separately, so
|
||||||
it can be seen also when the description is empty.
|
it can be seen also when the description is empty.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- When triples with an empty object list where added to an `RDF.Graph`, it
|
||||||
|
included empty descriptions, which lead to inconsistent behaviour
|
||||||
|
(for example it would be counted in `RDF.Graph.subject_count/1`).
|
||||||
|
|
||||||
|
|
||||||
[Compare v0.11.0...HEAD](https://github.com/rdf-elixir/rdf-ex/compare/v0.11.0...HEAD)
|
[Compare v0.11.0...HEAD](https://github.com/rdf-elixir/rdf-ex/compare/v0.11.0...HEAD)
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@ defmodule RDF.Graph do
|
||||||
alias RDF.{Description, IRI, PrefixMap, PropertyMap}
|
alias RDF.{Description, IRI, PrefixMap, PropertyMap}
|
||||||
alias RDF.Star.Statement
|
alias RDF.Star.Statement
|
||||||
|
|
||||||
import RDF.Utils
|
|
||||||
|
|
||||||
@type graph_description :: %{Statement.subject() => Description.t()}
|
@type graph_description :: %{Statement.subject() => Description.t()}
|
||||||
|
|
||||||
@type t :: %__MODULE__{
|
@type t :: %__MODULE__{
|
||||||
|
@ -192,20 +190,21 @@ defmodule RDF.Graph do
|
||||||
@spec add(t, input, keyword) :: t
|
@spec add(t, input, keyword) :: t
|
||||||
def add(graph, input, opts \\ [])
|
def add(graph, input, opts \\ [])
|
||||||
|
|
||||||
def add(%__MODULE__{} = graph, {subject, predications}, opts),
|
def add(%__MODULE__{descriptions: descriptions} = graph, %Description{} = description, opts) do
|
||||||
do: do_add(graph, RDF.coerce_subject(subject), predications, opts)
|
if Enum.empty?(description) do
|
||||||
|
|
||||||
def add(%__MODULE__{} = graph, {subject, _, _} = triple, opts),
|
|
||||||
do: do_add(graph, RDF.coerce_subject(subject), triple, opts)
|
|
||||||
|
|
||||||
def add(graph, {subject, predicate, object, _}, opts),
|
|
||||||
do: add(graph, {subject, predicate, object}, opts)
|
|
||||||
|
|
||||||
def add(%__MODULE__{} = graph, %Description{} = description, opts) do
|
|
||||||
if Description.count(description) > 0 do
|
|
||||||
do_add(graph, description.subject, description, opts)
|
|
||||||
else
|
|
||||||
graph
|
graph
|
||||||
|
else
|
||||||
|
%__MODULE__{
|
||||||
|
graph
|
||||||
|
| descriptions:
|
||||||
|
Map.update(
|
||||||
|
descriptions,
|
||||||
|
description.subject,
|
||||||
|
description,
|
||||||
|
&Description.add(&1, description, opts)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|> RDF.Star.Graph.handle_addition_annotations(description, opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -234,26 +233,19 @@ defmodule RDF.Graph do
|
||||||
|> Enum.reduce(graph, &add(&2, &1, opts))
|
|> Enum.reduce(graph, &add(&2, &1, opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add(%__MODULE__{} = graph, {subject, predications}, opts),
|
||||||
|
do: add(graph, Description.new(subject, Keyword.put(opts, :init, predications)), opts)
|
||||||
|
|
||||||
|
def add(%__MODULE__{} = graph, {subject, _, _} = triple, opts),
|
||||||
|
do: add(graph, Description.new(subject, Keyword.put(opts, :init, triple)), opts)
|
||||||
|
|
||||||
|
def add(graph, {subject, predicate, object, _}, opts),
|
||||||
|
do: add(graph, {subject, predicate, object}, opts)
|
||||||
|
|
||||||
def add(graph, input, opts) when is_list(input) or (is_map(input) and not is_struct(input)) do
|
def add(graph, input, opts) when is_list(input) or (is_map(input) and not is_struct(input)) do
|
||||||
Enum.reduce(input, graph, &add(&2, &1, opts))
|
Enum.reduce(input, graph, &add(&2, &1, opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_add(%__MODULE__{descriptions: descriptions} = graph, subject, statements, opts) do
|
|
||||||
%__MODULE__{
|
|
||||||
graph
|
|
||||||
| descriptions:
|
|
||||||
lazy_map_update(
|
|
||||||
descriptions,
|
|
||||||
subject,
|
|
||||||
# when new: create and initialize description with statements
|
|
||||||
fn -> Description.new(subject, Keyword.put(opts, :init, statements)) end,
|
|
||||||
# when update: merge statements description
|
|
||||||
fn description -> Description.add(description, statements, opts) end
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|> RDF.Star.Graph.handle_addition_annotations({subject, statements}, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Adds statements to a `RDF.Graph` overwriting existing statements with the subjects given in the `input` data.
|
Adds statements to a `RDF.Graph` overwriting existing statements with the subjects given in the `input` data.
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,11 @@ defmodule RDF.DescriptionTest do
|
||||||
assert description_includes_predication(desc, {EX.p(), iri(EX.O2)})
|
assert description_includes_predication(desc, {EX.p(), iri(EX.O2)})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "with a predicate-object tuple and an empty list of objects" do
|
||||||
|
assert Description.add(description(), {EX.p(), []}) ==
|
||||||
|
description()
|
||||||
|
end
|
||||||
|
|
||||||
test "with a list of predicate-object tuples" do
|
test "with a list of predicate-object tuples" do
|
||||||
desc =
|
desc =
|
||||||
Description.add(description(), [
|
Description.add(description(), [
|
||||||
|
|
|
@ -74,6 +74,10 @@ defmodule RDF.GraphTest do
|
||||||
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object2})
|
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object2})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "initial triples with an empty object list" do
|
||||||
|
assert Graph.new({EX.Subject, EX.predicate(), []}) == Graph.new()
|
||||||
|
end
|
||||||
|
|
||||||
test "creating a named graph with an initial description" do
|
test "creating a named graph with an initial description" do
|
||||||
g =
|
g =
|
||||||
Description.new(EX.Subject, init: {EX.predicate(), EX.Object})
|
Description.new(EX.Subject, init: {EX.predicate(), EX.Object})
|
||||||
|
@ -336,6 +340,12 @@ defmodule RDF.GraphTest do
|
||||||
assert graph_includes_statement?(g, {EX.S2, EX.P2, EX.O2})
|
assert graph_includes_statement?(g, {EX.S2, EX.P2, EX.O2})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "empty object list" do
|
||||||
|
assert Graph.add(graph(), {EX.S, EX.P, []}) == graph()
|
||||||
|
graph = Graph.new({EX.S, EX.P, EX.O})
|
||||||
|
assert Graph.add(graph, {EX.S, EX.P, []}) == graph
|
||||||
|
end
|
||||||
|
|
||||||
test "a mixed list" do
|
test "a mixed list" 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}])
|
||||||
|
|
Loading…
Reference in a new issue