Add :base_description option on the RDF.Turtle.Encoder

This commit is contained in:
Marcel Otto 2021-12-19 02:37:07 +01:00
parent eab7c9e117
commit 3acda86d7e
2 changed files with 80 additions and 1 deletions

View file

@ -19,7 +19,12 @@ defmodule RDF.Turtle.Encoder do
- `:implicit_base`: This boolean flag allows to use a base URI to get relative IRIs
without embedding it explicitly in the content with a `@base` directive, so that
the URIs will be resolved according to the remaining strategy specified in
section 5.1 of [RFC3986](https://www.ietf.org/rfc/rfc3986.txt).
section 5.1 of [RFC3986](https://www.ietf.org/rfc/rfc3986.txt) (default: `false`).
- `:base_description`: Allows to provide a description of the resource denoted by
the base URI. This option is especially useful when the base URI is actually not
specified, eg. in the common use case of wanting to describe the Turtle document
itself, which should be denoted by the URL where it is hosted as the implicit base
URI.
- `:only`: Allows to specify which parts of a Turtle document should be generated.
Possible values: `:base`, `:prefixes`, `:directives` (means the same as `[:base, :prefixes]`),
`:triples` or a list with any combination of these values.
@ -64,6 +69,8 @@ defmodule RDF.Turtle.Encoder do
]
@ordered_properties MapSet.new(@predicate_order)
@implicit_default_base "http://this-implicit-default-base-iri-should-never-appear-in-a-document"
@impl RDF.Serialization.Encoder
@spec encode(Graph.t() | Description.t(), keyword) :: {:ok, String.t()} | {:error, any}
def encode(data, opts \\ [])
@ -80,6 +87,9 @@ defmodule RDF.Turtle.Encoder do
Keyword.get(opts, :prefixes)
|> prefixes(graph)
{graph, base, opts} =
add_base_description(graph, base, Keyword.get(opts, :base_description), opts)
{:ok, state} = State.start_link(graph, base, prefixes)
try do
@ -149,6 +159,21 @@ defmodule RDF.Turtle.Encoder do
end
end
defp add_base_description(graph, base, nil, opts), do: {graph, base, opts}
defp add_base_description(graph, nil, base_description, opts) do
add_base_description(
graph,
@implicit_default_base,
base_description,
Keyword.put(opts, :implicit_base, true)
)
end
defp add_base_description(graph, base, base_description, opts) do
{Graph.add(graph, Description.new(base, init: base_description)), base, opts}
end
defp graph_statements(state, opts) do
indent = indent(opts)

View file

@ -174,6 +174,60 @@ defmodule RDF.Turtle.EncoderTest do
"""
end
test ":base_description with a base IRI" do
assert Turtle.Encoder.encode!(
Graph.new([{EX.S1, EX.p1(), EX.O1}],
prefixes: %{}
),
base_iri: EX,
base_description: %{EX.P2 => [EX.O2, EX.O3]}
) ==
"""
@base <#{to_string(EX.__base_iri__())}> .
<>
<P2> <O2>, <O3> .
<S1>
<p1> <O1> .
"""
assert Turtle.Encoder.encode!(
Graph.new([{EX.S1, EX.p1(), EX.O1}],
prefixes: %{},
base_iri: EX
),
base_description: %{EX.P2 => [EX.O2, EX.O3]}
) ==
"""
@base <#{to_string(EX.__base_iri__())}> .
<>
<P2> <O2>, <O3> .
<S1>
<p1> <O1> .
"""
end
test ":base_description without a base IRI" do
assert Turtle.Encoder.encode!(
Graph.new([{EX.S1, EX.p1(), EX.O1}],
prefixes: %{ex: EX}
),
base_description: %{EX.P2 => [EX.O2, EX.O3]}
) ==
"""
@prefix ex: <#{to_string(EX.__base_iri__())}> .
<>
ex:P2 ex:O2, ex:O3 .
ex:S1
ex:p1 ex:O1 .
"""
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(), NS.XSD.string()})) ==
"""