Endlich melde ich mich nach etwas längerer Pause mit einem neuen Artikel zurück. In der Zwischenzeit ist auch das eine oder andere geschehen, auch hinsichtlich meiner Diplomarbeit. Heute möchte ich mich dem Thema “Metamodellierung” widmen:

Grundlage: Jan’s Diplomarbeit

Grundlage dieses Teils meiner Arbeit war diesmal vor allem die Diplomarbeit von Jan Kadathukalam, der in den Abschnitten 3.1 und 3.3 die benötigten theoretischen Hintergrund erläutert. Aus seiner praktischen Arbeit habe ich das auf MDT UML2 basierte KobrA2 Metamodell verwendet und an meine Anforderungen angepasst. Diese Anpassungen sind in erster Linie das Umbenennen der Packages, das Ausgliedern der Elemente K2Model und K2Package sowie die Erweiterung des Package Structure (ehemals StructureClasses) um die voraussichtlich für meine Arbeit benötigten Elemente des KobrA2 Metamodells.

Erweiterung des UML-Metamodells

Die Aufgabenstellung meiner Diplomarbeit fordert die Erzeugung eines simplen Metamodells, so dass die in erster Linie geforderten Transformationen (SUM->View und View->SUM) realisiert werden können. Eine Erweiterung des UML-Metamodells liegt quasi auf der Hand.

Da die Views selbst mit einer Lightweight Erweiterung der UML (durch Profile/Stereotypen) umgesetzt werden sollen, war mein erster Gedanke natürlich, auch das Metamodell des SUM über die Lightweight Extension zu realisieren, so dass das Quell- und Zielmodell der Transformationen im Prinzip das selbe Metamodell haben. Der Lehrstuhl allerdings propagiert die Erstellung eines eigenen KobrA2-Metamodells, so dass letztendlich nur eine Middle- oder Heavyweight Extension der UML in Frage kommt, wenn man die Vorteile der Metamodellierung mittels MDT UML2 nutzen möchte (vgl. Abschnitt 3.3.1 in Jans DA):

  • property redefinition
  • property subsetting
  • profiles (users of your metamodel can extend it using profiles just like you can extend UML)
  • package merge to separate the concerns in your DSL (not really much impact on the generated result, though)
  • pluralized getter methods for singular property names

Plus, you get certain code-generation enhancements provided by UML2:

  • Operations classes to factor out single implementations of your operations in a multiple-inheritance context
  • derived-value caching in the CacheAdapter
  • creation methods (including support for named elements)
  • name-based search accessors for list properties

Die Wahl fiel schließlich auf die Middleweight-Extension, aus Gründen, die bereits Jan in seiner Diplomarbeit erwähnt, weshalb ich hier nicht weiter darauf eingehe. Jedoch die Vor- und Nachteile der Middleweight-Extension möchte ich an dieser Stelle nochmals auflisten:

Vorteile

  • First class extension mechanism.
  • Easier than heavyweight to create initially.
  • Easy for end user to use programmatically than profiles.
  • Can add behavior.
  • Can add structure.
  • Can add constraints.

Nachteile

  • Creates dependence on specific version of UML.
  • Difficult to maintain especially if UML changes.
  • User must know about 2 factories for creating elements, the UMLFactory and the new one defined by the extension.

(Quelle: James Bruck, Christian Damus; Tutorial: Creating Robust Scalable DSLs with UML; eclipseCON 2008)

KobrA2 Metamodell erstellen

Nun zum praktischen Teil :)

Ich gehe mal davon aus, dass der Leser – falls er (also du) diese Schritte nachvollziehen möchte – die erforderlichen Eclipse-Plugins bereits installiert hat, bzw. selbst herausfinden kann, was er benötigt, weshalb ich an dieser Stelle nur mit zwei Stichworten Hilfestellung geben möchte: EMF und UML2.

Zunächst habe ich in Eclipse ein neues Projekt erstellt, genauer gesagt ein neues EMF Project. Hier habe ich Jan’s UML-KobrA2-Metamodell eingefügt, das ich dann mit dem mit MDT UML2 mitgelieferten Editor öffnen konnte. Dieser Editor bietet zwar die Möglichkeit, ein Modell in ein Metamodell umzuwandeln, doch dieser Schritt war nicht mehr notwendig, da ja bereits ein Metamodell vorlag.

Nachdem ein Modell bereits in ein Metamodell umgewandelt wurde, ist es notwendig einer neu hinzugefügten Klasse den Stereotyp Metaclass zu verpassen, um sie zur Metaklasse aufzuwerten. Das benötigte UML-Profil wurde bei der Umwandlung automatisch referenziert.

Nach den bereits in der Einleitung erwähnten Umstrukturierungen und Ergänzungen einiger Metaklassen hatte ich schließlich eine erste Version meines KobrA2-Metamodells. Als nächstes versuchte ich das Metamodell mittels Topcased zu visualisieren, was mir auch ohne Probleme gelang und mir war es auf komfortablem Weg möglich kleinere Änderungen vorzunehmen. Vor allem die Generalisierungen der KobrA2-Elemente ließen sich so sehr einfach in das Metamodell einfügen.

KobrA2 Metamodell (MDT UML2 basiert)
KobrA2 Metamodell grafisch (z.B. für Topcased)

Baumstruktur des Metamodells

Structure Package des Metamodells in Topcased

EMF-Model (generator model) erstellen

Der nächste Schritt war, dem Projekt ein EMF Model hinzuzufügen, das auf dem erstellten Metamodell basiert. Im Package Explorer von Eclipse rief ich über RECHTSKLICK auf den Ordner MODEL > NEW > OTHER > ECLIPSE MODELING FRAMEWORK > EMF MODEL den entsprechenden Wizard auf.

Im Wizard muss man zunächst den Namen des EMF Model mit der Endung .genmodel angeben. Im nächsten Schritt wählt man als Model Importer den Eintrag UML Model. Nach einem Klick auf next habe ich dann das erstellte KobrA2 Metamodell ausgewählt und bei den Optionen zunächst auf Process All geklickt und anschließend die Option Camel Case Names wieder auf ignore gestellt, so dass die von mir verwendeten Namen 1:1 übernommen werden. Im letzten Schritt des Wizards habe ich als root package das Metamodell ausgewählt (Eintrag KobrA2SUM) und die übrigen Modelle (ecore und UML2) referenziert.

Das Ergebnis waren zwei Dateien: das generator model (KobrA2Metamodel.genmodel) und eine ecore-Repräsentation des Metamodells (KobrA2SUM.ecore).

Code generierung

Öffnet man nun das generator model mit dem entsprechenden Editor erhält man in Eclipse wieder eine Baumstruktur. Mit einem Rechtsklick auf den Wurzelknoten des Baums erhält man die Einträge zur Code-Generierung.

Ich möchte hier nicht weiter auf die Code-Generierung eingehen, da es hierzu ausfürliche Tutorials in der Eclipse documentation gibt, z.B. Generating an EMF Model.

Schlusswort

Den generieten Code werde ich in weitere Schritten verwenden, um meine Modelltransformationen zu programmieren – zumindest werde ich es versuchen ;)

So, genug an dieser Stelle. Ich habe Bärenhunger und muss mal sehen, was es im Kühlschrank zu jagen gibt.