Use RDF.PrefixMap.prefixed_name/2 in Turtle encoder

This commit is contained in:
Marcel Otto 2020-11-02 02:05:23 +01:00
parent 27a4c177e2
commit 929e2a8c81
3 changed files with 14 additions and 39 deletions

View file

@ -17,6 +17,8 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
- more compact Inspect form for `RDF.PrefixMap` - more compact Inspect form for `RDF.PrefixMap`
- the `RDF.Turtle.Encoder` accepts `RDF.Vocabulary.Namespace` modules as `base` - the `RDF.Turtle.Encoder` accepts `RDF.Vocabulary.Namespace` modules as `base`
- the performance of the `RDF.Turtle.Encoder` was improved (by using a more
efficient method for resolving IRIs to prefixed names for most use cases)
- `RDF.BlankNode.new/0` creates integer-based blank nodes, which is much more - `RDF.BlankNode.new/0` creates integer-based blank nodes, which is much more
efficient in terms of performance and memory consumption than the previous efficient in terms of performance and memory consumption than the previous
ref-based blank nodes ref-based blank nodes

View file

@ -46,7 +46,6 @@ defmodule RDF.Turtle.Encoder do
prefixes = prefixes =
Keyword.get(opts, :prefixes) Keyword.get(opts, :prefixes)
|> prefixes(data) |> prefixes(data)
|> init_prefixes()
with {:ok, state} = State.start_link(data, base, prefixes) do with {:ok, state} = State.start_link(data, base, prefixes) do
try do try do
@ -111,12 +110,6 @@ defmodule RDF.Turtle.Encoder do
defp prefixes(nil, _), do: RDF.default_prefixes() defp prefixes(nil, _), do: RDF.default_prefixes()
defp prefixes(prefixes, _), do: PrefixMap.new(prefixes) defp prefixes(prefixes, _), do: PrefixMap.new(prefixes)
defp init_prefixes(prefixes) do
Enum.reduce(prefixes, %{}, fn {prefix, iri}, reverse ->
Map.put(reverse, iri, to_string(prefix))
end)
end
defp base_directive(nil, _), do: "" defp base_directive(nil, _), do: ""
defp base_directive({_, base}, opts) do defp base_directive({_, base}, opts) do
@ -126,7 +119,7 @@ defmodule RDF.Turtle.Encoder do
end <> "\n\n" end <> "\n\n"
end end
defp prefix_directive({ns, prefix}, opts) do defp prefix_directive({prefix, ns}, opts) do
case Keyword.get(opts, :directive_style) do case Keyword.get(opts, :directive_style) do
:sparql -> "PREFIX #{prefix}: <#{to_string(ns)}>\n" :sparql -> "PREFIX #{prefix}: <#{to_string(ns)}>\n"
_ -> "@prefix #{prefix}: <#{to_string(ns)}> .\n" _ -> "@prefix #{prefix}: <#{to_string(ns)}> .\n"
@ -390,28 +383,7 @@ defmodule RDF.Turtle.Encoder do
}] }]
def prefixed_name(iri, prefixes) do def prefixed_name(iri, prefixes) do
with {ns, name} <- split_iri(iri) do PrefixMap.prefixed_name(prefixes, iri)
case prefixes[ns] do
nil -> nil
prefix -> prefix <> ":" <> name
end
end
end
defp split_iri(%IRI{} = iri),
do: iri |> IRI.parse() |> split_iri()
defp split_iri(%URI{fragment: fragment} = uri) when not is_nil(fragment),
do: {RDF.iri(%URI{uri | fragment: ""}), fragment}
defp split_iri(%URI{path: nil}),
do: nil
defp split_iri(%URI{path: path} = uri) do
with [{pos, _}] = Regex.run(~r"[^/]*$"u, path, return: :index),
{ns_path, name} = String.split_at(path, pos) do
{RDF.iri(%URI{uri | path: ns_path}), name}
end
end end
defp quoted(string) do defp quoted(string) do

View file

@ -5,7 +5,7 @@ defmodule RDF.Turtle.EncoderTest do
doctest Turtle.Encoder doctest Turtle.Encoder
alias RDF.Graph alias RDF.{Graph, PrefixMap}
alias RDF.NS alias RDF.NS
alias RDF.NS.{RDFS, OWL} alias RDF.NS.{RDFS, OWL}
@ -202,9 +202,9 @@ defmodule RDF.Turtle.EncoderTest do
""" """
@base <#{to_string(EX.__base_iri__())}> . @base <#{to_string(EX.__base_iri__())}> .
@prefix owl: <#{to_string(OWL.__base_iri__())}> .
@prefix rdf: <#{to_string(RDF.__base_iri__())}> . @prefix rdf: <#{to_string(RDF.__base_iri__())}> .
@prefix rdfs: <#{to_string(RDFS.__base_iri__())}> . @prefix rdfs: <#{to_string(RDFS.__base_iri__())}> .
@prefix owl: <#{to_string(OWL.__base_iri__())}> .
<> <>
a owl:Ontology . a owl:Ontology .
@ -331,9 +331,9 @@ defmodule RDF.Turtle.EncoderTest do
assert Turtle.Encoder.encode!(dataset) == assert Turtle.Encoder.encode!(dataset) ==
""" """
@prefix ex: <http://example.org/#> . @prefix ex: <http://example.org/#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
<http://other.example.com/S2> <http://other.example.com/S2>
a rdfs:Class . a rdfs:Class .
@ -366,10 +366,11 @@ defmodule RDF.Turtle.EncoderTest do
describe "prefixed_name/2" do describe "prefixed_name/2" do
setup do setup do
{:ok, {:ok,
prefixes: %{ prefixes:
RDF.iri(EX.__base_iri__()) => "ex", PrefixMap.new(
~I<http://example.org/> => "ex2" ex: EX,
}} ex2: ~I<http://example.org/>
)}
end end
test "hash iri with existing prefix", %{prefixes: prefixes} do test "hash iri with existing prefix", %{prefixes: prefixes} do
@ -383,7 +384,7 @@ defmodule RDF.Turtle.EncoderTest do
end end
test "hash iri with non-existing prefix" do test "hash iri with non-existing prefix" do
refute Turtle.Encoder.prefixed_name(EX.foo(), %{}) refute Turtle.Encoder.prefixed_name(EX.foo(), PrefixMap.new())
end end
test "slash iri with existing prefix", %{prefixes: prefixes} do test "slash iri with existing prefix", %{prefixes: prefixes} do
@ -397,7 +398,7 @@ defmodule RDF.Turtle.EncoderTest do
end end
test "slash iri with non-existing prefix" do test "slash iri with non-existing prefix" do
refute Turtle.Encoder.prefixed_name(~I<http://example.org/foo>, %{}) refute Turtle.Encoder.prefixed_name(~I<http://example.org/foo>, PrefixMap.new())
end end
end end