lib/fountainedge/workflow.ex

defmodule Fountainedge.Workflow do
  @moduledoc """
  Models a workflow (stateful.)

  The workflow has a `Fountainedge.Schema`, which defines its nodes and edges.

  The status of the flowchart is saved in a `Fountainedge.State` list,
  which tracks current nodes and any forking tokens.
  """

  alias Fountainedge.{Workflow, Schema, State}

  @enforce_keys [:schema, :states]

  defstruct schema: %Schema{nodes: [], edges: []},
    states: []

  @typedoc """
  Workflow structure.
  * `:schema` - The `Fountainedge.Schema`.
  * `:states` - Workflow status.
  """

  @type t :: %__MODULE__{
    schema: Schema.t(),
    states: list(State.t()) | []
  }

  @doc """
  Initialises a workflow.

  Will set the current state to the initial node specified in the schema.
  """
  @spec initialize(Schema.t()) :: Workflow.t()
  def initialize %Schema{} = schema do
    initial_node = Enum.find(schema.nodes,  fn n -> n.type == :initial end)

    if initial_node == nil do
      raise "Cannot initialise a workflow where the schema does not specify an initial node."
    end

    %Workflow{
      schema: schema,
      states: [
        %State{id: initial_node.id},
      ],
    }
  end
end