core: delete statements from a Graph

This commit is contained in:
Marcel Otto 2017-06-02 16:24:15 +02:00
parent 5575260aee
commit 377707f0ef
2 changed files with 134 additions and 0 deletions

View file

@ -112,6 +112,11 @@ defmodule RDF.Graph do
@doc """ @doc """
Adds triples to a `RDF.Graph`. Adds triples to a `RDF.Graph`.
Note: When the statements to be added are given as another `RDF.Graph`,
the graph name must not match graph name of the graph to which the statements
are added. As opposed to that `RDF.Data.merge/2` will produce a `RDF.Dataset`
containing both graphs.
""" """
def add(graph, triples) def add(graph, triples)
@ -219,6 +224,61 @@ defmodule RDF.Graph do
do: put(graph, subject, [predications]) do: put(graph, subject, [predications])
@doc """
Deletes statements from a `RDF.Graph`.
"""
def delete(graph, subject, predicate, object),
do: delete(graph, {subject, predicate, object})
@doc """
Deletes statements from a `RDF.Graph`.
Note: When the statements to be deleted are given as another `RDF.Graph`,
the graph name must not match graph name of the graph from which the statements
are deleted. If you want to delete only graphs with matching names, you can
use `RDF.Data.delete/2`.
"""
def delete(graph, triples)
def delete(%RDF.Graph{} = graph, {subject, _, _} = triple) do
do_delete(graph, subject, triple)
end
def delete(%RDF.Graph{} = graph, triples) when is_list(triples) do
Enum.reduce triples, graph, fn (triple, graph) ->
delete(graph, triple)
end
end
def delete(%RDF.Graph{} = graph, %Description{subject: subject} = description) do
do_delete(graph, subject, description)
end
def delete(%RDF.Graph{} = graph, %RDF.Graph{descriptions: descriptions}) do
Enum.reduce descriptions, graph, fn ({_, description}, graph) ->
delete(graph, description)
end
end
defp do_delete(%RDF.Graph{name: name, descriptions: descriptions} = graph,
subject, statements) do
with subject = convert_subject(subject),
description when not is_nil(description) <- descriptions[subject],
new_description = Description.delete(description, statements)
do
%RDF.Graph{name: name,
descriptions:
if Enum.empty?(new_description) do
Map.delete(descriptions, subject)
else
Map.put(descriptions, subject, new_description)
end
}
else
nil -> graph
end
end
@doc """ @doc """
Fetches the description of the given subject. Fetches the description of the given subject.

View file

@ -199,6 +199,7 @@ defmodule RDF.GraphTest do
end end
end end
describe "put" do describe "put" do
test "a list of triples" do test "a list of triples" do
g = Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}]) g = Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}])
@ -261,6 +262,79 @@ defmodule RDF.GraphTest do
end end
end end
describe "delete" do
setup do
{:ok,
graph1: Graph.new({EX.S, EX.p, EX.O}),
graph2: Graph.new(EX.Graph, {EX.S, EX.p, [EX.O1, EX.O2]}),
graph3: Graph.new([
{EX.S1, EX.p1, [EX.O1, EX.O2]},
{EX.S2, EX.p2, EX.O3},
{EX.S3, EX.p3, [~B<foo>, ~L"bar"]},
])
}
end
test "a single statement as a triple",
%{graph1: graph1, graph2: graph2} do
assert Graph.delete(Graph.new, {EX.S, EX.p, EX.O}) == Graph.new
assert Graph.delete(graph1, {EX.S, EX.p, EX.O}) == Graph.new
assert Graph.delete(graph2, {EX.S, EX.p, EX.O1}) ==
Graph.new(EX.Graph, {EX.S, EX.p, EX.O2})
assert Graph.delete(graph2, {EX.S, EX.p, EX.O1}) ==
Graph.new(EX.Graph, {EX.S, EX.p, EX.O2})
end
test "multiple statements with a triple with multiple objects",
%{graph1: graph1, graph2: graph2} do
assert Graph.delete(Graph.new, {EX.S, EX.p, [EX.O1, EX.O2]}) == Graph.new
assert Graph.delete(graph1, {EX.S, EX.p, [EX.O, EX.O2]}) == Graph.new
assert Graph.delete(graph2, {EX.S, EX.p, [EX.O1, EX.O2]}) == Graph.new(EX.Graph)
end
test "multiple statements with a list of triples",
%{graph1: graph1, graph2: graph2, graph3: graph3} do
assert Graph.delete(graph1, [{EX.S, EX.p, EX.O},
{EX.S, EX.p, EX.O2}]) == Graph.new
assert Graph.delete(graph2, [{EX.S, EX.p, EX.O1},
{EX.S, EX.p, EX.O2}]) == Graph.new(EX.Graph)
assert Graph.delete(graph3, [
{EX.S1, EX.p1, [EX.O1, EX.O2]},
{EX.S2, EX.p2, EX.O3},
{EX.S3, EX.p3, ~B<foo>}]) == Graph.new({EX.S3, EX.p3, ~L"bar"})
end
test "multiple statements with a Description",
%{graph1: graph1, graph2: graph2, graph3: graph3} do
assert Graph.delete(graph1, Description.new(EX.S,
[{EX.p, EX.O}, {EX.p2, EX.O2}])) == Graph.new
assert Graph.delete(graph2, Description.new(EX.S, EX.p, [EX.O1, EX.O2])) ==
Graph.new(EX.Graph)
assert Graph.delete(graph3, Description.new(EX.S3, EX.p3, ~B<foo>)) ==
Graph.new([
{EX.S1, EX.p1, [EX.O1, EX.O2]},
{EX.S2, EX.p2, EX.O3},
{EX.S3, EX.p3, [~L"bar"]},
])
end
test "multiple statements with a Graph",
%{graph1: graph1, graph2: graph2, graph3: graph3} do
assert Graph.delete(graph1, graph2) == graph1
assert Graph.delete(graph1, graph1) == Graph.new
assert Graph.delete(graph2, Graph.new(EX.Graph, {EX.S, EX.p, [EX.O1, EX.O3]})) ==
Graph.new(EX.Graph, {EX.S, EX.p, EX.O2})
assert Graph.delete(graph3, Graph.new([
{EX.S1, EX.p1, [EX.O1, EX.O2]},
{EX.S2, EX.p2, EX.O3},
{EX.S3, EX.p3, ~B<foo>},
])) == Graph.new({EX.S3, EX.p3, ~L"bar"})
end
end
test "pop" do test "pop" do
assert Graph.pop(Graph.new) == {nil, Graph.new} assert Graph.pop(Graph.new) == {nil, Graph.new}