// Copyright 2024 Matthew Rich . All rights reserved. package machine import ( _ "errors" "fmt" "log/slog" ) type Transitioner interface { Run(m Modeler) error Subscribe(s Subscriber) } type Transition struct { trigger string source []State dest State subscriptions []Subscriber } func NewTransition(trigger string, source []State, dest State) Transitioner { return &Transition{trigger: trigger, source: source, dest: dest} } func (r *Transition) Run(m Modeler) error { slog.Info("Transition.Run()", "transition", r, "model", m) currentState := m.InspectState() if currentState == r.dest { return nil } for _, transitionSource := range r.source { if currentState == transitionSource || transitionSource == "*" { res := m.ChangeState(r.dest) if res == currentState { r.Notify(EXITSTATEEVENT, currentState, r.dest) r.Notify(ENTERSTATEEVENT, currentState, r.dest) return nil } } } return fmt.Errorf("Transition from %s to %s failed on model state %s", r.source, r.dest, currentState) } func (r *Transition) Subscribe(s Subscriber) { r.subscriptions = append(r.subscriptions, s) } func (r *Transition) Notify(on Eventtype, source State, dest State) { for _, s := range r.subscriptions { s.Notify(&EventMessage{On: on, Source: source, Dest: dest}) } }