EMFText einsetzen


Flattr this

Motivation

Auf der Suche nach geeigneten Technologien zur Softwareproduktion am Fließband bin ich über Xtext nun auf EMFTText gestossen. EMFTText scheint eine weitere Integration von Xtext in die Eclipse Umgebung zu sein. Grund genug einmal damit zu spielen und ein Gefühl für das neue Werkzeug zu entwickeln.

Erster Eindruck

Nachdem ich meinen uralt Eclipsestand (Helios mit EMF 2.5.0) manuell recht umständlich aktualisiert hatte, bin ich nun im Besitz einer Eclipse Indigo mit EMFTText 1.4.0. Das hätte ich auch einfacher haben können wenn ich EMFTText gekannt hätte und einfach nach Anleitung vorgegangen wäre.

 

Nachdem ich das Tutorial durchgearbeitet hatte, war ich beeindruckt und würde die für mich wichtigen Features wie folgt beschreiben:


  • Kernpunkt der Modellierung stellt ein ecore Modell dar
  • Alles was zur Modellierung benötigt wird stellen zusätzliche Plugins bereit (Ecore Tools). So kann auf der Grundlage von Diagrammen und DSLs gearbeitet werden ohne direkt im ecore Modell hantieren zu müssen.
  • Für jeden Schritt in der Modellierung gibt es passende Generatoren und Werkzeuge.
  • Es gibt neue EMFTText Projektarten. Wie das Tutorial beweist, kommt man aber auch zu Fuß über normale Java Projekte ans Ziel (auch sehr einfach).
  • Die Beschreibung der DSLs erfolgt bei EMFTText wieder deutlich mehr an den Grundlagen der Compilertechnik orientiert als bei Xtext. Hier sieht man wieder Tokendefinitionen und Grammatikregeln. Wer mit lex und yacc angefangen hat und sich über LIGA, LIDO, GAG und Eli freuen konnte, der fühlt sich sofort wieder heimisch.
  • Auch dieses Eclipse Tool hat sich wieder nicht an der Standard Maven Directory Struktur orientiert. Packages werden wieder unter ${base}/src und ${base}/metamodell angelegt obgleich ${base}/src/main/java genauso super wäre.
  • Eine Anpassung an Maven ist aber mit der aktuellsten Version von EMFTText möglich. Dazu kann man in der Sprachdefinitionsdatei (*.cs) beispielsweise folgende Optionen setzen:

    OPTIONS{
    srcFolder = "src/main/java";
    srcGenFolder = "target/generated-sources/java";
    uiSrcFolder = "src/main/java";
    uiSrcGenFolder = "target/generated-sources/java";
    }

    Die aktuellste Version von EMFTText  bekommt man durch Einbinden der folgenden Update Site in Eclipse: http://www.emftext.org/update_trunk
  • Eine generell gute Idee scheint es zu sein in folgender Reihenfolge (wie im Tutorial) vorzugehen:

    1. Erstellen eines ecore Modells über den Ecore Diagram Editor
    2. Erstellen eines Ecore GeneratorModels aus dem Ecore Modell
    3. Generierung einer HUTN Syntax aus dem GeneratorModel
    4. Anpassen der HUTN Syntax um komplett konform zum Ecore Modell zu sein
    5. Nutzung des entstandenen DSL Editor Plugins um Texte in der neuen DSL zu schreiben.

Details am Beispiel zur Arbeit mit EMFText

Für das Spielen und zum Sammeln von Erfahrungen habe ich das ERM-DSL Projekt auf sourceforge.net verwendet. Die Quellen sind für jeden zugänglich und können unter svn://svn.code.sf.net/p/ddd-tools/erm-dsl/svn/trunk mittels subversion ausgescheckt werden.

Auswirkung der Namensvergabe

Für mich ist es in speziellen Fällen nicht leicht nach zu vollziehen wie sich die im ecore Modell verwendeten Bezeichner genau auf die Generierung auswirken. Anbei die Auflistung der beim Spielen beobachteten Auswirkungen:

 

Im verlinkten Kommentar gibt es einige Details zu diesem Thema: https://funthomas424242.wordpress.com/2011/08/16/emftext-einsetzen/#comment-28. Persönlich bevorzuge ich das Setzen der Namen über die Sprachdefinitionsdatei (*.cs). Dafür eignen sich folgende Optionen:


  • basePackage
  • uiBasePackage
  • resourcePluginID
  • resourceUIPluginID

Iteratives Arbeiten

Ich habe mit Hilfe des EMF Diagram Editors zunächst eine sehr simple Sprache mit wenigen Sprachelementen entworfen. Anschließend auf der Basis des ecore Modells ein EMF Generator Model erstellt und daraus ein HUTN Syntax File erzeugen lassen. Die Syntax habe ich noch ein bischen auf das ecore Modell abgestimmt und dann daraus die Projekte generieren lassen. Scheinbar wird der selbe Generator gestartet wenn ich auf das Generator Modell gehe und per Rechtsklick „Alles Generieren“ wähle. Anschließend die Runtime Eclipse gestartet und das DSL Editor Plugin getestet -> funktioniert🙂

 

Jetzt soll die Sprache natürlich erweitert werden. Also wieder ins EMF Diagram, dort ein paar Änderungen durchgeführt und abgespeichert. Dann Rechtsklick auf das EMF Generator Modell „Reload“ von dem bestehenden ecore Modell durchführen. Schon ist das aktualisiert. Jetzt ins Syntax File und die Regeln für die neuen Konstrukte eingefügt – fertig. Wieder alles generieren lassen und? Einiges ist rot. Löschen und neu generieren hilft – komisch. Kurzer Test in der Runtime Eclipse – Editor funzt.

Ergo, nach Syntaxänderungen wird nicht alles was vorher erzeugt wurde wieder gelöscht. Macht Sinn, da manche Dinge nur einmal generiert werden sollen. Dennoch händisch weg löschen ist störend. Hier such ich noch nach einem Automatismus. Eine anderswo gesehene Lösung bestand darin, die Folder Struktur anzupassen. Also in 3 Arten zu unterteilen:


  • src Folder – alles handgeschrieben, nichts generiertes
  • src-gen Folder – alles wird vor der Generierung gelöscht und dann neu generiert
  • src-gen-one Folder – alles wird generiert aber nichts überschrieben und nichts gelöscht (also jedes Artefakt wird beim ersten Mal generiert und dann nie wieder)

Ob das Sinn ergibt wird sich zeigen. Hier bin ich noch am Ausprobieren. Was auf jeden Fall Sinn macht, wenn die DSL noch stark unter Entwicklung ist, sind folgende Optionen in der Sprachdefinitionsdatei (*.cs):

OPTIONS{
reloadGeneratorModel="true";
generateCodeFromGeneratorModel="true";
}

Damit wird das GeneratorModel vor dem Erzeugen der Text Ressourcen neu aus dem ecore Modell erstellt und es wird aus dem GeneratorModel heraus generiert.

Kodegenerierung

Die Kodegenerierung funktioniert über Builder. Bei der Generierung der DSL Ressourcen werden bereits Stubs für diese Builder mit erzeugt. Das Überschreiben dieser Stubs kann mittels folgender Optionen in der Sprachdefnitionsdatei (*.cs) abgeschaltet werden:

OPTIONSÂ {
overrideBuilder = "false";
}

Dadurch kann man die Logik der Builder implementieren ohne das ein neuer Generatorlauf diese Änderungen überschreibt.

 

Persönlich finde ich es allerdings eleganter ein separates Plugin Projekt für den Generator zu erstellen und dort von diesen Buildern abzuleiten. So kann sichergestellt werden, dass die Implementierung der Stubs immer zur DSL passt. Außerdem lässt sich so auch die Generator Entwicklung von der DSL Entwicklung trennen. Dies ist nützlich wenn die Arbeit auf mehrere Teams verteilt werden soll. Dann können die neuen Sprachfeatures in einem Sprint vom Team A implementiert werden und der Generator wird im nachfolgenden Sprint vom Team B überarbeitet.

Sehr erfreulich finde ich in diesem Zusammenhang die Tatsache, dass ein solches Generator Projekt im Handumdrehen aufgesetzt werden kann, da es sich um eine Ankopplung an den Standard Extension Point org.eclipse.core.resources.builders handelt. Die Erstellung eines solchen Projektes ist per Wizard über Eclipse Bordmittel möglich. Dabei werden der Builder, eine Nature, eine MenuAction und ein Marker erstellt. Benötigt wird eigentlich nur die Nature und der Builder. Die MenuAction für ToggleNature kann einfach in der Checkbox des Wizards abgewählt werden. Allerdings ist es ohne diesen Menüeintrag nicht mehr so einfach den Builder an ein bestimmtes Projekt zu binden. Letzlich muss man den Marker Extension Point einfach in der Plugin.xml löschen. Jetzt noch die zugehörigen Klassen entfernen und schon steht das Grundgerüst für den Builder. Anschließend noch die eigene Builder Klasse von [DSL]BuilderAdapter.java ableiten und schon kann der Generatorbau beginnen.

Um nicht alles manuell implementieren zu müssen, macht es Sinn den Generator selbst als Xtend oder Acceleo Projekt zu implementieren. Hier sind 2 Aspekte zu beachten:


  1. Erstellung des Generatorprojektes. Dies kann auf Grundlage des ecore Model (Metamodell der neuen DSL) statisch sowohl über Xtend als auch Acceleo erfolgen. Vermutlich lohnt sich hier die Generierung, da das Grundgerüst für ein Generatorprojekt vermutlich sehr stabil gehalten werden kann und nur die Templates von DSL zu DSL verändert werden müssen. Diese Templates könnte man in einem separaten Ordner ablegen der nicht generiert wird.
  2. Generierung der Zielartefakte aus einer Modellinstanz der DSL. Hier reden wir über die Laufzeitumgebung unseres DSL Editors. Also einen Zeitpunkt in dem wir mit dem Editor Texte in der von uns definierten Sprache erstellen können, mit Syntaxauszeichnung und Eingabeassistenten – das konkrete Model aber nur im Speicher vorliegt. Die einzige zu dieser Zeit existierende externe Repräsentation des konkreten Modells ist die Textdatei verfasst in unserer DSL.
    Ein Generator muss also an die Extension Points des DSL Editors andocken um das konkrete Modell auszulesen oder die ganze DSL Datei selbst parsen und transformieren. Hierfür dient uns der Builder welcher vom EMFText Framework generiert wurde. Zusätzlich müssen wir hier entweder mit Xtend oder mit Acceleo einen konkreten Generatorprozess implementieren. Wichtig ist, es geht stets um InMemory Modelle aus denen generiert werden soll. Letzteres ist ein Punkt der nicht immer sofort ins Auge fällt, da die Beispiele der Frameworks stets auf eine vorhandene ecore oder UML Datei basieren. Doch zur Laufzeit ist eben keine ecore Datei mehr vorhanden, da diese ja nur das Metamodell unserer DSL enthält und sämtliche Informationen in Plugin Kode überführt wurden.
    Nachdem ich es mal mit Acceleo probiert habe, bin ich der Meinung das es nicht so geeignet ist. Acceleo benötigt ein MetaModel (ecore geht) und ein Model in xmi (unsere DSL in XMI). Letzteres geht natürlich, dürfte aber aufwendig sein. Also Acceleo doch nur für Punkt 1 einfach einsetzbar.

Bewertung

Insgesamt macht das Framework einen sehr guten und durchdachten Eindruck. Die Lernkurve erschien mir recht steil. Das liegt nach meinem Empfinden aber weniger am Framework als mehr an der DSL Technologie allgemein. Wenn man die DSL Technologie allerdings mit den klassischen Methoden der Compilertechnik vergleicht, dann stellen Frameworks wie EMFText oder Xtext praktisch ein Paradies an Werkzeugen bereit.

 

Hinsichtlich einer Werkzeugstraße für industrielle Softwareentwicklung vom Fließband stellt EMFText eindeutig einen Grundbaustein dar. Vor allem auch weil durchweg bereits bestehende Quasi-Standards genutzt und nicht neu erschaffen werden.

Weiterführende Links

Ähnliche Technologien

Ganz nett fand ich auch folgenden Artikel Elinson, S.; Hanns, M. & Kronseder, S. (2010), ‚Für die Sprachenvielfalt – Xtext 1.0: Tiefere Integration in Eclipse‘, Java Magazin (10) , 76 – 78 .

Post a comment or leave a trackback: Trackback URL.

Kommentare

  • Mirko Seifert  On 16. August 2011 at 15:08

    Hallo Thomas,

    sind außer dem Anpassen des Source Pfades auf (${base}/src/main/java) noch andere Änderungen nötig, damit die generierten Plug-ins zur Verarbeitung mit Maven geeignet sind? Falls nein, lässt sich das sicher im Handumdrehen einbauen.

    Viele Grüße,

    Mirko

  • Mirko Seifert  On 18. August 2011 at 15:59

    Hi Thomas,

    du kannst das Maven Directory Layout bekommen indem Du folgende Optionen der .cs Datei hinzufügst:

    OPTIONS {
    srcFolder = „src/main/java“;
    srcGenFolder = „src/main/java“;
    uiSrcFolder = „src/main/java“;
    uiSrcGenFolder = „src/main/java“;
    }

    Achtung: Das geht nur mit der aktuellsten EMFText Version (http://www.emftext.org/update_trunk).

    Leider sieht das Standardlayout von Maven kein Directory für generierte Sourcen vor, so dass man die ’src‘ und die ’srcGen‘ Ordner mergen muss (siehe oben). Sicher kann man Maven auch beibringen, dass es noch einen zusätzlichen Ordner mit Java Sourcen gibt, aber das Default Directory Layout sieht es, glaube ich, nicht vor.

    Da EMFText infolge des Mergens dann erkennt, dass es in manchen Packages Klassen gibt, die da nicht hingehören, bekommt man eine Warnung (Found unused class … in analysis package). Die wird man wieder los, indem man @SuppressWarnings(unusedResolverClass) an den Anfang der .cs Datei einfügt.

    Danach kann man sich mit Tycho Maven POM Deskriptoren erzeugen lassen. Das habe ich auch gerade mal ausprobiert, aber die POMs mussten noch ein wenig angepasst werden. Außerdem funktionierte der Build bei mir nicht ohne ein Parent-POM in dem die 3 Plug-ins als Module aufgezählt wurden.

    Ich habe das Beispiel mal unter:

    http://www.emftext.org/temp/emftext-maven-example.zip

    abgelegt.

    Man muss in dem Ordner in dem sich das Parent-POM befindet, folgenden Befehl ausführen, um ein Build zu starten:

    mvn clean install -Dtycho.targetPlatform=C:\Pfad\zu\deiner\Eclipse\Instanz\

    Viele Grüße,

    Mirko

    • Huluvu424242  On 18. August 2011 at 23:37

      Hallo Mirko,

      vielen Dank für die Hinweise. Die Optionen hatte ich zwar bereits gefunden und ausprobiert, doch die ui-Folder wurden nicht erkannt. Nach der Aktualisierung über den von Dir angegebenen URL (ich hab ihn einfach als Update-Site eingebunden) werden die ui-Folder erkannt und die Generierung aus Eclipse heraus funktioniert mit Maven Layout – genau wie ich es wollte. Vielen Dank dafür. Zur Info ich nutze folgende Optionen:

      OPTIONS{
      generateCodeFromGeneratorModel=“true“;
      usePredefinedTokens=“true“;
      srcFolder = „src/main/java“;
      srcGenFolder = „target/generated-sources/java“;
      uiSrcFolder = „src/main/java“;
      uiSrcGenFolder = „target/generated-sources/java“;
      }

      (Du hast Recht, das Maven Standard Layout spezifiert keinen Ort für generierte Sourcen – mir schien target/generated-sources/java gebräulich)

      Dein Beispielprojekt habe ich ausprobiert, leider klappt es bei mir noch nicht. Bitte nenne mir die Versionen Deiner Entwicklungsumgebung (eclipse, maven und emftext version). Dann setzte ich es mal komplett neu auf (Das targetPlatform Argument hab ich beachtet🙂 zeigt auf mein Eclipse Home).

      Hinweis zum Parent-Pom:
      Du musst ihn nicht in den Workspache hoch legen. Nenn den Parent POM pom.xml und den des ersten Moduls pom-dsl.xml und lege beide im ersten Modul ab.
      Im Parent POM dann den Aufruf des ersten Moduls durch ./pom-dsl.xml ersetzen und im pom-dsl.xml von Gebrauch machen. Das sollte auch gehen ohne ein verschachteltes Projekt in Eclipse aufbauen zu müssen.
      (Zumindest ging es mal. Konnte es jetzt nicht ausprobieren da ich Dein Beispiel noch nicht am Laufen hab).

      Viele Grüße

      Thomas

      • Mirko Seifert  On 19. August 2011 at 10:01

        Hallo Thomas,

        ich habe eine Eclipse Classic 3.7 für Windows 64bit (eclipse-SDK-3.7-win32-x86_64). Darin habe ich die trunk Version von EMFText installiert (Im Update Manager die Kategorie ‚EMFText‘ ausgewählt.

        Dazu nutze ich apache-maven-3.0.3.

        Welche Fehlermeldung bekommst Du denn?

        Viele Grüße,

        Mirko

      • Huluvu424242  On 19. August 2011 at 10:42

        Hallo Mirko,

        Es waren bisher verschiedene Fehlermeldungen je nach Update Stand.

        • Es konnte die equinox umgebung/container nicht gefunden werden
        • Nullpointer in einem Maven Plugin

        Nach dem letzten Update findet er die richtigen Features nicht. Der Ordner unter org.eclipse.xtext.sdk.source_2.0.1.v201107291403 ist leer der korrekte Ordner wäre org.eclipse.xtext.sdk.source_2.0.1.v201108060904 aber den sucht er nicht – warum nicht?

        Anbei der Stacktrace:
        Stacktrace.doc

        P.s.
        Ich bin ab morgen früh eine Woche im Urlaub, nehme meinen Laptop zwar mit – kann aber sein, dass ich mich nicht ransetze🙂 Mal sehen ob ich des schaff🙂
        Ab 27.08. antworte ich dann auf jeden Fall wieder.
        Bis dahin schon mal vielen Dank für die vielen Hinweise.

        Vg Thomas

      • Mirko Seifert  On 19. August 2011 at 11:05

        Hi Thomas,

        versuch es doch noch mal mit einer „sauberen“ Eclipse Installation (Nur Classic Indigo + EMFText). Der Fehler scheint ja von dem Xtext Plugin verursacht zu werden, evtl. versteht Tycho da auch etwas aus dem Plugin nicht.

        Viele Grüße und einen schönen Urlaub!

        Mirko

      • Huluvu424242  On 19. August 2011 at 13:58

        Hallo Mirko,

        ja die eclipse Installation war das Problem. Waren vermutlich zu viele Updates und zu viele irgendwie gelöste Abhängigkeitsprobleme seit ganymede. Ohnehin erstaunlich, dass es soweit ging.
        Ich habe jetzt eine Indigo Classic mit EMFText und Dein Beispiel hat sofort funktioniert. Jetzt kann ich meins anpassen und über den Builder einen Generator bauen. Wenn ich das Beispiel dann im Artikel beschreibe, wird dieser sogar interessant🙂
        Schade eigentlich, dass ich in wordpress bei bereits publizierten Artikeln die weiteren Änderungen nicht temporär speichern kann und dann alle zu einem Termin veröffentlichen kann. Dadurch muss jede kleine Überarbeitung publiziert werden und es werden vermutlich jedes Mal Mails generiert.

        Schönes WE

        Thomas

  • Mirko Seifert  On 18. August 2011 at 16:09

    P.S.: Die Properties ‚Name‘ und ‚NsPrefix‘ im Ecore Modell haben nur indirekt Auswirkung auf die Namen der generierten Plug-ins. EMF benutzt ‚Name‘ um die Eigenschaft ‚Prefix‘ für das Generator Modell, bzw. das Generator Package abzuleiten. Setzt man dann noch die Eigenschaft BasePackage (was der EMFText New Project Wizard tut), so bekommt man:

    basePackage.Name

    als Package Name für die Ecore Modell Klassen. Achtung: Ändert man die Eigenschaft ‚Name‘ später, so wird der Prefix im Generator Modell nicht aktualisiert.

    EMFText benutzt diesen zusammengesetzten Namen wiederum als Basis für die Namen der Resource Plugins. Es hängt noch ‚.resource.syntaxName‘, bzw. ‚.resource.syntaxName.ui‘ hinten dran. ’syntaxName‘ ist dabei der Name der in der .cs Datei ganz oben festgelegt wird.

    Man kann diese Namen aber auch alle über Optionen in der .cs Datei selbst festlegen.

    Viele Grüße,

    Mirko

  • Mirko Seifert  On 19. August 2011 at 10:09

    Hi Thomas,

    hier noch ein Hinweis zum Generieren von Code aus deinen DSL Modellen: EMFText generiert per default einen Builder, den Du nur aktivieren musst. Wie das genau geht steht in der EMFText Doku (dem PDF). Der Builder wird dann automatisch aufgerufen, immer wenn Du ein .dsl File speicherst. Im EMFText Syntax Zoo (siehe Webseite) finden sich viele Sprachen die einen Builder dabei haben (Forms, Dot, MinimalEcore etc.).

    Üblicherweise ruft man aus diesem Builder dann einen Code Generator auf. Dafür kannst Du Xtend benutzen, aber auch Acceleo oder einen eigenen Generator. Acceleo habe ich schon benutzt. Da dort die Code Templates interpretiert werden, kann man sehr schnell damit experimentieren. Änderungen werden immer sofort sichtbar, ohne dass man Eclipse neu starten muss.

    Viele Grüße,

    Mirko

  • Mirko Seifert  On 19. August 2011 at 13:59

    Schön, dass es jetzt geht!

    Viele Grüße,

    Mirko

Trackbacks

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: