Adding a behaviour to the FSM meta-model consists in to make a simulation of execution with operations and an execution context represented by the current state of the FSM. That's why you need to add a currentState reference and three operation :
run() for FSM class,
step(String): String for State class,
and fire(): String for Transition class
Adding behavior to this meta model look like change the meta model according the following schema :
The old way to add behavior in Kermeta was transform the ecore meta model into a Kermeta file and add the code for the methods. This tutorial presents the new approach, use aspect to add this new operations. With aspect, you can add new elements and new operations to a fixed meta-model. You can also combine several aspects. This section show you how to add behaviour with aspect into a metamodel. Have a look on the file fsm_Operationnal_Semantics.kmt from fr.irisa.triskell.samples.fsm.demo/kermeta/semantics which contains the fsm 's behaviour operations.
So, this part presents the use of aspects to implement behavior. An aspect into a KerMeta file can be created simply with :
require kermeta require "http://www.kermeta.org/fsm" using fsm using kermeta::standard aspect class Transition { // Fire the transition operation fire() : String is do [...] end } }
You need to load the meta model where you will weave aspects. | |
The key word using fsm permits to simplify the writing of the elements from the fsm meta model like an import in the Java language. | |
The key word aspect is used to add attribute or operation to an existing metaclass (in this case Transition) of the loaded meta model. | |
Now, you can add attribute or operation like in a classical Kermeta file. |
Example 8.1. Aspect in Kermeta
None of the elements added by aspect take part of the ecore meta model, so these elements are transient that’s why it cannot be serialized by this way. If you want to serialize a new element to the meta model you need to add it into. |
Have a look on the Kermeta file fsm_Operationnal_Semantics.kmt in the folder kermeta/semantics of fr.irisa.triskell.kermeta.samples.fsm.demo. You can add several aspects in the same file. So, this code is structured like this :
package fsm; require kermeta require "http://www.kermeta.org/fsm" using fsm using kermeta::standard using kermeta::persistence using kermeta::exceptions aspect class FSM { reference currentState : State // Operational semantic operation run() : Void raises FSMException is do // [...] end /** Initialize a new automaton from an existing one * param : * p_state : the initial state * isInitComb */ operation initialize(p_state : State, isInitComb : Boolean) is do // [...] end } aspect class State { // Go to the next state operation step(c : String) : String raises FSMException //[...] end } aspect class Transition { // Fire the transition operation fire() : String is do //[...] end }
The reference currentState is added by aspect into the fsm meta model. | |
The key word raises declare an exception that an operation can throw. | |
Don't forget to close the brace at the and of an aspect definition. |
Example 8.2. Structuration of the fsm_Operationnal_Semantics.kmt file
The next section presents the differents algorithms in details.
Now, we will present in details the algorithm for the operations run(), step(String) and fire (String).
The run operation is used as a user interface. Thanks to this operation, we are going to display information about the finite state machine, read user input and process steps.
The step operation is used to go to an other state depending on the user's input and the transitions available from the current state.
The fire operation is used to change the current state and to get the produced string.
Let us see the behavior of these three operations.
Behavior :
1 – initialize current state
2 – loop until the user's input equal to "quit"
print the current state
read a string
process a step
catch exceptions if there are some and exit the program displaying the error.
Here is the code of the operation :
operation run() : Void raises FSMException is do // reset if there is no current state if self.currentState == void then self.currentState := self.initialState end self from var str : String init "init" until str == "quit" loop stdio.writeln("Current state : " + self.currentState.name) str := stdio.read("give me a letter : ") if str == "quit" then stdio.writeln("") stdio.writeln("quitting ...") else if str == "print" then stdio.writeln("") else stdio.writeln(str) stdio.writeln("stepping...") do var textRes : String textRes := self.currentState.step(str) if( textRes == void or textRes == "" ) then textRes := "NC" end stdio.writeln("string produced : " + textRes) rescue (err : ConstraintViolatedPre) stdio.writeln(err.toString) stdio.writeln(err.message) str := "quit" rescue (err : ConstraintViolatedPost) stdio.writeln(err.toString) stdio.writeln(err.message) str := "quit" rescue(err : NonDeterminism) stdio.writeln(err.toString) str := "quit" rescue(err : NoTransition) stdio.writeln(err.toString) str := "quit" end end end end end
In this operation, there are pre and post conditions. These are conditions checked each time the operation is called. If they are evaluated to false an exception is raised. You can choose to check them or not. The following chapter presents how to run configurations.
Behavior :
1 – Select the possible transitions.
2 – If there is none raise a NoTransition exception.
If there is more than one raise a NonDeterminism exception.
3 – If there is only one transition, call its fire operation and return its result.
// Go to the next state operation step(c : String) : String raises FSMException is do // Get the valid transitions var validTransitions : Collection<Transition> validTransitions := outgoingTransition.select { t | t.input.equals(c) } // Check if there is one and only one valid transition if validTransitions.empty then raise NoTransition.new end if validTransitions.size > 1 then raise NonDeterminism.new end // Fire the transition result := validTransitions.one.fire end
In this example we execute a step into the fsm behaviour algorithm with the file samplerun.fsm stored into fr.irisa.triskell.kermeta.samples.fsm.demo/models/samplerun.fsm. The following image presents the file samplerun.fsm.
In this example, you use the transition c to go to s1 to s2 and produce the string v . the behaviour can be produced thanks to the operations run(), step() and fire() defined in the last section. To run this behaviour right click on FSM Aspect Behaviour -> Run as -> FSM Aspect Behaviour.
You should obtain the following trace :
You can continue the behaviour of finite state machine if you want. This section has presented how to add a behaviour on the meta model. The next section present how to use model transformation.