Tag Archives: dsl

DSL Projekt aufsetzen (mit Xtext)


Flattr this

Motivation

Da es ein wenig Mühe bereitet hat und ich nach einem Jahr nicht noch einmal den Aufwand investieren möchte schreibe ich hier eine kleine Anleitung wie man ein DSL Projekt unter folgenden Randbedingungen aufsetzt:

  • Als Entwicklungsumgebung wird eclipse eingesetzt
  • Zur Sicherstellung einer einheitlichen eclipse Installation wird yatta-profiles genutzt
  • Zur Modellierung der DSL wird Xtext verwendet
  • Die Sourcen werden auf github.com gehostet
  • Als CI System kommt travis-ci.org zum Einsatz
  • Zur Verteilung der Releasestände wird bintray.com genutzt

Die Eclipse aufsetzen

Lange habe ich nach einer Möglichkeit gesucht um diesen Schritt zu automatisieren. Angefangen über das Niederschreiben der Installation hier im Blog (Eclipse konfigurierenEclipse aufsetzen) über CloudConnect bin ich letztlich auf Yatta-Profiles gekommen. Yatta Profiles hat sich für meine Arbeitsweise als am besten geeignet erwiesen um die zu installierenden Plugins und die aus zu checkenden Projekte einheitlich für ein Team zu verteilen (Allerdings nutze ich das Angebot nicht als Team sondern als einzelner Entwickler. Halte mir aber die Möglichkeit offen mit mehreren Leuten zu gleich an einem Projekt zu entwickeln.)

Bleibt das Speichern der eigentlichen Konfiguration der installierten Plugins. Diese Arbeit kann ich an das Oomph Plugin delegieren. Zum Glück hat das Projekt jetzt eine Reife erlangt die zur produktiven Arbeit genügen sollte. 

Wer meine Eclipse Installation ausprobieren möchte, kann sich einfach das Yatta-Profile installieren: ECLIPSE XTEXT DSL TOOLS

Die Sourcen erstellen

Generell beginne ich mit dem Anlegen eines leeren Repositories (Projekt) auf Github. Dabei wähle ich zunächst den Namen aus, dann gebe ich java als Programmiersprache an und wähle eine mir genehme Lizenz aus. Weiterhin selektiere und aktiviere ich die Checkbox „Readme erstellen“. Nach dem Fertigstellen bietet github.com ein neues Projekt zum clonen an und genau das mache ich dann auch – ich klone das Projekt mittels git clone <url> in ein lokales Verzeichnis auf meinem PC. 

Nun starte ich eclipse und erzeuge über den Dialog „Neu/Projekt/Xtext“ ein neues xtext Projekt.

Hierbei sind bereits ein paar wichtige Dinge zu beachten. Da ich später auf bintray deployen möchte benötige ich eine einheitliche GroupId über alle Projekte hinweg. Gern hätte ich hier com.github.funthomas424242.dsl verwendet, doch das funktioniert nicht mehr falls ich mal ein Maven Plugin entwickeln sollte dann hätte ich nämlich gern die gropuId com.github.funthomas424242.maven.plugins verwendet. Damit bräuchte ich aber zwei groupId’s und das würde zwar gehen aber ist von bintray nicht gewünscht. Da man nie weiß wann solche Wünsche mal in Vorgaben umgewandelt werden (besonders wenn man die kostenlosen Services nutzt) habe ich mich also für die groupId com.github.funthomas424242 entschieden. Als Folge daraus muss ich meine Projekte mit dieser groupId versehen. Damit das funktioniert und ich trotzdem noch verschieden DSL Projekte verwalten kann gehe ich wie folgt weiter vor. 

Die nachfolgenden Einstellungen im Wizard werden am Beispiel meines Projektes ahnen.dsl auf github erklärt. Und so fülle ich die erste Dialogseite des Wizards aus:

Xtext Projekt Basisdaten

 

Ja, der Projektname ist richtig. Zwar wird dieser als groupId verwendet doch lässt sich das später manuell gut abändern.

Xtext Projekt Settings

 

Als Source Layout wurde Plain gewählt da eine andere Kombination mit der Einstellung Eclipse Plugin aktuell noch nicht unterstützt wird.

Nun werden diverse Projekte vom Wizard in der eclipse erzeugt.  Von jedem Projekt öffnen wir nun die pom.xml und korrigieren die groupId manuell auf z.B. com.github.funthomas424242 Anschließend selektieren wir alle Projekte und führen ein Maven update Projekt über das Kontext Menü in der eclipse durch. Nun sollten alle Projekte wieder fehlerlos erscheinen. Falls nicht einfach die Xtext Datei öffnen und noch mal alle Sourcen generieren lassen. 

Bevor wir einen commit durchführen sollten wir noch im parent Projekt eine .gitignore anlegen. Meine sieht wie folgt aus:

.settings/
target/
src-gen/
xtend-gen/
.project
.classpath
*_gen

Man beachte, dass ich hier die führenden / (Slashes) weggelassen habe damit die Regeln auch für die Unterprojekte gelten. Nun testen wir zunächst unser Projekt indem wir eine Eclipse Instanz mit Runtime Workspace starten:

Runtime Start

 

In der gestarteten Runtime Eclipse legen wir ein einfaches Projekt „Test“ an und darin eine Datei test.ahnen. Beim Öffnen dieser Datei können wir sehen ob unser Plugin prinzipiell schon funktioniert, denn es muß der entsprechende Editor zum Öffnen angeboten werden. In meinem Fall nennt sich dieser Ahnen Editor und ist vorhanden. Verwenden wir diesen Editor zum Öffnen werden wir gefragt ob das Projekt in ein Xtext Projekt konvertiert werden soll – ja natürlich. Wir müssen nichts dazu tun eclipse trägt nun ein paar Metadaten in die Projektbeschreibungsdatei .project ein und das scheint es gewesen zu sein. Den Editor prüfen wir indem wir seine Vorschlagsfunktion unter Ctrl+Space nutzen und den ganzen Beispieltext damit eingeben.

Das war es erstmal. Jetzt können wir die Runtime Instanz der eclipse schließen und unseren Projektstand commiten (aber noch nicht pushen). Wir müssen zwar noch alle Projekte ein Verzeichnis nach oben verschieben aber das sollte git als Verschiebung erkennen und somit sollte dies kein Problem ergeben. Also commited ist.

Jetzt löschen wir alle Projekte aus unserer eclipse aber nicht auf der lokalen Festplatte!!!

Nun unbedingt die eclipse schließen da sie meist die Projekte trotzdem noch lockt und dadurch nachfolgende Schritte fehlschlagen würden. 

In einer Shell navigieren wir jetzt zum Parent Projekt (in diesem ist die pom.xml des parents zu finden) von dort aus verschieben wir alle Verzeichnisse und Dateien ins übergeordnete Verzeichnis. Anschliessend navigieren wir selber in das übergeordnete Verzeichnis und löschen das nun leere alte parent Projekt.

Jetzt ist unser normales root Verzeichnis aus dem github repository das parent Projekt und wir können es ganz normal in  unsere Eclipse neu importieren. 

Diesen Stand commiten wir ebenfalls wobei wir ihn dem letzten Commit hinzufügen (amend commit). Jetzt noch ein kurzer Test mit der Runtime eclipse. Wenn alles noch so funktioniert wie vorher, dann können wir jetzt pushen.

Maven Build anpassen

Durch die manuelle Umbenennung der groupId haben wir unser Definitionsfile der target platform invalidisiert. Das sollten wir unverzüglich beheben. Das Problem wird deutlich wenn wir im Root Verzeichnis unseres Projektes ein mvn clean install ausführen.

Das Problem lässt sich leicht korrigieren durch eine Anpassung in der parent/pom.xml. Dort muss die groupId der TargetPlatform angepasst werden. Ich bevorzuge eine generische Lösung. Anbei der relevante Abschnitt aus der parent/pom.xml:

<plugin>
 <groupId>org.eclipse.tycho</groupId>
 <artifactId>target-platform-configuration</artifactId>
 <version>${tycho-version}</version>
 <configuration>
  <target>
   <artifact>
    <groupId>${project.groupId}</groupId>
    <artifactId>com.github.funthomas424242.dsl.ahnen.target</artifactId>
    <version>${project.version}</version>
   </artifact>
  </target>

So jetzt funktioniert der Maven Build wieder. Zeit für einen neuen commit. Aber mit dem Push ruhig noch warten, den wollen wir gleich durch das CI System schicken.

Das CI System aktivieren

Dazu gehen wir auf travis-ci.org und loggen uns mit unserem github.com Account per OAuth ein. In der rechten oberen Ecke wird der Nutzername angezeigt beim überstreichen mit der Maus ploppt ein Menü auf. Daraus wählen wir den Punkt Accounts aus. Da das Repository neu ist, wird es travis-ci noch nicht kennen und wir nutzen den Sync Button oben rechts um unsere github Projekte zu importieren. In der erscheinenden Liste an Projekten suchen wir unser Projekt und aktivieren den Schalter davor. Ab jetzt sucht travis-ci bei jedem push in das Projekt eine Datei .travis.yml und falls gefunden wird anschließend ein Build ausgeführt.

Natürlich müssen wir diese Datei noch ins Projekt einchecken. Sie gehört ins parent Projekt und muss wirklich mit einem Punkt beginnen (also ein Problem für alle Windows Freunde – aber ein lösbares 🙂 )

language:
 - java

jdk:
 - oraclejdk8

Nun noch ein commit und ein push und die Maschinerie springt an 🙂 Nach ungefähr 10 Minuten sollte das Projekt in travis erscheinen und der Build lässt sich prüfen. Es empfiehlt sich ein entsprechendes Build Icon von travis in die Projekt Readme zu integrieren. So kann man auf einem Blick erkennen wenn der Status auf rot geht. 

Bintray Deployment anbinden

Zu den Formalitäten wie Registrierung und ähnliches bei bintray.com möchte ich hier nicht eingehen. Nur eins dazu das Passwort für die oss.jfrog.org Seite ist Euer API Key von bintray.com. Möglicherweise müsst ihr Euch erst freischalten lassen etc. Aber das sollte sich jeder selbst durchlesen, da es teilweise auch Sicherheitsrelevant ist.

Weiterhin ist bei maven die settings.xml anzupassen. Hier sind die Zugangsdaten für den Server zu hinterlegen. Vorsicht – die Datei darf kein Anderer in die Hände bekommen. Idealerweise nutzt ihr die Verschlüsselungsmechanismen. 

Im Projekt ist auch noch eine Anpassung durchzuführen. Die Deplyoment Repositories sind im parent/pom.xml bekannt zu geben. Dazu fügen wir folgenden Eintrag in die parent/pom.xml ein.

<distributionManagement>
 <snapshotRepository>
  <id>snapshots</id>
  <name>oss-jfrog-artifactory-snapshots</name>
  <url>https://oss.jfrog.org/artifactory/oss-snapshot-local</url>
 </snapshotRepository>
 <repository>
  <id>bintray-funthomas424242-dsl</id>
  <name>oss-jfrog-artifactory-releases</name>
  <url>https://oss.jfrog.org/artifactory/oss-release-local</url>
 </repository>
</distributionManagement>

Mit einem mvn deploy lassen sich ab jetzt Snapshots und Releases nach oss.jfrog.org deployen. Von dort aus können diese im angemeldeten Zustand über das Kontextmenü nach bintray.com in ein beliebiges Package kopiert werden. Jedes Package muss auf bintray in einem Repository liegen. Ein Package welches im jCenter veröffentlicht werden soll muss einigen Anforderungen genügen (mindestens ein jar, ein src.zip, ein pom.xml und optional noch ein javadoc archive). Die Freischaltung für das jCenter dauert ein wenig Zeit – am besten rechnet man mit 24h – und erfolgt nur auf Antrag. Eine weitere Freischaltung für das maven central erfordert dann noch ein Sonatype Login. Parallel zur Beantragung der ganzen Accounts kann dann schon mal Fachlichkeit umgesetzt werden 🙂

Noch ein paar Tipps

  1. Tycho kann bereits in der Version 0.25.0 benutzt werden. Das muss man manuell in der parent/pom.xml in den Properties eintragen. 
  2. Um das Deployment zu verringern nutze ich in der parent/pom.xml:
    <maven.deploy.skip>true</maven.deploy.skip>
    und in der pom.xml des repository Subprojektes:
    <maven.deploy.skip>false</maven.deploy.skip>
    So wird nur das Zip mit der eclipse update site hochgeladen.

Soweit zum Aufsetzen eines DSL Projektes und viel  Spass beim Ausprobieren. Jetzt muss nur noch die Fachlichkeit umgesetzt werden 😉

 

Advertisements

GUIs deklarativ – never ending story


Flattr this

Motivation

Der Traum eine Programmoberfläche möglichst einfach, mit wenig Text und doch mit exakter Anordnung der GUI Elemente beschreiben zu können ist schon sehr alt. Immer wieder tauchten dazu Konzepte auf – doch diese konnten sich am Markt nie wirklich fortsetzen, nicht zu Letzt auch mangels der Unterstützung großer Firmen. Das letzte mir bekannte Exemplar ist JavaFX Script welches nun auch schon fast als ausgestorben bezeichnet werden kann.

Für alle die sich dennoch eine deklarative Sprache für die GUI Entwicklung wünschen zeigt dieser Artikel Projekte und mögliche Fortsetzungen auf.

Thinlet

Das erste mir bekannte Projekt welches seine GUI deklarativ beschrieb war Thinlet. Ich nenne es mal Thinlet one denn der Autor hat das Projekt inzwischen eingestampft und hat unter gleichem Namen ein völlig neues Framework herausgebracht. Letzteres konnte mich aber nicht weiter begeistern.

Das ursprüngliche Projekt war im Prinzip ein Jar mit einer Klasse. In dieser Klasse war die gesamte Logik. In der eigenen Anwendung waren die Oberflächen dann per xml zu beschreiben. Das Framework unterstützte sogar bereits das Binding von GUI Elementen an Java Klassen. Allerdings war das Eventhandling irgenwie nicht optimal gelöst – ich hatte damit jedenfalls Probleme – ich glaube mit der Richtung aus Java Klasse zum GUI Element oder von GUI Element zu GUI Element. Das kann ich leider nicht mehr genau sagen.

Dokumente zum ursprünglichen Projekt lassen sich kaum noch finden – man muss halt ein bisschen googeln denn die URLs wechseln stetig – aber offensichtlich gibt es noch genug Leute welche die Dokumentation retten. Hier ein Beispiel: http://wolfpaulus.com/thinlet/doc/widget/overview.html

Canoo

Diese Firma muss ich hier einfach aufzählen, weil sie mit ULC (Ultra Light Client) das fertiggestellt hat von dem alle Welt träumt. Allerdings proprietär und teuer 😦 Das war der Grund weshalb ihr Framework für den Open Source Bereich nicht in Frage kommt. Aber die Technologie ist genial – Half Object Plus Protocol (HOPP) Entwurfmuster. Das wäre das Ziel nur eben frei und Oracle hat es mit JavaFX eindeutig vermasselt. Hier ein Beispiel wie leicht alles gehen könnte.

GUI4J

Das GUI4J Projekt funktionierte ähnlich wie Thinlet wurde aber von mehr Leuten entwickelt und länger durchgehalten.

Zu guter Letzt gibt es natürlich tausende Projekte die in Richtung XML deklarierte Oberfläche gehen aber keine welches wirklich später dafür relevant wurde. Hier eine von vielen Listen die im Internet findbar sind: http://www.java2s.com/Product/Java/XML/XML-UI.htm

JavaFX

JavaFX in der ersten Version hatte mit JavaFX Script wirklich Potential den Sprung in Richtung Canoo zu schaffen. Doch Oracle hat es getötet aus welchen Gründen auch immer: http://www.heise.de/developer/meldung/Das-endgueltige-Aus-fuer-JavaFX-Script-1444903.html

JavaFX selbst hat Oracle dennoch zur Schlüsseltechnologie erhoben. Bislang steht diese allerdings irgendwo außerhalb des aktiv von Oracle gepushten ADF. ADF selbst setzt weiterhin auf Swing und eine dirty Click and Drop Oberfläche. Letztere hinterlässt in der Praxis nach einiger Zeit auch gern mal korrupte Arbeitsstände. Dann darf der Entwickler wieder zurück auf LOS ohne einen Erfolg einzustreichen. Wie soll man also die Signale aus dem Hause Oracle deuten? Möglicherweise ist sich Oracle intern selbst uneins und setzt später einfach auf die Technologie die sich durchsetzt. Einige Entwickler greifen daher selbst zur IDE und bauen schon wieder ihre eigenen RIA Frameworks:

Captain Casa Framework

Da ich dieses RIA Dilemma schon einige Zeit betrachte setzte ich immer wieder meine Hoffnung auf das Captain Casa Framework. Captain Casa ist eine Firma welche für den lokalen Mittelstand diverse Softwarelösungen erarbeitet hat. Diese basieren alle auf dem Captain Casa Framework. Diese wiederum setzte bis vor einigen Jahren ausschließlich auf Swing, sprang aber nach Erscheinen von JavaFX sofort auf diesen Zug auf. Aktuell steht wieder ein Community Treffen an und ich hoffe das es mir dieses Jahr endlich wieder möglich ist teilzunehmen und meinem kurzfristigen Urlaubsantrag zugestimmt wird. Falls ja werde ich natürlich wieder über das Treffen berichten.

Anbei ähnliche Artikel zum RIA Dilemma

DSL Tutorial Teil 2


Flattr this

Um was geht es?

Dies ist der letzte Teil meines 2 teiligen DSL Tutorials. Ziel des Tutorials ist das Erstellen einer DSL zur Beschreibung von Vektorgrafiken und der Bereistellung eines Generators um daraus svg Dateien zu erzeugen. Die DSL wird in [DSL-1] erstellt. Dieser 2. Teil befasst sich aufbauend auf Teil 1 mit der Erstellung eines Generators.

Einrichten der Arbeitsumgebung

Vor Beginn dieses Teils müssen Sie alles unter [DSL-1] beschriebene durcharbeiten. Ich setze die funktionierende DSL mit der im Teil 1 vorgenommenen Definition voraus.

Los gehts

Die folgend dargestellten Projekte sollten im Eclipse Arbeitsbereich zu sehen sein.

015 ProjektUebersicht

Als Erstes fügen wir dem DSL Projekt die Acceleo Nature hinzu und aktualisieren die Ansicht.

016 AddNature

Nun weisst unser DSL Projekt ein Overlay Icon von Acceleo auf und wir können über das Kontextmenü das Generatorprojekt erzeugen.

017 GeneratorProjektErzeugen

Es erscheint ein geführter Dialog per Wizard. Hier passen wir den Projektnamen so an, dass er statt auf ui auf generator endet. Außerdem nehmen wir Änderungen an den Settings (letzte Tab) vor. Die nachfolgenden Bilder verdeutlichen dies.

018 Dialog 019 Einstellungen

Wichtig der Filter der Dateinamen! Er entscheidet darüber für welche Dateien der Generator zur Verfügung stehen wird. Außerdem habe ich mich für einen eigenen Target Pfad entschieden (target/generated-sources), damit nicht ausversehen Projektdateien überschrieben werden.

Zum Abschluss bitte mit Finish bestätigen.

Im neuen Projekt setzen wir als Erstes den Java Output Build Pfad auf target/classes, da ohne diesen Schritte manchmal keine Templates angelegt werden können. Nun müssen wir auch dem neuen Generator Projekt zunächst manuell die Acceleo Nature zuweisen (leider nimmt Acceleo diese Zuweisung nicht automatisch vor). Nun stehen auch hier weitere Kontextmenüeinträge zur Verfügung. Somit können wir nun im Package org.emftext.language.svgd.generator ein Main Template anlegen. Dazu bitte auf dem Package Ordner über das Kontextmenü den Neu Dialog aufrufen und Acceleo Main Module File auswählen. Dann einfach Next und Finish – der Rest ist bereits korrekt vorbelegt.

020 MainTemplateAnlegen

Jetzt sind 2 neue Dateien im Package entstanden: eine Main.java (interessiert uns nicht weiter) und eine main.mtl. Letztere sollte auch geöffnet wurden sein und wird von uns nun mit folgendem Inhalt gefüllt:

[comment encoding = UTF-8 /][module main(‚http://www.emftext.org/language/svgd&#8216;)/][template public main(model : SVGModel)][comment @main /][for (element : Form | model.elements)] [file (element.name.concat(‚.java‘), false, ‚UTF-8‘)] Testfile [/file][/for][/template]

Im common Package in der Klasse GenerateAll ersetzen wir die doGenerateMethode mit folgendem Code:

Code der doGenerate Methode in GenerateAll.java

Wenn wir unsere DSL jetzt wieder als Eclipse Anwendung starten, können wir dort zu unserem Beispiel bereits Code generieren. Achtung die verschiedenen Formen sollten auch verschiedene Namen bekommen damit nicht alle die gleiche Java Klasse generieren 🙂

021 BeispielInstanz

So sieht ein erstes Beispiel aus. Damit ist der Generator prinzipiell arbeitsfähig und wir können uns dem Implementieren der Fachlichkeit zuwenden.

Den vollständigen Umfang der Acceleo Sprache zu erklären möchte ich hier gar nicht erst versuchen (dazu gibt es eine sehr schöne Hilfe in Eclipse selber). Aber damit das Tutorial am Ende auch eine SVG Datei generiert, habe ich folgende Änderung an der main.mtl durchgeführt. Bitte den Inhalt der Datei komplett ersetzen mit dieser main.mtl (odt) oder dieser main.mtl (doc) .

Leider lies sich der Code hier im Blog nur schlecht formatieren. Auf jeden Fall muss die <?xml Zeile ganz links anfangen da sonst der Browser das Bild nicht interpretieren kann. Und so kann ein funktionierendes Beispiel in Eclipse aussehen.

022 FinalesBeispiel

Ich hoffe das Tutorial konnte einen Einblick in die Praxis des Generatorbaus geben. Ziel war den Leser schrittweise zu einem funktionierenden Beispiel zu verhelfen. Der Aufwand zur Erstellung des Tutorials hat dann doch mehr als ein Wochenende in Anspruch genommen. Daher habe ich auch auf die Erklärung vieler Details verzichtet.

Falls jemand weitere Fragen dazu hat oder Details wissen möchte, bitte kommentieren dann liefere ich diese noch nach.

Vielen Dank fürs Lesen und viel Spass beim Generieren 🙂

[DSL-1]

DSL Tutorial Teil 1

DSL Tutorial – Teil 1


Flattr this

Motivation

Nachdem ich letztens in [EMFText einsetzen] einen Blick auf EMFText geworfen hatte möchte ich nun die Erfahrungen welche ich inzwischen mit dem Framework sammeln durfte in einem kleinen Tutorial zusammenfassen. Dieses werde ich an einem kleinen Beispiel durchführen, in welchem eine primitive DSL für die Erstellung von svg Grafiken erstellt werden soll. Wer tatsächlich Bedarf an einer solchen DSL hat, kann die DSL dann selbständig erweitern. Es würde mich freuen, wenn solche Projekte unter dem Artikel kurz kommentiert werden – es genügt ein Link auf das Projekt 🙂

Vor dem Einstieg in mein Tutorial empfehle ich die Abarbeitung des Original ScreenCast hier: http://www.emftext.org/index.php/EMFText_Getting_Started_Screencast
So sind die wesentlichen Grundbegriffe schon bekannt und ich kann auf spezielle Punkte eingehen.

Das Tutorial wird in 2 Teilen realisiert:

  1. Teil: Erstellen und Anpassen einer DSL in Iterationen auf Basis von Eclipse und den EMFText Plugins

  2. Teil: Erstellen eines Generators für die DSL auf Basis von Eclipse und den Acceleo Plugins

Aufsetzen der Arbeitsumgebung

 

1) Download Eclipse Classic Version von:
http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.7.1-201109091335/eclipse-SDK-3.7.1-win32.zip

In der eclipse.ini setzen wir folgende Werte:

-vmargs
-XX:MaxPermSize=256m
-Xms128m
-Xmx512m

2) Start der Eclipse und Einrichten folgender Update Sites:

  1. EMFText Updates Site – http://www.emftext.org/update_trunk
  2. Eclipse Indigo Updates – http://download.eclipse.org/releases/indigo (sollte bereits eingerichtet sein)

3) Installieren der aktuellen Versionen von:

  • EMFText über den 1. URL und dann Auswahl Paket EMFText.
  • Acceleo und EcoreTools über den 2. URL und dann Auswahl Modeling/Acceleo SDK und Modeling/Ecore Tools

Beispielprojekt

 

Als Beispiel werde ich in diesem Artikel zeigen wie wir ein DSL Projekt aufsetzen, was alles benötigt wird und wie wir die DSL nach und nach erweitern können. Die Realisierung eines XMI Builders und die Erstellung eines Generator Projektes mittels Acceleo werden dann in späteren Artikeln beschrieben.

Los geht’s

1) DSL Projekt anlegen

  1. Neu/Projekt/EMFText/EMFText Projekt
  2. Felder im Dialog befüllen

001 NewEMFTextProject

 

Weiter mit Finish

2) Ecore Diagramm aus dem Model erstellen

Dazu suchen wir im DSL Projekt den Ordner metamodel, selektieren dort das Ecore Model svgd.ecore und dann über das Kontextmenü den Punkt Initialisiere Ecore Diagramm File auswählen.

003 EcoreDiagram

Den anschließenden Dialog mit Finish bestätigen. Als Ergebnis finden wir eine neue Datei svgd.ecorediag . Diese wird auch gleich geöffnet und das aktuelle Ecore Model als Grafik angezeigt. Der Wizard war zu uns nett und hat schon ein paar Modelelemente für ein ER Model angelegt. Diese nutzen wir gleich weiter, passen sie aber unseren Bedürfnissen an:

  1. Type benennen wir in Form um (selektieren und in der Properties View den Namen ändern).
  2. DataType wird in Rechteck umbenannt (nach jedem Schritt am besten speichern – Obacht! Das Fenster muss als gespeichert markiert werden – also kein * mehr)
  3. EntityModel wird zu SVGModel und
  4. Entity wird zu Kreis
  5. Die Kante von Kreis zu Feature wird entfernt
  6. Das Attribut abstract in Kreis wird entfernt
  7. Die Kante von Feature zu Form wird entfernt
  8. Feature wird in Linie umbenannt
  9. FeatureKind wird in Linienart umbenannt
  10. attribute in Linienart wird zu durchgezogen, reference zu gestrichelt und containment zu gepunktet umbenannt (Bitte stets Name = Literal setzen)
  11. Alles Speichern und das ecore Model svgd.ecore öffnen und prüfen ob die Änderungen auch hier korrekt durchgeführt wurden.

An dieser Stelle sehen wir, dass es nicht ganz geklappt hat. Kreis enthält noch eine Verbindung features zu Linie – die muss natürlich weg. Ein wichtiger Schritt beim iterativen Vorgehen immer Diagramm gegen Ecore Model vergleichen! Letztlich ist das Ecore Model der Master für alle Modellierungswerkzeuge.

 

Also jetzt erstmal im Ecore Model aufräumen:

  1. features unter Kreis entfernen
  2. type unter Linie entfernen
  3. kind unter Linie umbenennen in stil
  4. Super von Linie (NamedElement) wechseln und dafür Form auswählen
  5. types unter SVGModel umbenennen in elements

004 FertigesEcoreModell

 

Nun alles Speichern und ins Ecore Diagramm zurück wechseln. Nach dem Wechseln in das Ecore Diagramm, stellen wir fest, dass einige Änderungen nicht korrekt dargestellt werden. Bei umfangreichen Änderungen im Ecore Model passiert dies leider immer wieder. An dieser Stelle empfielt es sich das Diagram zu löschen und wie oben bereits durchgeführt erneut aus dem Ecore Model zu erzeugen. Einen effizienteren Weg habe ich hierfür leider nicht gefunden. So schaut das neu erstellte Diagramm aus.

005 FertigesEcoreDiagram

Da die Anpassungen auch für das GeneratorModell und die HUTN Syntax zu umfangreich waren, werden wir auch diese beiden Dateien neu erzeugen (Später werden wir diese Schritte teilweise automatisch ausführen lassen).

Zunächst aktualisieren wir das Generator Model. Also Rechtsklick auf svgd.genmodel und Reload auswählen. Im Wizard dann Ecore Model auswählen. Auf der nächsten Tab das konkrete Modell auswählen (Der korrekte Pfad sollte bereits hinterlegt sein). Kurzer Klick auf Load und dann geht es auf Weiter . Zum Abschluss Finish und es ist geschafft.

006 ReloadGenModel

Nun löschen wir das Syntax File svgd.cs und erzeugen uns ein Neues. Also nach dem Löschen bitte einen Rechtsklick auf svgd.genmodel und den Eintrag generateSyntax/HUTN-Syntax ausgewählt. Erledigt.

007 GeneriereHutnSyntax

Jetzt schauen wir uns die Syntax an. Die entstandene Datei sollte wie folgt aussehen.

008 FertigeHUTNSyntax

Die Syntaxdefinition ist recht rudimentär und wir müssen sie zunächst ein wenig an das Metamodell anpassen bzw. ein paar erleichternde Optionen einfügen.

Fangen wir mit den Optionen an welche uns die iterative Arbeit künftig erleichtern werden – dazu folgenden Abschnitt vor TOKENS einfügen.

OPTIONS{
reloadGeneratorModel=“true“;
generateCodeFromGeneratorModel=“true“; //wichtig um Fehler im Generat zu vermeiden
disableLaunchSupport=“false“;
usePredefinedTokens=“true“;
}

Anschließend generieren wir die TextResourcen.

 

009 GeneriereTextResourcen

Nun müssen wir noch die alten, vom NewWizard erzeugten Klassen entfernen:

  • DataTypeImpl

  • EntityImpl

  • EntityModelImpl

  • FeatureImpl

  • TypeImpl

010 KlassenEntfernen

 

Alles rot markierten Klassen sind zu entfernen – das sind Rückstände aus früheren Iterationen oder vom Neu Anlegen Dialog.

Starten wir nun das Projekt über Run As Eclipse Application können wir in der sich öffnenden Runtime-Eclipse über den Neu Wizard ein Projekt vom Typ svgd anlegen. Das gleich mit angelegte File new_file.svgd unterstützt bereits unsere HUTN Syntax mit einem leistungsfähigen Editor inklusive automatischer Syntaxvorschläge und farblicher Syntaxauszeichnung.

011 SimpleModelInstanz

Allerdings ist die Syntax nicht wirklich tauglich eine Vectorgrafik zu beschreiben. Damit sich dies ändert, werden wir nachfolgend die Syntax und falls notwendig auch das Ecore Modell nach und nach erweitern und anpassen.

Bis hierher eine kleine Zusammenfassung als Video

SVG – die fachliche Domain

Wenn man eine DSL erstellt, sollte man sich auch in der fachlichen Domain auskennen. Einen guter Einstieg für den Bau einer DSL findet sich auf Wikipedia unter [SVG]. Für uns ist wichtig welche Grundelemente der Sprache es gibt und welche Attribute diese besitzen müssen. Da SVG nur wenige Elemente definiert werden diese im Folgenden kurz aufgezählt:

  • Pfad …
  • Kreis definiert über Mittelpunkt und Radius
  • Ellipse definiert über Mittelpunkt und Radius1 sowie Radius2
  • Rechteck definiert über Position der linken oberen Ecke sowie Breite und Höhe
  • Linie definiert über die Positionen der beiden Endpunkte
  • Polygonzug definiert über eine Liste von Positionen der Punkte
  • Polygon definiert über eine Liste von Positionen der Punkte
  • Text …
  • Image …

Zu jedem Element lassen sich noch Style und Transformationsangaben hinterlegen. Für unsere DSL sollen die 3 Grundelemente (oben in fett) ohne Style und Transformationen genügen.

 

DSL erweitern

Die Grundelement Kreis, Rechteck und Linie sind in unserer DSL bereits definiert. Was fehlt sind Attribute der Grundformen. Also gleich ins Ecore Diagram und die benötigten Attribute wie folgt definiert.

  • Kreis um die Attribute x und y sowie radius ergänzt. Alle vom Datentyp EFloat.
  • Rechteck um die Attribute x und y sowie hoehe und breite ergänzt. Alle vom Datentyp EFloat.
  • Linie um die Attribute x1 und y1 sowie x2 und y2 ergänzt und auch diese alle vom Datentyp EFloat .

Das finale Ecore Diagramm sollte wie folgt aussehen.

 

012 FinalesEcoreDiagram

Da diesmal nur Objekte hinzugefügt wurden, sollte kein Unterschied zum Ecore Modell entstanden sein. Vorsichtshalber aber ruhig vergleichen ob das Ecore Modell dem Ecore Diagramm entspricht. Gegebenenfalls natürlich anpassen.

Auf jeden Fall sollten wir jetzt eine Syntax definieren in welcher eine sinnvolle Beschreibung der Grafik möglich ist. Dazu öffnen wir die Syntaxdefinition sgvd.cs und führen folgende Anpassungen durch.

  • Zunächst entfernen wir die extra definierten Token. Diese benötigen wir nicht! Wir beschränken uns auf die von EMFText vordefinierten Standardtoken (siehe Option: usePredefinedTokens)
  • Nun passen wir die Syntax-Regel für das Rechteck an:
    Rechteck ::= „Rechteck“ „{“ „name=“ name[‚“‚,'“‚] „x=“ x[‚“‚,'“‚] „y=“ y[‚“‚,'“‚] „höhe=“ hoehe[‚“‚,'“‚] „breite=“ breite[‚“‚,'“‚] „}“;
  • Weiterhin ist die Syntax-Regel für Kreis wie folgt anzupassen:
    Kreis ::= „Kreis“ „{“ „name=“ name[‚“‚,'“‚] „x=“ x[‚“‚,'“‚] „y=“ y[‚“‚,'“‚] „radius=“ radius[‚“‚,'“‚] „}“;
  • Die Zeichenkette „elements“ im SVG Modell ist auch überflüssig also die Regel für SVGModel angepasst:
    SVGModel ::= „SVGModel“ „{“ (elements)* „}“;
  • Schlussendlich muss auch Linie noch angepasst werden:
    Linie ::= „Linie“ „{“ „name=“ name[‚“‚,'“‚] „x1=“ x1[‚“‚,'“‚] „y1=“ y1[‚“‚,'“‚] „x2=“ x2[‚“‚,'“‚] „y2=“ y2[‚“‚,'“‚] „stil“ „:“ stil[durchgezogen:“durchgezogen“, gestrichelt:“gestrichelt“, gepunktet:“gepunktet“] „}“;

Zum Schluss nehmen wir noch den angebotenen Quickfix in Anspruch und lassen den ungenutzten Resolver entfernen. Schon steht die neue Syntax. Die finale Syntaxdefinition sollte wie folgt aussehen.

 

013 FinaleSyntax

Über einen Start des DSL Projektes als Eclipse Application lässt sich nun bereits eine SVG Grafikbeschreibung wie die Folgende formulieren.

014 FinaleSyntaxInstanz

Anbei noch die letzten Schritte als Video zusammengefasst.

Damit ist der erste Teil des Tutorials beendet. Ich hoffe es hat Spaß gemacht zu sehen wie einfach eine eigene DSL geschrieben werden kann. Nun wünsche ich viel Freude beim Ausprobieren und Schreiben Eurer eigenen DSLs. Falls Ihr zu dem Thema Open Source Projekte im Internet startet würde ich mich über einen Kommentar mit Link zum Projekt freuen.

Im nächsten Teil des Tutorials [DSL-2] werden wir mittels Acceleo für die hier definierte DSL einen Generator bauen. Mit dem Generator sind wir dann in der Lage aus einer Grafikbeschreibung in unserer DSL per Rechtsklick eine svg Datei zu erzeugen. Richtig Sinn macht dieses Vorgehen natürlich erst, wenn die DSL leistungsfähiger als ein herkömmlicher SVG Editor ist. Eine solche Erweiterung ist aber zu groß für dieses Tutorial. Von daher probiert doch einfach selbst aus die DSL um Konstrukte zu erweitern, mit denen Grafikobjekte zu neuen Objekten gruppiert werden können. Wird eine entsprechende große Bibliothek aufgebaut, ist es dann auf diese Weise recht einfach komplexe Grafiken in SVG zu erstellen.

Weiter geht es mit [DSL-2].

Quellennachweise

 

[DSL-2]
https://funthomas424242.wordpress.com/2011/10/16/dsl-tutorial-teil-2/
[EMFText einsetzen]
Entwickler Blog auf www.funthomas424242.wordpress.com
[SVG]
href=“http://de.wikipedia.org/wiki/Scalable_Vector_Graphics&#8220;
[EMFText Screencast]
http://www.emftext.org/index.php/EMFText_Getting_Started_Screencast

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 .