Allow use of aliases in @prefix declarations in graph builder blocks
This commit is contained in:
parent
1a51aea606
commit
e9fd42430b
4 changed files with 61 additions and 31 deletions
|
@ -37,6 +37,11 @@ The generated namespaces are much more flexible now and compile faster.
|
||||||
had to be given as the first argument).
|
had to be given as the first argument).
|
||||||
- several performance improvements
|
- several performance improvements
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- The RDF vocabulary namespaces used in `@prefix` and `@base` declarations in a
|
||||||
|
`RDF.Graph.build` block no longer have to be written out which had to be done
|
||||||
|
previously even when parts of the module were available as an alias.
|
||||||
|
|
||||||
[Compare v0.12.0...HEAD](https://github.com/rdf-elixir/rdf-ex/compare/v0.12.0...HEAD)
|
[Compare v0.12.0...HEAD](https://github.com/rdf-elixir/rdf-ex/compare/v0.12.0...HEAD)
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ defmodule RDF.Graph do
|
||||||
For a description of the DSL see [this guide](https://rdf-elixir.dev/rdf-ex/description-and-graph-dsl.html).
|
For a description of the DSL see [this guide](https://rdf-elixir.dev/rdf-ex/description-and-graph-dsl.html).
|
||||||
"""
|
"""
|
||||||
defmacro build(opts \\ [], do: block) do
|
defmacro build(opts \\ [], do: block) do
|
||||||
Builder.build(block, opts)
|
Builder.build(block, __CALLER__, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
|
@ -16,13 +16,14 @@ defmodule RDF.Graph.Builder do
|
||||||
def exclude(_), do: nil
|
def exclude(_), do: nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def build({:__block__, _, block}, opts) do
|
def build({:__block__, _, block}, env, opts) do
|
||||||
|
env_aliases = env_aliases(env)
|
||||||
{declarations, data} = Enum.split_with(block, &declaration?/1)
|
{declarations, data} = Enum.split_with(block, &declaration?/1)
|
||||||
{base, declarations} = extract_base(declarations)
|
{base, declarations} = extract_base(declarations, env_aliases)
|
||||||
base_string = base_string(base)
|
base_string = base_string(base)
|
||||||
data = resolve_relative_iris(data, base_string)
|
data = resolve_relative_iris(data, base_string)
|
||||||
declarations = resolve_relative_iris(declarations, base_string)
|
declarations = resolve_relative_iris(declarations, base_string)
|
||||||
{prefixes, declarations} = extract_prefixes(declarations)
|
{prefixes, declarations} = extract_prefixes(declarations, env_aliases)
|
||||||
|
|
||||||
quote do
|
quote do
|
||||||
alias RDF.XSD
|
alias RDF.XSD
|
||||||
|
@ -42,8 +43,8 @@ defmodule RDF.Graph.Builder do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def build(single, opts) do
|
def build(single, env, opts) do
|
||||||
build({:__block__, [], List.wrap(single)}, opts)
|
build({:__block__, [], List.wrap(single)}, env, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
@ -95,11 +96,14 @@ defmodule RDF.Graph.Builder do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp extract_base(declarations) do
|
defp extract_base(declarations, env_aliases) do
|
||||||
{base, declarations} =
|
{base, declarations} =
|
||||||
Enum.reduce(declarations, {nil, []}, fn
|
Enum.reduce(declarations, {nil, []}, fn
|
||||||
{:@, line, [{:base, _, [{:__aliases__, _, ns}] = aliases}]}, {_, declarations} ->
|
{:@, line, [{:base, _, [{:__aliases__, _, ns}] = aliases}]}, {_, declarations} ->
|
||||||
{Module.concat(ns), [{:alias, line, aliases} | declarations]}
|
{
|
||||||
|
ns |> expand_module(env_aliases) |> Module.concat(),
|
||||||
|
[{:alias, line, aliases} | declarations]
|
||||||
|
}
|
||||||
|
|
||||||
{:@, _, [{:base, _, [base]}]}, {_, declarations} ->
|
{:@, _, [{:base, _, [base]}]}, {_, declarations} ->
|
||||||
{base, declarations}
|
{base, declarations}
|
||||||
|
@ -111,15 +115,16 @@ defmodule RDF.Graph.Builder do
|
||||||
{base, Enum.reverse(declarations)}
|
{base, Enum.reverse(declarations)}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp extract_prefixes(declarations) do
|
defp extract_prefixes(declarations, env_aliases) do
|
||||||
{prefixes, declarations} =
|
{prefixes, declarations} =
|
||||||
Enum.reduce(declarations, {[], []}, fn
|
Enum.reduce(declarations, {[], []}, fn
|
||||||
{:@, line, [{:prefix, _, [[{prefix, {:__aliases__, _, ns} = aliases}]]}]},
|
{:@, line, [{:prefix, _, [[{prefix, {:__aliases__, _, ns} = aliases}]]}]},
|
||||||
{prefixes, declarations} ->
|
{prefixes, declarations} ->
|
||||||
{[prefix(prefix, ns) | prefixes], [{:alias, line, [aliases]} | declarations]}
|
{[prefix(prefix, ns, env_aliases) | prefixes],
|
||||||
|
[{:alias, line, [aliases]} | declarations]}
|
||||||
|
|
||||||
{:@, line, [{:prefix, _, [{:__aliases__, _, ns}] = aliases}]}, {prefixes, declarations} ->
|
{:@, line, [{:prefix, _, [{:__aliases__, _, ns}] = aliases}]}, {prefixes, declarations} ->
|
||||||
{[prefix(ns) | prefixes], [{:alias, line, aliases} | declarations]}
|
{[prefix(ns, env_aliases) | prefixes], [{:alias, line, aliases} | declarations]}
|
||||||
|
|
||||||
declaration, {prefixes, declarations} ->
|
declaration, {prefixes, declarations} ->
|
||||||
{prefixes, [declaration | declarations]}
|
{prefixes, [declaration | declarations]}
|
||||||
|
@ -128,18 +133,25 @@ defmodule RDF.Graph.Builder do
|
||||||
{prefixes, Enum.reverse(declarations)}
|
{prefixes, Enum.reverse(declarations)}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp prefix(namespace) do
|
defp prefix(namespace, env_aliases) do
|
||||||
|
namespace
|
||||||
|
|> determine_prefix()
|
||||||
|
|> prefix(namespace, env_aliases)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp prefix(prefix, namespace, env_aliases) do
|
||||||
|
{prefix, namespace |> expand_module(env_aliases) |> Module.concat()}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp determine_prefix(namespace) do
|
||||||
namespace
|
namespace
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|> hd()
|
|> hd()
|
||||||
|> to_string()
|
|> to_string()
|
||||||
|> Macro.underscore()
|
|> Macro.underscore()
|
||||||
|> String.to_atom()
|
|> String.to_atom()
|
||||||
|> prefix(namespace)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp prefix(prefix, namespace), do: {prefix, Module.concat(namespace)}
|
|
||||||
|
|
||||||
defp declaration?({:=, _, _}), do: true
|
defp declaration?({:=, _, _}), do: true
|
||||||
defp declaration?({:@, _, [{:prefix, _, _}]}), do: true
|
defp declaration?({:@, _, [{:prefix, _, _}]}), do: true
|
||||||
defp declaration?({:@, _, [{:base, _, _}]}), do: true
|
defp declaration?({:@, _, [{:base, _, _}]}), do: true
|
||||||
|
@ -161,4 +173,26 @@ defmodule RDF.Graph.Builder do
|
||||||
defp rdf?(invalid) do
|
defp rdf?(invalid) do
|
||||||
raise Error, message: "invalid RDF data: #{inspect(invalid)}"
|
raise Error, message: "invalid RDF data: #{inspect(invalid)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp expand_module([first | rest] = module, env_aliases) do
|
||||||
|
if full = env_aliases[first] do
|
||||||
|
full ++ rest
|
||||||
|
else
|
||||||
|
module
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp env_aliases(env) do
|
||||||
|
Map.new(env.aliases, fn {short, full} ->
|
||||||
|
{
|
||||||
|
module_to_atom_without_elixir_prefix(short),
|
||||||
|
full |> Module.split() |> Enum.map(&String.to_atom/1)
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp module_to_atom_without_elixir_prefix(module) do
|
||||||
|
[short] = Module.split(module)
|
||||||
|
String.to_atom(short)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,7 @@ defmodule RDF.Graph.BuilderTest do
|
||||||
@compile {:no_warn_undefined, __MODULE__.TestNS.EX}
|
@compile {:no_warn_undefined, __MODULE__.TestNS.EX}
|
||||||
@compile {:no_warn_undefined, __MODULE__.TestNS.Custom}
|
@compile {:no_warn_undefined, __MODULE__.TestNS.Custom}
|
||||||
|
|
||||||
alias __MODULE__.TestNS.EX
|
alias TestNS.EX
|
||||||
alias RDF.NS
|
alias RDF.NS
|
||||||
|
|
||||||
defmodule UseTest do
|
defmodule UseTest do
|
||||||
|
@ -346,7 +346,6 @@ defmodule RDF.Graph.BuilderTest do
|
||||||
(fn ->
|
(fn ->
|
||||||
RDF.Graph.build do
|
RDF.Graph.build do
|
||||||
alias TestNS.Custom
|
alias TestNS.Custom
|
||||||
# alias RDF.Graph.BuilderTest.TestNS.Custom
|
|
||||||
Custom.S |> Custom.p(Custom.O)
|
Custom.S |> Custom.p(Custom.O)
|
||||||
end
|
end
|
||||||
end).()
|
end).()
|
||||||
|
@ -359,8 +358,8 @@ defmodule RDF.Graph.BuilderTest do
|
||||||
graph =
|
graph =
|
||||||
(fn ->
|
(fn ->
|
||||||
RDF.Graph.build do
|
RDF.Graph.build do
|
||||||
import RDF.Graph.BuilderTest.TestNS.ImportTest
|
import TestNS.ImportTest
|
||||||
EX.S |> foo(RDF.Graph.BuilderTest.TestNS.ImportTest.Bar)
|
EX.S |> foo(TestNS.ImportTest.Bar)
|
||||||
end
|
end
|
||||||
end).()
|
end).()
|
||||||
|
|
||||||
|
@ -399,9 +398,7 @@ defmodule RDF.Graph.BuilderTest do
|
||||||
graph =
|
graph =
|
||||||
(fn ->
|
(fn ->
|
||||||
RDF.Graph.build do
|
RDF.Graph.build do
|
||||||
# TODO: the following leads to a (RDF.Namespace.UndefinedTermError) Elixir.TestNS is not a RDF.Namespace
|
@prefix cust: TestNS.Custom
|
||||||
# @prefix cust: TestNS.Custom
|
|
||||||
@prefix cust: RDF.Graph.BuilderTest.TestNS.Custom
|
|
||||||
|
|
||||||
Custom.S |> Custom.p(Custom.O)
|
Custom.S |> Custom.p(Custom.O)
|
||||||
end
|
end
|
||||||
|
@ -418,9 +415,7 @@ defmodule RDF.Graph.BuilderTest do
|
||||||
graph =
|
graph =
|
||||||
(fn ->
|
(fn ->
|
||||||
RDF.Graph.build do
|
RDF.Graph.build do
|
||||||
# TODO: the following leads to a (RDF.Namespace.UndefinedTermError) Elixir.TestNS is not a RDF.Namespace
|
@prefix TestNS.Custom
|
||||||
# @prefix TestNS.Custom
|
|
||||||
@prefix RDF.Graph.BuilderTest.TestNS.Custom
|
|
||||||
|
|
||||||
Custom.S |> Custom.p(Custom.O)
|
Custom.S |> Custom.p(Custom.O)
|
||||||
end
|
end
|
||||||
|
@ -437,9 +432,7 @@ defmodule RDF.Graph.BuilderTest do
|
||||||
graph =
|
graph =
|
||||||
(fn ->
|
(fn ->
|
||||||
RDF.Graph.build prefixes: [custom: EX] do
|
RDF.Graph.build prefixes: [custom: EX] do
|
||||||
# TODO: the following leads to a (RDF.Namespace.UndefinedTermError) Elixir.TestNS is not a RDF.Namespace
|
@prefix custom: TestNS.Custom
|
||||||
# @prefix custom: TestNS.Custom
|
|
||||||
@prefix custom: RDF.Graph.BuilderTest.TestNS.Custom
|
|
||||||
|
|
||||||
Custom.S |> Custom.p(Custom.O)
|
Custom.S |> Custom.p(Custom.O)
|
||||||
end
|
end
|
||||||
|
@ -460,9 +453,7 @@ defmodule RDF.Graph.BuilderTest do
|
||||||
graph =
|
graph =
|
||||||
(fn ->
|
(fn ->
|
||||||
RDF.Graph.build do
|
RDF.Graph.build do
|
||||||
# TODO: the following leads to a (RDF.Namespace.UndefinedTermError) Elixir.TestNS is not a RDF.Namespace
|
@base TestNS.Custom
|
||||||
# @base TestNS.Custom
|
|
||||||
@base RDF.Graph.BuilderTest.TestNS.Custom
|
|
||||||
|
|
||||||
~I<S> |> Custom.p(~I<O>)
|
~I<S> |> Custom.p(~I<O>)
|
||||||
{~I<foo>, ~I<bar>, ~I<baz>}
|
{~I<foo>, ~I<bar>, ~I<baz>}
|
||||||
|
|
Loading…
Reference in a new issue