Ein Editor zur Konfiguration von Model-to-Model-Transformationen für AndroMDA

Magische Momente mit GMF

Matthias Lau und Philipp Rettberg

Grafische Editoren, wie sie mit dem Graphical Editing Framework (GEF) erstellt werden können, begeistern die User meist mehr als zum Beispiel eine simple XML-Darstellung. Diese Begeisterung zu zaubern kostet jedoch viel Aufwand, der heutzutage möglichst reduziert werden soll. Das Graphical Modeling Framework (GMF) hilft hier weiter und verspricht große Magie ohne viel Zutun. Wie effizient der Einsatz dieses Frameworks in der Praxis ist und inwiefern GMF großer Zauber oder nur ein Laientrick ist, zeigt ein Praxisprojekt von Studenten der FH Nordakademie in Kooperation mit dem AndroMDA-Team.

Ein zentrales Problem des Software Engineering ist die Reduktion der Kosten für die Softwareentwicklung. Ein probates Mittel ist die Verwendung von so genannten Domain Specific Models (DSM), die es ermöglichen, Anwendungen auf einer hohen Abstraktionsebene mit Begriffen des Problembereichs zu beschreiben. Aus diesen Modellen werden durch Programmgeneratoren Anwendungen in einer General Purpose Language (Java, C# etc.) erzeugt. Man verspricht sich von diesem Vorgehen bessere Qualität, Produktivität, Zuverlässigkeit, Wartbarkeit, Übertragbarkeit und Wiederverwendbarkeit.
Das Eclipse Modeling Framework (EMF) ermöglicht den Entwurf eines DSM und die Speicherung von Modellen in XML-basierten Dateien. GMF erweitert die Fähigkeiten von EMF um eine grafische Darstellungs- und Bearbeitungsmöglichkeit. Für Android (kurz für AndroMDA IDE, siehe Kasten) sollte diese Möglichkeit genutzt werden, um einen grafischen Editor zur Konfiguration von Model-to-Model-Transformationen zu erstellen. Dieser Editor soll die Modellierung von Transformationen und Modellen in einem Diagramm bei möglichst intuitiver Bedienbarkeit ermöglichen. GMF erscheint besonders interessant, da viele vertraute und aus anderen grafischen Editoren bekannte Funktionen serienmäßig verfügbar sind. Die Projektumsetzung erfolgte unter dem Namen AndroGen durch eine Gruppe von Studenten der FH Nordakademie unter der Anleitung von Peter Friese von AndroMDA und Prof. Dr. Zimmermann im ersten Halbjahr 2006.

Android

Der hier beschriebene GMF-Editor wurde als Prototyp für eine Reihe von grafischen Editoren für das Eclipse-Plug-in Android entwickelt. Android ist eine Eclipse-basierte Entwicklungsumgebung für AndroMDA und wird vom AndroMDA-Team entwickelt. Neben Wizards zur Erstellung von neuen Projekten und Cartridges enthält Android eine Reihe von Editoren für AndroMDA-bezügliche Dateien. So gibt es auf Eclipse Forms basierende Editoren für die AndroMDA-Konfigurationsdateien und Texteditoren für die Bearbeitung der Templates (die in Velocity Template Language verfasst sind). Für das nächste Major-Release von AndroMDA sind neben einer Workflow Engine auch Model-to-Model-Transformationen geplant. Beide Module werden über XML-Dateien konfiguriert, da sich dieses Format gut zur Verarbeitung eignet. Um den Komfort für die Anwender zu erhöhen, sollen jedoch sowohl die Model-to-Model-Transformationen als auch die Workflows über einen grafischen Editor konfiguriert werden können. Hier liegt der Einsatz von GMF nahe, da mit relativ geringem Aufwand überzeugende Ergebnisse erzielt werden können. Die jeweils aktuellste Version von Android kann unter www.andromda.org/updatesite über den Eclipse-Update-Manager bezogen werden. Voraussetzung für den Einsatz von Android sind neben Eclipse 3.2 und einem JDK 5.0 auch Maven 2.0 und AndroMDA 3.2.

GMF ist keine komplett neue Technologie zur Erstellung eines grafischen Editors, sondern baut auf zwei bestehenden Eclipse-Frameworks auf. EMF bietet hierfür die Grundlage. Es ist ein Meta-Modeling-Framework ähnlich der Unified Modeling Language (UML), einziger Unterschied ist ein vereinfachtes Anwendungsfeld. UML ermöglicht die Beschreibung einer sehr großen Bandbreite von Sachverhalten durch die verschiedenen UML-Modellarten. Im Idealfall lassen sich somit neben einer kompletten Applikation auch menschliche Interaktion und Abhängigkeiten zur übrigen Umwelt beschreiben. Zur formalen Beschreibung eines einfachen Modells, für die spätere Umsetzung in Java, ist UML oft zu umfangreich. Hier setzt EMF an und ermöglicht die Erstellung strukturierter Modelle und die schnelle Umsetzung in entsprechenden Java-Code. EMF hilft einem dabei, sauberen und schnellen Code aus einem Modell zu generieren und bringt dabei noch einiges an Mehrwert. Hierzu gehört die Fähigkeit, andere Klassen über Änderungen im Modell zu informieren. Des Weiteren enthält dies ein effizientes API vergleichbar mit Reflections, um Modelle während der Laufzeit zu verändern, und die Möglichkeit, die Modelle in verschiedenen Formaten zu speichern. Zusätzlich existieren verschiedene Erweiterungen zu EMF, die z.B. die Validierung von Modellen erleichtern.
Das zweite Framework, auf dem GMF basiert, ist GEF. Wie der Name des Projekts bereits sagt, dient es der Editierung von grafischen Darstellungen. GEF stellt zwei Plug-ins für diese Aufgabe zur Verfügung. Das eine Plug-in (org.eclipse.draw2d) ist für die reine Darstellung zuständig und kann unabhängig vom zweiten Plug-in (org.eclipse.gef) genutzt werden. Letzteres dient der Bearbeitung der grafischen Darstellung. GEF arbeitet nach dem Model-View-Controller-(MVC-)Prinzip. Als View dienen hierzu die Komponenten aus dem draw2d-Plug-in. Die Basisklassen für die Controller befinden sich im org.eclipse.gef-Plug-in. Für das darunter liegende Modell ist der Entwickler im ersten Schritt auf sich allein gestellt, da GEF hier keine Vorgaben macht. Trotzdem existieren bestimmte Anforderungen an das Modell, wie z.B. die Implementierung des Observer Pattern. Daher wird GEF oft in Verbindung mit EMF eingesetzt. Möchte man ein strukturiertes Modell grafisch editierbar machen, unterstützt EMF durch Code-Generierung und nützliche Basisklassen. GEF dagegen stellt Basisklassen zur Verfügung, die selbst erweitert werden müssen, um auch nur einen grundlegenden grafischen Editor zu erstellen. Hierbei ist sowohl die Erstellung der kompletten View als auch die Erweiterung der Controller erforderlich, um eine Zusammenarbeit mit EMF zu ermöglichen.
Viel ist schon mit EMF und GEF möglich, doch wie unterstützt GMF? GMF setzt genau bei der aufwendigen Editorerstellung an. Es erzeugt mit wenigen Handgriffen einen kompletten, lauffähigen grafischen Editor, aufbauend auf einem EMF-Modell, ohne dass auch nur eine Zeile Java-Code geschrieben werden muss. GMF lässt sich unterteilen in eine Runtime und ein Paket von Entwicklungswerkzeugen. Das Werkzeugpaket besteht dabei im Wesentlichen aus Editoren, mit denen die Eigenschaften des späteren grafischen Editors angepasst werden können, und aus Generatoren, welche den Features der Runtime Leben einhauchen. Die Runtime selber stellt viele Funktionen zur Verfügung, die aus kommerziellen grafischen Editoren bekannt sind und somit nicht von neuem entwickelt werden müssen. GMF dient also dem erleichterten Arbeiten mit EMF und GEF. Inwieweit dies zutrifft, soll der Einsatz in dem Projekt zeigen.
Im Folgenden wird genau das Zusammenspiel der Komponenten betrachtet. Beginnend mit dem Entwurf eines EMF-Modells als Basis des grafischen Editors, folgt anschließend die Konfiguration, bei der mithilfe der GMF-Editoren die spätere Oberfläche eingestellt wird. Die Generatoren von GMF liefern einen lauffähigen grafischen Editor mit vielen angenehmen Features. Im Anschluss wird die Erweiterung des Editors beispielhaft anhand der Darstellung der Validierungsfehler gezeigt.

Modelle in AndroGen

Ziel des Projektes war die Erstellung eines grafischen Editors für Model-to-Model-Transformationen. Als erster Schritt musste das Domain Model für AndroGen erstellt werden. Das Domain Model enthält zum einen die Informationen über die Modelle (in AndroMDA auch als Cartridge bezeichnet, z.B. Enterprise Application Cartridge, Hibernate Cartridge, Spring Cartridge) und verfügt zum anderen über die entsprechenden Transformationen zwischen diesen Modellen. Hierfür nutzte das Team den EMF-Editor, um ein Ecore Model zu erstellen, welches die Definition des EMF Domain Model enthält. Alternativ wäre es auch möglich gewesen, ein bestehendes UML 2.0-Modell oder ein XSD-Schema-File zu benutzen, um daraus ein Ecore zu erstellen. Eine große Herausforderung des Projektes war die Umsetzung von beidseitig navigierbaren Relationen, also in AndroGen die Verbindung zwischen einem Model und einer Transformation und umgekehrt. Diese Anforderung ließ sich erfolgreich umsetzen, wobei in EMF die Relationen nicht als eigenes Element, sondern auf beiden Seiten als Attribute erstellt werden.
Ein grafischer Editor braucht mehr Informationen als nur das Domain Model, es muss ferner die Art der Darstellung definiert werden. Aus diesem Grund wurden im zweiten Schritt die grafischen Elemente definiert, die später das Aussehen der einzelnen Domain-Model-Elemente repräsentieren werden. GMF benötigt hierzu das GMFGraph Model. In dieser Datei werden die einzelnen grafischen Figuren definiert, die später das Aussehen des Editors ausmachen. Für das AndroGen-Projekt wurden hierfür nicht die vorgegebenen Figuren benutzt, da die Art der Darstellung durch das AndroMDA-Team vorgegeben wurde. Damit der Editor dieser Vorstellung entspricht, wurden die GMF/GEF-Figuren erweitert und um Funktionen zur Hervorhebung der Figuren ergänzt.
Um einen vollständigen grafischen Editor zu erstellen, benötigt GMF als letztes Teilstück noch die Werkzeuge, mit denen Elemente im Editor erstellt werden. Diese werden im GMFTool Model definiert. Später finden sich die im GMFTool Model definierten Elemente auf der rechten Seite in der Tool-Leiste des Editors wieder. In diesem Modell wird neben den einzelnen Werkzeugen zum Erstellen von Elementen auch die Gruppierung festgelegt, unter der später die einzelnen Werkzeuge in der Tool-Leiste wieder zu finden sind.
Nach der Erstellung der drei von GMF benötigten Modelle, dem EMF Domain Model, dem GMFGraph Model und dem GMFTool Model, wird alles über die Mapping-Definition (GMFMap) zu einem Ganzen zusammengefügt. In dieser Datei wird die Verknüpfung zwischen dem Domain Model und den Figuren aus dem GMFGraph Model geschaffen. Außerdem wird festgelegt, welche Werkzeuge zum Erstellen der Elemente im grafischen Editor zuständig sind.
Sind alle GMF Models definiert und über das Mapping zusammengefügt, müssen noch die Generator-Dateien für EMF und GMF erstellt werden. Diese definieren, in welchen Ordnern und Paketen die Klassen generiert werden. Die beiden Generator-Dateien müssen normalerweise nur angepasst werden, wenn die GMF- und EMF-Paketstruktur mit Vorgaben des Projektes kollidiert. Im AndroGen-Projekt wurden diese abgeändert, um der Paketstruktur des Android-Projektes zu entsprechen.
Im Anschluss an die Anpassung der Generator-Dateien konnte der komplette Editor generiert werden. GMF nutzt hier den gleichen Code-Generator wie EMF: Java Emitter Templates (JET). Ein Vorteil dieses Generators ist, dass Code-Modifikationen direkt in den generierten Klassen erfolgen können. Bei einer erneuten Generierung werden nur Teile überschrieben, die nicht von Hand angepasst wurden. JET nutzt hierfür Kommentare in den Java-Klassen, um angepassten von generiertem Code zu unterscheiden. Da der angepasste Sourcecode vermischt ist mit den generierten Klassen, ist eine Trennung auf Dateiebene nicht möglich. Dadurch muss der generierte Code ebenfalls mit in die Sourcecode-Verwaltung aufgenommen werden. Dies führte im AndroGen-Projekt öfter dazu, dass nur schwierig erkennbar war, an welchen Stellen wirklich etwas geändert worden war.

Abb. 1: Zusammenspiel der GMF Models

In diesen ersten Schritten der Editorerstellung wird schon ein wesentlicher Vorteil von GMF für das Projekt deutlich: Mit wenig Aufwand konnte so ein grafischer Editor mit hilfreichen Funktionen, wie z.B. Zoom und Exports, erstellt werden. Es wurde aber auch festgestellt, dass einige individuelle Anforderungen einen vergleichsweise großen Aufwand mit sich brachten. Im Weiteren wird der Einsatz von GMF in Bezug auf eine individuelle Erweiterung des Editors vorgestellt.

Anzeigen von Validierungsfehlern mit GMF

Im Anschluss an die Generierung des grafischen Editors folgte die Einbindung individueller Komponenten in AndroGen. Einer dieser Bausteine ist die Validierungsfunktion, die Diagramme auf Korrektheit überprüft. Dies umfasst hauptsächlich die Prüfung der Source- und Target-Modelle von Transformationen. Die erlaubten Modelle einer Transformation sind durch eine Konfiguration vorgegeben. Ist ein falsches Modell mit einer Transformation verbunden, so wird dies als Fehler markiert. Dies geschieht ebenso, falls ein laut Konfiguration benötigtes Modell nicht vorhanden ist. Des Weiteren werden Modelle ohne Transformation als falsch gekennzeichnet und Zyklen im Diagramm erkannt. Die erkannten Fehler sollen in Eclipse deutlich angezeigt werden. Dies soll in der Problem View und im Diagramm selbst erfolgen. Im folgenden Absatz ist diese Umsetzung beschrieben.

Abb. 2: Ablauf der Validierung

Die Integration der Validierung basiert auf dem Validation Framework des EMFT-Projektes. Dieses bietet die Möglichkeit, Java und OCL Constraints zu definieren, die für Modelle in gewissen Namespaces gelten sollen. Im ersten Schritt werden dafür Kategorien mit zugehörigen Constraint-Providern definiert und erstere an einen Kontext gebunden. Dieser Kontext, in unserem Fall unser Diagramm, besitzt einen Selector, der die zu prüfenden Klassen auswählt. Den Constraint-Providern werden dann Constraints zugeordnet, welche die oben genannten Fehlerprüfungen abdecken. Bei der Generierung von GMF muss nun noch das Validation Flag in dem GMFGen Model gesetzt werden, damit der Validation-Provider erzeugt wird.
Das EMFT Validation Framework ermöglicht eine Live- und eine Batch-Validierung. In unserem Fall ist eine Live-Validierung gewünscht, allerdings kontrolliert die gelieferte Live-Validierung nur das jeweils geänderte Element und nicht – wie benötigt – das vollständige Diagramm. Aus diesem Grund wird auf die Batch-Validierung zurückgegriffen und ein ValidationTrigger geschrieben, der sich bei allen Diagrammobjekten als Listener registriert und somit den Prüfungsvorgang initialisiert. Erhält dieser eine Change Notification, so wird die validate-Methode in der ValidateAction aufgerufen, die in Ausschnitten in Listing 1 gezeigt wird. Diese befindet sich als eingebettete Klasse in dem ValidationProvider, welcher von GMF generiert wird. Innerhalb dieser Methode werden nun in einem ersten Schritt die Überprüfungen mithilfe der Constraints angestoßen, welche die Objekte des Diagramms auf die oben genannten Fehler überprüfen und entsprechende Status verteilen. In einem zweiten Schritt wird die erste Visualisierung der Fehler durch Eclipse-Marker vorgenommen. Dazu werden zunächst alle Objekte mit einem Fehlerstatus und anschließend die dazugehörigen Views ermittelt. Für die Marker stellt GMF die addMarker-Methode in der ValidateAction zur Verfügung, welche einen Marker sogleich mit dem fehlerhaften Diagrammobjekt verknüpft. Hierbei ergab sich das Problem, dass zum Teil nicht nur das falsche Objekt markiert werden musste. Ergibt die Überprüfung einer Transformation, dass ein falsches Model angeschlossen ist, so müssen sowohl die Transformation als auch das falsche Model markiert werden. Zur Lösung dieser Problematik werden die Result Loci genutzt und ebenfalls gefärbt.

Listing 1
Ausschnitt der validate-Methode der Klasse ValidateAction
// Mark all Targets and decorate all Elements of the locus too.
for (Iterator it = allStatuses.iterator(); it.hasNext();)
{
Object nextStatusObj = it.next();
if (nextStatusObj instanceof IConstraintStatus)
{
IConstraintStatus nextStatus = (IConstraintStatus)nextStatusObj;
View view = findTargetView(nextStatus.getTarget(), viewMap);

addMarker(diagramFile, view != null ? view : diagram, nextStatus.getTarget(), nextStatus.getMessage(), nextStatus.getSeverity());

// Decorate the View.
decorateView(diagramFile, view != null ? view : diagram, nextStatus);
// Decorate to all elements in the Locus too!
for (Iterator iter = nextStatus.getResultLocus().iterator();iter.hasNext();)
{
EObject objectInLocus = (EObject)iter.next();
View viewOfLocus = findTargetView(objectInLocus, viewMap);

decorateView(diagramFile, viewOfLocus != null ? viewOfLocus : diagram, nextStatus);
}
}
}

Zur Einfärbung der Diagrammobjekte wird auf selbst geschriebene Decorator zurückgegriffen. Diese existieren sowohl für die Knoten als auch für die Kanten des Diagramms und hängen als Listener an den jeweiligen Views. Über eine eigene Methode decorateView des ValidationProviders wird eine ValidationNotification an die Views der fehlerhaften Objekte geschickt. Die Decorator werden von ihrem Listener in einen Fehlerstatus versetzt und reagieren in ihrer refresh-Methode darauf mit der Addition eines Fehler-Icons zu der View und mit der Einfärbung der fehlerhaften Elemente, wie in Listing 2 zu sehen ist. Somit sind abschließend alle Validierungsfehler in der Problem-View von Eclipse aufgeführt und mit einem Fehlericon und rot im Diagramm gekennzeichnet (Abb. 3).

Abb. 3: Screenshot der Fehlervisualisierungen

Abschließend werden nun die positiven und negativen Erfahrungen betrachtet, die im Projekt gemacht wurden. GMF hat in dem Android-Projekt viel Arbeit erspart und ließ sich gut einsetzen. Die zahlreichen Beispiele, der gut dokumentierte Code und die generierte Struktur ermöglichten ein schnelles Einarbeiten und zeigten Funktionalitäten auf, welche für das Projekt sehr hilfreich waren. Auch ist eine für den frühen Projektstand schon sehr große und aktive Community vorhanden. GMF schließt erfolgreich die Lücke zwischen EMF und GEF, erleichtert die Entwicklung von leistungsfähigen grafischen Editoren und bietet den Benutzern ein angenehmes, gewohntes Bild. Sinnvoll ist GMF folglich für Entwickler, die genau diese Symbiose von EMF und GEF erreichen wollen.
GMF eignet sich hingegen wenig für Entwickler, die lediglich schlanke Read-only-Visualisierungen umsetzen wollen, da hierbei der eigentliche Benefit von GMF verloren geht. Eine reine GEF-Umsetzung könnte hier sinnvoller sein, um überflüssigen Overhead zu sparen.
Trotz des Einsatzes von GMF ergab sich viel Aufwand bei der Erstellung individueller Features, welche in den meisten Projekten benötigt werden. Hier wurden viel GEF-Know-how und auch Kenntnisse über die Strukturen von GMF benötigt, um die selbst erstellten Komponenten einzuarbeiten. Viele Funktionalitäten sind allerdings auch noch in der Projektplanung von GMF vorgesehen. So ist die Persistenzschicht bisher fest verankert, soll aber in Zukunft entkoppelt und austauschbar werden. Zu einem späteren Zeitpunkt ist somit auch der Einsatz von z.B. MOF denkbar.
Zusammenfassend hat GMF dem Projekt bereits jetzt viel geholfen. Die Nutzenpotenziale scheinen noch höher zu sein, wenn bereits GEF-Know-how vorhanden ist. Der Einsatz von GMF ist nur dann sinnvoll, wenn die Funktionen der Runtime auch benötigt werden, nicht wenn nur eine leichtgewichtige Umsetzung gefragt ist. GMF ist also kein Wundermittel, das von alleine die Projekte abschließt, sondern eher ein Zauberartefakt, welches die Projektarbeit erleichtert. Seit dem RC 0 Mitte April laufen die vorhandenen Features von GMF weitestgehend stabil, aber die weitere Entwicklung der Magie von GMF bleibt spannend, insbesondere im Hinblick auf die konkurrierenden Entwicklungen in Microsoft Visual Studio 2005.
Matthias Lau ist Anwendungsentwickler bei der OTTO GmbH & Co. KG und beschäftigt sich mit den Einsatzmöglichkeiten von Open-Source-Technologien im Internetvertrieb. Philipp Rettberg ist Anwendungsentwickler bei der antauris AG, einem Hamburger Systemhaus, und ist zurzeit für B2B-Integration zuständig. Beide schließen dieses Jahr ihr Studium an der FH Nordakademie als Dipl.-Wirtschaftsinformatiker ab.

Geschrieben von
Matthias Lau und Philipp Rettberg
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.