2017-03-12 13:27:52 +00:00
|
|
|
defmodule RDF.Namespace do
|
|
|
|
@moduledoc """
|
2019-08-05 00:23:29 +00:00
|
|
|
A behaviour for resolvers of atoms to `RDF.IRI`s.
|
2017-03-12 13:27:52 +00:00
|
|
|
|
2017-06-10 19:52:16 +00:00
|
|
|
Currently there's only one type of such namespaces: `RDF.Vocabulary.Namespace`,
|
|
|
|
but other types are thinkable and might be implemented in the future, eg.
|
|
|
|
namespaces for JSON-LD contexts.
|
2017-03-12 13:27:52 +00:00
|
|
|
"""
|
|
|
|
|
2020-03-02 22:42:15 +00:00
|
|
|
alias RDF.IRI
|
2020-03-02 01:07:31 +00:00
|
|
|
|
2020-05-06 16:04:19 +00:00
|
|
|
import RDF.Guards
|
|
|
|
|
2017-06-10 19:52:16 +00:00
|
|
|
@doc """
|
2017-08-20 20:35:14 +00:00
|
|
|
Resolves a term to a `RDF.IRI`.
|
2017-06-10 19:52:16 +00:00
|
|
|
"""
|
2020-06-29 08:37:42 +00:00
|
|
|
@callback __resolve_term__(atom) :: {:ok, IRI.t()} | {:error, Exception.t()}
|
2017-03-12 13:27:52 +00:00
|
|
|
|
2017-06-10 19:52:16 +00:00
|
|
|
@doc """
|
|
|
|
All terms of a `RDF.Namespace`.
|
|
|
|
"""
|
2017-03-12 13:27:52 +00:00
|
|
|
@callback __terms__() :: [atom]
|
|
|
|
|
2017-06-10 19:52:16 +00:00
|
|
|
@doc """
|
2017-08-20 20:35:14 +00:00
|
|
|
Resolves a qualified term to a `RDF.IRI`.
|
2017-06-10 19:52:16 +00:00
|
|
|
|
|
|
|
It determines a `RDF.Namespace` from the qualifier of the given term and
|
|
|
|
delegates to remaining part of the term to `__resolve_term__/1` of this
|
|
|
|
determined namespace.
|
|
|
|
"""
|
2020-06-29 08:37:42 +00:00
|
|
|
@spec resolve_term(IRI.t() | module) :: {:ok, IRI.t()} | {:error, Exception.t()}
|
2017-03-12 13:27:52 +00:00
|
|
|
def resolve_term(expr)
|
|
|
|
|
2020-05-08 22:09:31 +00:00
|
|
|
def resolve_term(%IRI{} = iri), do: {:ok, iri}
|
2017-06-10 21:08:49 +00:00
|
|
|
|
2020-05-06 16:04:19 +00:00
|
|
|
def resolve_term(namespaced_term) when maybe_ns_term(namespaced_term) do
|
2017-06-10 21:08:49 +00:00
|
|
|
namespaced_term
|
|
|
|
|> to_string()
|
|
|
|
|> do_resolve_term()
|
|
|
|
end
|
|
|
|
|
2020-05-08 22:09:31 +00:00
|
|
|
@doc """
|
|
|
|
Resolves a qualified term to a `RDF.IRI` or raises an error when that's not possible.
|
|
|
|
|
|
|
|
See `resolve_term/1` for more.
|
|
|
|
"""
|
2020-06-29 08:37:42 +00:00
|
|
|
@spec resolve_term!(IRI.t() | module) :: IRI.t()
|
2020-05-08 22:09:31 +00:00
|
|
|
def resolve_term!(expr) do
|
|
|
|
with {:ok, iri} <- resolve_term(expr) do
|
|
|
|
iri
|
|
|
|
else
|
|
|
|
{:error, error} -> raise error
|
|
|
|
end
|
|
|
|
end
|
2017-03-12 13:27:52 +00:00
|
|
|
|
2017-06-10 02:26:11 +00:00
|
|
|
defp do_resolve_term("Elixir." <> _ = namespaced_term) do
|
2017-03-12 13:27:52 +00:00
|
|
|
{term, namespace} =
|
2017-06-10 02:26:11 +00:00
|
|
|
namespaced_term
|
2020-06-29 08:37:42 +00:00
|
|
|
|> Module.split()
|
2017-03-12 13:27:52 +00:00
|
|
|
|> List.pop_at(-1)
|
2020-05-08 22:09:31 +00:00
|
|
|
|
2017-06-10 21:08:49 +00:00
|
|
|
do_resolve_term(Module.concat(namespace), String.to_atom(term))
|
2017-06-10 02:26:11 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
defp do_resolve_term(namespaced_term) do
|
2020-05-08 22:09:31 +00:00
|
|
|
{:error,
|
2020-06-29 08:37:42 +00:00
|
|
|
%RDF.Namespace.UndefinedTermError{
|
|
|
|
message: "#{namespaced_term} is not a term on a RDF.Namespace"
|
|
|
|
}}
|
2017-03-12 13:27:52 +00:00
|
|
|
end
|
|
|
|
|
2017-06-10 21:08:49 +00:00
|
|
|
defp do_resolve_term(RDF, term), do: do_resolve_term(RDF.NS.RDF, term)
|
|
|
|
|
2020-05-16 22:01:18 +00:00
|
|
|
defp do_resolve_term(Elixir, term) do
|
|
|
|
{:error,
|
2020-06-29 08:37:42 +00:00
|
|
|
%RDF.Namespace.UndefinedTermError{
|
|
|
|
message: "#{term} is not a RDF.Namespace; top-level modules can't be RDF.Namespaces"
|
|
|
|
}}
|
2020-05-16 22:01:18 +00:00
|
|
|
end
|
|
|
|
|
2017-06-10 21:08:49 +00:00
|
|
|
defp do_resolve_term(namespace, term) do
|
2020-03-04 00:30:19 +00:00
|
|
|
is_module =
|
|
|
|
case Code.ensure_compiled(namespace) do
|
|
|
|
{:module, _} -> true
|
|
|
|
_ -> false
|
|
|
|
end
|
|
|
|
|
|
|
|
if is_module and Keyword.has_key?(namespace.__info__(:functions), :__resolve_term__) do
|
2017-06-10 21:08:49 +00:00
|
|
|
namespace.__resolve_term__(term)
|
|
|
|
else
|
2020-06-29 08:37:42 +00:00
|
|
|
{:error, %RDF.Namespace.UndefinedTermError{message: "#{namespace} is not a RDF.Namespace"}}
|
2017-06-10 21:08:49 +00:00
|
|
|
end
|
|
|
|
end
|
2017-03-12 13:27:52 +00:00
|
|
|
end
|