Fix graph addition of triples with an empty object list

This commit is contained in:
Marcel Otto 2022-03-31 00:13:57 +02:00
parent 8dcd949d24
commit ca724d0300
4 changed files with 44 additions and 31 deletions

View file

@ -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
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)

View file

@ -18,8 +18,6 @@ defmodule RDF.Graph do
alias RDF.{Description, IRI, PrefixMap, PropertyMap}
alias RDF.Star.Statement
import RDF.Utils
@type graph_description :: %{Statement.subject() => Description.t()}
@type t :: %__MODULE__{
@ -192,20 +190,21 @@ defmodule RDF.Graph do
@spec add(t, input, keyword) :: t
def add(graph, input, opts \\ [])
def add(%__MODULE__{} = graph, {subject, predications}, opts),
do: do_add(graph, RDF.coerce_subject(subject), predications, opts)
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
def add(%__MODULE__{descriptions: descriptions} = graph, %Description{} = description, opts) do
if Enum.empty?(description) do
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
@ -234,26 +233,19 @@ defmodule RDF.Graph do
|> Enum.reduce(graph, &add(&2, &1, opts))
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
Enum.reduce(input, graph, &add(&2, &1, opts))
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 """
Adds statements to a `RDF.Graph` overwriting existing statements with the subjects given in the `input` data.

View file

@ -124,6 +124,11 @@ defmodule RDF.DescriptionTest do
assert description_includes_predication(desc, {EX.p(), iri(EX.O2)})
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
desc =
Description.add(description(), [

View file

@ -74,6 +74,10 @@ defmodule RDF.GraphTest do
assert graph_includes_statement?(g, {EX.Subject, EX.predicate(), EX.Object2})
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
g =
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})
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
g =
Graph.new([{EX.S1, EX.p1(), EX.O1}, {EX.S2, EX.p2(), EX.O2}, {EX.S1, EX.p3(), EX.O3}])