From defd1857e56ccdba952ff5dcd2663d7712270bae Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Sat, 27 Oct 2018 16:30:19 +0200 Subject: [PATCH] Add values/1 on RDF.Description, RDF.Graph and RDF.Dataset --- CHANGELOG.md | 3 +++ lib/rdf/dataset.ex | 28 ++++++++++++++++++++++++++++ lib/rdf/description.ex | 22 ++++++++++++++++++++++ lib/rdf/graph.ex | 24 ++++++++++++++++++++++++ test/unit/dataset_test.exs | 15 +++++++++++++++ test/unit/description_test.exs | 6 ++++++ test/unit/graph_test.exs | 12 ++++++++++++ 7 files changed, 110 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dea8310..4b572c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ This project adheres to [Semantic Versioning](http://semver.org/) and - `RDF.Statement.values/1`, `RDF.Triple.values/1` and `RDF.Quad.values/1` returning a tuple of `RDF.Term.value/1` converted native Elixir values from a tuple of RDF terms +- `RDF.Description.values/1`, `RDF.Graph.values/1` and `RDF.Dataset.values/1` + returning a map of `RDF.Term.value/1` converted native Elixir values from the + respective structure of RDF terms ### Fixed diff --git a/lib/rdf/dataset.ex b/lib/rdf/dataset.ex index fd7e855..cc0d304 100644 --- a/lib/rdf/dataset.ex +++ b/lib/rdf/dataset.ex @@ -728,6 +728,34 @@ defmodule RDF.Dataset do end + @doc """ + Returns a nested map of the native Elixir values of a `RDF.Dataset`. + + ## Examples + + iex> [ + ...> {~I, ~I, ~L"Foo", ~I}, + ...> {~I, ~I, RDF.integer(42), } + ...> ] + ...> |> RDF.Dataset.new() + ...> |> RDF.Dataset.values() + %{ + "http://example.com/Graph" => %{ + "http://example.com/S" => %{"http://example.com/p" => ["Foo"]} + }, + nil => %{ + "http://example.com/S" => %{"http://example.com/p" => [42]} + } + } + + """ + def values(%RDF.Dataset{graphs: graphs}) do + Map.new graphs, fn {graph_name, graph} -> + {RDF.Term.value(graph_name), Graph.values(graph)} + end + end + + defimpl Enumerable do def member?(dataset, statement), do: {:ok, RDF.Dataset.include?(dataset, statement)} def count(dataset), do: {:ok, RDF.Dataset.statement_count(dataset)} diff --git a/lib/rdf/description.ex b/lib/rdf/description.ex index e93f3b9..f14b7ba 100644 --- a/lib/rdf/description.ex +++ b/lib/rdf/description.ex @@ -572,6 +572,28 @@ defmodule RDF.Description do end end + @doc """ + Returns a map of the native Elixir values of a `RDF.Description`. + + The subject is not part of the result. It can be converted separately with + `RDF.Term.value/1`. + + ## Examples + + iex> {~I, ~I, ~L"Foo"} + ...> |> RDF.Description.new() + ...> |> RDF.Description.values() + %{"http://example.com/p" => ["Foo"]} + + """ + def values(%RDF.Description{subject: subject, predications: predications}) do + Map.new predications, fn {predicate, objects} -> + { + RDF.Term.value(predicate), + objects |> Map.keys() |> Enum.map(&RDF.Term.value/1) + } + end + end defimpl Enumerable do def member?(desc, triple), do: {:ok, RDF.Description.include?(desc, triple)} diff --git a/lib/rdf/graph.ex b/lib/rdf/graph.ex index d8ab417..3052bc0 100644 --- a/lib/rdf/graph.ex +++ b/lib/rdf/graph.ex @@ -602,6 +602,30 @@ defmodule RDF.Graph do end + @doc """ + Returns a nested map of the native Elixir values of a `RDF.Graph`. + + ## Examples + + iex> [ + ...> {~I, ~I, ~L"Foo"}, + ...> {~I, ~I, RDF.integer(42)} + ...> ] + ...> |> RDF.Graph.new() + ...> |> RDF.Graph.values() + %{ + "http://example.com/S1" => %{"http://example.com/p" => ["Foo"]}, + "http://example.com/S2" => %{"http://example.com/p" => [42]} + } + + """ + def values(%RDF.Graph{descriptions: descriptions}) do + Map.new descriptions, fn {subject, description} -> + {RDF.Term.value(subject), Description.values(description)} + end + end + + defimpl Enumerable do def member?(graph, triple), do: {:ok, RDF.Graph.include?(graph, triple)} def count(graph), do: {:ok, RDF.Graph.triple_count(graph)} diff --git a/test/unit/dataset_test.exs b/test/unit/dataset_test.exs index 84b9459..74f6023 100644 --- a/test/unit/dataset_test.exs +++ b/test/unit/dataset_test.exs @@ -701,6 +701,21 @@ defmodule RDF.DatasetTest do end + test "values/1" do + assert Dataset.new() |> Dataset.values() == %{} + assert Dataset.new([{EX.s1, EX.p, EX.o1}, {EX.s2, EX.p, EX.o2, EX.graph}]) + |> Dataset.values() == + %{ + nil => %{ + RDF.Term.value(EX.s1) => %{RDF.Term.value(EX.p) => [RDF.Term.value(EX.o1)]} + }, + RDF.Term.value(EX.graph) => %{ + RDF.Term.value(EX.s2) => %{RDF.Term.value(EX.p) => [RDF.Term.value(EX.o2)]}, + } + } + end + + describe "Enumerable protocol" do test "Enum.count" do assert Enum.count(Dataset.new EX.foo) == 0 diff --git a/test/unit/description_test.exs b/test/unit/description_test.exs index 24f4697..6cf56a4 100644 --- a/test/unit/description_test.exs +++ b/test/unit/description_test.exs @@ -339,6 +339,12 @@ defmodule RDF.DescriptionTest do assert Enum.count(desc.predications) == 1 end + test "values/1" do + assert Description.new(EX.s) |> Description.values() == %{} + assert Description.new({EX.s, EX.p, ~L"Foo"}) |> Description.values() == + %{RDF.Term.value(EX.p) => ["Foo"]} + end + describe "Enumerable protocol" do test "Enum.count" do assert Enum.count(Description.new EX.foo) == 0 diff --git a/test/unit/graph_test.exs b/test/unit/graph_test.exs index ab4183d..d8a1eb0 100644 --- a/test/unit/graph_test.exs +++ b/test/unit/graph_test.exs @@ -363,6 +363,18 @@ defmodule RDF.GraphTest do assert Enum.count(graph.descriptions) == 1 end + + test "values/1" do + assert Graph.new() |> Graph.values() == %{} + assert Graph.new([{EX.s1, EX.p, EX.o1}, {EX.s2, EX.p, EX.o2}]) + |> Graph.values() == + %{ + RDF.Term.value(EX.s1) => %{RDF.Term.value(EX.p) => [RDF.Term.value(EX.o1)]}, + RDF.Term.value(EX.s2) => %{RDF.Term.value(EX.p) => [RDF.Term.value(EX.o2)]}, + } + end + + describe "Enumerable protocol" do test "Enum.count" do assert Enum.count(Graph.new EX.foo) == 0