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