From 2e49f8b73af89d0539809084bdb92cce285dc192 Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Mon, 1 Apr 2019 02:44:12 +0200 Subject: [PATCH] Let RDF.Turtle.Encoder use other prefixes when none provided --- CHANGELOG.md | 5 +++ lib/rdf/serializations/turtle_encoder.ex | 8 ++-- test/unit/turtle_encoder_test.exs | 49 ++++++++++++++++++++---- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c374b..15d3e9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 prefixes are merged - `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 are not supported in atoms on these versions diff --git a/lib/rdf/serializations/turtle_encoder.ex b/lib/rdf/serializations/turtle_encoder.ex index 3dc49a2..ee81a02 100644 --- a/lib/rdf/serializations/turtle_encoder.ex +++ b/lib/rdf/serializations/turtle_encoder.ex @@ -29,7 +29,7 @@ defmodule RDF.Turtle.Encoder do @impl RDF.Serialization.Encoder def encode(data, opts \\ []) do 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 try do State.preprocess(state) @@ -58,11 +58,13 @@ defmodule RDF.Turtle.Encoder do 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 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 diff --git a/test/unit/turtle_encoder_test.exs b/test/unit/turtle_encoder_test.exs index e438cb2..ea6a70b 100644 --- a/test/unit/turtle_encoder_test.exs +++ b/test/unit/turtle_encoder_test.exs @@ -19,16 +19,16 @@ defmodule RDF.Turtle.EncoderTest do describe "serializing a graph" 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 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.O2}, {EX.S1, EX.p2, EX.O3}, {EX.S2, EX.p3, EX.O4}, - ]) == + ]), prefixes: %{}) == """ , ; @@ -62,6 +62,41 @@ defmodule RDF.Turtle.EncoderTest do """ 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: . + + :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__)}> . + + + xsd:string . + """ + end + test "statements with empty prefixed names" do assert Turtle.Encoder.encode!(Graph.new({EX.S, EX.p, EX.O}), prefixes: %{"" => EX.__base_iri__}) == @@ -74,11 +109,11 @@ defmodule RDF.Turtle.EncoderTest do end 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"en}, {EX.S2, EX.p2, RDF.literal("strange things", datatype: EX.custom)}, - ]) == + ]), prefixes: %{}) == """ "foo"@en, "foo" . @@ -89,10 +124,10 @@ defmodule RDF.Turtle.EncoderTest do end 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.S2, EX.p1, [RDF.bnode(1), RDF.bnode("foo"), RDF.bnode(:bar)]}, - ]) == + ]), prefixes: %{}) == """ _:1, _:bar, _:foo .