Generation gap pattern, ecore, Graphiti and nice pieces of mwe/Xtext

When using a model driven approach, you will face the situation where you have to combine your manual code with the generated artifacts. Heiko Behrens has written an excellent post on that matter. Little known is a nice feature of the Xtext framework, that gives you support for generation gap even if your project is not Xtext based!

The problem at hand

When implementing the Autosar editors we faced the situation that we had to introduce our own complex shapes. However, Graphiti has a fixed diagram meta-model defined as ecore. That makes sense if you want a purely programmatic API – Graphiti provides helper function to store user defined properties at the graphical elements.

However, we would liked to have full OO support, i.e. adding new methods, using inheritance, type safety at compile time for the properties etc. So we would actually like to extend the graphiti meta model.

And that is not really a problem: If we inherit from the Graphiti classes, the Graphiti framework will perfectly handle our new classes and we can make use of our newly introduced classes in our own Graphiti features. So we just create a new ecore definition that references the original Graphiti meta-model and derive from that. Since we were lacking creativity, we called the derived class “SmartShape” and we have several subclasses of that for functionality.

The subclasses do have methods that know how to do some things (move an associated floating label, change the shape depending on the business object) etc. These methods have to be implemented manually and EMF has some mechanisms to support adding manual code. However, that is done in the generated code, marked with tags and is not so nice (see Heiko’s Blog).

The unexpected friend: Xtext

A nice solution is to reuse parts of the Xtext workflow.

Standard emf classes are generated into emf-gen. Our own custom classes are in src.

The Xtext team have a solution to actually call the EMF model for the genmodel in such a way, that it hooks in into any CustomImpl classes that are found on the classpath. So e.g. in our meta-model we have a SmartShape. The code-generator of EMF will generate a SmartShapeImpl, but we are not going to modify that. Instead, we have a SmartShapeImplCustom, which extends SmartShapeImpl. If we run the mwe2 workflow again, the EMF Factories and all other classes will be generated in such a way, that a SmartShapeImplCustom is instantiated each time the createSmartShape() method is called on the factory. The workflow is pretty simple. Our genmodel is mentioned at the end (duankou.genmodel).

Since the custom classes are not touched at code generation, they are separated from the generated classes. So we do not need to but the generated code into source code management, only the manual classes.

Tycho 0.16

Tycho and mwe2 actually work together quite fine. So we can invoke this generation not only in the IDE, but in any of our automated builds as well:

Summary

Graphiti is a nice framework for the implementation of graphical editors. Generation Gap pattern and some nice feature from Xtext make it even more fun to work with. As you can see in the code below, the diagram is stored as a regular Graphiti Diagram with graphics Algorithms etc., but the Shape hiere is our own SmartShapeAutosarComponent.

 

Leave a Reply

Your email address will not be published. Required fields are marked *