From 1276f252c5157a6a9ca69633d81c3676f1474574 Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Mon, 22 Oct 2018 00:52:22 +0200 Subject: [PATCH] Add values/1 on RDF.Triple, RDF.Quad and RDF.Statement --- CHANGELOG.md | 3 +++ lib/rdf/quad.ex | 27 ++++++++++++++++++++++++++- lib/rdf/statement.ex | 18 ++++++++++++++++++ lib/rdf/triple.ex | 25 ++++++++++++++++++++++++- test/unit/quad_test.exs | 16 ++++++++++++++++ test/unit/triple_test.exs | 14 ++++++++++++++ 6 files changed, 101 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eb79c6..141ec80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ This project adheres to [Semantic Versioning](http://semver.org/) and ### Added - `RDF.Term.value/1` returning the native Elixir value of a RDF term +- `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 [Compare v0.5.1...HEAD](https://github.com/marcelotto/rdf-ex/compare/v0.5.1...HEAD) diff --git a/lib/rdf/quad.ex b/lib/rdf/quad.ex index eefcc03..788493b 100644 --- a/lib/rdf/quad.ex +++ b/lib/rdf/quad.ex @@ -6,7 +6,7 @@ defmodule RDF.Quad do RDF values for subject, predicate, object and a graph context. """ - alias RDF.Statement + alias RDF.{Statement, Term} @doc """ Creates a `RDF.Quad` with proper RDF values. @@ -48,4 +48,29 @@ defmodule RDF.Quad do def new({subject, predicate, object, graph_context}), do: new(subject, predicate, object, graph_context) + + @doc """ + Returns a tuple of native Elixir values from a `RDF.Quad` of RDF terms. + + Returns `nil` if one of the components of the given tuple is not convertible via `RDF.Term.value/1`. + + ## Examples + + iex> RDF.Quad.values {~I, ~I, RDF.literal(42), ~I} + {"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"} + + """ + def values({subject, predicate, object, graph_context}) do + with subject_value when not is_nil(subject_value) <- Term.value(subject), + predicate_value when not is_nil(predicate_value) <- Term.value(predicate), + object_value when not is_nil(object_value) <- Term.value(object), + graph_context_value when not is_nil(graph_context_value) or is_nil(graph_context) <- + Term.value(graph_context) + do + {subject_value, predicate_value, object_value, graph_context_value} + end + end + + def values(_), do: nil + end diff --git a/lib/rdf/statement.ex b/lib/rdf/statement.ex index 2e9c3d9..44d2ebb 100644 --- a/lib/rdf/statement.ex +++ b/lib/rdf/statement.ex @@ -71,4 +71,22 @@ defmodule RDF.Statement do def coerce_graph_name(arg), do: raise RDF.Quad.InvalidGraphContextError, graph_context: arg + + @doc """ + Returns a tuple of native Elixir values from a `RDF.Statement` of RDF terms. + + Returns `nil` if one of the components of the given tuple is not convertible via `RDF.Term.value/1`. + + ## Examples + + iex> RDF.Statement.values {~I, ~I, RDF.literal(42)} + {"http://example.com/S", "http://example.com/p", 42} + iex> RDF.Statement.values {~I, ~I, RDF.literal(42), ~I} + {"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"} + + """ + def values({_, _, _} = triple), do: RDF.Triple.values(triple) + def values({_, _, _, _} = quad), do: RDF.Quad.values(quad) + def values(_), do: nil + end diff --git a/lib/rdf/triple.ex b/lib/rdf/triple.ex index 3a7f3fc..a033582 100644 --- a/lib/rdf/triple.ex +++ b/lib/rdf/triple.ex @@ -6,7 +6,7 @@ defmodule RDF.Triple do RDF values for subject, predicate and object. """ - alias RDF.Statement + alias RDF.{Statement, Term} @doc """ Creates a `RDF.Triple` with proper RDF values. @@ -46,4 +46,27 @@ defmodule RDF.Triple do """ def new({subject, predicate, object}), do: new(subject, predicate, object) + + @doc """ + Returns a tuple of native Elixir values from a `RDF.Triple` of RDF terms. + + Returns `nil` if one of the components of the given tuple is not convertible via `RDF.Term.value/1`. + + ## Examples + + iex> RDF.Triple.values {~I, ~I, RDF.literal(42)} + {"http://example.com/S", "http://example.com/p", 42} + + """ + def values({subject, predicate, object}) do + with subject_value when not is_nil(subject_value) <- Term.value(subject), + predicate_value when not is_nil(predicate_value) <- Term.value(predicate), + object_value when not is_nil(object_value) <- Term.value(object) + do + {subject_value, predicate_value, object_value} + end + end + + def values(_), do: nil + end diff --git a/test/unit/quad_test.exs b/test/unit/quad_test.exs index 0761ef0..a711d88 100644 --- a/test/unit/quad_test.exs +++ b/test/unit/quad_test.exs @@ -2,4 +2,20 @@ defmodule RDF.QuadTest do use RDF.Test.Case doctest RDF.Quad + + alias RDF.Quad + + describe "values/1" do + test "with a valid RDF.Quad" do + assert Quad.values({~I, ~I, RDF.integer(42), ~I}) + == {"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"} + assert Quad.values({~I, ~I, RDF.integer(42), nil}) + == {"http://example.com/S", "http://example.com/p", 42, nil} + end + + test "with an invalid RDF.Quad" do + refute Quad.values({~I, ~I}) + refute Quad.values({self(), self(), self(), self()}) + end + end end diff --git a/test/unit/triple_test.exs b/test/unit/triple_test.exs index 6ff686e..56a3866 100644 --- a/test/unit/triple_test.exs +++ b/test/unit/triple_test.exs @@ -2,4 +2,18 @@ defmodule RDF.TripleTest do use RDF.Test.Case doctest RDF.Triple + + alias RDF.Triple + + describe "values/1" do + test "with a valid RDF.Triple" do + assert Triple.values({~I, ~I, RDF.integer(42)}) + == {"http://example.com/S", "http://example.com/p", 42} + end + + test "with an invalid RDF.Triple" do + refute Triple.values({~I, ~I}) + refute Triple.values({self(), self(), self()}) + end + end end