Hi again

Here is a suggestion for a trait that can be used to define legal state 
transitions.  It also guards against illegal state transitions:

 /**
 * A simple extension of Akka's <code>FSM</code>.  In this class, state 
transitions can be defined with the
 * <code>from</code> state and <code>to</code> state constructs.  For 
instance see:
 * <pre>
 * <code>
 * from(Initialized) {
 * Seq(to(Enabled) {
 * action(Initialized, Enabled)
 * },
 * to(Disabled) {
 * action(Initialized, Disabled)
 * },
 * to(Terminated) {
 * action(Initialized, Terminated)
 * }
 * )
 * }
 * </code>
 * </pre>
 *
 * <p>
 * Note that <code>Function1</code> can be replaced with 
<code>PartialFunction</code>.
 *
 * @param S denotes the user specified state, e.g. Initialized, Started
 * @param D denotes the user specified data model
 */
trait MyFSM[S, D] {
  this: FSM[S, D] =>

  case class To[S](state: S, f: Function1[Event, Unit])

  def from(fromState: S)(toStates: Seq[To[S]]) {

    when(fromState) {
      case e @ Event(nextState: S, _) =>
        val option = toStates.find((to: To[S]) => to.state == nextState)
        option match {
          case Some(toState) =>
            toState.f(e)
            goto(nextState)
          case None =>
            stay
        }

      case _ =>
        println _
        stay
    }
  }

  /**
   * A helper method to create a To object
   */
  def to(state: S)(f: Function1[Event, Unit]) = To[S](state, f)

}

The usage can be:

/**
 * The following classes represent the states that this state machine 
supports.
 */
sealed class MyState
case object Initialized extends MyState
case object Enabled extends MyState
case object Disabled extends MyState
case object Terminated extends MyState

/**
 * Some dummy data class.
 */
trait Data
case object Empty extends Data

/**
 * Some dummy message class.
 */
case class Message(message: String)
/**
 * A simple example that illustrates how <code>from</code> and 
<code>to</code> constructs can be used.  Note that it is still
 * possible to use all the methods from <code>FSM</code>.  For instance, 
<code>when</code> method is used to handle messsages.
 */
class FooFSM extends Actor with FSM[MyState, Data] with MyFSM[MyState, 
Data] {
  startWith(Initialized, Empty)

  when(Initialized) {
    case Event(m: Message, _) =>
      onState(Initialized, m)
  }
  when(Enabled) {
    case Event(m: Message, _) =>
      onState(Enabled, m)
  }

  from(Initialized) {
    Seq(to(Enabled) {
      action(Initialized, Enabled)
    },
      to(Disabled) {
        action(Initialized, Disabled)
      },
      to(Terminated) {
        action(Initialized, Terminated)
      }
    )
  }
  from(Enabled) {
    Seq(
      to(Disabled) {
        action(Enabled, Disabled)
      },
      to(Terminated) {
        action(Enabled, Terminated)
      }
    )
  }
  from(Disabled) {
    Seq(
      to(Enabled) {
        action(Disabled, Enabled)
      },
      to(Terminated) {
        action(Disabled, Terminated)
      }
    )
  }

  initialize

  private def action(fromState: MyState, toState: MyState): 
Function1[Event, Unit] = {
    case Event(nextState: MyState, _) =>
    case _ =>
  }

  private def onState(currentState: MyState, message: Message) = {
    stay
  }
}

object Main {
  def main(args: Array[String]) {

    val system = ActorSystem("MyActorSystem")

    val extension = system.actorOf(Props[FooFSM], "FooFSM")
    extension ! Enabled
    extension ! Message("Hello")

  }
}


-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: http://akka.io/faq/
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to