Current section
Files
Jump to
Current section
Files
lib/exonerate/combining/ref.ex
defmodule Exonerate.Combining.Ref do
@moduledoc false
alias Exonerate.Combining
alias Exonerate.Cache
alias Exonerate.Degeneracy
alias Exonerate.Tools
defmacro filter(resource, pointer, opts) do
# a ref might be:
# - reference to something local (usually starts with #)
# - reference to something set with an id
# - remote reference.
# condition the options to accept unevaluatedProperties
{parent_pointer, "$ref"} = JsonPtr.pop(pointer)
{ref_resource_uri, ref_pointer} =
Cache.traverse_ref!(__CALLER__.module, resource, parent_pointer)
ref_resource = to_string(ref_resource_uri)
__CALLER__
|> Tools.subschema(ref_resource, ref_pointer)
|> build_filter(resource, pointer, ref_resource, ref_pointer, opts)
|> Combining.dedupe(__CALLER__, resource, pointer, opts)
|> Tools.maybe_dump(__CALLER__, opts)
end
defp build_filter(context, resource, pointer, ref_resource, ref_pointer, opts) do
call = Tools.call(resource, pointer, opts)
call_path =
if String.starts_with?(resource, "exonerate://") do
JsonPtr.to_path(pointer)
else
{resource, JsonPtr.to_path(pointer)}
end
ref_call = Tools.call(ref_resource, ref_pointer, opts)
context
|> Degeneracy.class()
|> case do
:ok ->
quote do
@compile {:inline, [{unquote(call), 2}]}
defp unquote(call)(_content, _path), do: :ok
end
:error ->
# in this case we still need to regenerate the context because the degeneracy
# failure is stored in the remote call.
quote do
@compile {:inline, [{unquote(call), 2}]}
defp unquote(call)(content, path) do
unquote(ref_call)(content, path)
end
require Exonerate.Context
Exonerate.Context.filter(unquote(ref_resource), unquote(ref_pointer), unquote(opts))
end
:unknown ->
quote do
defp unquote(call)(content, path) do
case unquote(ref_call)(content, path) do
{:error, error} ->
ref_trace = Keyword.get(error, :ref_trace, [])
new_error = Keyword.put(error, :ref_trace, [unquote(call_path) | ref_trace])
{:error, new_error}
ok ->
ok
end
end
require Exonerate.Context
Exonerate.Context.filter(unquote(ref_resource), unquote(ref_pointer), unquote(opts))
end
end
end
end