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).
|
||||
- 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)
|
||||
|
||||
|
|
|
@ -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).
|
||||
"""
|
||||
defmacro build(opts \\ [], do: block) do
|
||||
Builder.build(block, opts)
|
||||
Builder.build(block, __CALLER__, opts)
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
|
|
@ -16,13 +16,14 @@ defmodule RDF.Graph.Builder do
|
|||
def exclude(_), do: nil
|
||||
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)
|
||||
{base, declarations} = extract_base(declarations)
|
||||
{base, declarations} = extract_base(declarations, env_aliases)
|
||||
base_string = base_string(base)
|
||||
data = resolve_relative_iris(data, base_string)
|
||||
declarations = resolve_relative_iris(declarations, base_string)
|
||||
{prefixes, declarations} = extract_prefixes(declarations)
|
||||
{prefixes, declarations} = extract_prefixes(declarations, env_aliases)
|
||||
|
||||
quote do
|
||||
alias RDF.XSD
|
||||
|
@ -42,8 +43,8 @@ defmodule RDF.Graph.Builder do
|
|||
end
|
||||
end
|
||||
|
||||
def build(single, opts) do
|
||||
build({:__block__, [], List.wrap(single)}, opts)
|
||||
def build(single, env, opts) do
|
||||
build({:__block__, [], List.wrap(single)}, env, opts)
|
||||
end
|
||||
|
||||
@doc false
|
||||
|
@ -95,11 +96,14 @@ defmodule RDF.Graph.Builder do
|
|||
end)
|
||||
end
|
||||
|
||||
defp extract_base(declarations) do
|
||||
defp extract_base(declarations, env_aliases) do
|
||||
{base, declarations} =
|
||||
Enum.reduce(declarations, {nil, []}, fn
|
||||
{:@, 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, declarations}
|
||||
|
@ -111,15 +115,16 @@ defmodule RDF.Graph.Builder do
|
|||
{base, Enum.reverse(declarations)}
|
||||
end
|
||||
|
||||
defp extract_prefixes(declarations) do
|
||||
defp extract_prefixes(declarations, env_aliases) do
|
||||
{prefixes, declarations} =
|
||||
Enum.reduce(declarations, {[], []}, fn
|
||||
{:@, line, [{:prefix, _, [[{prefix, {:__aliases__, _, ns} = aliases}]]}]},
|
||||
{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} ->
|
||||
{[prefix(ns) | prefixes], [{:alias, line, aliases} | declarations]}
|
||||
{[prefix(ns, env_aliases) | prefixes], [{:alias, line, aliases} | declarations]}
|
||||
|
||||
declaration, {prefixes, declarations} ->
|
||||
{prefixes, [declaration | declarations]}
|
||||
|
@ -128,18 +133,25 @@ defmodule RDF.Graph.Builder do
|
|||
{prefixes, Enum.reverse(declarations)}
|
||||
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
|
||||
|> Enum.reverse()
|
||||
|> hd()
|
||||
|> to_string()
|
||||
|> Macro.underscore()
|
||||
|> String.to_atom()
|
||||
|> prefix(namespace)
|
||||
end
|
||||
|
||||
defp prefix(prefix, namespace), do: {prefix, Module.concat(namespace)}
|
||||
|
||||
defp declaration?({:=, _, _}), do: true
|
||||
defp declaration?({:@, _, [{:prefix, _, _}]}), do: true
|
||||
defp declaration?({:@, _, [{:base, _, _}]}), do: true
|
||||
|
@ -161,4 +173,26 @@ defmodule RDF.Graph.Builder do
|
|||
defp rdf?(invalid) do
|
||||
raise Error, message: "invalid RDF data: #{inspect(invalid)}"
|
||||
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
|
||||
|
|
|
@ -19,7 +19,7 @@ defmodule RDF.Graph.BuilderTest do
|
|||
@compile {:no_warn_undefined, __MODULE__.TestNS.EX}
|
||||
@compile {:no_warn_undefined, __MODULE__.TestNS.Custom}
|
||||
|
||||
alias __MODULE__.TestNS.EX
|
||||
alias TestNS.EX
|
||||
alias RDF.NS
|
||||
|
||||
defmodule UseTest do
|
||||
|
@ -346,7 +346,6 @@ defmodule RDF.Graph.BuilderTest do
|
|||
(fn ->
|
||||
RDF.Graph.build do
|
||||
alias TestNS.Custom
|
||||
# alias RDF.Graph.BuilderTest.TestNS.Custom
|
||||
Custom.S |> Custom.p(Custom.O)
|
||||
end
|
||||
end).()
|
||||
|
@ -359,8 +358,8 @@ defmodule RDF.Graph.BuilderTest do
|
|||
graph =
|
||||
(fn ->
|
||||
RDF.Graph.build do
|
||||
import RDF.Graph.BuilderTest.TestNS.ImportTest
|
||||
EX.S |> foo(RDF.Graph.BuilderTest.TestNS.ImportTest.Bar)
|
||||
import TestNS.ImportTest
|
||||
EX.S |> foo(TestNS.ImportTest.Bar)
|
||||
end
|
||||
end).()
|
||||
|
||||
|
@ -399,9 +398,7 @@ defmodule RDF.Graph.BuilderTest do
|
|||
graph =
|
||||
(fn ->
|
||||
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: RDF.Graph.BuilderTest.TestNS.Custom
|
||||
@prefix cust: TestNS.Custom
|
||||
|
||||
Custom.S |> Custom.p(Custom.O)
|
||||
end
|
||||
|
@ -418,9 +415,7 @@ defmodule RDF.Graph.BuilderTest do
|
|||
graph =
|
||||
(fn ->
|
||||
RDF.Graph.build do
|
||||
# TODO: the following leads to a (RDF.Namespace.UndefinedTermError) Elixir.TestNS is not a RDF.Namespace
|
||||
# @prefix TestNS.Custom
|
||||
@prefix RDF.Graph.BuilderTest.TestNS.Custom
|
||||
@prefix TestNS.Custom
|
||||
|
||||
Custom.S |> Custom.p(Custom.O)
|
||||
end
|
||||
|
@ -437,9 +432,7 @@ defmodule RDF.Graph.BuilderTest do
|
|||
graph =
|
||||
(fn ->
|
||||
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: RDF.Graph.BuilderTest.TestNS.Custom
|
||||
@prefix custom: TestNS.Custom
|
||||
|
||||
Custom.S |> Custom.p(Custom.O)
|
||||
end
|
||||
|
@ -460,9 +453,7 @@ defmodule RDF.Graph.BuilderTest do
|
|||
graph =
|
||||
(fn ->
|
||||
RDF.Graph.build do
|
||||
# TODO: the following leads to a (RDF.Namespace.UndefinedTermError) Elixir.TestNS is not a RDF.Namespace
|
||||
# @base TestNS.Custom
|
||||
@base RDF.Graph.BuilderTest.TestNS.Custom
|
||||
@base TestNS.Custom
|
||||
|
||||
~I<S> |> Custom.p(~I<O>)
|
||||
{~I<foo>, ~I<bar>, ~I<baz>}
|
||||
|
|
Loading…
Reference in a new issue