Add a values/2 variant with a custom mapping function
This commit is contained in:
parent
535e5b3713
commit
4336602dcc
16 changed files with 391 additions and 30 deletions
|
@ -16,6 +16,9 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
|
|||
- `RDF.Description.values/1`, `RDF.Graph.values/1`, `RDF.Dataset.values/1` and
|
||||
`RDF.Data.values/1` returning a map of `RDF.Term.value/1` converted native
|
||||
Elixir values from the respective structure of RDF terms
|
||||
- for all of aforementioned `values/1` functions a variant `values/2` which
|
||||
allows to specify custom mapping function to be applied when creating the resp.
|
||||
structure
|
||||
- `RDF.Literal.compare/2`, `RDF.Literal.less_than?/2` and `RDF.Literal.greater_than?/2`
|
||||
for `RDF.Datatype` aware comparisons of `RDF.Literal`s
|
||||
|
||||
|
|
79
README.md
79
README.md
|
@ -689,6 +689,83 @@ iex> RDF.list(["foo", EX.Bar, ~B<bar>, [1, 2]]) |> RDF.List.values
|
|||
%RDF.Literal{value: 2, datatype: ~I<http://www.w3.org/2001/XMLSchema#integer>}]]
|
||||
```
|
||||
|
||||
### Mapping of RDF terms and structures
|
||||
|
||||
The `RDF.Term.value/1` function converts RDF terms to Elixir values:
|
||||
|
||||
```elixir
|
||||
iex> RDF.Term.value(~I<http://example.com/>)
|
||||
"http://example.com/"
|
||||
iex> RDF.Term.value(~L"foo")
|
||||
"foo"
|
||||
iex> RDF.integer(42) |> RDF.Term.value()
|
||||
42
|
||||
```
|
||||
|
||||
It returns `nil` if no conversion is possible.
|
||||
|
||||
All structures of RDF terms also support a `values` function. On `RDF.Triple.values`, `RDF.Quad` and `RDF.Statement` the tuple of RDF terms is converted to an tuple of the resp. Elixir values. On all of the other RDF data structures (`RDF.Description`, `RDF.Graph` and `RDF.Dataset`) and the general `RDF.Data` protocol the `values` functions produces a map of the converted Elixir values.
|
||||
|
||||
```elixir
|
||||
iex> RDF.Triple.values {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)}
|
||||
{"http://example.com/S", "http://example.com/p", 42}
|
||||
|
||||
iex> {~I<http://example.com/S>, ~I<http://example.com/p>, ~L"Foo"}
|
||||
...> |> RDF.Description.new()
|
||||
...> |> RDF.Description.values()
|
||||
%{"http://example.com/p" => ["Foo"]}
|
||||
|
||||
iex> [
|
||||
...> {~I<http://example.com/S1>, ~I<http://example.com/p>, ~L"Foo"},
|
||||
...> {~I<http://example.com/S2>, ~I<http://example.com/p>, 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]}
|
||||
}
|
||||
|
||||
iex> [
|
||||
...> {~I<http://example.com/S>, ~I<http://example.com/p>, ~L"Foo", ~I<http://example.com/Graph>},
|
||||
...> {~I<http://example.com/S>, ~I<http://example.com/p>, 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]}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
All of these `values` functions also support an optional second argument for a function with a custom mapping of the terms depending on their statement position. The function will be called with a tuple `{statement_position, rdf_term}` where `statement_position` is one of the atoms `:subject`, `:predicate`, `:object` or `:graph_name`, while `rdf_term` is the RDF term to be mapped.
|
||||
|
||||
```elixir
|
||||
iex> [
|
||||
...> {~I<http://example.com/S1>, ~I<http://example.com/p>, ~L"Foo"},
|
||||
...> {~I<http://example.com/S2>, ~I<http://example.com/p>, RDF.integer(42)}
|
||||
...> ]
|
||||
...> |> RDF.Graph.new()
|
||||
...> |> RDF.Graph.values(fn
|
||||
...> {:predicate, predicate} ->
|
||||
...> predicate
|
||||
...> |> to_string()
|
||||
...> |> String.split("/")
|
||||
...> |> List.last()
|
||||
...> |> String.to_atom()
|
||||
...> {_, term} ->
|
||||
...> RDF.Term.value(term)
|
||||
...> end)
|
||||
%{
|
||||
"http://example.com/S1" => %{p: ["Foo"]},
|
||||
"http://example.com/S2" => %{p: [42]}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Serializations
|
||||
|
||||
|
@ -739,7 +816,7 @@ The `Date` and `DateTime` modules of Elixir versions < 1.7.2 don't handle negati
|
|||
## Getting help
|
||||
|
||||
- [Documentation](http://hexdocs.pm/rdf)
|
||||
- [A tutorial about working with RDF.ex vocabularies](https://medium.com/@tonyhammond/early-steps-in-elixir-and-rdf-5078a4ebfe0f)
|
||||
- [A tutorial about working with RDF.ex vocabularies by Tony Hammond](https://medium.com/@tonyhammond/early-steps-in-elixir-and-rdf-5078a4ebfe0f)
|
||||
- [Google Group](https://groups.google.com/d/forum/rdfex)
|
||||
|
||||
|
||||
|
|
|
@ -97,6 +97,10 @@ defprotocol RDF.Data do
|
|||
"""
|
||||
def values(data)
|
||||
|
||||
@doc """
|
||||
Returns a nested map of the native Elixir values of a RDF data structure with values mapped with the given function.
|
||||
"""
|
||||
def values(data, mapping)
|
||||
end
|
||||
|
||||
defimpl RDF.Data, for: RDF.Description do
|
||||
|
@ -164,6 +168,7 @@ defimpl RDF.Data, for: RDF.Description do
|
|||
def subject_count(_), do: 1
|
||||
def statement_count(description), do: RDF.Description.count(description)
|
||||
def values(description), do: RDF.Description.values(description)
|
||||
def values(description, mapping), do: RDF.Description.values(description, mapping)
|
||||
end
|
||||
|
||||
|
||||
|
@ -225,6 +230,7 @@ defimpl RDF.Data, for: RDF.Graph do
|
|||
def subject_count(graph), do: RDF.Graph.subject_count(graph)
|
||||
def statement_count(graph), do: RDF.Graph.triple_count(graph)
|
||||
def values(graph), do: RDF.Graph.values(graph)
|
||||
def values(graph, mapping), do: RDF.Graph.values(graph, mapping)
|
||||
end
|
||||
|
||||
|
||||
|
@ -279,4 +285,5 @@ defimpl RDF.Data, for: RDF.Dataset do
|
|||
def subject_count(dataset), do: dataset |> subjects |> Enum.count
|
||||
def statement_count(dataset), do: RDF.Dataset.statement_count(dataset)
|
||||
def values(dataset), do: RDF.Dataset.values(dataset)
|
||||
def values(dataset, mapping), do: RDF.Dataset.values(dataset, mapping)
|
||||
end
|
||||
|
|
|
@ -731,6 +731,11 @@ defmodule RDF.Dataset do
|
|||
@doc """
|
||||
Returns a nested map of the native Elixir values of a `RDF.Dataset`.
|
||||
|
||||
The optional second argument allows to specify a custom mapping with a function
|
||||
which will receive a tuple `{statement_position, rdf_term}` where
|
||||
`statement_position` is one of the atoms `:subject`, `:predicate`, `:object`,
|
||||
or `graph_name` while `rdf_term` is the RDF term to be mapped.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> [
|
||||
|
@ -748,10 +753,38 @@ defmodule RDF.Dataset do
|
|||
}
|
||||
}
|
||||
|
||||
iex> [
|
||||
...> {~I<http://example.com/S>, ~I<http://example.com/p>, ~L"Foo", ~I<http://example.com/Graph>},
|
||||
...> {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.integer(42), }
|
||||
...> ]
|
||||
...> |> RDF.Dataset.new()
|
||||
...> |> RDF.Dataset.values(fn
|
||||
...> {:graph_name, graph_name} ->
|
||||
...> graph_name
|
||||
...> {:predicate, predicate} ->
|
||||
...> predicate
|
||||
...> |> to_string()
|
||||
...> |> String.split("/")
|
||||
...> |> List.last()
|
||||
...> |> String.to_atom()
|
||||
...> {_, term} ->
|
||||
...> RDF.Term.value(term)
|
||||
...> end)
|
||||
%{
|
||||
~I<http://example.com/Graph> => %{
|
||||
"http://example.com/S" => %{p: ["Foo"]}
|
||||
},
|
||||
nil => %{
|
||||
"http://example.com/S" => %{p: [42]}
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
def values(%RDF.Dataset{graphs: graphs}) do
|
||||
def values(dataset, mapping \\ &RDF.Statement.default_term_mapping/1)
|
||||
|
||||
def values(%RDF.Dataset{graphs: graphs}, mapping) do
|
||||
Map.new graphs, fn {graph_name, graph} ->
|
||||
{RDF.Term.value(graph_name), Graph.values(graph)}
|
||||
{mapping.({:graph_name, graph_name}), Graph.values(graph, mapping)}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -578,6 +578,11 @@ defmodule RDF.Description do
|
|||
The subject is not part of the result. It can be converted separately with
|
||||
`RDF.Term.value/1`.
|
||||
|
||||
The optional second argument allows to specify a custom mapping with a function
|
||||
which will receive a tuple `{statement_position, rdf_term}` where
|
||||
`statement_position` is one of the atoms `:predicate` or `:object`,
|
||||
while `rdf_term` is the RDF term to be mapped.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> {~I<http://example.com/S>, ~I<http://example.com/p>, ~L"Foo"}
|
||||
|
@ -585,16 +590,33 @@ defmodule RDF.Description do
|
|||
...> |> RDF.Description.values()
|
||||
%{"http://example.com/p" => ["Foo"]}
|
||||
|
||||
iex> {~I<http://example.com/S>, ~I<http://example.com/p>, ~L"Foo"}
|
||||
...> |> RDF.Description.new()
|
||||
...> |> RDF.Description.values(fn
|
||||
...> {:predicate, predicate} ->
|
||||
...> predicate
|
||||
...> |> to_string()
|
||||
...> |> String.split("/")
|
||||
...> |> List.last()
|
||||
...> |> String.to_atom()
|
||||
...> {_, term} ->
|
||||
...> RDF.Term.value(term)
|
||||
...> end)
|
||||
%{p: ["Foo"]}
|
||||
|
||||
"""
|
||||
def values(%RDF.Description{subject: subject, predications: predications}) do
|
||||
def values(description, mapping \\ &RDF.Statement.default_term_mapping/1)
|
||||
|
||||
def values(%RDF.Description{predications: predications}, mapping) do
|
||||
Map.new predications, fn {predicate, objects} ->
|
||||
{
|
||||
RDF.Term.value(predicate),
|
||||
objects |> Map.keys() |> Enum.map(&RDF.Term.value/1)
|
||||
mapping.({:predicate, predicate}),
|
||||
objects |> Map.keys() |> Enum.map(&(mapping.({:object, &1})))
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
defimpl Enumerable do
|
||||
def member?(desc, triple), do: {:ok, RDF.Description.include?(desc, triple)}
|
||||
def count(desc), do: {:ok, RDF.Description.count(desc)}
|
||||
|
|
|
@ -605,6 +605,11 @@ defmodule RDF.Graph do
|
|||
@doc """
|
||||
Returns a nested map of the native Elixir values of a `RDF.Graph`.
|
||||
|
||||
The optional second argument allows to specify a custom mapping with a function
|
||||
which will receive a tuple `{statement_position, rdf_term}` where
|
||||
`statement_position` is one of the atoms `:subject`, `:predicate` or `:object`,
|
||||
while `rdf_term` is the RDF term to be mapped.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> [
|
||||
|
@ -618,10 +623,32 @@ defmodule RDF.Graph do
|
|||
"http://example.com/S2" => %{"http://example.com/p" => [42]}
|
||||
}
|
||||
|
||||
iex> [
|
||||
...> {~I<http://example.com/S1>, ~I<http://example.com/p>, ~L"Foo"},
|
||||
...> {~I<http://example.com/S2>, ~I<http://example.com/p>, RDF.integer(42)}
|
||||
...> ]
|
||||
...> |> RDF.Graph.new()
|
||||
...> |> RDF.Graph.values(fn
|
||||
...> {:predicate, predicate} ->
|
||||
...> predicate
|
||||
...> |> to_string()
|
||||
...> |> String.split("/")
|
||||
...> |> List.last()
|
||||
...> |> String.to_atom()
|
||||
...> {_, term} ->
|
||||
...> RDF.Term.value(term)
|
||||
...> end)
|
||||
%{
|
||||
"http://example.com/S1" => %{p: ["Foo"]},
|
||||
"http://example.com/S2" => %{p: [42]}
|
||||
}
|
||||
|
||||
"""
|
||||
def values(%RDF.Graph{descriptions: descriptions}) do
|
||||
def values(graph, mapping \\ &RDF.Statement.default_term_mapping/1)
|
||||
|
||||
def values(%RDF.Graph{descriptions: descriptions}, mapping) do
|
||||
Map.new descriptions, fn {subject, description} ->
|
||||
{RDF.Term.value(subject), Description.values(description)}
|
||||
{mapping.({:subject, subject}), Description.values(description, mapping)}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -54,23 +54,44 @@ defmodule RDF.Quad do
|
|||
|
||||
Returns `nil` if one of the components of the given tuple is not convertible via `RDF.Term.value/1`.
|
||||
|
||||
The optional second argument allows to specify a custom mapping with a function
|
||||
which will receive a tuple `{statement_position, rdf_term}` where
|
||||
`statement_position` is one of the atoms `:subject`, `:predicate`, `:object` or
|
||||
`:graph_name`, while `rdf_term` is the RDF term to be mapped. When the given
|
||||
function returns `nil` this will be interpreted as an error and will become
|
||||
the overhaul result of the `values/2` call.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> RDF.Quad.values {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
|
||||
{"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"}
|
||||
|
||||
iex> {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
|
||||
...> |> RDF.Quad.values(fn
|
||||
...> {:object, object} ->
|
||||
...> RDF.Term.value(object)
|
||||
...> {:graph_name, graph_name} ->
|
||||
...> graph_name
|
||||
...> {_, resource} ->
|
||||
...> resource |> to_string() |> String.last() |> String.to_atom()
|
||||
...> end)
|
||||
{:S, :p, 42, ~I<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)
|
||||
def values(quad, mapping \\ &Statement.default_term_mapping/1)
|
||||
|
||||
def values({subject, predicate, object, graph_context}, mapping) do
|
||||
with subject_value when not is_nil(subject_value) <- mapping.({:subject, subject}),
|
||||
predicate_value when not is_nil(predicate_value) <- mapping.({:predicate, predicate}),
|
||||
object_value when not is_nil(object_value) <- mapping.({:object, object}),
|
||||
graph_context_value <- mapping.({:graph_name, graph_context})
|
||||
do
|
||||
{subject_value, predicate_value, object_value, graph_context_value}
|
||||
else
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
def values(_), do: nil
|
||||
def values(_, _), do: nil
|
||||
|
||||
end
|
||||
|
|
|
@ -25,9 +25,9 @@ defmodule RDF.Statement do
|
|||
|
||||
## Examples
|
||||
|
||||
iex> RDF.Statement.new {"http://example.com/S", "http://example.com/p", 42}
|
||||
iex> RDF.Statement.coerce {"http://example.com/S", "http://example.com/p", 42}
|
||||
{~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)}
|
||||
iex> RDF.Statement.new {"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"}
|
||||
iex> RDF.Statement.coerce {"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"}
|
||||
{~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
|
||||
"""
|
||||
def coerce(statement)
|
||||
|
@ -77,6 +77,13 @@ defmodule RDF.Statement do
|
|||
|
||||
Returns `nil` if one of the components of the given tuple is not convertible via `RDF.Term.value/1`.
|
||||
|
||||
The optional second argument allows to specify a custom mapping with a function
|
||||
which will receive a tuple `{statement_position, rdf_term}` where
|
||||
`statement_position` is one of the atoms `:subject`, `:predicate`, `:object` or
|
||||
`:graph_name`, while `rdf_term` is the RDF term to be mapped. When the given
|
||||
function returns `nil` this will be interpreted as an error and will become
|
||||
the overhaul result of the `values/2` call.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> RDF.Statement.values {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)}
|
||||
|
@ -84,9 +91,28 @@ defmodule RDF.Statement do
|
|||
iex> RDF.Statement.values {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
|
||||
{"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"}
|
||||
|
||||
iex> {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
|
||||
...> |> RDF.Statement.values(fn
|
||||
...> {:subject, subject} ->
|
||||
...> subject |> to_string() |> String.last()
|
||||
...> {:predicate, predicate} ->
|
||||
...> predicate |> to_string() |> String.last() |> String.to_atom()
|
||||
...> {:object, object} ->
|
||||
...> RDF.Term.value(object)
|
||||
...> {:graph_name, graph_name} ->
|
||||
...> graph_name
|
||||
...> end)
|
||||
{"S", :p, 42, ~I<http://example.com/Graph>}
|
||||
|
||||
"""
|
||||
def values({_, _, _} = triple), do: RDF.Triple.values(triple)
|
||||
def values({_, _, _, _} = quad), do: RDF.Quad.values(quad)
|
||||
def values(_), do: nil
|
||||
def values(statement, mapping \\ &default_term_mapping/1)
|
||||
def values({_, _, _} = triple, mapping), do: RDF.Triple.values(triple, mapping)
|
||||
def values({_, _, _, _} = quad, mapping), do: RDF.Quad.values(quad, mapping)
|
||||
def values(_, _), do: nil
|
||||
|
||||
@doc false
|
||||
def default_term_mapping(qualified_term)
|
||||
def default_term_mapping({:graph_name, nil}), do: nil
|
||||
def default_term_mapping({_, term}), do: RDF.Term.value(term)
|
||||
|
||||
end
|
||||
|
|
|
@ -52,21 +52,39 @@ defmodule RDF.Triple do
|
|||
|
||||
Returns `nil` if one of the components of the given tuple is not convertible via `RDF.Term.value/1`.
|
||||
|
||||
The optional second argument allows to specify a custom mapping with a function
|
||||
which will receive a tuple `{statement_position, rdf_term}` where
|
||||
`statement_position` is one of the atoms `:subject`, `:predicate` or `:object`,
|
||||
while `rdf_term` is the RDF term to be mapped. When the given function returns
|
||||
`nil` this will be interpreted as an error and will become the overhaul result
|
||||
of the `values/2` call.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> RDF.Triple.values {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)}
|
||||
{"http://example.com/S", "http://example.com/p", 42}
|
||||
|
||||
iex> {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)}
|
||||
...> |> RDF.Triple.values(fn
|
||||
...> {:object, object} -> RDF.Term.value(object)
|
||||
...> {_, term} -> term |> to_string() |> String.last()
|
||||
...> end)
|
||||
{"S", "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)
|
||||
def values(triple, mapping \\ &Statement.default_term_mapping/1)
|
||||
|
||||
def values({subject, predicate, object}, mapping) do
|
||||
with subject_value when not is_nil(subject_value) <- mapping.({:subject, subject}),
|
||||
predicate_value when not is_nil(predicate_value) <- mapping.({:predicate, predicate}),
|
||||
object_value when not is_nil(object_value) <- mapping.({:object, object})
|
||||
do
|
||||
{subject_value, predicate_value, object_value}
|
||||
else
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
def values(_), do: nil
|
||||
def values(_, _), do: nil
|
||||
|
||||
end
|
||||
|
|
|
@ -423,7 +423,7 @@ defmodule RDF.DataTest do
|
|||
assert RDF.Data.statement_count(dataset) == 14
|
||||
end
|
||||
|
||||
test "values", %{dataset: dataset} do
|
||||
test "values/1", %{dataset: dataset} do
|
||||
assert RDF.Data.values(dataset) ==
|
||||
%{
|
||||
nil => %{
|
||||
|
@ -459,6 +459,52 @@ defmodule RDF.DataTest do
|
|||
}
|
||||
}
|
||||
end
|
||||
|
||||
test "values/2", %{dataset: dataset} do
|
||||
mapping = fn
|
||||
{:graph_name, graph_name} ->
|
||||
graph_name
|
||||
{:predicate, predicate} ->
|
||||
predicate |> to_string() |> String.split("/") |> List.last() |> String.to_atom()
|
||||
{_, term} ->
|
||||
RDF.Term.value(term)
|
||||
end
|
||||
|
||||
assert RDF.Data.values(dataset, mapping) ==
|
||||
%{
|
||||
nil => %{
|
||||
RDF.Term.value(RDF.iri(EX.S)) => %{
|
||||
p1: [
|
||||
RDF.Term.value(RDF.iri(EX.O1)),
|
||||
RDF.Term.value(RDF.iri(EX.O2))
|
||||
],
|
||||
p2: [RDF.Term.value(RDF.iri(EX.O3))],
|
||||
p3: ["_:foo", "bar"],
|
||||
},
|
||||
RDF.Term.value(RDF.iri(EX.S2)) => %{
|
||||
p2: [
|
||||
RDF.Term.value(RDF.iri(EX.O3)),
|
||||
RDF.Term.value(RDF.iri(EX.O4))
|
||||
],
|
||||
},
|
||||
},
|
||||
RDF.iri(EX.NamedGraph) => %{
|
||||
RDF.Term.value(RDF.iri(EX.S)) => %{
|
||||
p1: [
|
||||
RDF.Term.value(RDF.iri(EX.O1)),
|
||||
RDF.Term.value(RDF.iri(EX.O2))
|
||||
],
|
||||
p2: [RDF.Term.value(RDF.iri(EX.O3))],
|
||||
p3: ["_:foo", RDF.Term.value(RDF.iri(EX.O5)), "bar"],
|
||||
},
|
||||
RDF.Term.value(RDF.iri(EX.S3)) => %{
|
||||
p3: [
|
||||
RDF.Term.value(RDF.iri(EX.O5))
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -715,6 +715,29 @@ defmodule RDF.DatasetTest do
|
|||
}
|
||||
end
|
||||
|
||||
test "values/2" do
|
||||
mapping = fn
|
||||
{:graph_name, graph_name} ->
|
||||
graph_name
|
||||
{:predicate, predicate} ->
|
||||
predicate |> to_string() |> String.split("/") |> List.last() |> String.to_atom()
|
||||
{_, term} ->
|
||||
RDF.Term.value(term)
|
||||
end
|
||||
|
||||
assert Dataset.new() |> Dataset.values(mapping) == %{}
|
||||
assert Dataset.new([{EX.s1, EX.p, EX.o1}, {EX.s2, EX.p, EX.o2, EX.graph}])
|
||||
|> Dataset.values(mapping) ==
|
||||
%{
|
||||
nil => %{
|
||||
RDF.Term.value(EX.s1) => %{p: [RDF.Term.value(EX.o1)]}
|
||||
},
|
||||
EX.graph => %{
|
||||
RDF.Term.value(EX.s2) => %{p: [RDF.Term.value(EX.o2)]},
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
describe "Enumerable protocol" do
|
||||
test "Enum.count" do
|
||||
|
|
|
@ -345,6 +345,19 @@ defmodule RDF.DescriptionTest do
|
|||
%{RDF.Term.value(EX.p) => ["Foo"]}
|
||||
end
|
||||
|
||||
test "values/2" do
|
||||
mapping = fn
|
||||
{:predicate, predicate} ->
|
||||
predicate |> to_string() |> String.split("/") |> List.last() |> String.to_atom()
|
||||
{_, term} ->
|
||||
RDF.Term.value(term)
|
||||
end
|
||||
|
||||
assert Description.new(EX.s) |> Description.values(mapping) == %{}
|
||||
assert Description.new({EX.s, EX.p, ~L"Foo"}) |> Description.values(mapping) ==
|
||||
%{p: ["Foo"]}
|
||||
end
|
||||
|
||||
describe "Enumerable protocol" do
|
||||
test "Enum.count" do
|
||||
assert Enum.count(Description.new EX.foo) == 0
|
||||
|
|
|
@ -374,6 +374,23 @@ defmodule RDF.GraphTest do
|
|||
}
|
||||
end
|
||||
|
||||
test "values/2" do
|
||||
mapping = fn
|
||||
{:predicate, predicate} ->
|
||||
predicate |> to_string() |> String.split("/") |> List.last() |> String.to_atom()
|
||||
{_, term} ->
|
||||
RDF.Term.value(term)
|
||||
end
|
||||
|
||||
assert Graph.new() |> Graph.values(mapping) == %{}
|
||||
assert Graph.new([{EX.s1, EX.p, EX.o1}, {EX.s2, EX.p, EX.o2}])
|
||||
|> Graph.values(mapping) ==
|
||||
%{
|
||||
RDF.Term.value(EX.s1) => %{p: [RDF.Term.value(EX.o1)]},
|
||||
RDF.Term.value(EX.s2) => %{p: [RDF.Term.value(EX.o2)]},
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
describe "Enumerable protocol" do
|
||||
test "Enum.count" do
|
||||
|
|
|
@ -18,4 +18,16 @@ defmodule RDF.QuadTest do
|
|||
refute Quad.values({self(), self(), self(), self()})
|
||||
end
|
||||
end
|
||||
|
||||
test "values/2" do
|
||||
assert {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.integer(42), ~I<http://example.com/Graph>}
|
||||
|> Quad.values(fn
|
||||
{:subject, subject} -> subject |> to_string() |> String.last() |> String.to_atom()
|
||||
{:predicate, _} -> :p
|
||||
{:object, object} -> object |> RDF.Term.value() |> Kernel.+(1)
|
||||
{:graph_name, _} -> nil
|
||||
end)
|
||||
== {:S, :p, 43, nil}
|
||||
end
|
||||
|
||||
end
|
||||
|
|
6
test/unit/statement_test.exs
Normal file
6
test/unit/statement_test.exs
Normal file
|
@ -0,0 +1,6 @@
|
|||
defmodule RDF.StatementTest do
|
||||
use RDF.Test.Case
|
||||
|
||||
doctest RDF.Statement
|
||||
|
||||
end
|
|
@ -16,4 +16,14 @@ defmodule RDF.TripleTest do
|
|||
refute Triple.values({self(), self(), self()})
|
||||
end
|
||||
end
|
||||
|
||||
test "values/2" do
|
||||
assert {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.integer(42)}
|
||||
|> Triple.values(fn
|
||||
{:object, object} -> object |> RDF.Term.value() |> Kernel.+(1)
|
||||
{_, term} -> term |> to_string() |> String.last()
|
||||
end)
|
||||
== {"S", "p", 43}
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue