Add RDF.Graph.take/3

This commit is contained in:
Marcel Otto 2019-10-15 17:29:46 +02:00
parent cf568dd06e
commit 2cfa89125f
5 changed files with 103 additions and 4 deletions

View file

@ -11,6 +11,8 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
- `RDF.Description.take/2` creates a description from another one by limiting
its statements to a set of predicates
- `RDF.Graph.take/3` creates a graph from another one by limiting
its statements to a set of subjects and optionally also a set of predicates
- Mix formatter configuration for using `defvocab` without parens

View file

@ -367,6 +367,15 @@ defmodule RDF.Description do
|> List.first
end
# def update(description = %RDF.Description{}, predicate, initial \\ [], fun) do
# triple_predicate = coerce_predicate(predicate)
# description.predicates
# |> Map.update(triple_predicate, initial, fn objects ->
# end)
# end
@doc """
Gets and updates the objects of the given predicate of a Description, in a single pass.
@ -620,7 +629,13 @@ defmodule RDF.Description do
Creates a description from another one by limiting its statements to those using one of the given `predicates`.
If `predicates` contains properties that are not used in the `description`, they're simply ignored.
If `nil` is passed, the description is left untouched.
"""
def take(description, predicates)
def take(%RDF.Description{} = description, nil), do: description
def take(%RDF.Description{predications: predications} = description, predicates) do
predicates = Enum.map(predicates, &(coerce_predicate/1))
%RDF.Description{description | predications: Map.take(predications, predicates)}

View file

@ -686,6 +686,33 @@ defmodule RDF.Graph do
end
end
@doc """
Creates a graph from another one by limiting its statements to those using one of the given `subjects`.
If `subjects` contains IRIs that are not used in the `graph`, they're simply ignored.
The optional `properties` argument allows to limit also properties of the subject descriptions.
If `nil` is passed as the `subjects`, the subjects will not be limited.
"""
def take(graph, subjects, properties \\ nil)
def take(%RDF.Graph{} = graph, nil, nil), do: graph
def take(%RDF.Graph{descriptions: descriptions} = graph, subjects, nil) do
subjects = Enum.map(subjects, &(coerce_subject/1))
%RDF.Graph{graph | descriptions: Map.take(descriptions, subjects)}
end
def take(%RDF.Graph{} = graph, subjects, properties) do
graph = take(graph, subjects, nil)
%RDF.Graph{graph |
descriptions: Map.new(graph.descriptions, fn {subject, description} ->
{subject, Description.take(description, properties)}
end)
}
end
@doc """
Checks if two `RDF.Graph`s are equal.

View file

@ -357,12 +357,25 @@ defmodule RDF.DescriptionTest do
%{p: ["Foo"]}
end
test "take/2" do
describe "take/2" do
test "with a non-empty property list" do
assert Description.new([{EX.S, EX.p1, EX.O1}, {EX.S, EX.p2, EX.O2}])
|> Description.take([EX.p2, EX.p3]) ==
Description.new({EX.S, EX.p2, EX.O2})
end
test "with an empty property list" do
assert Description.new([{EX.S, EX.p1, EX.O1}, {EX.S, EX.p2, EX.O2}])
|> Description.take([]) == Description.new(EX.S)
end
test "with nil" do
assert Description.new([{EX.S, EX.p1, EX.O1}, {EX.S, EX.p2, EX.O2}])
|> Description.take(nil) ==
Description.new([{EX.S, EX.p1, EX.O1}, {EX.S, EX.p2, EX.O2}])
end
end
test "equal/2" do
assert Description.new({EX.S, EX.p, EX.O}) |> Description.equal?(Description.new({EX.S, EX.p, EX.O}))
refute Description.new({EX.S, EX.p, EX.O}) |> Description.equal?(Description.new({EX.S, EX.p, EX.O2}))

View file

@ -479,6 +479,48 @@ defmodule RDF.GraphTest do
}
end
describe "take/2" do
test "with a non-empty subject list" do
assert Graph.new([{EX.s1, EX.p, EX.o1}, {EX.s2, EX.p, EX.o2}])
|> Graph.take([EX.s2, EX.s3]) ==
Graph.new([{EX.s2, EX.p, EX.o2}])
end
test "with an empty subject list" do
assert Graph.new([{EX.s1, EX.p, EX.o1}, {EX.s2, EX.p, EX.o2}])
|> Graph.take([]) == Graph.new()
end
test "with nil" do
assert Graph.new([{EX.s1, EX.p, EX.o1}, {EX.s2, EX.p, EX.o2}])
|> Graph.take(nil) ==
Graph.new([{EX.s1, EX.p, EX.o1}, {EX.s2, EX.p, EX.o2}])
end
end
describe "take/3" do
test "with non-empty subject and property lists" do
assert Graph.new([{EX.s1, EX.p1, EX.o1}, {EX.s1, EX.p2, EX.o1}, {EX.s2, EX.p1, EX.o2}])
|> Graph.take([EX.s1, EX.s3], [EX.p2]) ==
Graph.new([{EX.s1, EX.p2, EX.o1}])
end
test "with an empty subject list" do
assert Graph.new(
[
{EX.s1, EX.p1, EX.o1},
{EX.s1, EX.p2, EX.o1},
{EX.s2, EX.p1, EX.o2}
], name: EX.Graph)
|> Graph.take([], [EX.p1]) == Graph.new(name: EX.Graph)
end
test "with nil" do
assert Graph.new([{EX.s1, EX.p1, EX.o1}, {EX.s1, EX.p2, EX.o1}, {EX.s2, EX.p1, EX.o2}])
|> Graph.take(nil, [EX.p1]) ==
Graph.new([{EX.s1, EX.p1, EX.o1}, {EX.s2, EX.p1, EX.o2}])
end
end
test "equal/2" do
assert Graph.new({EX.S, EX.p, EX.O}) |> Graph.equal?(Graph.new({EX.S, EX.p, EX.O}))