FSM example
Build date: 3-November-2010
Abstract
This tutorial is part of a serie of tutorials that explain step by step the process explained in the Building DSL main process. In this case, it rely on the classical Finite State Machine example.
Table of Contents
Kermeta is a Domain Specific Language dedicated to metamodel engineering. It fills the gap let by MOF which defines only the structure of metamodels, by adding a way to specify static semantic (similar to OCL) and dynamic semantic (using operational semantic in the operation of the metamodel). Kermeta uses the object-oriented paradigm like Java or Eiffel.This document presents various aspects of the language, including the textual syntax, the metamodel (which can be viewed as the abstract syntax) and some more advanced features typically included in its framework.
![]() | Important |
|---|---|
Kermeta is an evolving software and despite that we put a lot of attention to this document, it may contain errors (more likely in the code samples). If you find any error or have some information that improves this document, please send it to us using the bug tracker in the forge: http://gforge.inria.fr/tracker/?group_id=32 or using the developer mailing list (kermeta-developers@lists.gforge.inria.fr) Last check: v1.3.2 |
![]() | Tip |
|---|---|
The most update version of this document is available on line from http://www.kermeta.org . |
This tutorial gives an overview of many concepts used through KerMeta project creation. You can retrieve all the steps defined in the Manual Process to build a DSL on which you can iterate in order to progress in your development. Following this tutorial should give you the knowledge : to create a meta model, check its invariants, run configurations, add pre and post conditions and add behaviour on it. To cover all this features, we decided to start from an existing example. Because it is a complete KerMeta project, you should use it as a reference guide. This example is about the finite state machine which acronym is FSM. Firstly, a section explains how to load files of the example in your Eclipse workspace. The next section is dedicated to the finite state machine we want to model. You will have access to every files. Then we present the features presented above. Moreover, we present here examples of graphical editors but this step comes only when the metamodel is stabilized. In this tutorial we will have access to the base project in order to follow it (cf section Install FSM project) . You can have also have access of the solution of this tutorial ( cf section Install the tutorial 's solution )
![]() | Caution |
|---|---|
KerMeta must be installed (FSM tutorial is only available in this case). If not, please read the "How to install KerMeta" tutorial. |
We start from the main Eclipse window.
Select : "File" > "New">> "Example.. A window appears. You are asked to choose a wizard for project creation. At the bottom of the list, you will find "Kermeta samples" item. Browse it and select "FSM tutorial Demo". The "Finish" button has been enabled. Click on it.
Thanks to the wizard creation project, a project named "fr.irisa.triskell.kermeta.samples.fsm.demoAspect" appeared on the left side of Eclipse.
If you directly want to see the results, the solutions are available into File -> New -> Example -> Kermeta Samples -> FSM Solutions.
Now, you have the reference project and you can follow the tutorial.The next chapter presents the metamodel used in this tutorial.
We want to represent IO/state machines. Inputs and outputs can be attached on each transition. To illustrate finite state machine, here is a simple example. This state machine recognizes the "hello!" motif and produces the "world!" motif. Here, we present this finite-state machine in a specific graphical syntax where states are represented as squares and transitions by arrow between squares. Input and outputs are present above transitions. Here, "h/w" says that we consume an "h" to produce a "w".
This simple state machine can be modeled and executed easily in Kermeta. See the following meta-model presented in a class diagram syntax. You can retrieve this metamodel named fsm.ecore into fr.irisa.triskell.kermeta.samples.fsm.demoAspect/metamodels/fsm.ecore
In this tutorial we want to create the fsm metamodel with EMF. To start with, create a new EMF project (File-> New-> Other -> Eclipse Modeling Framework -> Empty EMF Project) and name it org.kermeta.fsm.emf . Then create a new folder model on it. If you want to create an EMF metamodel for fsm from scratch you can follow the tutorial "How to create an EMF meta model?"" and use the EMF Sample reflexive editor to create a metamodel like in the following figure into the folder model. Name it fsm.ecore. Otherwise, you can simply copy the file fsm.ecore from fr.irisa.triskell.kermeta.samples.fsm.demoAspect/metamodels/fsm.ecore to org.kermeta.fsm.emf/model folder.
![]() | Tip |
|---|---|
An FSM EMF editor is ever deployed into the Kermeta Eclipse. It is available in File-> New -> Other -> Kermeta -> FSM Samples -> Fsm Model. |
At this stage of the tutorial, you should have the following metamodel:
Then you can use this metamodel to create instances of models conform to it, like detailed in the next section.
In this chapter we present how to create instances of the Fsm metamodel. You can use two ways to do that, creating dynamic instances directly or using an EMF tree editor.
Like shown in the Process tutorial create a dynamic instance is an easy way to create an instance of a metamodel during the first development phases. To do so :
Create a new folder dynamic_instance in org.eclipse.fsm.emf .Open the fsm.ecore file with the Sample Ecore Model Editor (Right click on the file -> Open with -> Sample Reflective Ecore Model Editor)
To open the content of thid file click on the arrows at the left. Then, right click on the FSM metaclass -> Create Dynamic Instance and select the folder dynamic_instance. Name your instance fsm.xmi.
Open this instance with the Sample Reflexive Ecore Model Editor (like shown above). You can add two State st1 and st2 on the FSM class and then a transition a that produce b between st1 and st2 like in the following image :
The Logo tutorial ( chapter 4 Editor, section 4.1 Dynamic Instance) presents how to create a dynamic instance with an ecorediag. The next section presents another way to create instances of a given metamodel, create a tree view editor with an EMF project.
Tree view editors should be favoured for meta-models that are relatively stable and for final development phase. It allows to customize the generated editor to match meta-model specificities. (see the end of this article: Eclipse Corner Article : Using EMF)
This is the most ergonomic – but longest – way to create an instance of a meta-model. This method is here presented in its main lines:
Create a new project and a new ecore metamodel ( this step was ever made in the section Create the fsm meta-model )
Once the meta-model is created, it is possible to create a model for model generation, called genmodel:
Right click on the file fsm.ecore New > Other > Eclipse Modeling Framework folder > EMF Generator Model and select Next;
Keep the proposed name (fsm.genmodel) and click on Next. Then, select Ecore model in the following wizard and click on Next;
Here, the metamodel is ever selected. Otherwise, select Browse workspace button, and find the meta-model file (fsm.ecore into or.kermeta.fsm.emf/model). Then click on Load button and on Next;
Select the package fsm at the top of the window and click on Finish
In order to avoid weird behaviour (particularly if the current project was not set as a “Java project”) the model directory of the genmodel needs to be changed in the Properties tab of the genmodel. For this purpose, click on the root node of the fsm.genmodel and change the property called Model Directory (in the Model folder) to /org.kermeta.fsm.emf.model/src, so that the EMF source code is generated in a new empty project that will exclusively contain this source code. You need also to change the property Model Plug-in ID to org.kermeta.fsm.emf.model .
Right-click on the package node of the fsm.genmodel (second sub node, it corresponds to the fsm package), and choose the Generate all item.
You should obtain the following plugins (if we not consider the folder dynamic_instance which is not linked with the EMF editor creation) :
You can customize this EMF editor following the example given on the section Customize the generated EMF editor . The next section presents how to use this newly created tree view editor.
To be able to use the generated reflexive editor, a new runtime workbench has to be launched through the tool bar menu:
In Eclipse Galileo (3.5), right click on org.kermeta.fsm.emf.editor and select Run As -> Eclipse Application
Once the new eclipse application is launched, create a new General project (File -> New -> Other-> General -> Project). Call it MyFirstEMFInstances). Then select File > New > Other > Example EMF Model Creation Wizards folder > Fsm Model to create your instance file and choose FSM as Model Object;
To add elements to your model just right click on the FSM container and add new Child or new Sibling like in metamodels 's creation steps (cf fsm.xmi example in the section Dynamic Instances ;
![]() | Parallelism between edit a model or a metamodel |
|---|---|
Creation of an EMF model follows the same principles that the creation of an Ecore model. Note that the model object, which was EPackage in the meta-model creation, becomes Fsm in the EMF model creation. |
You can use another editors to create instances models such as graphical or textual editors. The following sections presents rapidly this kind of editors.
You can also use textuals editors like XText , EMFText, Sintaks (which is part of the Kermeta project) . This textuals editors are not detailed here, please refer to the Logo tutorial (chapter 4 Editor, section 4.3 Textual Editor).
EMF metamodels can be used with tools like GMF (Graphical Modelling Framework) or Topcased (the FSM Diagram from Kermeta -> Samples FSM was created with Topcased) to create graphical editors for model instances. The tutorial How to create a FSM graphical editor with GMF? explains the creation of an GMF editor with a very simple FSM metamodel. You can retrieve the result of this tutorial and the gmf models into fr.irisa.triskell..kermeta.samples.fsm.gmf.
You know how to create a model conform to the Fsm metamodel. The next chapter explains how to manipulate models with Kermeta.
Firstly, we present to you how to create a KerMeta file. Then loading a first Kermeta program can be achieved by just copying the code provided in the following sections, following carefully the suggested instructions. Readers who want to directly load their own models should directly go to the section A template for a complete Kermeta program and customize the given template.
You can start with opening the Kermeta perspective with Window->Open Perspective -> Other -> Kermeta and create a new Kermeta project (File -> New -> New Kermeta Project into the Kermeta perspective). Name it org.kermeta.fsm.serialisation, copy the file fsm.ecore (from fr.irisa.triskell.kermeta.samples.fsm.demoAspect/metamodels/fsm.ecore) into metamodel folder. The following section presents how to create a new Kermeta file.
We want to add a new kermeta file into the folder kermeta into org.kermeta.fsm.serialisation/src.
![]() | Tip |
|---|---|
This sample is available in the FSM Solutions in the project fr.irisa.triskell.kermeta.samples.fsm.serialisation |
To do this, select in the main menu of Eclipse
"File" > "New" ->"New Kermeta File"
This action opens the following window.
Give a name (Serialisation.kmt for instance) to the new file, select a location (The default one is good for us) and change the package to fsm_package. Click on "Finish".
Now your main window should look like the one below. The file is written in KerMeta language. So you can edit this file to add some classes, attributes and so on using the KerMeta language (read Kermeta Manual for more details on KerMeta language).
![]() | Create a Kermeta file into another perspective |
|---|---|
If you are not into the Kermeta perspective you can create a new Kermeta file with File -> New -> Other -> Kermeta -> New Kermeta File |
![]() | Add the Kermeta nature to a project |
|---|---|
If your project is not a Kemeta project you can add the Kermeta nature on it. Right click on the project Kermeta-> Add Kermeta nature. It permit to check the .kmt files at the beginning of Eclipse. |
Now, we add Kermeta code to load and save models compliant with the fsm.ecore metamodel. For this you need to register the EMF metamodel into the Package Registry.
If you want to save a model conform to a particular metamodel whatever you want into the workspace it is useful to register its metamodel into the EMF Package Registry. Indeed, if the meta-model is not registered into the EMF Package Registry, a relative path is used to link the instance file with its meta-model. So we need to register this meta model into the EMF Package Registry. There is two ways to do that, deploying an EMF plugin like in the section Tree view editor which add permanently the meta model to the Eclipse's EMF Package Registry or register dynamically the meta model on it thanks clicking on the ecore metamodel file -> EPackages registration -> Register EPackages into repository.
![]() | Dynamical EMF Registration is not permanent |
|---|---|
You need to register again the meta models for each new instance of Eclipse. |
The following menu EPackages registration have three entries :
Re-Register EPackages into registry : unregister and register again the EPackage in order to take into account the meta model's changes
Unregister EPackages into registry : remove EPackage from EMF EPackage registry
Register EPackages into registry : add EPackage from EMF EPackage registry
Then click on the followings icons :
Now, we use Kermeta to load an save models i.e to serialise the models. So, register the fsm.ecore model as we presented above to use it in the example.
By serialisation, we mean here : to save and load models thanks to the presistence library. For these following sections copy and paste on your new file Serialisation.kmt or look at the file serialisation.kmt into fr.irisa.triskell.kermeta.sample.fsm.serialisation/kermeta. Create a new dynamic instance for FSM named Fsm_dyn_sample1.xmi in the folder model like in the section Dynamic instances . Add on it two states st1 et st2 and two transitions. The first transition from st1 to st2 consume an "a" and produce a "b" whereas the second transition from st2 to st2 consume a "c" and produce a "d". This xmi file should look like this :
The following code sample load a previously created FSM model. Copy and paste it on org.kermeta.fsm.serialisation/src/kermeta/serialisation.kmt or see the serialisation.kmt file on fr.irisa.triskell.kermeta.samples.fsm.serialisation/src/kermeta/serialisation.kmt.
@mainClass "fsm_package::Main"
@mainOperation "main"
package fsm_package;
require kermeta
require "http://www.kermeta.org/fsm"
using kermeta::persistence
using kermeta::standard
class Main
{
operation main() : Void is do
// Input fsm
var fsm1 : fsm::FSM
// Create the repository, then the resource
var repository : EMFRepository init EMFRepository.new
var resource : EMFResource
resource ?= repository.getResource("platform:/resource/org.kermeta.fsm.serialisation/model/Fsm_dyn_sample1.xmi")
resource.load
// Load the fsm (we get the instance)
fsm1 ?= resource.one
// Check that the fsm was correctly loaded
fsm1.ownedState.each { s | stdio.writeln("-> "+s.name)
s.outgoingTransition.each { ti | stdio.writeln( "outgoing : " + " source " + ti.source.name + " target " + ti.target.name + " input : " + ti.input + " output : " + ti.output)}
s.incomingTransition.each { to | stdio.writeln( "incoming : " + " source " + to.source.name + " target " + to.target.name +" input : " + to.input + " output : " + to.output )}
}
end
}
To serialize the class definition, the nsURI of the meta model need to be known. | |||||||
This method permits to retrieve the resource where the model is stored or create a new resource if it does not exist. | |||||||
The persistence permits to load and save EMF models. The key word using is used to simplify writing code like import in Java. | |||||||
resource is collection of instances which are in the root file. The first instance of this resource is retrieve by the method one.
|
Example 5.1. Load an EMF model with Kermeta
To run this file simply right click on it (Run
As -> Run As Kermeta Application). You
should obtain the following trace in the Eclipse's console :
At this stage, it should be interesting to be able to modify a previously loaded model using Kermeta before saving it. The procedure is very simple: do your manipulation as if your loaded FSM model is a Kermeta model (which is, in effect, the case!), and then, simply call a save method on the handling resource. For this purpose, the following code can be added at the end of the main operation defined in the above section:
var newstate : fsm::State init fsm::State.new
newstate.name := "s_new"
fsm1.ownedState.add(newstate)
// save fsm1
resource.save()A new state s_new appears on the file Fsm_dyn_sample1.xmi.
It is also possible to save the modified model in a new file instead of overwriting
the initial one by using the saveWithNewURI() method. To this end, just
replace the last line of above code (resource.save()) by the following
one:
resource.saveWithNewURI("platform:/resource/org.kermeta.fsm.serialisation/model/modified_dyn_sample1.xmi")Saving a programmatically generated model requires to use a new specific instruction
that add the created Fsm root class to the destination resource. The
following code chunk creates a simple EMF model with 2 states (named “foo”, and “bar”),
and 2 transitions. Saving it then consists in adding the root class (i.e. the model
object) stored in the variable fsm2 into the resource instances.
var another_resource : EMFResource
another_resource ?= repository.createResource(
"platform:/resource/org.kermeta.fsm.serialisation/model/Fsm_scratch_sample.xmi",
"platform:/resource/org.kermeta.fsm.serialisation/metamodel/fsm.ecore")
var fsm2 : fsm::FSM init fsm::FSM.new
var s0 : fsm::State init fsm::State.new
var s1 : fsm::State init fsm::State.new
var t01 : fsm::Transition init fsm::Transition.new
var t11 : fsm::Transition init fsm::Transition.new
s0.name := "foo"
s1.name := "bar"
t01.source := s0
t01.target := s1
t11.source := s1
t11.target := s1
fsm2.ownedState.add(s0)
fsm2.ownedState.add(s1)
s0.outgoingTransition.add(t01)
s1.outgoingTransition.add(t11)
// save the from-scratch model!
another_resource.add(fsm2)
another_resource.save()This program should return the following FSM model (viewed with the reflexive editor):
The following short code sample provides a comprehensive code template (replace the <words>) for model loading. Note here that the term model object is appropriate (better than root class!): loading a model consists in getting the root class, from which, thanks to the containment property (see section, all the contained instances can be accessed.
@mainClass "fsm_package::Main"
@mainOperation "main"
package fsm_package;
require kermeta
require "< nsURI of the metamodel >"
using kermeta::persistence
using kermeta::standard
class Main
{
operation main() : Void is do
// Variable for your input EMF model
var <my_model_object> : <type_of_my_model>
// Create the repository, then the resource
var <my_rep> : EMFRepository init EMFRepository.new
var <my_resource> : EMFResource
<my_resource> ?= repository.getResource(
"<relative_path_of_my_model_to_load>"),
<my_resource>.load
// Load the emf model - get the root class
<my_model_object> ?= resource.one
// You can now browse your model through its attributes/references
<my_model_object>.<an_attribute_of_it>.each { o |
stdio.writeln("-> "+o.toString) } )
// Save your model in another file
<my_resource>.saveWithNewUri("<relative_path_of_a_file_where_to_save_model>")
end
}
![]() | Depending models on the same EMFRepository |
|---|---|
Several models which have links between them must be saved into the same EMFRepository. Be careful on saving the resources (unlike load which retrieve all the resources). |
If your models have no dependancy between them, you can save them into several EMFRepository.
In the following chapters, we will study the sample fr.irisa.triskell.kermeta.samples.fsm.demoAspect.
Check all the invariants for a model can be useful if you use a model provided by a third party or resulting from a transformation, it permits to check well-formed rules. For more informations about it, please refer to the Model Checking Manual. Look at the file checkInvariants.kmt in fr.irisa.triskell.kermeta.samples.fsm.demoAspect/launcher/checkInvariants.kmt . This class permits to check all the invariants from the meta model thanks to the method checkAllInvariants.
class InvariantChecker
{
operation main(input_automaton : String) : Void is do
var rep : EMFRepository init EMFRepository.new
var theFSM : FSM init AutomatonHelper.new.loadEMFAutomaton(rep, input_automaton, "http://www.kermeta.org/fsm")
// To check all contained elements by "theFSM"
stdio.writeln("> call of the checkAllInvariants method")
theFSM.checkAllInvariants
// To check only the states that are contained in "theFSM"
stdio.writeln("> call of the checkInvariants method")
end
}
Look at the Run Configuration FSM check invariant. If you run it you should obtain the following trace :
Now, we will study the case of an error which violate an invariant. Look at the file FSMConstraints.kmt into fr.triskell.kermeta.fsm.demo/kermeta/constraints/FSMConstraints.kmt . You will see the following invariant
aspect class State{ inv invariant1 is do self.outgoingTransition.forAll{ tr1 | self.outgoingTransition.forAll{ tr2 | tr2.input.equals(tr1.input).equals(tr1.equals(tr2))}} end } It means that several outgoing transitions from a state cannot have the same input. Look at the file samplerunErrorInvariant.fsm. Right click on Aspect check invariantsError and click on Apply and Run. This fsm model have two transitions with the same input. Like invariant is violated, Kermeta raises an exception. So, you should obtain the following trace :
Now you know how to check models. The next section explains how you can improve kermeta programs adding on them Design by contract which consist in adding pre and post conditions.
By Design by contract, we mean add pre or post condition to our ecore model in order to add constraints on the Fsm's execution. It permits to use good practices into kermeta development. You can retrieve the Design by Contract concepts languages like Eiffel. Firstly, we present how to run configurations to parametrize this pre or post conditions. Then we present examples of pre and post conditions. In this section we study the example available in fr.irisa.kemeta.samples.fsm.demoAspect.
We want to execute an FSM model. To do that we must call the "run" operation of the "FSM" class. We are going to do that thanks to a KerMeta script. This script will : load an instance of the FSM meta model stored in a file and call the run operation of these instance.
![]() | Tip |
|---|---|
To launch a script, the interpreter must know the entry point of the program. It can "ask" it to the user thanks to an Eclipse window. Another way might be to add the following statements into your kermeta code :
|
In the FSM example ( fr.irisa.triskell.kermeta.samples.fsm.demoAspect) , those scripts are in the "launcher" directory. Look at "minimization.kmt" script. Here the interpreter knows that entry point of the program is the operation "main" in the "Minimization" class.
Let's have a look at the file named "minimization.kmt". Open it. Look at the code of the main operation. There is no parameter. To run this script with constraint checking, right click on "minimization.kmt" and select "Run As" and "Kermeta Constrained Application". To run this script without constraint checking, right click on "minimization.kmt" and select "Run As" and "Run As Kermeta Application".
The program asks you for a filename. Put in "../models/sample1.fsm" for example. You are lastly asked for a filename which will correspond to the file generated by the program. Put in "../generated.fsm" and see the execution.
Now if you have a look at the three others scripts (checkInvariants, determinization and fsmLauncher) into fr.triskell.kermeta.samples.fsm.demoAspect/launcher you will notice that the main operation of the main class takes one argument. Let's focus on "fsmLauncher.kmt" launcher. The main operation takes one parameter which is the name of the file containing the FSM model. It loads the model, prints it and runs it. If you try the running method above, an exception is raised because the parameterized file does not exist. Indeed we did not specify any filename to the program. So, you cannot use the method above to run those kind of script. That is the reason why we are going to use run configurations. Then right click on "fsmLauncher.kmt" file and select "Run As" and "Run Configurations...". A window appears like the one below. Select the run configuration named "loaderFSM" and look at the different options. Have a special look at the file parameters :
"Location of your program file", here this is "fsmLauncher.kmt" filename relative to the project's root directory.
"Class qualified name", that is to say the main class of the program.
"Operation name", that is to say the main operation of the main class.
"Operation arguments", the parameters you want to send to the main operation.
Here, we give the string "../models/sample1.fsm" as a parameter to mainLoadFSM operation to "fsm::Main" class. By clicking on "Run" button, it will start the execution. You can create yourself some new run configurations. Just by left clicking on "Kermeta Application " or "Kermeta Constraint Application" (depending on the constraint checking you want) and select "New" and fill in the required fields.
![]() | Caution |
|---|---|
Eclipse is slash sensible. It only accepts front slash and no backslash. Then /fr.irisa.triskell.kermeta.samples.fsm.demo/launcher/fsmLauncher.kmt is a valid filename whereas \fr.irisa.triskell.kermeta.samples.fsm.demo\launcher\fsmLauncher.kmt is not. |
![]() | Tip |
|---|---|
If you want to create a new configuration, just right click on Kermeta Application, or Kermeta Constrained Application and New. Then, fill the fields like above. |
This section will present an example of constraint checking execution. Have a look at the "fsm.kmt" file (into fr.triskell.kermeta.samples.fsm.demo/kermeta. This kermeta file requires two files :
fsm_Operationnal_Semantics.kmt from fr.triskell.kermeta.samples.fsm.demo/kermeta/semantics/ which defines the fsm 's behaviour ( cf section Behaviour )
The following code shows the behaviour of the step operation :
aspect class State { reference combination : Set<State> // 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 // Create a new state from self state operation copy() : State is do result := State.new result.name := String.clone(name) result.combination := Set<State>.new end }![[Tip]](http://www.kermeta.org/docs/fr.irisa.triskell.kermeta.samples.fsm.documentation/build/html.single/KerMeta-The-FSM-example/gfx/admonitions/tip.gif)
Tip The key-word aspect (cf Behaviour ) permits to add some operations.
FSMConstraints.kmt from fr.triskell.kermeta.samples.fsm.demo/kermeta/constraints/ which defines an invariant and pre and post conditions.
aspect class State{ inv invariant1 is do self.outgoingTransition.forAll{ tr1 | self.outgoingTransition.forAll{ tr2 | tr2.input.equals(tr1.input).equals(tr1.equals(tr2))}} end } aspect class State{ operation step(c : String) :String pre pre2 is do c.equals(void).~not.~and(c.size.isGreater(0)) end post post3 is do result.equals(void).~not.~and(result.size.isGreater(0)) end is abstract }
There is a pre condition (pre2) which says that the character given as a parameter must not be void or empty string. The post condition (post3) says that the result must not be void or empty string. For each "step" method call, the pre and post conditions will be checked. If there are evaluated as false, the program is aborted otherwise the program goes on. Look at the run configuration named "FSM Aspect loader with pre-post check". If you do not retrieve this configuration right click on FSM Aspect loader with pre-post check.launch Run As -> FSM Aspect loader with pre-post check. Open the file (../models/sample1postv.fsm) used as parameter for this configuration. Observe the finite state diagram.
Execute "FSM Aspect loader with pre-post check" configuration. When you are asked for a letter , just press enter to send an empty string. Normally, it should provoke the violation of the pre condition. You should obtain the following trace into the console :
State : s1 Transition : s1-(c/NC)->s2 State : s2 Transition : s2-(x/y)->s2 Current state : s1 give me a letter : stepping... [kermeta::exceptions::ConstraintViolatedPre:4603] pre pre2 of operation step of class State violated
Execute "FSM Aspect loader with pre-post check" configuration. When you are asked for a letter , press c and then press enter. Normally, the post condition will be violated because the result will be an empty string. You should obtain the following trace into the console :
State : s1 Transition : s1-(c/NC)->s2 State : s2 Transition : s2-(x/y)->s2 Current state : s1 give me a letter : c c stepping... [kermeta::exceptions::ConstraintViolatedPost:5548] post post3 of operation step of class State violated
This chapter presented the use of pre and post condition on an execution.The next chapter explain how you can simulate an execution of the modelling system thank to behaviour.
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
endIn 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.
The files minimization.kmt and determinization.kmt from fr.irisa.triskell.kermeta.samples.fsm.demo/launcher are examples of transformation of one model to one another,let you have a look on it. These examples are separated into three main steps :
load the model to transform and initialize the output model
traitment of the transformation (use an algoritm to determin the new results and add it into other output model).
save the output model
You can execute these examples following the section Run configurations. This section give you an example of model transformation. The next section will present how to customize the EMF editor presented on section Tree view editor.
You can customize your user interface like shown below. For more samples please refer to the Logo tutorial (chapter 9 : UI Improvement).
Generated code can be modified for customization. An EMF editor for FSM models is ever deployed into Eclipse Kermeta. Retrieve the plugin code source with File -> Import -> Plug-in Development -> Plug-ins and Fragments and click two times on Next. Then choose the following plugins :
The plugin .model, .edit and .editor correspond to the fsm EMF editor whereas the .graphicalEditor represents the Topcased editor.
![]() | Add custom code |
|---|---|
To keep your customized code for each generation you need to add
/**
*
* @generated NOT
*/
just before the name of the method you want to customize. |
To change an icon you need only to replace the icon from fr.triskell.kermeta.samples.fsm.edit/icons/full/obj16 to another with the same name and the same extension. It is the case on this deployed plugin. The following image presents this plugin, the .gif images have been changed from the initial EMF generation.
Respectively the icons FSM.gif, State.gif and Transition.gif look like this :
![]() | Note |
|---|---|
Like GMF use EMF icons for the palette you can customize the palette icons by this way. |
You will see the change when you will use the generated editor like in the following section.
The following method comes from FSMItemProvider in the package fr.triskell.kermeta.samples.fsm.provider in the project fr.irisa.triskell.kermeta.samples.fsm.model.edit. It permits to disply thr initial state or if it is missing or if the final state is missing.
/**
* This returns the label text for the adapted class.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public String getText(Object object) {
String initialState = " [an initial state is required]";
if(object instanceof FSM && ((FSM) object).getInitialState()!=null) {
initialState = " [initial state = " + ((FSM) object).getInitialState().getName() + "]";
}
String finalState = " - [at least one final state is required]";
if(object instanceof FSM && ((FSM) object).getFinalState().size()>0 ) {
finalState = "";
}
return getString("_UI_FSM_type") + initialState + finalState;
}
.
This tutorial give an illustration of the steps presented into the Processes to build a DSL Document (cf hyperlien), in particular it focus on traitment of an ecore meta model into Kermeta. For more informations please refer to others tutorials available http://www.kermeta.org/documents/tutorials .
![[Important]](http://www.kermeta.org/docs/fr.irisa.triskell.kermeta.samples.fsm.documentation/build/html.single/KerMeta-The-FSM-example/gfx/admonitions/important.gif)
![[Caution]](http://www.kermeta.org/docs/fr.irisa.triskell.kermeta.samples.fsm.documentation/build/html.single/KerMeta-The-FSM-example/gfx/admonitions/caution.gif)










![[Note]](http://www.kermeta.org/docs/fr.irisa.triskell.kermeta.samples.fsm.documentation/build/html.single/KerMeta-The-FSM-example/gfx/admonitions/note.gif)


![[Warning]](http://www.kermeta.org/docs/fr.irisa.triskell.kermeta.samples.fsm.documentation/build/html.single/KerMeta-The-FSM-example/gfx/admonitions/warning.gif)
















