To load your first kermeta program, you will just have to copy the code provided in the following chapters, following carefully the suggested instructions. Readers who want to directly load their own models should directly go to the section 4.5, p.15 and copy the given template.
The persistence library is inspired from the resource manager of EMF models. There is a repository (called EMFRepository), that is aimed at containing a set of resources (the EMFResources). Each resource contains a reference called instances, that contains all the root classes (usually you only have one root class) of the loaded model. So, the procedure of creation of a resource that will handle your EMF models is the following (code exammple is provided in next sections) :
instanciate an EMFRepository
create a new EMF resource in this repository
load this resource
get the instances, i.e the root class(es). When you have them, you can access all the other instances through accessing the root class(es) properties.
As a reminder, here is the common skeleton of a kermeta program, inside which you will add any library that is necessary to load and save the fsm samples.
@mainClass "fsm_package::Main" @mainOperation "main" package fsm_package; require kermeta require "../metamodels/fsm.ecore" using kermeta::persistence // <- used to load and save EMF models. using kermeta::standard class Main { operation main() : Void is do // TODO: implement 'main' operation end }
Here, we will load one of the Fsm models that we previously created:
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.createResource("../models/Fsm_dyn_sample1.xmi", "../metamodels/fsm.ecore") resource.load // Load the fsm (we get the instance) fsm1 ?= resource.instances.one // Check that the fsm was correctly loaded fsm1.state.each { s | stdio.writeln("-> "+s.name) } fsm1.transition.each { t | stdio.writeln( t.source.name " -- " +s.target.name ) } end
Now, you want to modify your model using Kermeta, and then to save 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. Thus, you can add the following code 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.state.add(newstate) // save fsm1 resource.save()
You can also save your model in a new file instead of overwriting the initial one by using save()
:(we just replace the last line of above code (resource.save()
) into this one:
resource.saveWithNewURI("../models/modified_dyn_sample1.xmi")
For this purpose, you will only have to do one specific instruction, that is, add the Fsm root class created from scratch to the destination resource. The following code chunk creates a simple EMF model with 2 states (named “foo”, and “bar”), and 2 transitions. Then saving it consists on adding the root class (i.e the model object) stored in the variable fsm2
in the instances of the resource .
var another_resource : EMFResource another_resource ?= repository.createResource( "../models/Fsm_scratch_sample.xmi", "../metamodels/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.state.add(s0) fsm2.state.add(s1) fsm2.transition.add(t01) fsm2.transition.add(t11) // save the from-scratch model! another_resource.instances.add(fsm2) another_resource.save()
You should have the following result (viewed with the reflexive editor):
To load your own models, you can simply fill in the short template code (replace the <words>) given below. Note that we can see that the term model object is appropriate, (better than root class!) : loading a model consists on getting the root class, from which, thanks to the containment property (see section 1.2, p.2), we access all the contained instances.
@mainClass "fsm_package::Main" @mainOperation "main" package fsm_package; require kermeta require "<relative_path_of_the_metamodel>" // NOTE : same as param of createResource 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.createResource( "<relative_path_of_my_model_to_load>", "<relative_path_of_the_metamodel>") <my_resource>.load // Load the emf model - get the root class <my_model_object> ?= resource.instances.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 }