Add prefixed_name/2 and prefixed_name_to_iri/2 to RDF.PrefixMap

This commit is contained in:
Marcel Otto 2020-09-16 00:38:56 +02:00
parent bee5e3a81b
commit a4b71b3f9d
3 changed files with 110 additions and 1 deletions

View file

@ -15,11 +15,13 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
switched to SPARQL style with the option `:directive_style` and the value `:sparql`
- the most common conflict resolution strategies on `RDF.PrefixMap.merge/3` can now
be chosen directly with the atoms `:ignore` and `:overwrite`
- `RDF.PrefixMap.prefixed_name/2` to convert an IRI to a prefixed name
- `RDF.PrefixMap.prefixed_name_to_iri/2` to convert a prefixed name to an IRI
### Changed
- when serializing a `RDF.Dataset` with the Turtle encoder the prefixes of all of its graphs
are used
are used now
### Fixed

View file

@ -327,6 +327,65 @@ defmodule RDF.PrefixMap do
Map.values(map)
end
@doc """
Converts an IRI into a prefixed name.
Returns `nil` when no prefix for the namespace of `iri` is defined in `prefix_map`.
## Examples
iex> RDF.PrefixMap.new(ex: "http://example.com/")
...> |> RDF.PrefixMap.prefixed_name(~I<http://example.com/Foo>)
"ex:Foo"
iex> RDF.PrefixMap.new(ex: "http://example.com/")
...> |> RDF.PrefixMap.prefixed_name("http://example.com/Foo")
"ex:Foo"
"""
@spec prefixed_name(t, IRI.t() | String.t()) :: String.t() | nil
def prefixed_name(prefix_map, iri)
def prefixed_name(%__MODULE__{} = prefix_map, %IRI{} = iri) do
prefixed_name(prefix_map, IRI.to_string(iri))
end
def prefixed_name(%__MODULE__{} = prefix_map, iri) when is_binary(iri) do
Enum.find_value(prefix_map, fn {prefix, namespace} ->
case String.replace_leading(iri, IRI.to_string(namespace), ":") do
^iri ->
nil
truncated_name ->
unless String.contains?(truncated_name, ~w[/ #]) do
to_string(prefix) <> truncated_name
end
end
end)
end
@doc """
Converts a prefixed name into an IRI.
Returns `nil` when the prefix in `prefixed_name` is not defined in `prefix_map`.
## Examples
iex> RDF.PrefixMap.new(ex: "http://example.com/")
...> |> RDF.PrefixMap.prefixed_name_to_iri("ex:Foo")
~I<http://example.com/Foo>
"""
@spec prefixed_name_to_iri(t, String.t()) :: IRI.t() | nil
def prefixed_name_to_iri(%__MODULE__{} = prefix_map, prefixed_name)
when is_binary(prefixed_name) do
Enum.find_value(prefix_map, fn {prefix, namespace} ->
case String.replace_leading(prefixed_name, "#{prefix}:", IRI.to_string(namespace)) do
^prefixed_name -> nil
iri -> IRI.new(iri)
end
end)
end
defimpl Enumerable do
def reduce(%RDF.PrefixMap{map: map}, acc, fun), do: Enumerable.reduce(map, acc, fun)

View file

@ -1,6 +1,8 @@
defmodule RDF.PrefixMapTest do
use RDF.Test.Case
doctest RDF.PrefixMap
alias RDF.PrefixMap
@ex_ns1 ~I<http://example.com/foo/>
@ -295,6 +297,52 @@ defmodule RDF.PrefixMapTest do
assert PrefixMap.namespaces(PrefixMap.new()) == ~w[]a
end
describe "prefixed_name/2" do
test "when given an RDF.IRI and the used prefix is defined" do
assert PrefixMap.prefixed_name(@example2, ~I<http://example.com/foo/Test>) ==
"ex1:Test"
assert PrefixMap.prefixed_name(@example2, ~I<http://example.com/bar#Test>) ==
"ex2:Test"
end
test "when given a string and the used prefix is defined" do
assert PrefixMap.prefixed_name(@example2, "http://example.com/foo/Test") ==
"ex1:Test"
assert PrefixMap.prefixed_name(@example2, "http://example.com/bar#Test") ==
"ex2:Test"
end
test "when the used prefix is not defined" do
assert PrefixMap.prefixed_name(@example2, ~I<http://example.com/fo/Test>) == nil
assert PrefixMap.prefixed_name(@example2, "http://example.com/baz#Test") == nil
end
test "when the given IRI is under a sub-path of a defined namespace" do
assert PrefixMap.prefixed_name(@example2, ~I<http://example.com/foo/bar/Test>) == nil
assert PrefixMap.prefixed_name(@example2, ~I<http://example.com/foo/bar#Test>) == nil
end
end
describe "prefixed_name_to_iri/2" do
test "when the used prefix is defined" do
assert PrefixMap.prefixed_name_to_iri(@example2, "ex1:Test") ==
~I<http://example.com/foo/Test>
assert PrefixMap.prefixed_name_to_iri(@example2, "ex2:Test") ==
~I<http://example.com/bar#Test>
end
test "when the used prefix is not defined" do
assert PrefixMap.prefixed_name_to_iri(@example2, "ex3:Test") == nil
end
test "when the given string does not have a prefix" do
assert PrefixMap.prefixed_name_to_iri(@example2, "Test") == nil
end
end
describe "Enumerable protocol" do
test "Enum.count" do
assert Enum.count(PrefixMap.new()) == 0