From 929e2a8c8186f4876114e806343e86979f542fc5 Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Mon, 2 Nov 2020 02:05:23 +0100 Subject: [PATCH] Use RDF.PrefixMap.prefixed_name/2 in Turtle encoder --- CHANGELOG.md | 2 ++ lib/rdf/serializations/turtle_encoder.ex | 32 ++---------------------- test/unit/turtle_encoder_test.exs | 19 +++++++------- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91cdae1..ce7d351 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ This project adheres to [Semantic Versioning](http://semver.org/) and - more compact Inspect form for `RDF.PrefixMap` - 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 efficient in terms of performance and memory consumption than the previous ref-based blank nodes diff --git a/lib/rdf/serializations/turtle_encoder.ex b/lib/rdf/serializations/turtle_encoder.ex index df92d73..97bde34 100644 --- a/lib/rdf/serializations/turtle_encoder.ex +++ b/lib/rdf/serializations/turtle_encoder.ex @@ -46,7 +46,6 @@ defmodule RDF.Turtle.Encoder do prefixes = Keyword.get(opts, :prefixes) |> prefixes(data) - |> init_prefixes() with {:ok, state} = State.start_link(data, base, prefixes) do try do @@ -111,12 +110,6 @@ defmodule RDF.Turtle.Encoder do defp prefixes(nil, _), do: RDF.default_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({_, base}, opts) do @@ -126,7 +119,7 @@ defmodule RDF.Turtle.Encoder do end <> "\n\n" end - defp prefix_directive({ns, prefix}, opts) do + defp prefix_directive({prefix, ns}, opts) do case Keyword.get(opts, :directive_style) do :sparql -> "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 - with {ns, name} <- split_iri(iri) do - 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 + PrefixMap.prefixed_name(prefixes, iri) end defp quoted(string) do diff --git a/test/unit/turtle_encoder_test.exs b/test/unit/turtle_encoder_test.exs index 95d9d9d..eba2668 100644 --- a/test/unit/turtle_encoder_test.exs +++ b/test/unit/turtle_encoder_test.exs @@ -5,7 +5,7 @@ defmodule RDF.Turtle.EncoderTest do doctest Turtle.Encoder - alias RDF.Graph + alias RDF.{Graph, PrefixMap} alias RDF.NS alias RDF.NS.{RDFS, OWL} @@ -202,9 +202,9 @@ defmodule RDF.Turtle.EncoderTest do """ @base <#{to_string(EX.__base_iri__())}> . + @prefix owl: <#{to_string(OWL.__base_iri__())}> . @prefix rdf: <#{to_string(RDF.__base_iri__())}> . @prefix rdfs: <#{to_string(RDFS.__base_iri__())}> . - @prefix owl: <#{to_string(OWL.__base_iri__())}> . <> a owl:Ontology . @@ -331,9 +331,9 @@ defmodule RDF.Turtle.EncoderTest do assert Turtle.Encoder.encode!(dataset) == """ @prefix ex: . + @prefix owl: . @prefix rdf: . @prefix rdfs: . - @prefix owl: . a rdfs:Class . @@ -366,10 +366,11 @@ defmodule RDF.Turtle.EncoderTest do describe "prefixed_name/2" do setup do {:ok, - prefixes: %{ - RDF.iri(EX.__base_iri__()) => "ex", - ~I => "ex2" - }} + prefixes: + PrefixMap.new( + ex: EX, + ex2: ~I + )} end test "hash iri with existing prefix", %{prefixes: prefixes} do @@ -383,7 +384,7 @@ defmodule RDF.Turtle.EncoderTest do end 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 test "slash iri with existing prefix", %{prefixes: prefixes} do @@ -397,7 +398,7 @@ defmodule RDF.Turtle.EncoderTest do end test "slash iri with non-existing prefix" do - refute Turtle.Encoder.prefixed_name(~I, %{}) + refute Turtle.Encoder.prefixed_name(~I, PrefixMap.new()) end end