From a1cbbd24b603c53c29cafaf9a23e59c1f2ae00b6 Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Wed, 20 Nov 2019 01:45:34 +0100 Subject: [PATCH] Add RDF.Diff.apply/2 --- lib/rdf/diff.ex | 23 ++++++++++- test/unit/diff_test.exs | 85 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/lib/rdf/diff.ex b/lib/rdf/diff.ex index d8224ef..5aa6d11 100644 --- a/lib/rdf/diff.ex +++ b/lib/rdf/diff.ex @@ -30,7 +30,7 @@ defmodule RDF.Diff do defp coerce_graph(data), do: Graph.new(data) @doc """ - Computes the diff between two `RDF.Graph`s or `RDF.Description`s. + Computes a diff between two `RDF.Graph`s or `RDF.Description`s. The first argument represents the original and the second argument the new version of the RDF data to be compared. Any combination of `RDF.Graph`s or @@ -149,4 +149,25 @@ defmodule RDF.Diff do deletions: Graph.add(diff1.deletions, diff2.deletions) ) end + + @doc """ + Applies a diff to a `RDF.Graph` or `RDF.Description` by deleting the `deletions` and adding the `additions` of the `diff`. + + Deletions of statements which are not present in the given graph or description + are simply ignored. + + The result of an application is always a `RDF.Graph`, even if a `RDF.Description` + is given and the additions from the diff are all about the subject of this description. + """ + def apply(diff, rdf_data) + + def apply(%__MODULE__{} = diff, %Graph{} = graph) do + graph + |> Graph.delete(diff.deletions) + |> Graph.add(diff.additions) + end + + def apply(%__MODULE__{} = diff, %Description{} = description) do + __MODULE__.apply(diff, Graph.new(description)) + end end diff --git a/test/unit/diff_test.exs b/test/unit/diff_test.exs index 3e9364e..2336383 100644 --- a/test/unit/diff_test.exs +++ b/test/unit/diff_test.exs @@ -197,4 +197,89 @@ defmodule RDF.DiffTest do ]) ) end + + describe "apply/2" do + test "on a graph" do + assert Diff.new( + additions: Graph.new([ + EX.S1 + |> EX.p(EX.O3) + |> EX.p3(EX.O), + EX.S3 + |> EX.p(EX.O) + ]), + deletions: Graph.new([ + EX.S1 + |> EX.p(EX.O1) + |> EX.p2(EX.O), + EX.S2 + |> EX.p(EX.O) + ])) + |> Diff.apply(Graph.new([ + EX.S1 + |> EX.p(EX.O1, EX.O2) + |> EX.p2(EX.O), + EX.S2 + |> EX.p(EX.O) + ])) == + Graph.new([ + EX.S1 + |> EX.p(EX.O2, EX.O3) + |> EX.p3(EX.O), + EX.S3 + |> EX.p(EX.O) + ]) + end + + test "on a description" do + assert Diff.new( + additions: Graph.new([ + EX.S1 + |> EX.p(EX.O3) + |> EX.p3(EX.O), + EX.S3 + |> EX.p(EX.O) + ]), + deletions: Graph.new([ + EX.S1 + |> EX.p(EX.O1) + |> EX.p2(EX.O), + ])) + |> Diff.apply( + EX.S1 + |> EX.p(EX.O1, EX.O2) + |> EX.p2(EX.O) + ) == + Graph.new([ + EX.S1 + |> EX.p(EX.O2, EX.O3) + |> EX.p3(EX.O), + EX.S3 + |> EX.p(EX.O) + ]) + end + + test "when the statements to be deleted are not present" do + assert Diff.new( + additions: Graph.new( + EX.S1 + |> EX.p(EX.O4) + ), + deletions: Graph.new([ + EX.S1 + |> EX.p(EX.O2, EX.O3) + |> EX.p2(EX.O), + EX.S2 + |> EX.p(EX.O) + ])) + |> Diff.apply(Graph.new( + EX.S1 + |> EX.p(EX.O1, EX.O2) + )) == + Graph.new( + EX.S1 + |> EX.p(EX.O1, EX.O4) + ) + end + end end