A set of additions to DMN 1.6 that a caller switches on when it compiles a model (DD-28), as Feel.Extension is for FEEL (D-81 of feel).
DMN 1.6 defines what a model means, and the models that exist were written for other versions and other engines. An extension is a module that says what it adds, and the compiler asks the extensions that are on at the few places where it decides. Nothing in the compiler names an extension.
Dmn.compile(model, extensions: [:dmn_1_1_types])The option takes names (registry/0) and modules that implement this behaviour. It is [] by default, and then the engine is DMN 1.6
and nothing else. The extensions are those of the compile: they are not a property of a run, and the compiled model does not hold them.
A name that is not one, a module that is not an extension, and two extensions that give one name two meanings are
{:error, %Dmn.Error{kind: :compile, code: :invalid_options}}, as the options of a run are.
What an extension can do
An extension adds: it never changes what a model that is valid without it means. What it adds was an error before (a typeRef
that names no type), and a name that the model defines itself is the model's, whatever an extension says of it. The DMN TCK is run
with the extensions of Dmn.TCK on, and a node that is exact without them must stay exact.
| Callback | Adds |
|---|---|
type_aliases/0 | names of types that stand for another type, such as the names that DMN 1.1 gave the date and time types |
feel_extensions/0 | the Feel.Extensions that the expressions of the model are prepared with |
external_functions/0 | the kinds of external function that the extension runs (:java), each with the kind of FEEL ("java") that it is run as |
External functions
A functionDefinition of a kind other than FEEL (kind="Java") describes a function that something outside the model runs, and DMN 1.6
does not say how. The engine does not run one: the function is null and an :unsupported_function_kind error. An extension that
names the kind in external_functions/0 has it read as the external function of FEEL of that kind, with the body of the definition
for the description, and the function of FEEL extension that runs that kind (Feel.Analysis.External, D-211 of feel) is the one
that feel_extensions/0 brings. dmn does not know any kind: dmn_java is the one that runs Java.
Summary
Callbacks
The kinds of external function that the extension runs: the kind of a functionDefinition (:java, :pmml, :onnx) to the kind
that the function is in FEEL, the key of function(...) external {kind: ...} ("java"). A function of such a kind is compiled to
the external function of FEEL, which the extensions of FEEL that the extension brings have to run (feel_extensions/0).
The extensions of FEEL that the expressions of the model are prepared with (Feel.Extension: names or modules). Those of all the
extensions that are on are given together.
The name of the extension, for the messages about it.
Type names that stand for a type of FEEL: the name that is written in a typeRef, to the name of the type it stands for
(Feel.Type.builtin/1). A model that defines an item definition of a name is not asked: its definition is the type.
Functions
The external function kinds that the extensions that are on run: the kind of the functionDefinition to the kind in FEEL. A later
extension wins for a kind that two give.
The extensions of FEEL that the extensions that are on bring, each once, in the order given.
The extensions that extensions: knows by name, each with the module it stands for.
The modules for a list of names and modules, each once, in the order given. The names are those of registry/0, or of the map
given as the second argument.
The type aliases of the extensions that are on, from the name to the type it stands for. resolve/1 has seen that no two give one
name two types.
Callbacks
@callback external_functions() :: %{optional(:java | :pmml | :onnx) => String.t()}
The kinds of external function that the extension runs: the kind of a functionDefinition (:java, :pmml, :onnx) to the kind
that the function is in FEEL, the key of function(...) external {kind: ...} ("java"). A function of such a kind is compiled to
the external function of FEEL, which the extensions of FEEL that the extension brings have to run (feel_extensions/0).
@callback feel_extensions() :: [atom()]
The extensions of FEEL that the expressions of the model are prepared with (Feel.Extension: names or modules). Those of all the
extensions that are on are given together.
@callback name() :: atom()
The name of the extension, for the messages about it.
Type names that stand for a type of FEEL: the name that is written in a typeRef, to the name of the type it stands for
(Feel.Type.builtin/1). A model that defines an item definition of a name is not asked: its definition is the type.
Functions
The external function kinds that the extensions that are on run: the kind of the functionDefinition to the kind in FEEL. A later
extension wins for a kind that two give.
The extensions of FEEL that the extensions that are on bring, each once, in the order given.
The extensions that extensions: knows by name, each with the module it stands for.
iex> Dmn.Extension.registry()
%{dmn_1_1_types: Dmn.Extension.Dmn11Types}
The modules for a list of names and modules, each once, in the order given. The names are those of registry/0, or of the map
given as the second argument.
iex> Dmn.Extension.resolve([:dmn_1_1_types, Dmn.Extension.Dmn11Types])
{:ok, [Dmn.Extension.Dmn11Types]}
iex> {:error, message} = Dmn.Extension.resolve([:nope])
iex> message =~ ":nope"
true
The type aliases of the extensions that are on, from the name to the type it stands for. resolve/1 has seen that no two give one
name two types.