Let RDF.Turtle.Encoder use other prefixes when none provided

This commit is contained in:
Marcel Otto 2019-04-01 02:44:12 +02:00
parent eb71b26f08
commit 2e49f8b73a
3 changed files with 52 additions and 10 deletions

View file

@ -26,6 +26,11 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
- when `RDF.Graph.add` and `RDF.Graph.put` are called with another graph, its - when `RDF.Graph.add` and `RDF.Graph.put` are called with another graph, its
prefixes are merged prefixes are merged
- `RDF.Turtle.Decoder` saves the prefixes now - `RDF.Turtle.Decoder` saves the prefixes now
- `RDF.Turtle.Encoder` now takes the prefixes to be serialized in the following
order of precedence:
- from the `prefixes` option (as before)
- from the `prefixes` field of the given graph
- from the `RDF.default_prefixes`
- drop support for OTP < 20, since prefixes can consist of UTF characters which - drop support for OTP < 20, since prefixes can consist of UTF characters which
are not supported in atoms on these versions are not supported in atoms on these versions

View file

@ -29,7 +29,7 @@ defmodule RDF.Turtle.Encoder do
@impl RDF.Serialization.Encoder @impl RDF.Serialization.Encoder
def encode(data, opts \\ []) do def encode(data, opts \\ []) do
with base = Keyword.get(opts, :base) |> init_base(), with base = Keyword.get(opts, :base) |> init_base(),
prefixes = Keyword.get(opts, :prefixes, %{}) |> init_prefixes(), prefixes = Keyword.get(opts, :prefixes) |> prefixes(data) |> init_prefixes(),
{:ok, state} = State.start_link(data, base, prefixes) do {:ok, state} = State.start_link(data, base, prefixes) do
try do try do
State.preprocess(state) State.preprocess(state)
@ -58,11 +58,13 @@ defmodule RDF.Turtle.Encoder do
end end
end end
defp init_prefixes(nil), do: %{} defp prefixes(nil, %RDF.Graph{prefixes: prefixes}) when not is_nil(prefixes), do: prefixes
defp prefixes(nil, _), do: RDF.default_prefixes()
defp prefixes(prefixes, _), do: RDF.PrefixMap.new(prefixes)
defp init_prefixes(prefixes) do defp init_prefixes(prefixes) do
Enum.reduce prefixes, %{}, fn {prefix, iri}, reverse -> Enum.reduce prefixes, %{}, fn {prefix, iri}, reverse ->
Map.put(reverse, RDF.iri(iri), to_string(prefix)) Map.put(reverse, iri, to_string(prefix))
end end
end end

View file

@ -19,16 +19,16 @@ defmodule RDF.Turtle.EncoderTest do
describe "serializing a graph" do describe "serializing a graph" do
test "an empty graph is serialized to an empty string" do test "an empty graph is serialized to an empty string" do
assert Turtle.Encoder.encode!(Graph.new) == "" assert Turtle.Encoder.encode!(Graph.new, prefixes: %{}) == ""
end end
test "statements with IRIs only" do test "statements with IRIs only" do
assert Turtle.Encoder.encode!(Graph.new [ assert Turtle.Encoder.encode!(Graph.new([
{EX.S1, EX.p1, EX.O1}, {EX.S1, EX.p1, EX.O1},
{EX.S1, EX.p1, EX.O2}, {EX.S1, EX.p1, EX.O2},
{EX.S1, EX.p2, EX.O3}, {EX.S1, EX.p2, EX.O3},
{EX.S2, EX.p3, EX.O4}, {EX.S2, EX.p3, EX.O4},
]) == ]), prefixes: %{}) ==
""" """
<http://example.org/#S1> <http://example.org/#S1>
<http://example.org/#p1> <http://example.org/#O1>, <http://example.org/#O2> ; <http://example.org/#p1> <http://example.org/#O1>, <http://example.org/#O2> ;
@ -62,6 +62,41 @@ defmodule RDF.Turtle.EncoderTest do
""" """
end end
test "when no prefixes are given, the prefixes from the given graph are used" do
assert Turtle.Encoder.encode!(Graph.new([
{EX.S1, EX.p1, EX.O1},
{EX.S1, EX.p1, EX.O2},
{EX.S1, EX.p2, XSD.integer},
{EX.S2, EX.p3, EX.O4},
], prefixes: %{
"": EX.__base_iri__,
xsd: XSD.__base_iri__
})) ==
"""
@prefix : <#{to_string(EX.__base_iri__)}> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
:S1
:p1 :O1, :O2 ;
:p2 xsd:integer .
:S2
:p3 :O4 .
"""
end
test "when no prefixes are given and no prefixes are in the given graph the default_prefixes are used" do
assert Turtle.Encoder.encode!(Graph.new({EX.S, EX.p, XSD.string})) ==
"""
@prefix rdf: <#{to_string(RDF.__base_iri__)}> .
@prefix rdfs: <#{to_string(RDFS.__base_iri__)}> .
@prefix xsd: <#{to_string(XSD.__base_iri__)}> .
<http://example.org/#S>
<http://example.org/#p> xsd:string .
"""
end
test "statements with empty prefixed names" do test "statements with empty prefixed names" do
assert Turtle.Encoder.encode!(Graph.new({EX.S, EX.p, EX.O}), assert Turtle.Encoder.encode!(Graph.new({EX.S, EX.p, EX.O}),
prefixes: %{"" => EX.__base_iri__}) == prefixes: %{"" => EX.__base_iri__}) ==
@ -74,11 +109,11 @@ defmodule RDF.Turtle.EncoderTest do
end end
test "statements with literals" do test "statements with literals" do
assert Turtle.Encoder.encode!(Graph.new [ assert Turtle.Encoder.encode!(Graph.new([
{EX.S1, EX.p1, ~L"foo"}, {EX.S1, EX.p1, ~L"foo"},
{EX.S1, EX.p1, ~L"foo"en}, {EX.S1, EX.p1, ~L"foo"en},
{EX.S2, EX.p2, RDF.literal("strange things", datatype: EX.custom)}, {EX.S2, EX.p2, RDF.literal("strange things", datatype: EX.custom)},
]) == ]), prefixes: %{}) ==
""" """
<http://example.org/#S1> <http://example.org/#S1>
<http://example.org/#p1> "foo"@en, "foo" . <http://example.org/#p1> "foo"@en, "foo" .
@ -89,10 +124,10 @@ defmodule RDF.Turtle.EncoderTest do
end end
test "statements with blank nodes" do test "statements with blank nodes" do
assert Turtle.Encoder.encode!(Graph.new [ assert Turtle.Encoder.encode!(Graph.new([
{EX.S1, EX.p1, [RDF.bnode(1), RDF.bnode("foo"), RDF.bnode(:bar)]}, {EX.S1, EX.p1, [RDF.bnode(1), RDF.bnode("foo"), RDF.bnode(:bar)]},
{EX.S2, EX.p1, [RDF.bnode(1), RDF.bnode("foo"), RDF.bnode(:bar)]}, {EX.S2, EX.p1, [RDF.bnode(1), RDF.bnode("foo"), RDF.bnode(:bar)]},
]) == ]), prefixes: %{}) ==
""" """
<http://example.org/#S1> <http://example.org/#S1>
<http://example.org/#p1> _:1, _:bar, _:foo . <http://example.org/#p1> _:1, _:bar, _:foo .