Let's now add some static semantic to our metamodel i.e. add missing pre/post-conditions to our .ecore in order to express the contraints specified in the metamodel. From now on, we are going to learn how to weave aspects with Kermeta.
For this step we are going to add two contracts to our metamodel:
"no two formal parameters of a procedure may have the same name";
"each procedure call provide the same number of arguments as specified in its declaration".
In OCL you will have the listing below to express it (you can find the corresponding OCL file inside org.kermeta.kmlogo.logoasm.tutorial/parts/2.constracts ) :
package kmLogo::ASM context ProcCall inv apropriate_number_of_actual_parameters : actualArgs->size() = declaration.args->size() context ProcDeclaration inv unique_names_for_formal_arguments : args->forAll ( a1 | args->forAll ( a2 | a1.name = a2.name implies a1 = a2 )) endpackage
Kermeta offers same mechanism as OCL to navigate inside the elements (<Collection>.each, <Collection>.forAll, ...). Through aspect weaving, Kermeta allow to reopen a class and weave an aspect inside in order to add this pre/post conditions. Let's implement the example above in Kermeta :
Create a new plug-in project org.kermeta.kmlogo.logoasm.srcKermeta (set all by default, hit next and finish, if you're not familiar with plug-in perspective choose "no" if asked).
Create a folder kermeta on the root of this project. This is the folder where we are going to put all kermeta sources for this tutorial.
Inside the folder kermeta, create a folder 2.Constraints.
Inside the folder 2.Constraints, create a new kermeta file ASMLogoStaticSemantics.kmt. Aanalyse the content of the following listing and then copy/paste into the newly created file :
package kmLogo::ASM; require kermeta require "http://www.kermeta.org/kmLogo" aspect class ProcDeclaration{ /** * No two formal parameters of a procedure may have the same name */ inv unique_names_for_formal_arguments is do args.forAll{ a1 | args.forAll{ a2 | a1.name.equals(a2.name).implies(a1.equals(a2))}} end } aspect class ProcCall{ /** * A procedure is called with the same number of arguments as specified in its declaration */ inv same_number_of_formals_and_actuals is do actualArgs.size == declaration.args.size end }
It reopen the ProcDeclaration and ProcCall classes and weave invariants as aspects into it
Note | |
---|---|
If you get errors on "http://www.kermeta.org/kmLogo", check your package registration. you may hit the check this file button (on Kermeta's perspective toolbar) to refresh. |
After saving it, let's see the results.
To do so go back to the project org.kermeta.kmlogo.logoasm.tutorial for a while.
Copy the folders:
org.kermeta.kmlogo.logoasm.tutorial/parts/2.constracts/models which contains the models conform to our ecore metamodel;
org.kermeta.kmlogo.logoasm.tutorial/parts/2.constracts/tests which contains the main operation for testing the constraints on these models.
Paste these folders and their content into org.kermeta.kmlogo.logoasm.srcKermeta/kermeta/2.Constraints.
Open the file tests/CheckModels.kmt, remove the two comment blocs inside and analyse its purpose.
It loads the models inside the models folder and require the kermeta file that we've created before.
Let's now run our first Kermeta application : Right-click on the file CheckModels.kmt and choose Run as > Run as Kermeta application.
Note | |
---|---|
If you get errors, again, check that you did not forget to register you ecore. Maybe it is necessary to clean all the projects or launch the kermeta cleaner (trash bin with kermeta icon on your toolbar) or hit the kermeta validator ("check this file" button in Kermeta perspective toolbar) |
On your console view, you should view the result below though the model instances are conform to our metamodel (you can right-clic and "validate" to see its conformance to the ecore ) :
Important | |
---|---|
Remember : To check the constraints in Kermeta, you should call the method checkAllInvariants() on root element of the model (here the one from models/carre.logoasm) |