defmodule Retex.Node.Select do
@moduledoc """
The select nodes are checking for attributes, if they exists and are linked to the
right owner from above, they will be activated and pass the tokens down in the test
nodes (that will check for their value instead).
"""
defstruct class: nil, id: nil, parent: nil
@type t() :: %Retex.Node.Select{}
def new(parent, class) do
item = %__MODULE__{class: class, parent: parent}
%{item | id: Retex.hash(item)}
end
defimpl Retex.Protocol.Activation do
def activate(
%Retex.Node.Select{class: "$" <> variable} = neighbor,
%Retex{} = rete,
%Retex.Wme{attribute: attribute} = wme,
bindings,
tokens
) do
rete
|> Retex.create_activation(neighbor, wme)
|> Retex.add_token(neighbor, wme, Map.merge(bindings, %{variable => attribute}), tokens)
|> Retex.continue_traversal(Map.merge(bindings, %{variable => attribute}), neighbor, wme)
end
def activate(
%Retex.Node.Select{class: attribute} = neighbor,
%Retex{} = rete,
%Retex.Wme{attribute: attribute} = wme,
bindings,
tokens
) do
rete
|> Retex.create_activation(neighbor, wme)
|> Retex.add_token(neighbor, wme, bindings, tokens)
|> Retex.continue_traversal(bindings, neighbor, wme)
end
def activate(
%Retex.Node.Select{class: _class} = _neighbor,
%Retex{} = rete,
%Retex.Wme{attribute: _attribute},
bindings,
_tokens
) do
Retex.stop_traversal(rete, bindings)
end
@spec active?(%{id: any}, Retex.t()) :: boolean()
def active?(%{id: id}, %Retex{activations: activations}) do
Enum.any?(Map.get(activations, id, []))
end
end
end