uOttawaUniversity of Ottawa - Canadas University
list of dots

Umple User Manual    [Previous]   [Next]   

Loading

Basic State Machines

A state machine has a fixed set of of values (called states) The state machine transitions from state to state by the occurrence of events. State machines are very useful for quickly defining a program's behaviour.

In Umple, a state machine is modeled as a special type of attribute. In any class, simply specify the state machine name, and follow the name by a block starting with '{' and ending with '}'. This indicates to Umple that you are defining a state machine, and not an ordinary attribute.

Within the block, you list the names of the various states. Each state is followed by a block, again indicated using '{' to start and '} to end. This block defines the details of a state.

Details of each state can include:

  • Transitions. A transition has an event name, the symbol '->', and then the name of a destination state. The event name will become the name of a generated method. To trigger the transition, you simply call the method. When the event occurs while the state machine is in the origin state, the state machine will change to the destination state.
    Transitions can also have: 
    • transition actions, specified as '/' followed by a block of code to execute.
    • guards, which are boolean expressions in square brackets. Even if the event occurs, the transition only takes place if the guard evaluates to true.
  • Entry actions, exit actions and do activities. See the separate manual page.
  • Nested states. See the separate manual page. You can nest state machines to arbitrary levels of depth.

Note that, in addition, you can specify code to be executed whenever an event is processed by using before or after directives.

The following diagram shows a garage door state machine as a UML diagram. The Umple code for this is at the bottom of this page. Note that UmpleOnline currently cannot draw state machines. state machne for garage door  

Example


// This example shows a simple state machine without any actions or guards
//
// In the following, status is a state machine, and acts like an
// attributes, whose value is set by various events.
//
// Open, Closing, Closed, Opening and HalfOpen are the possible
// values, or states, of status.
//
// buttonOrObstacle, reachBottom and reachTop are events. These
// become generated methods that can be called to cause a state
// change.
//
// To make the state diagram appear in UmpleOnline, select 'Options'
// then choose 'GraphViz State Diagram'
class GarageDoor
{
   status {
      Open { buttonOrObstacle -> Closing;  }
      Closing {
          buttonOrObstacle -> Opening;
          reachBottom -> Closed;
      }
      Closed { buttonOrObstacle -> Opening; }
      Opening {
          buttonOrObstacle -> HalfOpen;
          reachTop -> Open;
      }
      HalfOpen { buttonOrObstacle -> Opening; }
  }
}


      

Load the above code into UmpleOnline

 

Another Example

// This is a more fully-featured state machine for
// a garage door corresponding to the diagram above
class Garage {
  lazy Boolean entranceClear=true;
  GarageDoor { 
    Closed {
      entry/{stopMotor();}  
      entry/{triggerEnergySaveMode();}
      exit/ {triggerNormalEnergyMode();}
      pressButton -> /{turnLightOn();} Opening; 
    }
    Opening {
      entry/{runMotorForward();}
      openingCompleted -> Open;
    }
    Open {
      entry/{stopMotor();}
      // do {wait(60000); turnLightOff();}
      pressButton [getEntranceClear()] -> Closing;
    }
    Closing {
      entry/{runMotorInReverse();}
      closingCompleted -> Closed;
      pressButton -> /{flashLightOn();} Opening; 
    }
  }
  
  boolean runMotorInReverse() {
     System.out.println("Running motor in reverse");
    return true;
  }
  
  boolean flashLightOn() {
     System.out.println("Flashing light on");
    return true;
  }

  boolean turnLightOn() {
     System.out.println("Turning light on");
    return true;
  }
  
   boolean turnLightOff() {
     System.out.println("Turning light off");
    return true;
  }
  
  boolean runMotorForward() {
     System.out.println("Running motor forwards");
    return true;
  }

  boolean triggerEnergySaveMode() {
     System.out.println("Triggering Energy Saving Mode");
    return true;
  }

  boolean stopMotor() {
     System.out.println("Stopping motor");
    return true;
  }

  boolean triggerNormalEnergyMode() {
     System.out.println("Triggering Normal Energy Mode");
         return true;
  }
  
  boolean waitawhile() {
    System.out.println("Waiting");
    return true;
  }
  
  boolean test() {
          System.out.println("Testing");
         return true;
  }
  
}

      

Load the above code into UmpleOnline

 

Syntax


stateMachine : [[enum]]
    | [[inlineStateMachine]]
    | [[referencedStateMachine]]
    | [[activeDefinition]]

//Issue 148
inlineStateMachine : [=queued]? [=pooled]? [~name] { ( [[comment]]
    | [[state]]
    | [[trace]]
    | [=||]
    | [[standAloneTransition]])* }

// An enum is a state machine that has no events
// stateName is prefixed with ~ to match alphanumeric names only.
// This is needed to solve issue 399, which is cause when a terminating } is parsed as part of the statename.
enum : [~name:key] { [~stateName]? (, [~stateName])* }

state : [=final]? [stateName] { [[stateInternal]]* }

stateEntity- : [=||]
    | [[entryOrExitAction]]
    | [[autoTransition]]
    | [[transition]]
    | [[activity]]
    | [[state]]
    | [[trace]]
    | ;

autoTransition : [[activity]]? [[autoTransitionBlock]]

// Autotransitions have no event. The transition is immediately taken
// or taken after the do activity ends[[guard]]? -> [[action]]?
// The action can come before or after the arrow
autoTransitionBlock- : [[guard]]? ( [[action]] -> | -> [[action]] | -> ) [stateName] ;

// A transition guard can come before or after the arrow
// The order of guard and event definition can also be interchanged
transition : ( [[eventDefinition]] [[guard]]
    | [[guard]] [[eventDefinition]]
    | [=unspecified]? [[guard]]
    | [[eventDefinition]])? ( [[action]] ->
    | -> [[action]]
    | -> ) [stateName] ;

eventDefinition- : [[afterEveryEvent]] | [[afterEvent]] | [~event] ( [[parameterList]] )?

// The timer in a timed event can be an number, variable, function() or function(num)
afterEveryEvent- : afterEvery ( [!timer:[+*/a-zA-Z0-9_\.-]+(\([0-9\.]*\))?] )

afterEvent- : after ( [!timer:[+*/a-zA-Z0-9_\.-]+(\([0-9\.]*\))?] )

// An action can be executed on a transition, or on entry or exit
action : / [[moreCode]]+

entryOrExitAction : [=type:entry|exit] / [[moreCode]]+

// A do activity is long-lasting and can be interrupted
activity : do [[moreCode]]+

guard : [ [[constraint]] ]