Chapter 5.  Model manipulation in 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.

5.1.  Create a new Kermeta file

We want to add a new kermeta file into the folder kermeta into org.kermeta.fsm.serialisation/src.

[Tip]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.

Wizard to create a new Kermeta file

Figure 5.1.  Wizard to create a new Kermeta file


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).

New Kermeta file

Figure 5.2.  New Kermeta file


[Tip] 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

[Tip] 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.

5.2.  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.

[Warning] 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 :

  1. Re-Register EPackages into registry : unregister and register again the EPackage in order to take into account the meta model's changes

  2. Unregister EPackages into registry : remove EPackage from EMF EPackage registry

  3. Register EPackages into registry : add EPackage from EMF EPackage registry

Register the meta model into the EMF EPackage Registry

Figure 5.3. Register the meta model into the EMF EPackage Registry


Then click on the followings icons :

Kermeta icon

Figure 5.4.  Kermeta icon


Reload icon

Figure 5.5. Reload icon


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.

5.3.  Serialisation

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 :

Fsm_dyn_sample1.xmi

Figure 5.6. Fsm_dyn_sample1.xmi


5.3.1. Load an EMF model with Kermeta

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"
         1
         
        using kermeta::persistence 
           2
           
         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")
         3
         resource.load

// Load the fsm (we get the instance)
 fsm1 ?= resource.one
 4
// 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
 }      

1

To serialize the class definition, the nsURI of the meta model need to be known.

2

This method permits to retrieve the resource where the model is stored or create a new resource if it does not exist.

3

The persistence permits to load and save EMF models. The key word using is used to simplify writing code like import in Java.

4

resource is collection of instances which are in the root file. The first instance of this resource is retrieve by the method one.

[Tip]Browse through the resource

You can use resource.each if you want to browse through the resource.

[Tip] Create new resource for your instance model

You can create a nex resource to contain your model with the method repository.createResource(NsURI instance model, NsURI metamodel)

repository is an EMFRepository that contain the resource.

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 :

Fsm_dyn_sample1.xmi content

Figure 5.7. Fsm_dyn_sample1.xmi content


5.3.2. Modify and save an EMF model with Kermeta

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")

5.3.3. Create a model in Kermeta, and save it as an EMF model

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):

Fsm_scratch_sample view

Figure 5.8. Fsm_scratch_sample view


5.3.4. A template for a complete Kermeta program

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
}

5.3.5.  Load and save for models divided into several resources

[Warning] 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.