Packages

A native Elixir loader, validator, and evaluator for Decision Model and Notation 1.5 models.

Current section

Files

Jump to
boxic_dmn lib boxic dmn compatibility.ex
Raw

lib/boxic/dmn/compatibility.ex

defmodule Boxic.DMN.Compatibility do
@moduledoc """
The DMN compatibility profile supported by this Boxic release.
Boxic targets the formally released DMN 1.5 profile for strict loading,
validation, evaluation, and XML encoding. Inspection remains tolerant of
older and namespace-less documents, but compatibility with those profiles is
not part of the executable contract.
"""
@dmn_1_5_model_namespace "https://www.omg.org/spec/DMN/20230324/MODEL/"
@dmn_1_4_model_namespace "https://www.omg.org/spec/DMN/20211108/MODEL/"
@dmn_1_3_model_namespace "https://www.omg.org/spec/DMN/20191111/MODEL/"
@feel_namespace "https://www.omg.org/spec/DMN/20230324/FEEL/"
@dmndi_namespace "https://www.omg.org/spec/DMN/20230324/DMNDI/"
@dc_namespace "http://www.omg.org/spec/DMN/20180521/DC/"
@di_namespace "http://www.omg.org/spec/DMN/20180521/DI/"
@tck_revision "a162739daee85fb28e9d3bec2f306505992dae0f"
@type source_profile ::
:dmn_1_5 | :dmn_1_4 | :dmn_1_3 | :unqualified | {:unknown, String.t()}
@type profile :: %{
version: String.t(),
source_profile: :dmn_1_5,
model_namespace: String.t(),
feel_namespace: String.t(),
dmndi_namespace: String.t(),
dc_namespace: String.t(),
di_namespace: String.t(),
schema: String.t(),
tck_revision: String.t()
}
@doc "Returns the single DMN profile emitted and evaluated by this release."
@spec pinned_profile() :: profile()
def pinned_profile do
%{
version: "1.5",
source_profile: :dmn_1_5,
model_namespace: @dmn_1_5_model_namespace,
feel_namespace: @feel_namespace,
dmndi_namespace: @dmndi_namespace,
dc_namespace: @dc_namespace,
di_namespace: @di_namespace,
schema: "DMN15.xsd",
tck_revision: @tck_revision
}
end
@doc "Classifies the namespace used by a loaded definitions element."
@spec source_profile(String.t() | nil) :: source_profile()
def source_profile(nil), do: :unqualified
def source_profile(""), do: :unqualified
def source_profile(@dmn_1_5_model_namespace), do: :dmn_1_5
def source_profile(@dmn_1_4_model_namespace), do: :dmn_1_4
def source_profile(@dmn_1_3_model_namespace), do: :dmn_1_3
def source_profile(namespace) when is_binary(namespace), do: {:unknown, namespace}
@doc """
Resolves the effective expression language for a source profile.
The local declaration takes precedence over the definitions declaration.
Omission at both levels selects the DMN 1.5 FEEL default. The internal
`"feel"` marker is accepted for authored normalized models but is never a
standards namespace emitted by the writer.
"""
@spec expression_language(source_profile(), String.t() | nil, String.t() | nil) ::
{:ok, String.t()} | {:error, {:unsupported_expression_language, term()}}
def expression_language(:dmn_1_5, definitions_declaration, local_declaration) do
effective = local_declaration || definitions_declaration || @feel_namespace
if effective in ["feel", @feel_namespace] do
{:ok, @feel_namespace}
else
{:error, {:unsupported_expression_language, effective}}
end
end
def expression_language(source_profile, _definitions_declaration, local_declaration) do
{:error,
{:unsupported_expression_language,
%{source_profile: source_profile, declaration: local_declaration}}}
end
end