Chapter 2. Cookbook for Kermeta MDK

This chapter presents some of the uses of this MDK.

2.1. Saving a km model with references to ClassDefinitions in framework.km

When creating a km model, you may need to create references to ClassDefinition that are defined in the framework.km. Typically, when you create an Operation, you'll also have to create a Class whose reference typeDefinition points to the ClassDefinition in the framework.

A first but wrong approach would be to use the reflectivity :

var anOperation : kermeta::language::structure::Operation init kermeta::language::structure::Operation.new       
anOperation.name := "Op1"       
var aClass : kermeta::language::structure::Class init kermeta::language::structure::Class.new
// set the return type of the Operation to Boolean
aClass.typeDefinition := kermeta::standard::Boolean.typeDefinition      // will typecheck, but cannot be saved !!!  
anOperation.type := aClass
anOperation.containedType.add(aClass)
      	

This code will correctly typecheck, but cannot be saved. This is because it mixes model element and program definitions. Unfortunatly, it is not possible to ensure that those definitions comes from a concrete model file. For example, the definition can come from an ecore or a kmt file (which are NOT km models).

The solution consists in explicitly loading the km file that contains the ClassDefinition and then, retrieve the ClassDefinition in it. In our sample we probably want to load framework.km and find the ClassDefinition Boolean in it.

The MDK will help us in this task by providing a function getTypeDefinitionByQualifiedName to ModelingUnit. The code will then look like :

...
// get the helper
require "platform:/plugin/org.kermeta.language.mdk/src/kmt/language/helpers/structure/ModelingUnitHelper.kmt"
...
      	
var repository : EMFRepository init EMFRepository.new
var resFramework : kermeta::persistence::EMFResource
		
resFramework ?= repository.getResource("platform:/plugin/fr.irisa.triskell.kermeta.io/src/kermeta/framework.km")
// find Boolean in the resource
var booleanTypeDef : kermeta::language::structure::GenericTypeDefinition 
var mainModelingUnit : kermeta::language::structure::ModelingUnit 
mainModelingUnit ?= resFramework.detect{ m | m.isInstanceOf(kermeta::language::structure::ModelingUnit)}
	// use the helper to find Boolean in the ModelingUnit		
booleanTypeDef ?= mainModelingUnit.getTypeDefinitionByQualifiedName("kermeta::standard::Boolean")      	
      	
var anOperation : kermeta::language::structure::Operation init kermeta::language::structure::Operation.new       
anOperation.name := "Op1"       
var aClass : kermeta::language::structure::Class init kermeta::language::structure::Class.new
// set the return type of the Operation to Boolean
aClass.typeDefinition := booleanTypeDef      // correct, can be saved (using the same repository that was used to load framework.km)  
anOperation.type := aClass
anOperation.containedType.add(aClass)
      	

Obviously, you can load any km file you want.

[Note]Note

If you want to point to a definition that is in a kmt (textual) or in an ecore file, you'll need to convert it into a km file first.

2.2. Sample use of the kmt prettyprinter : prettyprinting a failed Constraint

[Note]Note

The base of this prettyprinter was written before the introduction of aspect in Kermeta. For a better design, we would have now weaved the prettyprint operation rather than weaved a visitor.

Here is a sample use of this printer (prettyprints the body of a failed invariant). Its main class is kermeta::utils::BasicPrettyPrinter

      	...
      	require "platform:/plugin/org.kermeta.language.mdk/src/kmt/language/visitor/prettyprinters/kmtPrettyPrinter.kmt"
      	
      	...
      	do 
	    	// checking invariants
	    	inputResource.instances.each{e|
	    		e.checkAllInvariants
    		}
    		stdio.writeln("model is valid")
    		
    	rescue (myError : ConstraintViolatedInv)
    		// note that this locator helper work only for UMl model and is provided by UML MDK
    		// you 
    		var locatorhelper : UMLUtils::UMLElementLocatorHelper init UMLUtils::UMLElementLocatorHelper.new
		    stdio.errorln(myError.message)
		    stdio.errorln("Faulty object is : " + locatorhelper.getLocationString(myError.constraintAppliedTo))
		    
		    // Do not forget to initialize the BasicPrettyPrinter !
		    var basicPP : kermeta::utils::BasicPrettyPrinter init kermeta::utils::BasicPrettyPrinter.new.initialize
		    stdio.errorln("Violated constraint is : " +basicPP.accept(myError.failedConstraint.body, 0))
		    stdio.errorln(myError.stackTrace)
		end   
      	
[Warning]Warning

Do not forget to initialize the BasicPrettyPrinter !