Skip to content

Instantly share code, notes, and snippets.

@timothyklim
Created August 2, 2014 13:21
Show Gist options
  • Save timothyklim/6be66718c6c3705ddc1f to your computer and use it in GitHub Desktop.
Save timothyklim/6be66718c6c3705ddc1f to your computer and use it in GitHub Desktop.
package ru.nectarin.mediatron.utils.fsm
sealed class StateException(s: String) extends IllegalStateException(s)
trait Event
sealed abstract class State
sealed trait Source extends State
sealed trait Target extends State
case class LeafState(state: String) extends Source with Target {
override def toString = state
}
case class FinalState(state: String) extends Target {
override def toString = state
}
abstract class FSM[T](protected val initialState: State) {
def is(state: State) = initialState eq state
def current(): State = initialState
protected type Transition = ((Source, Event), Target)
protected val transitions: Set[Transition]
private def transitionTable: Map[(Source, Event), Target] = transitions.toMap
def apply(event: Event): T = {
initialState match {
case source: Source =>
val target: Target = transition(source, event)
val copied = this.copyWithState(target)
copied.asInstanceOf[T]
case _ => throw new StateException("State machine is finalized")
}
}
def copyWithState(newState: State): T
def canTo(event: Event) = {
initialState match {
case source: Source =>
val key = source -> event
transitionTable.get(key).isDefined
case _ => false
}
}
private def transition(state: Source, event: Event): Target = {
val key = state -> event
transitionTable.get(key) match {
case Some(toState) ⇒ toState
case None ⇒ throw new StateException(s"$state cannot handle $event")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment