Software Factories Skript zur Lehrveranstaltung Hartmut Fritzsche Hochschule für Technik und Wirtschaft Dresden Fakultät Informatik/Mathematik 11. Januar 2016 Inhaltsverzeichnis 1 Grundlagen der Softwaretechnik 1.1 Der Softwareentwicklungsprozess . . . . . . . . . . . . . . . . . . . . 1.1.1 Die Phasen des Softwareentwicklungsprozesses . . . . . . . . 1.1.2 Prozessmodellierung . . . . . . . . . . . . . . . . . . . . . . . 1.1.3 Konfigurationsmanagement . . . . . . . . . . . . . . . . . . . 1.1.3.1 Verwaltung von Konfigurationselementen: Mercurial 1.1.3.2 Build-Management . . . . . . . . . . . . . . . . . . . 1.2 Methodologie der Softwareentwicklung . . . . . . . . . . . . . . . . . 1.2.1 Objekttechnologie/UML . . . . . . . . . . . . . . . . . . . . . 1.2.2 Agile Softwareentwicklung/eXtreme-Programming . . . . . . 1.2.3 Generatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Softwareentwicklungswerkzeuge . . . . . . . . . . . . . . . . . . . . . 1.3.1 CASE-Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.2 Die Plattform Eclipse . . . . . . . . . . . . . . . . . . . . . . 1.3.2.1 Installieren neuer Software (Features, Plug-ins) . . . 1.3.2.2 Entwicklung von Java-Applikationen . . . . . . . . . 1.3.2.3 Unterstützung der UML . . . . . . . . . . . . . . . . 2 Werkzeugentwicklung mit Eclipse 2.1 Plug-ins . . . . . . . . . . . . . . . . . . . . . 2.2 Technologie zur Entwicklung von Plug-ins . . 2.3 Kommunikation zwischen Plug-ins . . . . . . 2.3.1 Erstellen des ersten Plug-ins . . . . . 2.3.2 Erstellung eines Plug-ins, welches vom werden kann . . . . . . . . . . . . . . 2.3.3 Testen der Kommunikation . . . . . . 2.4 Features und Update-Sites . . . . . . . . . . 2.4.1 Features erzeugen . . . . . . . . . . . 2.4.2 Erzeugung einer Eclipse-Update-Site . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ersten Plugin aufgerufen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 4 8 8 8 8 9 9 9 10 10 10 11 12 13 13 . . . . 16 16 19 38 38 . . . . . 40 41 43 43 47 INHALTSVERZEICHNIS 2.5 2.6 2 Entwicklung von RCP-Applikationen . . . . . . . . . . . . . . . . . . . . 51 Eclipse: Produkt und Applikation . . . . . . . . . . . . . . . . . . . . . . 53 3 Modellgetriebene Softwareentwicklung 3.1 Modelle und Modellebenen . . . . . . . . . . . . . . . . . . . . . 3.2 Definition und Verarbeitung formaler Sprachen . . . . . . . . . . 3.2.1 Formale Sprachen (Wiederholung) . . . . . . . . . . . . . 3.2.2 Abstrakte und konkrete Syntax . . . . . . . . . . . . . . . 3.2.3 Semantik . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.4 Lexikalische und syntaktische Analyse . . . . . . . . . . . 3.3 MOF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 Domänenspezifische Sprachen . . . . . . . . . . . . . . . . . . . . 3.5 Plattformen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6 Werkzeuge zur Metamodellierung: EMF . . . . . . . . . . . . . . 3.6.1 Einführungsbeispiel . . . . . . . . . . . . . . . . . . . . . 3.6.2 Erstellung von EMF-Modellen aus UML-Diagrammen . . 3.6.3 Erstellen von EMF-Modellen mit Hilfe des Ecore-Editors 3.7 Modellaustausch . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Werkzeuge zur Unterstützung der MDSD 4.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Xtext . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1 Installation . . . . . . . . . . . . . . . . . . . . . 4.2.2 Erstes Anwendungsbeispiel . . . . . . . . . . . . 4.2.3 Zweites Anwendungsbeispiel . . . . . . . . . . . . 4.2.4 Die Xtext-Grammatiksprache . . . . . . . . . . . 4.3 Xtend . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 Die Sprache Xtend . . . . . . . . . . . . . . . . . 4.3.2 Entwicklung eines Code-Generators mit Xtend . 4.3.3 Beispiel . . . . . . . . . . . . . . . . . . . . . . . 4.4 Xpand . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.5 Aspektorientierte Programmierung . . . . . . . . . . . . 4.6 Grafische Beschreibung einer DSL . . . . . . . . . . . . 4.6.1 GMF . . . . . . . . . . . . . . . . . . . . . . . . 4.6.2 Beispiel . . . . . . . . . . . . . . . . . . . . . . . 4.6.3 Beispiel: Erstellen eines grafischen Klasseneditors 4.7 AndroMDA . . . . . . . . . . . . . . . . . . . . . . . . . 4.7.1 Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 60 61 61 65 65 65 73 73 74 74 75 91 95 97 . . . . . . . . . . . . . . . . . . 99 99 101 102 102 105 107 110 110 110 112 114 115 117 117 118 118 119 119 INHALTSVERZEICHNIS 5 Software Factories 5.1 Der Begriff „Software Factory” . . . . . . . . . 5.2 Anforderungen an eine Factory . . . . . . . . . 5.3 Ein Fallbeispiel: Architektur von Java-Enterprise-Applikationen 5.3.1 DSL . . . . . . . . . . . . . . . . . . . . 5.3.2 Konzept . . . . . . . . . . . . . . . . . . 5.3.3 Implementierung . . . . . . . . . . . . . 5.3.4 Installation der Factory . . . . . . . . . Literaturverzeichnis 3 120 . . . . . . . . . . . . . . 120 . . . . . . . . . . . . . . 121 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 122 124 124 127 128 Kapitel 1 Grundlagen der Softwaretechnik Ziel dieses Kapitels ist die Schaffung einer einheitlichen fachlichen Basis - hinsichtlich Begrifflichkeit, Methodenwissen und Fähigkeiten zur Werkzeuganwendung - für die Behandlung der Themen, die nachfolgend Gegenstand der Lehrveranstaltung „Software Factories” sind. Im praktischen Teil basiert die Lehrveranstaltung ausschließlich auf Open-SourceProdukten. Das bedeutet aber nicht, dass auch alle in der Lehrveranstaltung entwickelten Produkte Open-Source-Produkte sein werden. 1.1 1.1.1 Der Softwareentwicklungsprozess Die Phasen des Softwareentwicklungsprozesses Der Softwareentwicklungsprozess (SEP) lässt sich als Menge von Aktivitäten definieren, die zur Produktion eines Softwaresystems führen (vgl. [Som07], S. 94). Dabei sind folgende Fälle zu unterscheiden: 1. es handelt sich um eine komplette Neuentwicklung, 2. bestehende Systeme werden erweitert bzw. verändert (Rekonstruktion, Refactoring), 3. Systemkomponenten werden konfiguriert oder integriert, 4. Konsistenz- und Äquivalenzprüfungen auf verschiedenen Abstraktionsstufen (Validation und Verifikation). Für die Beschreibung des Softwareentwicklungsprozesses existieren Lebenszyklusmodelle, Vorgehensmodelle und Phasenmodelle (V-Modell, vgl. Abb. 1.1.1). Grundlegende Abläufe, die alle Softwareentwicklungsprozesse gemeinsam haben, sind: 4 KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK 5 • Analyse (Definition der Anforderungen) • Entwurf (Spezifikation, Definition der Funktion und der Constraints, Algorithmenentwurf), • Implementierung (Algorithmenentwurf, Erstellung der Software, die der Spezifikation genügt, weitestgehend Generierung) • Validation und Verifikation (entwicklungsbegleitend und phasenübergreifend, Nachweise für Konsistenz und Äquivalenz auf verschiedenen Entwicklungsstufen, Test) • Evolution (Wartung, Weiterentwicklung, Anpassung an Kundenwünsche) Abbildung 1.1.1: V-Modell Kernaktivitäten der Analysephase sind die Problemdefinition, die Anforderungsanalyse, die Anforderungsdefinition (mit Lastenheft und Pflichtenheft), Aufwands- und Risikoabschätzungen, Festlegung des Vorgehens. Die Analysephase bei Einsatz der Objekttechnologie schließt die objektorientierte Analyse ein. In der Entwurfsphase werden die Systemarchitektur und die Softwarearchitektur festgelegt. Die Entwurfsphase schließt den objektorientierten Entwurf ein. Abbildung 1.1.2 zeigt den traditionellen, Code- bzw. Programmzentrierten SEP im Überblick. Das „Werkzeug” Compiler besteht aus einem Frontend und einem Backend. Der Syntaxbaum (allgemein ein Graph) bildet die zentrale Datenstruktur (vgl. Abb. 1.1.3). KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK 6 Abbildung 1.1.2: SEP - Programm-zentriert: Ps - Quellprogramm, Sp - Programmspezifikation, PT - Zielprogramm, RError - Fehlerbericht, RT est - Testbericht KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK Abbildung 1.1.3: SEP - Programm-zentriert 7 KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK 1.1.2 8 Prozessmodellierung Die Prozessmodellierung im Software Engineering befasst sich damit, Teile des Softwareentwicklungsprozesses zu modellieren und damit zu automatisieren. Versuche, den gesamten Softwareentwicklungsprozess umfassend zu automatisieren, waren bisher wenig erfolgreich. Die am besten verstandene Form der Automatisierung bezieht sich auf das Übersetzen, Verbinden und Laden von Programmen, geht also vom Quelltext aus. Andererseits sind heute Modelle verschiedener Art (UML-Diagramme) als Ausgangspunkt der Programmerzeugung Stand der Technik. Es ist deshalb sinnvoll, zwischen Codezentrierter und Modellzentrierter Entwicklung unterschieden. 1.1.3 Konfigurationsmanagement Für diesen Abschnitt dient [Pop06] als Quelle. Ziele des Konfigurationsmanagements (KM): • Im SEP entstehende Artefakte sicher verwalten • Zugriffskontrolle für verteilt arbeitende Entwickler • Kontrolle über Veränderungen an Artefakten im Laufe der Entwicklung Das KM umfasst Aufgaben wie • die Kontrolle der entwickelten Quellprogramme • die Bereitstellung von „Build“-Funktionalität • das Release-Engineering 1.1.3.1 Verwaltung von Konfigurationselementen: Mercurial Als ein neueres Versionsverwaltungssystem wird nachfolgend Mercurial betrachtet. Für Mercurial steht ein Kommandozeilen-orientiertes Werkzeug zur Verfügung (alle Kommandos beginnen mit hg, vgl. http://mercurial.selenic.com/, Distributionen sind plattformspezifisch). Dieses System wird in einem online verfügbaren Buch von Bryan O’Sullivan beschrieben. Eine integrierte Webschnittstelle steht ebenfalls zur Verfügung. Drittanbieter stellen grafische Frontends oder Plug-ins für Entwicklungsumgebungen zur Verfügung. 1.1.3.2 Build-Management Hier wird wesentlich auf ANT und Maven fokussiert. KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK 1.2 9 Methodologie der Softwareentwicklung Gegenstand der nachfolgenden Betrachtungen ist die Methodik zur Entwicklung von Anwendungssystemen. Programmcode soll vorrangig nicht mehr “per Hand” als Quellcode geschrieben werden. Modelle repräsentieren Spezifikationen verschiedener Aspekte der zu entwickelnden Software. Modelle dienen als Ausgangspunkt für die Generierung von Quellcode und ausführbarem Code während eines Build-Prozesses, wir sprechen von Modellgetriebener Softwareentwicklung (MDSD). Zunehmende Bedeutung hat das Roundtrip Engineering erlangt (vgl. Abb. 1.2.1). Diagramme als grafische Darstellungen und Quellcode sind gleichermaßen Repräsentationen von Modell-Aspekten eines zu entwickelnden Anwendungssystems. Dabei führen Änderungen der grafischen Darstellung zu Änderungen am Modell und über das Modell zu Änderungen im Quell-Code und umgekehrt werden Codeänderungen unmittelbar im Modell verortet und führen zu Änderungen grafischer Darstellungen. Erreicht wird ein Roundtrip Engineering dadurch, dass ein Syntaxbaum (Syntaxgraph) die zentrale Datenstruktur bildet (die das Modell verkörpert), auf den alle Änderungen abgebildet werden und der jeweils Änderungen in die konkrete Darstellung überführt. 1.2.1 Objekttechnologie/UML Die Objekttechnologie gibt eine technische Unterstützung für verschiedene Abstraktionen und für die Darstellung von Verhalten. • Klassen-Instanzen-Abstraktion • Generalisierung-Spezialisierung • Assoziationen zwischen Klassen Die UML ist zu einem Standard zur Modellierung auf der Basis der Objekttechnologie geworden. Diagramme visualisieren Ausschnitte aus bzw. Sichten auf Modelle. Die UML ist eine grafische Sprache, die auch zur Metamodellierung geeignet ist, d.h. die Konzepte der UML lassen sich mit der UML selbst beschreiben. 1.2.2 Agile Softwareentwicklung/eXtreme-Programming Ziel der Agilen Softwareentwicklung ist es, den Softwareentwicklungsprozess gegenüber herkömmlichen Vorgehensmodellen „beweglicher” zu machen. eXtreme Programming ist ein Beispiel für Agile Softwareentwicklung. KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK 10 Abbildung 1.2.1: SEP - Roundtrip Engineering 1.2.3 Generatoren Generatoren spielen Traditionell bei der Herstellung von Werkzeugen für die Verarbeitung von Programmiersprachen eine wichtige Rolle (Scanner/Parser). 1.3 1.3.1 Softwareentwicklungswerkzeuge CASE-Tools Softwareentwicklungsumgebungen (SEU) sind komplexe Werkzeugverbünde, die für die Entwicklung von Software eingesetzt werden und die in der Regel alle Phasen des Softwareentwicklungsprozesses unterstützen. Solche Verbünde von Werkzeugen werden oft auch als CASE (Computer Aided Software Engineering) bzw. CASE-Tools bezeichnet. Case-Tools werden in „upper CASE” und „lower CASE” klassifiziert. „lower CASE”Umgebungen unterstützen die „späten” Pasen der Softwareentwicklung (hauptsächlich Implementation und Test) und sind damit im wesentlichen Programmierumgebungen. „upper CASE”-Umgebungen unterstützen insbesondere die „frühen” Phasen der Softwareentwicklung. KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK 11 SEU, die Werkzeuge für unterschiedliche Sprachen und Zielplattformen integrieren bzw. die Integration ermöglichen, werden als IDE (Integrated Development Environment) bezeichnet. Eine Liste freier und proprietärer integrierter Entwicklungsumgebungen ist unter http://de.wikipedia.org/wiki/Liste_von_integrierten_Entwicklungsumgebungen veröffentlicht. Die Lehrveranstaltung baut wesentlich auf der Entwicklungsplattform Eclipse auf. Als Werkzeug zur Modellierung wird TOPCASED verwendet, das die UML unterstützt. 1.3.2 Die Plattform Eclipse Eclipse ist eine der meist genutzten Integrierten Entwicklungsumgebungen (IDE - Integrated Development Environment) und Open Source-Software (EPL - Eclipse Public License) [Ecl]. Aktuell verwendet wird zu Beginn des Jahres 2011 die Eclipse Version 3.6.1- Helios. Eclipse ist keine Softwareentwicklungsumgebung (SEU) im herkömmlichen Sinne. Es ist eine Plattform, die zu einer komfortablen Softwareentwicklungsumgebung erweitert werden kann. In der Lehrveranstaltung wird Eclipse Helios (3.6) verwendet. Eine onlineDokumentation mit zahlreichen Hilfe-Themen steht unter http://help.eclipse.org/helios/index.jsp bereit. Zu installieren ist zunächst ein Eclipse SDK. Es umfasst: • die Eclipse-Plattform, • Werkzeuge zur Java-Entwicklung (Java Development Tools - JDT ), • eine Umgebung zur Entwicklung von Plug-ins (Plug-in Development Environment - PDE). Eclipse basiert auf einer „Plug-in”-Technologie, die es erlaubt, ein System zur Laufzeit (d.h. ohne neu zu compilieren) um vorgefertigte Komponenten zu erweitern, wenn sie eine vorgegebene Schnittstellenkonvention erfüllen. Das Konzept der Plug-ins kennt Erweiterungspunkte (engl. extension points) und Erweiterungen (engl. extensions). Erweiterungen sind Applikationen, die in Erweiterungspunkte „eingehängt” werden können. Solche Erweiterungen können ihrerseits wieder Erweiterungspunkte anbieten. Das System Eclipse selbst besteht bereits weitgehend aus Plug-ins. Was übrig bleibt, wenn man alle Plug-ins wegnimmt, ist ein Kern. Auch das grafische Benutzerinterface (GUI) von Eclipse ist ein Plug-in. Abb. 1.3.2 zeigt die Architektur von Eclipse. KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK 12 Abbildung 1.3.1: Eclipse-Helios Hilfe - Themenübersicht Eclipse besteht aus Subsystemen (und Plug-ins sind), die auf einer Runtime-Maschine arbeiten. Der Begriff „Workbench” wird in Eclipse zur Bezeichnung der Desktop-Entwicklungsumgebung verwendet. SWT ist das (open source) Standard Widget Toolkit für Java. JFace ist ein UI-Framework und enthält Klassen, die von UI-Plug-ins benötigt werden. Team ist ein Subsystem zur Unterstützung der Versionsverwaltung. Die meisten Komponenten von Eclipse sind Plug-ins (vgl. Kapitel 1.3.3). Abb. 1.3.3 zeigt das GUI der um Plug-ins zur Unterstützung der UML erweiterten Eclipse-IDE (Topcased) in einer Perspektive, in der die Herstellung von UMLDiagrammen unterstützt wird. 1.3.2.1 Installieren neuer Software (Features, Plug-ins) Viele Komponenten (Features, Plug-ins) stehen bei http://www.eclipse.org/downloads/ zum Download bereit. Plug-ins können auf unterschiedliche Art und Weise zur Nutzung KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK Abbildung 1.3.2: Architektur http://help.eclipse.org/helios/index.jsp) von Eclipse 13 (Abb. nach bereitgestellt werden: 1. es wird ein bereits spezialisiertes Eclipse aus dem Netz installiert (Beispiel Topcased), 2. direkt aus Eclipse heraus: Zunächst Help →Install New Software... und Angabe des entfernten Download-Archives oder 3. download von Installationsdateien und Ausführen (im Falle von .jar-Archiven oder Speichern in die Ordener Plugin und Features oder 4. Platzierung in einem separaten, Produkt-spezifischen Verzeichnis und Erzeugung eines Link-Files, so dass Eclipse die Plug-ins findet. Die zuletzt aufgeführte Variante eignet sich besonders gut, wenn ein Plug-in in verschiedenen Eclipse-Installationen genutzt werden soll. 1.3.2.2 Entwicklung von Java-Applikationen Die Entwicklung von Java-Applikationen - beginnend mit der Erstellung von JavaQuelltexten - erfolgt in der Java-Perspektive. 1.3.2.3 Unterstützung der UML Zur Unterstützung der UML 2 in Eclipse gibt es verschiedene Erweiterungen. Wir beschreiben nachfolgend eine auf EMF basierende Erweiterung zu Eclipse, die eine Implementierung des UML 2.1.1 - Metamodells darstellt. KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK 14 Abbildung 1.3.3: Eclipse in der TOPCASED-Perspektive Ein Werkzeug, das die Erstellung von UML-Diagrammen in Eclipse unterstützt, ist das Plug-in UML2-Tools. Dazu ist mittels des Update-Managers die aktuelle Version der UML2-Tools zu installieren (vgl. Abb. 1.3.4): Help → Install New Software ... → unter Work with eintragen: http://download.eclipse.org/modeling/mdt/updates/releases/ KAPITEL 1. GRUNDLAGEN DER SOFTWARETECHNIK Abbildung 1.3.4: Installation MDT 15 Kapitel 2 Werkzeugentwicklung mit Eclipse In dieser Lehrveranstaltung liegt der Fokus auf der Entwicklung von Anwendungen, die Werkzeuge für die Softwareentwicklung sind. Nachfolgend soll die Entwicklung von Softwareentwicklungswerkzeugen auf zwei unterschiedlichen Wegen betrachtet werden: 1. Die IDE Eclipse wird selbst als Softwareentwicklungswerkzeug weiter spezialisiert. Dazu werden Plug-ins entwickelt und integriert, die bereits bestehende Erweiterungspunkte nutzen und so die Workbench erweitern. 2. Es werden Applikationen entwickelt, die nur den minimalen Kern von Eclipse nutzen und diesen um Plug-ins erweitern. Die minimale Menge von Plug-ins, die für die Erzeugung einer Client-Applikation erforderlich ist, wird als Rich Client Platform (RCP) bezeichnet. Dazu werden zwei Plug-ins und deren Voraussetzungen benötigt: org.eclipse.ui und org.eclipse.core.runtime. Mehr über RCP erfährt man unter http://wiki.eclipse.org/index.php/Rich_Client_Platform. Anwendungen der zweiten Art können insbesondere eine eigene Art von GUIs besitzen, die von der Eclipse-GUI verschieden sein kann. Für beide Fälle ist es erforderlich, zunächst das Konzept der Plug-ins kennen zu lernen. Der Inhalt dieses Kapitels basiert im wesentlichen auf dem Buch eclipse Plug-ins von E. Clayberg und D. Rubel [CR09]. 2.1 Plug-ins Eclipe besteht aus einem kleinen Kern, der einen Plug-in-Loader enthält, und einer Vielzahl von Plug-ins, die in ihrer Gesamtheit eine Struktur bilden. Der Kern, der die Mechanismen zur Unterstützung der Verarbeitung von Plug-ins enthält, ist eine 16 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 17 Implementation der OSGi R4 -Spezifikation und stellt eine Umgebung bereit, in der Plug-ins ausgeführt werden können. Diese Laufzeitumgebung Equinox ist die Referenzimplementierung von OSGi. Ein Plug-in entspricht in der OSGi-Terminologie einem OSGi-Bundle. Ein Bundle und die zugeordneten Klassen spezifizieren und implementieren den Prozess des Ladens von Java-Klassen und den Lebenszyklus des Bundles. Jedes Plug-in kann auf Diensten aufbauen, die andere Plug-ins bereitstellen. Plug-ins werden bei Bedarf geladen, aber nicht entladen (aus: Platform Plug-in Developer Guide → Programmer’s Guide → Runtime overview → The runtime plug-in model). Das Verhalten von Plug-ins wird in Code beschrieben, Abhängigkeiten und Dienste in den Dateien MANIFEST.MF (darin die „Require-Bundle”-Deklaration) und plugin.xml. Plug-in-Code wird erst geladen, wenn er benötigt wird (lazy loading, „as needed”). Der Plug-in-Loader analysiert die Dateien MANIFEST.MF und plugin.xml und erzeugt für jedes Plug-in eine Struktur, die diese Informationen enthält (nur im workspace). Der Plug-in-Loader instantiiert einen separaten Class-Loader für jedes Plug-in. Erweiterungen (Extensions) und Erweiterungspunkte (Extension Points) werden für jedes Plug-in in der XML-Datei plugin.xml beschrieben. Die Plug-in-Konfiguration und ihre Integration in die Plattform werden in der Datei MANIFEST.MF beschrieben. In dem in Abb. 2.1.1 gezeigten Beispiel hängt sich ein neues Plug-in („BundleSymbolicName” = com.qualityeclipse.favorites ) in den Erweiterungspunkt org.eclipse.ui.views des Plug-ins org.eclipse.ui ein. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.1.1: Struktur von Plug-ins nach [CR09] 18 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 2.2 19 Technologie zur Entwicklung von Plug-ins Um als Anwender selbst Plug-ins entwickeln zu können, muss das Plug-in Development Environment (PDE) in der Eclipse-IDE verfügbar sein. Das PDE-Subprojekt ist in drei Teilprojekte (und entsprechende Komponenten) unterteilt: 1. PDE Build (Ant-basierte Tools und Scripts um den build-Prozess zu automatisieren) 2. PDE UI (eine Menge von Modelllen, Buildern, Editoren und weiteren Werkzeugen, um Plug-ins (bzw. OSGi bundles) zu entwickeln), 3. PDE API Tooling (Unterstützung der Dokumentation und Wartung der API) Zusätzlich gibt es PDE Doc zur Weiterentwicklung der HELP-Dokumentation als übergreifendes Projekt und PDE Incubator für die Entwicklung neuer Werkzeuge, die bisher nicht zum Eclipse SDK gehören. Nachfolgend wird zunächst die Entwicklung eines Plug-ins beschrieben, das die Eclipse-IDE um eine neue Sicht (View) erweitert. Bei der durch Eclipse gesteuerten Erzeugung eines neuen Plug-ins wird auch Programmcode (z.B. für Editoren oder Views) - hier aus bereits vorgefertigten Vorlagen (Templates) - erzeugt. Zur Entwicklung eines neuen Plug-ins sind folgende Aktivitäten erforderlich: 1. Erzeugen eines Plug-in-Projektes 2. Review des generierten Codes (optional) 3. „Build” des Plug-ins 4. Installation und Ausführung des Plug-ins Diese Aktivitäten werden nachfolgend im Detail beschrieben. 1. Erzeugen eines Plugin-Projektes Zum Erzeugen eines Plug-in-Projektes wird typischerweise ein Wizard (mit 5 Schritten) verwendet. Erster Schritt ist das Starten des Wizards: » File → New → Project... (vgl. Abb. 2.2.1) und die Auswahl Plug-in Project. Ein Wechsel in die PDE-Perspektive erfolgt automatisch beim Erzeugen eines PDEProjekts. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 20 Abbildung 2.2.1: Wizard zum Erzeugen eines Plugin-Projektes Im zweiten Schritt wird (vgl. Abb. 2.2.2) • der Projektname (= Plug-in-Identifier) festgelegt, • Create a Java-Project markiert (sonstige Voreinstellungen beibehalten), • die Zielplattform festgelegt (hier Eclipse IDE). Im dritten Schritt wird (vgl. Abb. 2.2.3) • die Versionsnummer festgelegt, hier 1.0.0.1, • der Name des Plug-ins festgelegt, • der Provider festgelegt (kann zunächst entfallen), • festgelegt, dass eine Activator-Klasse generiert werden soll (ein Activator (.classDatei) kontrolliert den Lebenszyklus des Plug-ins, wird benachrichtigt, wenn das Bundle startet oder stoppt), • festgelegt, dass sich das Plug-in auf die grafische Oberfläche von Eclipse beziehen soll, KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 21 Abbildung 2.2.2: Wizard zum Erzeugen eines Plugin-Projektes, Seite 2 • festgelegt, dass das entwickelte Plug-in keine Rich Client Applikation sein soll. Im vierten Schritt kann spezifiziert werden, welche vorgefertigten Code-Stücke integriert werden sollen. Zur Erzeugung von Plug-ins können solche Code-Stücke (Templates) verwendet werden. Das als Beispiel erzeugte Plug-in soll das UI der Eclipse-IDE um eine View erweitern (vgl. Abb. 2.2.4, Plug-in with a view ausgewählt). Im fünften Schritt wird die View genauer definiert (vgl. Abb. 2.2.5): Der „Java Package Name” de.htwdd.sf.favorites ist schon voreingestellt und wird beibehalten. In diesem Package ist später der generierte Programmcode zu finden. FavoritesView als Klassenname und Favorites als View-Name werden eingetragen und ersetzen die Vorgaben. Das vorgegebene Sample Category wird ersetzt durch de.htw-dresden.sf.favorites. Die Boxen „Add the View ...” und „Add context ...” werden unchecked gesetzt (vereinfacht die generierte Manifest-Datei). Nach Klicken von Finish wird zum Schluss der Wechsel in die „Plug-in Development Perspective” mit Yes bestätigt (vgl. Abb. 2.2.6 ). Das Plug-in-Projekt wird erzeugt und der Plug-in-Manifest-Editor wird automatisch geöffnet. Der Plug-in Mani- KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 22 Abbildung 2.2.3: Wizard zum Erzeugen eines Plugin-Projektes, Seite 3 fest Editor wird nach Beenden des beschriebenen Wizards automatisch mit der ersten Seite (Registerkarte) geöffnet (vgl. Abb. 2.2.8). Dieser Editor kann - falls geschlossen später auch jederzeit duch Doppelklick auf MANIFEST.MF im Projektmanager geöffnet werden. Man beachte die Registerkarten („Seiten”) am unteren Rand der Abbildung. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.4: Wizard zum Erzeugen eines Plugin-Projektes, Seite 4 23 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.5: Wizard zum Erzeugen eines Plugin-Projektes, Seite 5 Abbildung 2.2.6: Wizard zum Erzeugen eines Plugin-Projektes, Seite 6 24 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 25 2. Review des generierten Codes Nachfolgend ist die Perspektive Plug-in Development eingestellt. Im Projekt-Manager wird die in Abb. 2.2.7 dargestellte Struktur gezeigt. Im src-Verzeichnis wurden die Packages de.htwdd.sf.favorites und de.htwdd.sf.favorites.views generiert. Abbildung 2.2.7: Sicht des Plug-ins im Projekt-Manager Ein Review der Ergebnisse der Generierung des Projektes wird anhand der Registerkarten des Plug-in Manifest Editors durchgeführt. Jedes erzeugte Plug-in hat ein Verzeichnis/eine Datei META-INF/MANIFEST.MF. Im Projekt-Verzeichnis können sich außerdem eine Datei plugin.xml und eine .class-Datei befinden. Eine zentrale Datenstruktur in jedem Plugin ist der Plug-in Descriptor, als Datei plugin.xml gespeichert. Darin werden wesentliche Eigenschaften festgelegt (vgl. Abb. 2.2.9): • der Plugin-Name, • der Classpath, • benötigte Extensions, • implementierte Extensions, • selbst publizierte Extension-Points, • etc. Die Datei plugin.xml kann mit dem Plugin-Manifest-Editor bearbeitet werden (entsprechende Registerkarte). Für das Favorietes-Plug-in ist die Datei plugin.xml in Abb. 2.2.10 dargestellt. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.8: Plug-in-Manifest-Editor, Übersichtsseite Ein Plug-in kann als .jar-File (Java-Archiv) abgespeichert werden. 26 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.9: Bild aus der Eclipse Slide Show Abbildung 2.2.10: Datei plugin.xml für das Favorites-Plug-in 27 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 28 Im MANIFEST.MF (vgl. Abb. 2.2.11) werden Abhängigkeiten beschrieben. Die Angaben beziehen sich auf die Laufzeit der Plug-ins, sollten aber mit dem build-Pfad synchronisiert sein. Die in der Übersichtsseite des Plug-in-Manifest-Editors gezeigten Informationen entsprechen den Einträgen in MANIFEST.MF. Abbildung 2.2.11: Plug-in-Manifest-Editor: MANIFEST.MF Die ersten zwei Zeilen definieren die Datei als OSGi Manifest Datei. Danach sind der Plug-in-Name, die Version etc festgelegt. Reqire-Bundle enthält die Namen der Plug-ins, die von dem neuen Plug-in benötigt werden (auf denen es aufbaut, von denen es abhängt). Die Activator-Klasse beschreibt, wie sich das Plug-in beim Laden und Beenden verhalten soll. Die Klasse heißt im Beispiel Activator und ist von AbstractUIPlugin abgeleitet. Im Beispiel wird beim Erzeugen des Plug-in-Projekts auch Code für eine einfache View generiert. Die Klasse heißt FavoritesView und wird von ViewPart abgeleitet. Auf der Dependencies-Seite wird gezeigt, welche Plug-ins zum Laufen des Plug-ins erforderlich sind (vgl. Abb. 2.2.12). Diese Angaben entsprechen den Zeilen 8 und 9 des Manifests (vgl. Abb. 2.2.11). Es ist zu beachten, dass diese Angaben verschieden von denen im Java-Classpath sind. Die Angaben im Classpath werden zur Compilezeit ausgewertet, während die KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 29 Abbildung 2.2.12: Manifest Editor, Seite „Dependencies” Dependencies-Angaben während der Ausführung des Plug-ins ausgewertet werden. Die Dependencies-Angaben wirken sich auf den Build-Pfad aus, aber nicht umgekehrt. Die Registerkarte Runtime (vgl. Abb. 2.2.13) korrespondiert mit dem Bundle-ClasspathAbschnitt der Manifest-Datei. Speziell für das Favorites-Plug-in sind keine Deklarationen erforderlich. Es werden keine Packages exportiert. Die Registerkarte Extensions zeigt die implementierten Extensions (vgl. Abb. 2.2.14). Die Angaben korrespondieren mit den Extension-Angaben in der Datei plugin.xml. Es wird gezeigt, dass die Extension am Extension-Point org.eclipse.ui.views hängt. Bei Auswahl eines Eintrags auf der linken Seite werden rechts im Fenster die zugeordneten Eigenschaften gezeigt. Die Angaben korrespondieren wieder mit den Einträgen in der plugin.xml-Datei. Die Registerkarte Extension Points zeigt die Definition neuer Extension Points. Das Favorites-Plug-in definiert keine Extension Points. Die Activator-Klasse Activator.java enthält den Programmcode, der das Plug-in steuert. Im Beispiel des Favorites-Plug-ins hat sie den in Abb. 2.2.15 gezeigten Inhalt. Das Eclipse-System instantiiert die Activator-Klasse, bevor irgendwelche Klassen geladen werden. Diese Activator-Instanz wird während des gesamten Lebenszyklus des Plug-ins benutzt, es wird keine andere Instanz erzeugt (Singleton). Die static-Variable plugin bekommt eine Referenz auf das Singleton zugewiesen. UI-basierte Plug-ins besitzen einen Activator, der von AbstractUIPlugin abgeleitet ist, Nicht-UI-basierte Plug-ins sind von Plugin abgeleitet. Der Wizard „New Plug-in Project” hat außerdem Code für eine einfache View generiert (vgl. Abb. 2.2.16, 2.2.17). Die View erzeugt und visualisiert Informationen von einem einfachen Modell. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.13: Manifest Editor, Seite Runtime Abbildung 2.2.14: Manifest Editor: Extensions von Favorites 30 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.15: Activator-Klasse 31 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.16: View von Favorites (1) 32 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.17: View von Favorites (2) 33 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.18: View von Favorites (3) 34 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.2.19: View von Favorites (4) Abbildung 2.2.20: View von Favorites (5) 35 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 36 3. „Build” des Plug-ins Das Build kann manuell oder mittels eines ANT-Scipts (oder eines anderen Skripts) erfolgen. Das Endprodukt kann als komprimiertes File (mit oder ohne Quelltexte) geliefert werden. 1. Manuelles Build: Ein Start des build-Prozesses erfolgt mittels des Export-Wizards, der mittels » File → Export gestartet wird. Auf der ersten Wizard-Seite wird Deployable plug-ins and fragments ausgewählt. Auf der 2. Seite des Export-Wizards werden die zu exportierenden Plug-ins ausgewählt und der Name des zip-Files festgelegt, das das Ergebnis enthält. Im Beispiel wird ein .zip-File erstellt, das ein .jar-File enthält. 2. Alternativ zur manuellen Erzeugung des Plug-ins wird ein ANT-Script erstellt. Der Export-Wizard generiert ein ANT-Skript, das für das Favorites-Beispiel in der Datei build-favorites.xml in de.htwdresden.sf.favorites enthalten ist. Um das ANT-Skript auszuführen, ist ein Rechtsklick auf die Datei build-favorites.xml auszuführen und die Option Run in the same JRE as the workspace zu wählen. Die durch Build erzeugte .jar-Datei enthält • Klassen (.class-Dateien, inklusive Package-Struktur) • Image-Dateien in einem Verzeichnis icons (falls benötigt), sie werden in pugin.xml oder in .class-Dateien referenziert • MANIFEST.MF (beschreibt Laufzeitaspekte) • plugin.xml (beschreibt extensions und extension points) 4. Installation und Ausführung des Plug-ins Um das Plug-in auszuführen (zu testen), gibt es zwei Möglichkeiten. 1. Nutzung der Debug-Umgebung mit dem im Workspace entwickelten Plug-in 2. Beenden und Neustart von Eclipse Zu (1): • Erzeugung einer Debug-Konfiguration Zu (2): KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 37 • Beenden von Eclipse • Entpacken des .zip-Files in das Eclipse-Verzeichnis (z.B. C:/eclipse). Das Plug-in soll anschließend im /plugins-Verzeichnis sein. Beispiel: C:/eclipse/plugins/com.qualityeclipse.favorites_1.0.0.jar • Neustart von Eclipse Um das Plugin "In Aktion" zu erleben, muss der Punkt "Launch an Eclipse application" ausgeführt werden. Es wird eine neue Eclipse-Umgebung gestartet, mit der man in der Lage ist, die entwickelten Plugins zu testen. Im Falle des Favorite-Plug-ins kann vom Window-Menü Show View > Other... ausgewählt werden, um den neuen Dialog zu öffnen. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 2.3 38 Kommunikation zwischen Plug-ins Dieser Abschnitt beschäftigt sich mit der Entwicklung von zwei Plug-ins mit dem Ziel, die Ansteuerung und Ausführung von Funktionen darzustellen. Aufgabe ist es, beide Plug-ins zu erstellen und diese miteinander kommunizieren zu lassen. Ein Plug-in A ruft über einen definierten Extension Point eine in einer Extension des Plug-ins B definierte Funktion (d.h. JAva-Methode) auf, welche ihrerseits einen einfachen Text anzeigen soll. Dabei ist das den Extension Point definierende Plug-in A als Sender und das die Extension definierende Plug-in B als Empfänger bzw. Ausführender zu betrachten. Das Plug-in B wird als "Ausführbares Plugin" betrachtet, welches bei dem Funktionsaufruf erst instanziiert wird. Um bereits „laufende” Plug-ins zu steuern, müssen deren Instanzen ermittelt werden. Dazu muss allerdings die rufende Funktion des Extension Point-Plug-ins modifiziert werden. 2.3.1 Erstellen des ersten Plug-ins Nach der Erzeugung eines neuen Plug-in-Projektes kann ein Extension Point definiert werden. Beispiel: Erzeugen eines Plug-in-Projektes mit dem Namen de.htwdd.sf.provider, „Activator generieren” auswählen, „contributions to UI” auswählen, Template „Hello, World” auswählen. Nach Beenden des Wizards sind bereits auch .class-Dateien erzeugt worden. Die über das Template vordefinierte Klasse SampleAction enthält zunächst Code, um ein Fenster zu öffnen und darin einen Text anzuzeigen. Die Definition des Extension Points erfolgt mittels des Eclipse-Manifest-Editors über die Registerkarte „Extension Points”. Der Extension Point wird mit add ... hinzugefügt und erhält die ID de.htwdd.sf.extensionpoint.aufruf sowie den Namen "Aufruf". Die Eingabe der Daten bestätigen wir mit "Finish" und sehen im Anschluss die Übersicht des neuen Extension Points. Um die Definition des Punktes einzusehen, muss nach Öffnen des Extension Point Schemas (→ „Open extension point schema”) der untere Reiter "Definition" gewählt werden. Es wird ein neues Element mit dem Namen „client” erstellt („extension” auswählen → „new element”) und ein Attribut mit dem Namen „class” („client” auswählen → „new attribute”) und dem Typ „java” hinzugefügt (vgl. Abb) 2.3.1. Die Klasse soll das Interface IAufruf implementieren, de.htwdd.sf.provider.IAufruf (im Bild wurde statt dessen de.htwdd.sf.prakt.prov1.IAufruf verwendet) kann aber erst ausgewählt werden, nachdem es angelegt wurde. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 39 Abbildung 2.3.1: Festlegen der Eigenschaften des definierten Extension Points Deshalb wird das Interface IAufruf im Quellcode-Verzeichnis zunächst hinzugefügt (vgl. Abb. 2.3.2), anschließend erfolgt dann der Eintrag hinter „Implements”. Abbildung 2.3.2: Bereitstellen des Interfaces IAufruf im Provider Abb. 2.3.3 zeigt die Interface-Datei. Nachdem das Plug-in erstellt wurde, ist ein Build durchzuführen. Mittels Export ... kann ein Verzeichnis (oder alternativ eine .zip-Datei) erzeugt werden, das (die) das Plugin als .jar Datei enthält. Der Dateiname wird wie folgt gebildet: <Plug-in-Name>_<versionsnummer>.jar . Die Methode run(IAction action) der Klasse SampleAction ist zu erweitern und wird wie folgt realisiert: Der Code in diesem Codefragment bewirkt, dass (nach Klicken auf „OK” im Frame) in allen Plug-ins nach dem Extensionpoint de.htwdd.sf.extensionpoint.aufruf gesucht wird und für den gefundenen Extensionpoint dessen Funktion aufruf() aufge- KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 40 package de . htwdd . s f . p r a k t . prov1 ; public i n t e r f a c e I A u f r u f { void a u f r u f ( ) ; } Abbildung 2.3.3: Interface-Datei IAufruf.java rufen wird. 2.3.2 Erstellung eines Plug-ins, welches vom ersten Plugin aufgerufen werden kann Zunächst erstellen wir ein vorlagenloses Plug-in Project mit dem Namen de.htwdd.sf.Usage. Um den ExtensionPoint des ersten Plugins nutzen zu können, muss die Abhängigkeit von diesem angegeben werden. Diese Einstellung ist unter "Dependencies" vorzunehmen. Dort fügen wir Plugin "de.htwdd.sf.Provider" hinzu (nach Eingabe „de” im Textfeld des Wizards werden Plug-ins angegeben, dort auswählen). Danach ist unter „Extensions” der Extension Point de.htwdd.sf.extensionpoint.aufruf hinzuzufügen. Als letzter Schritt ist eine Klasse ExternerAufruf hinzuzufügen, der die Funktion Aufruf() implementiert. Der Quellcode kann wie folgt aussehen: public class ExternerAufruf implements IAufruf { public void Aufruf () { System . out . println ( " Aufruf des Plug - ins de . htwdd . sf . Usage " ); Display display = Display . getDefault (); Shell shell = new Shell ( display ); shell . setText ( " Aufruf des Plug - ins " ); shell . setBounds (100 ,100 ,200 ,50); shell . setLayout ( new FillLayout ()); Label label = new Label ( shell , SWT . CENTER ); label . setText ( " Aufruf des Plug - ins " ); shell . open (); while (! shell . isDisposed ()){ if (! display . readAndDispatch ()) display . sleep (); } display . dispose (); } } KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 41 public void run ( I A c t i o n a c t i o n ) { MessageDialog . openInformation ( window . g e t S h e l l ( ) , " Provid1 " , " H e l l o , E c l i p s e world " ) ; try { IConfigurationElement [ ] c o n f i g = Platform . getExtensionRegistry ( ) . g e t C o n f i g u r a t i o n E l e m e n t s F o r ( " de . htwdd . s f . e x t e n s i o n p o i n t . a u f r u f " ) ; System . out . p r i n t l n ( " In run d e s P r o v i d e r s . . . " ) ; for ( IConfigurationElement e : c o n f i g ) { f i n a l Ob ject o = e . c r e a t e E x e c u t a b l e E x t e n s i o n ( " c l a s s " ) ; i f ( o instanceof I A u f r u f ) { I S a f e R u n n a b l e r u n n a b l e = new I S a f e R u n n a b l e ( ) { @Override public void h a n d l e E x c e p t i o n ( Throwable e x c e p t i o n ) { System . out . p r i n t l n ( " E x c e p t i o n i n c l i e n t " ) ; } @Override public void run ( ) throws E x c e p t i o n { (( IAufruf ) o ) . aufruf ( ) ; } }; SafeRunner . run ( r u n n a b l e ) ; } } } catch ( E x c e p t i o n ex ) { System . out . p r i n t l n ( ex . getMessage ( ) ) ; } } Abbildung 2.3.4: Quelltext der Methode run Es ist zu beachten, dass die Klasse Label aus dem Package org.eclipse.swt.widgets zu verwenden ist (nicht java.awt)! 2.3.3 Testen der Kommunikation Um die Plug-ins in Aktion zu erleben, ist zunächst eine Testumgebung zu konfigurieren (» Run → Run Configurations... → Eclipse Application → New launch configuration ). Danach ist eine neue Eclipse-Instanz zu erzeugen und in deren Oberfläche ist der Menüpunkt » Sample Menu → Sample Action auszuwählen. Die Dialogabfrage in dem sich öffnenden Fenster ist mit „OK” zu bestätigen. Die Ausgaben erscheinen auf der Console der ursprünglichen Eclipse-Instanz. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.3.5: Festlegung der Klasse die IAufruf implementiert 42 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 2.4 43 Features und Update-Sites Features gruppieren Plug-ins und unterstützen so das Laden (load), das Managen (manage) und das Branding (brand, Markenmanagement) der Plug-ins als Einheit („single unit“). Mittels Features können Plug-ins - zusammengepackt - über eine Web-Site zur Nutzung angeboten werden. Für das Laden solcher „single units“ in Eclipse kann der Eclipse Update Manager eingesetzt werden. 2.4.1 Features erzeugen Ein Feature wird mit Hilfe des „New Project”-Wizards als Feature-Projekt erstellt (vgl. Abb. 2.4.1). Als Projektname wird beispielsweise de.htwdd.sf.favorites.feature festgelet. Beim Erzeugen eines Feature-Projektes soll die Feature-ID mit der ID des Haupt-Plugins übereinstimmen. Außerdem wird ein Feature-Name festgelegt (vgl. Abb. 2.4.2). Abbildung 2.4.1: Erstellen eines Feature-Projektes mittels des „New Project”-Wizards Aus der nachfolgend im Wizard angezeigten Liste von Plug-ins werden zum Beispiel zwei Plug-ins ausgewählt (vgl. Abb. 2.4.3). Danach wird der Wizard mit „Finish” abgeschlossen. In einem Feature-ManifestEditor wird die vom Wizard erzeugte Manifest-Datei feature.xml geöffnet (vgl. Abb. 2.4.4). Auf der Seite „Overview” kann unter „Branding Plug-in:” der Name des Plug-ins angegeben werden, das die „Branding Files” des Features enthält. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 44 Abbildung 2.4.2: Feature spezifizieren Die Register-Seite „Information” ermöglicht die Notation von Lizenz-Vereinbarungen, Copyright-Angaben und anderen Angaben. Über die Register-Seite „Plug-ins” werden die als Inhalt des Features vorgesehenen Plug-ins angezeigt (vgl. Abb. 2.4.5). Die Register-Seite „Included Features” enthält eine Liste von Sub-Features. Die Register-Seite „Dependencies” zeigt eine Liste aller Features und Plug-ins, die für das Feature benötigt werden. Fehlen benötigte Features oder Plug-ins, kann das Feature nicht geladen werden. Mittels „Compute” kann die Liste neu erzeugt werden (vgl. Abb. 2.4.6). Mit Hilfe des Export-Wizards (vgl. Abb. 2.4.4) kann das neu erstellte Feature exportiert und anschließend installiert werden, um es zu testen. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.4.3: Auswahl der in das Feature aufzunehmenden Plug-ins Abbildung 2.4.4: Feature-Manifest-Editor 45 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.4.5: Ausgewählte Plug-ins des Features Abbildung 2.4.6: Abhängigkeiten des Features 46 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 2.4.2 47 Erzeugung einer Eclipse-Update-Site Eclipse unterstützt die Web-basierte Verteilung, Installation und das Updaten von Features. Eine Eclipse-Update-Site ist eine speziell konstruierte Web-Site, die entworfen wird, um Features und Plug-ins zu hosten. Eine Update-Site enthält eine spezielle Beschreibung in Form einer Manifest-Datei site.xml. Der Eclipse-Update-Manager kann diese Datei lesen und daraufhin Updates automatisch laden und installieren. Es ist zunächst ein Update Site Project zu erzeugen (vgl. Abb. 2.4.7). Auf der zweiten Wizard-Seite ist „Generate a web page ...” anzuklicken (vgl. Abb. 2.4.8). Abbildung 2.4.7: Wizard zur Erstellung eines Update-Site-Projektes (1) Nach der Erstellung des Projektes können die erzeugten Dateien im Projekt Manager betrachtet werden (vgl. Abb. 2.4.9). Ein Doppelklick auf site.xml öffnet den Site-Manifest-Editor. Jetzt können Features hinzugefügt werden (vgl. Abb. 2.4.11). Sollen mehr als ein Feature auf einer Update-Site bereit gestellt werden, können sie in Kategorien (Category) zusammengefasst werden. Nach Klicken auf ein Feature im „Managing the Site”-Editor können „Feature Properties” und „Feature Environments” angegeben werden. Das erforderliche URL-Feld spezifiziert die Lage des Features auf der Update-Site (relativ zur Lage der site.xml), wo der Update-Manager das jar-File finden soll. Das Klicken auf „Build All” ist notwendig und bewirkt, dass die Verzeichnisse KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 48 Abbildung 2.4.8: Wizard zur Erstellung eines Update-Site-Projektes (2) Abbildung 2.4.9: Update-Site-Projekt features und plugins zum Update-Site-Projekt hinzugefügt werden. Die Archiv-Auswahlkarte beschreibt die Update-Site. und spezifiziert die WebAdresse (vgl. Abb. 2.4.12). KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.4.10: Site-Manifest-Editor Abbildung 2.4.11: Feature Selection 49 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.4.12: „Archives”-Auswahl 50 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 2.5 51 Entwicklung von RCP-Applikationen Eine Basis für diesen Abschnitt bildet [Dau08]. Ein Tutorial ist unter www. eclipse. org/ articles/ Article-RCP-1/ tutorial1. html zu finden. Ein weiteres Tutorial dazu ist www. vogella. com/ articles/ EclipseRCP/ article. html . Die Architektur von Eclipse ist so gestaltet, dass dessen Komponenten zum Bau einer beliebigen Anwendung genutzt werden können. Die minimal erforderliche Menge von Plug-ins (einschließlich deren Voraussetzungen), die zum Bau einer Rich Client Application mit einer grafischen Benutzeroberfläche benötigt wird, wird als Rich Client Platform bezeichnet. Es werden mindestens zwei Plug-ins benötigt: org.eclipse.ui und org.eclipse.core.runtime. Eine Eclipse-RCP-Applikation muss folgende Elemente definieren: • eine Hauptklasse (Hauptprogramm), die das Interface IApplication implementiert. Eclipse erwartet, dass diese Anwendungsklasse über den Extension Point org.eclipse.core.runtime.applications definiert ist. • Eine Perspektive • Workbench-Advisor als unsichtbare technische Komponente. Darüber hinaus sind folgende Konfigurationsdateien erforderlich: • die Datei MANIFEST.MF • die Datei plugin.xml Beispielprojekt Zur Entwicklung einer RCP-Applikation beginnen wir praktisch mit der Entwicklung eines Plug-in-Projektes. Mittels des Wizards legen wir fest: • Projektname: de.htwdd.sf.rcp.firsttool • Auswahl „Rich Client Application”; Optionen: Generierung einer Activator-Klasse, Bezug des Plug-ins zum UI herstellen. • Nutzen der Template-Klasse „Hello RCP” • Anklicken „Add branding” Nach der Generierung des Projektes wird eine Inspektion mit Hilfe des Plug-inEditors durchgeführt. Die Anwendung nutzt folgende Extension Points: KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 52 Abbildung 2.5.1: RCP-Projekt in der Navigator-View • org.eclipse.core.runtime.applications • org.eclipse.ui.perspectives • org.eclipse.core.runtime.products In Abb. 2.5.1 sind die bei der Erzeugung des Plug-in-Projektes generierten Dateien dargestellt. Launch einer Eclipse-Application ( Run → Run Configurations ... ) erzeugt die in Abb. 2.5.2 dargestellte Anwendung. Während des Starts wird durch die Eclipse Runtime überprüft, welche Klasse im Extension Point org.eclipse.core.runtime.applications angegeben ist. Diese Klasse heißt typischerweise Application und implementiert das Interface IApplication. Diese Klasse ist verantwortlich für die Erstellung der SWT-Oberfläche und das Starten der Schleife der Ereignissteuerung. Display display = PlatformUI.createDisplay(); PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor()); KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 53 Abbildung 2.5.2: Launch einer einfachen RCP-Application aus einem Plug-in im Workspace PlatformUI.createAndRunWorkbench( ... ) erzeugt und startet eine Workbench. Die Workbench repräsentiert das grafische User-Interface von Eclipse. Der visuelle Teil der Workbench wird über die Klasse WorkbenchWindow dargestellt. Eine Workbench kann mehrere Objekte vom Typ WorkbenchWindow geöffnet haben. Der innere Teil eines WorkbenchWindow wird über die Klasse WorkbenchPage repräsentiert. Eine einfache SWT-Anwendung erfordert es, die SWT-Bibliothek zum Klassenpfad des Projektes hinzuzufügen. Dies erfolgt in folgenden Schritten: • Öffnen des Properties-Dialogs zum Projekt (über das Kontextmenü) • Java Build Path → Libraries → Add External JARs auswählen • plug-in-Verzeichnis auswählen • org.eclipse.swt.win32.win32 (oder entsprechendes) wählen 2.6 Eclipse: Produkt und Applikation Ein „Produkt” im Verständnis von Eclipse definiert alle Ressourcen, die mit der Applikation geliefert werden. Ein Produkt ist ein Entwicklungs-Artefakt und wird zur Laufzeit nicht benötigt. Die Eclipse-Applikation entspricht der Klasse, die normalerweise die Java- main-Methode enthält. Applikationen werden über den Extension Point org.eclipse.core.runtime.applications definiert und müssen IApplication implementieren. Einem Produkt ist immer eine Applikation zugeordnet. Die Produkt-Konfiguration wird in der Datei .product definiert. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE 54 Abb. 2.6.1 zeigt den Aufruf des Wizards zum Erstellen einer neuen Produktkonfiguration. Abb. 2.6.2 zeigt die im Wizard vorgenommenen Einstellungen. Ein Dateiname ist festzulegen. Hier ist es tool3.product. Abbildung 2.6.1: Erstellen eines Produktes initiieren Nach dem Erstellen der Produktkonfiguration wird automatisch der ProduktkonfigurationsEditor geöffnet (vgl. Abb. 2.6.3). Mittels new ... kann eine neue Produkt-Extension erzeugt werden (Abb. 2.6.4). Das exportierte Produkt (Abb. 2.6.7) kann per Doppelklick auf „eclipse” gestartet werden. KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.6.2: Wizard zum Erstellen einer Produktkonfiguration 55 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.6.3: Produktkonfigurations-Editor 56 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.6.4: Neue Produkt-Extension 57 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.6.5: Export der erzeugten Produktkonfiguration 58 KAPITEL 2. WERKZEUGENTWICKLUNG MIT ECLIPSE Abbildung 2.6.6: Export der erzeugten Produktkonfiguration - Wizard Seite 2 Abbildung 2.6.7: Exportiertes Produkt 59 Kapitel 3 Modellgetriebene Softwareentwicklung 3.1 Modelle und Modellebenen Ein Softwaresystem (Programm, Programmsystem) wird zentral durch ein (Hauptspeicherintern und persistent verwaltetes) Modell repräsentiert. Modell und Programm werden gleichgesetzt, ein Programm ist ein Modell. Das Modell besitzt damit wie das Programm eine Struktur (Syntax - Datenstruktur) und eine Bedeutung (Semantik Verhalten, Interpretation). Dient die Objekttechnologie als Entwicklungsbasis, handelt es sich um Klassen (Situation nach dem Laden zur Ausführungszeit), die den Gegenstandsbereich (die Domäne) des Softwaresystems modellieren. Dabei stellt sowohl der Quelltext als auch die grafische Repräsentation einer Klasse eine erste Abstraktionsebene im Vergleich zur Ausführung des Programmes zur Laufzeit dar. Objekte (jeder Abstraktionsebene) besitzen jeweils eine interne Repräsentation (als Modell bezeichnet). Der Quellcode ist eine der möglichen Sichten (View) auf dieses Modell des Objektes. Klassendiagramme oder Steuerflussgraphen sind andere mögliche Sichten. Unterschiedliche Sichten spiegeln unterschiedliche Aspekte eines Modells wieder. Die OMG hat mit der Model Driven Architecture (MDA) einen Vorschlag zur Standardisierung der MDSD gemacht. Modellierung im Sinne der MDSD unterscheidet mehrere Stufen bzw. Ebenen bezüglich einer Klasse-Instanzen-Abstraktion: • ein Modell (Ebene M1) beschreibt Instanzobjekte (Objekte der Ebene M0). Ein Modell ist in einer (grafischen oder textuellen) Sprache ausgedrückt. Instanzobjekte sind Laufzeitobjekte. • Ein Metamodell (Ebene M2) beschreibt die zur Modellierung verwendbaren Aus60 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 61 drucksmittel. Es definiert die Konstrukte einer Modellierungssprache. Je nach Gegenstandsbereich spricht man von einer domänenspezifischen Sprache (DSL). • Ein MetaMetamodell (Ebene M3) ist das Metamodell eines Metamodells. Modelle sind hier immer formale Modelle. Beispiel (vgl. Abb. 3.1.1): Eine Klasse Person beschreibt Eigenschaften und Verhalten von Personen und definiert u.a. das Attribut Name. Eine Klasse Person ist ein Objekt (ein Modellelement) auf der Modellebene M1. Eine Person Peter (Ausprägung eines Attributes Name) ist ein Instanzobjekt, also ein Objekt der Ebene M0. Das Metamodell auf der Ebene M2 definiert, dass es Klassen gibt und diese u.a. Attribute haben. Auf der Ebene M3 existiert ein Metametamodell, das Elemente zum Klassifizieren definiert. Eine spezielle Ausprägung (Instanz) des Metametamodells ist das Metamodell, das es erlaubt, Klassen zu bilden. Meta ist relativ: Die UML als Sprache ist das Metamodell für ein konkretes UMLModell (das z.B. einen Kaffeeautomaten beschreibt). Die Meta Object Facility (MOF) ist das Metamodell der UML. Die MOF ist ein im MDSD-Umfeld gängiges (textuelles) Metametamodell. Die MOF wird speziell im Abschnitt 3.3 behandelt. Seit der MOF 2.0 gibt es ein vereinfachtes Modell „Essential MOF”, kurz EMOF genannt. 3.2 Definition und Verarbeitung formaler Sprachen 3.2.1 Formale Sprachen (Wiederholung) Alphabet Ein Alphabet, bezeichnet mit Σ, ist eine nichtleere, endliche Menge. Die Elemente dieser Menge nennen wir Symbole. Beispiel: Σ = { a, b, c, d } Wort Sei Σ ein Alphabet. Ein Wort (eine Zeichenreihe) w über Σ ist eine endliche Folge von Symbolen aus Σ. Die Folge kann eine beliebige Länge k ≥ 0 haben. Die Länge eines Wortes ist die Anzahl der Symbole in der Folge und wird mit | w | bezeichnet. Das leere Wort, bezeichnet mit ε, ist das Wort der Länge 0. ε enthält kein Symbol. Beispiele für Wörter über Σ = { a, b, c, d } sind ab, bc, a, ad Die Menge aller Wörter über Σ wird mit Σ∗ bezeichnet und ist folgendermaßen definiert: • Das leere Wort ist ein Wort über Σ, d.h. ∈ Σ∗ . KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 62 Abbildung 3.1.1: Metamodellarchitektur nach [MOF05] • Wird ein Symbol x ∈ Σ an ein Wort w ∈ Σ∗ angehängt, dann ist auch wx ein Wort über Σ, d.h. wx ∈ Σ∗ . • Andere Wörter in Σ∗ gibt es nicht. Beispiel: Sei Σ = { a, b, c, d }, dann gilt Σ∗ = { ε, a, b, c, d, aa, ab, ac, ad, . . . }, abcdabcd ∈Σ∗ Eine häufig verwendete Menge ist Σ+ = Σ∗ \ {ε}. Formale Sprache Eine formale Sprache L über Σ ist eine Menge von Wörtern über Σ, d.h. L ⊆ Σ∗ bzw. L ∈ P(Σ∗ ). P(Σ∗ ) ist die Potenzmenge von Σ∗ , d.h. die Menge aller Teilmengen von Σ∗ . Grammatik Eine Grammatik G ist ein 4-Tupel G = (N, T, P, S0 ) mit KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 63 N : nichtleere Menge der Nichtterminalsymbole (kurz als Nichtterminale bezeichnet) T : nichtleere Menge der Terminalsymbole (kurz als Terminale bezeichnet) P : endliche Menge von Regeln aus (N ∪ T )+ × (N ∪ T )∗ S0 ∈ N : Startsymbol Eine so definierte Grammatik wird von Stetter et al. [Ste88] als Regelgrammatik bezeichnet. Die Menge N ∪ T heißt Vokabular. In Beispielen werden häufig Nichtterminale mit großen Buchstaben und Terminale mit kleinen Buchstaben bezeichnet. Verbreitet ist auch eine Notation, bei der Nichtterminale in spitze Klammern eingeschlossen werden (< ... > bzw. h. . . i). Regeln werden auch als Produktionen oder Produktionsregeln bezeichnet. Jede Regel ist ein geordnetes Paar (u, v) ∈ (N ∪ T )+ × (N ∪ T )∗ und wird als u → v notiert. Jede Regel enthält in u mindestens ein Nichtterminal. Die Menge aller Wörter aus Σ∗ , die aus S0 ableitbar ist, heißt die von G erzeugte Sprache L(G). Beispiel 1. G1 = (N1 , T1 , P1 , SAT Z) mit N1 T1 = = {SAT Z, S, P, O, SU BST } {prof essoren, studenten, und, evaluieren, ärgern} SAT Z → SPO P → P und P O → SU BST S → SU BST SU BST → prof essoren SU BST → studenten P → evaluieren P → ärgern Ableitbar sind z.B. SAT Z → studenten evaluieren prof essoren SAT Z → professoren evaluieren und ärgern studenten SAT Z → prof essoren evaluieren und evaluieren und evaluieren studenten P1 = Chomsky-Hierarchie Sei G = (N, T, P, S0 ) eine Grammatik mit N : nichtleere Menge der Nichtterminale. T : nichtleere Menge der Terminale P : endliche Menge von Regeln aus (N ∪ T )+ ×(N ∪ T )∗ S0 ∈ N : Startsymbol KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 64 Entscheidend für eine Klassifizierung von Grammatiken (und der entsprechenden formalen Sprachen) ist die Struktur der Regeln einer Grammatik. Es gelten: w1 , w2 ∈ T ∗ ; y1 , y2 ∈ T + ; A, B ∈ N . Regeln der Form A → v werden in Abhängigkeit der Gestalt der rechten Seite v der Regel wie folgt benannt: Regel linear rechtslinear linkslinear abschließend rekursiv rechtsrekursiv linksrekursiv v w1 Bw2 w1 B Bw2 w1 y1 A y2 y1 A A y2 Sind alle Regeln einer Grammatik von derselben Art oder abschließend, so nennt man die Grammatik entsprechend. Zum Beispiel ist eine Grammatik linear, wenn alle Regeln abschließend oder linear sind (rechtslineare Regeln und linkslineare Regeln sind auch linear). Man unterscheidet nach dem Linguisten Noam Chomsky vier verschiedene Typen von Grammatiken (und damit auch von Sprachen). Typ Name Regelform 3 regulär alle nichtabschließenden Regeln sind entweder linkslinear/linksrekursiv oder rechtslinear/rechtsrekursiv, es gibt keine Regel der Form A → ε 2 kontextfrei u ∈ N , v ∈ (N ∪T )+ für alle Regeln u → v 1 kontextabhängig u = w1 Aw2 ,v = w3 mit A ∈ N und wi ∈ (N ∪ T )∗ sowie | w1 Aw2 |5| w3 | für alle Regeln u → v 0 allgemein keine Einschränkungen Der Name „kontextfrei” bei einer Grammatik bedeutet, dass bei den Ableitungen ein Nichtterminal unabhängig von den im Kontext links oder rechts davon stehenden Zeichen ersetzt werden darf. Alle regulären Sprachen sind auch kontextfrei, da die abschließenden Regeln sowie die linkslinearen bzw. rechtslinearen Regeln von der Form A → w sind mit A ∈ N und w ∈ (N ∪ T )+ . KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 65 Alle kontextfreien Sprachen sind auch kontextsensitiv (d.h. kontextabhängig), wegen | A |≤| w | und (A→w) = (εAε →w). Die vier Sprachtypen bilden eine Hierarchie, die sog. Chomsky-Hierarchie. Aus praktischen Gründen wird eine ε-Sonderregel eingefüht, die es erlaubt, aus dem Startsymbol auch das leere Wort ε abzuleiten. 3.2.2 Abstrakte und konkrete Syntax Die Syntax einer formalen Sprache umfasst die abstrakte Syntax und die konkrete Syntax. Die abstrakte Syntax beschreibt die Modellelemente und die zwischen ihnen bestehenden Beziehungen. Die konkrete Syntax beschreibt, wie Quelltexte oder Diagramme tatsächlich aussehen. Zu einer abstrakten Syntax können mehrere unterschiedliche konkrete „Syntaxen” existieren. Eine konkrete Syntax kann grafisch oder textuell sein, für eine abstrakte Syntax gibt es diese Unterscheidung nicht. Die konkrete Syntax wird im Rahmen der lexikalischen und syntaktischen Analyse untersucht, sie drückt externe Repräsentationen aus. Die abstrakte Syntax ist beispielsweise die Grundlage für eine denotationelle Definition der Semantik. Ein Metamodell definiert die abstrakte Syntax und die statische Semantik einer formalen Sprache. Ein Metamodell definiert die abstrakte Syntax, nicht die konkrete Syntax der Modellierungssprache. 3.2.3 Semantik Es gibt unterschiedliche Arten der formalen Definition der Semantik von Programmiersprachen. Für Scheme z.B. ist im definierenden Bericht eine denotationelle Semantikdefinition angegeben. Die Semantik einer formalen Sprache umfasst die statische Semantik und die dynamische Semantik. Die statische Semantik legt Bedingungen (constraints) fest, die ein Modell erfüllen muss. Constraints werden gegen die abstrakte Syntax definiert, d. h. sie sind von ihr abhängig. Constraints sind besonders wichtig, um Modellierungsfehler möglichst früh zu erkennen. Zum Beispiel ist die Überprüfung der Typkonformität ein Problem der statischen Semantik. 3.2.4 Lexikalische und syntaktische Analyse Scheme Die Programmiersprache Scheme ist ein Dialekt der Programmiersprache LISP. Programme in der Programmiersprache Scheme sind auf der Ebene M1 einzuordnen: Programme der Programmiersprache Scheme sind Modelle. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 66 Das Metamodell definiert auf der Ebene M2 die Programmiersprache Scheme. Es umfasst die Definition der formalen Syntax, die die Definition der lexikalen Struktur, der externen Repräsentation (einschließlich der Repräsentation von Ausdrücken), die Verwendung von Quasiquotationen sowie die Definition von Programmen und Definitionen enthält, und die Definition der formalen denotationellen Semantik. Die formale Semantikdefinition baut auf einer abstrakten Syntax von Programmen (hprogrami) auf, wobei ein hprogrami eine Folge von Definitionen (hdefinitioni) oder Ausdrücken (hexpressioni) ist. Mit der Definition der Programmiersprache in M2 werden die Struktur und das Verhalten von Programmen in M1 beschrieben. Die lexikale Struktur gibt an, wie Token aus Sequenzen von Zeichen gebildet werden. Zeichen der Art hintertoken spacei können auf beiden Seiten jedes Tokens stehen, aber nicht innerhalb eines Tokens. htokeni −→ hidentifieri | hbooleani | hnumberi | hcharacteri | hstringi | ( | ) | #( | ’ | ‘ | , | ,@ | . hdelimiteri −→ hwhitespacei | ( | ) | " | ; hwhitespacei −→ hspace or newlinei hcommenti −→ ; hall subsequent characters up to a linebreaki hatmospherei −→ hwhitespacei | hcommenti hintertoken spacei −→ hatmospherei∗ hidentifieri −→ hinitialihsubsequenti∗ | hpeculiar identifieri hinitiali −→ hletteri | hspecial initiali hletteri −→ a | b | c | · · · | z hscpecial initiali −→ ! | $ | % | & | * | / | : | < | = | > | ? | _ | ^ hsubsequenti −→ hinitiali | hdigiti | hspecial subsequenti hdigiti −→ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 hspecial subsequenti −→ . | + | hpeculiar identifieri −→ + | − Lexikale Analyse am Beispiel von Scheme Problem: Eingabe von Zeichenreihen → Identifizierung der Lexeme (auch als Morpheme bezeichnet), Zuordnung der Lexeme entsprechend Syntaxdefinition zu Klassen, den Symbolen (auch: Morphemklassen) Lösungsschritte: 1. Modellierung als Zustandsgraph KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 67 (→ endlicher Automat) 2. Konstruktion eines Programms (Entscheidungstabelle + Interpreter) zur Analyse vorgelegter Zeichenreihen Der Definition für htokeni entspricht der in Abb. 3.2.1 bis Abb. 3.2.3 dargetellte Automat. Im ersten Schritt werden htokeni noch nicht spezialisiert (vgl. Abb. 3.2.1). Auch ein Dateiende (eof) kann ein htokeni begrenzen. Abbildung 3.2.1: Tokenerkennung in Scheme Aber auch manche anderen Zeichen - wie z.B. Klammern - können htokeni begrenzen, sie werden als Begrenzerzeichen (delimeter) bezeichnet (vgl. Abb. 3.2.2). Die in Abb. 3.2.3 gelb markierten Bezeichner stehen für weitere Teilmengen von Zeichen. Zur programmtechnischen Realisierung eines Automatenmodells - bei der lexikalen Analyse handelt es sich immer um einen deterministischen endlichen Automaten (DEA) - wird eine Entscheidungstabelle und ein Interpreter für die Entscheidungstabelle erstellt. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG Abbildung 3.2.2: Erkennung von Kommentaren in Scheme 68 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG Abbildung 3.2.3: Automat zur lexikalen Analyse von Scheme 69 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 70 Generatorwerkzeug JLex ist ein Werkzeug, dass eine Spezifikation der lexikalen Struktur aus einer Eingabedatei (Dateinamenerweiterung .lex) liest und ein JavaQuellprogramm generiert, das - nachdem es übersetzt wurde - Lexeme aus einer Eingabedatei erkennen und bereitstellen kann. JLex ist also ein Scanner-Generator. Eine .lex-Datei besteht aus drei Teilen, die jeweils durch %% voneinander getrennt sind. %{ Definitionen, die unverändert in C-Code des Scanners übernommen werden (z.B. symbolische Konstanten) %} Definitionen regulärer Ausdrücke %% Muster und zugeordnete Aktionen %% benötigte Hilfsfunktionen (evtl. Main-Funktion, falls der Scanner als selbständiges Programm arbeiten soll) Syntaktische Analyse Die Verfahren der Syntaxanalyse können eine Top-down- oder Bottom-up-Strategie verfolgen. Bei Top-down-Verfahren erfolgt die Analyse durch Herleitung eines Satzes der Sprache vom Startsymbol ausgehend. Wird während der Analyse ein Parse-Baum aufgebaut, so wird dieser von der Wurzel zu den Blättern hin konstruiert. Bei Bottomup-Verfahren erfolgt die Analyse durch Reduktion, von einem Satz der Sprache ausgehend hin zum Startsymbol. Wird ein Parse-Baum aufgebaut, so wird dieser von den Blättern zur Wurzel hin konstruiert. Die Anwendbarkeit einzelner Verfahren hängt von Eigenschaften der die jeweilige Sprache definierenden Grammatik ab. Die Symbole der Eingabe werden von Links nach rechts verarbeitet (der erste Buchstabe der Bezeichnung eines Verfahrens soll dies verdeutlichen). Bei LL(k)-Verfahren wird eine Linkskanonische Herleitung (Linksherleitung) realisiert (zweiter Buchstabe). Bei einer linkskanonischen Herleitung wird jeweils das am KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 71 Abbildung 3.2.4: Klassifikation von Verfahren zur syntaktischen Analyse weitesten links stehende Nichtterminalsymbol einer Satzform ersetzt. Bei LR(k)-Verfahren wird eine linkskanonische Reduktion realisiert. Eine linkskanonische Reduktion entspricht einer Rechtskanonischen Herleitung. Der Parameter k zeigt die Anzahl der benötigten „Lookahead”-Symbole an, die zur eindeutigen Identifizierung eines Satzes der Sprache benötigt werden. Syntaktische Analyse am Beispiel von Ausdrücken in PL/0 Die Grammatik für Ausdrücke in PL/0 ist durch G2 wie in Abb. 3.2.5 dargestellt definiert. G2 = ( N2 , T2 , R2 , < expr > ) mit N2 = { < expr >, < vz >, < term >, < eterm >, < fz >, < fact >, < efact > } T2 = { ident, number, +, -, *, /, lparen, rparen} < < < R2 = < < < < < expr > vz > eterm > term > efact > fact > fz > kexpr > → → → → → → → → [ < vz > ] < term > < eterm >∗ +|< vz > < term > < fact > < efact >∗ < fz > < fact > ident | number | < kexpr > *|/ lparen < expr > rparen Abbildung 3.2.5: Grammatik G2 : Ausdrücke in PL/0 Die folgende Scheme-Prozedur realisiert einen RD-Parser für die Grammatik G2 . KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 72 (define parser (lambda() (letrec ( ; Prozeduren fuer die Nichtterminalsymbole: (expr (lambda () (and (or (vz) #t) (term) (let loop () (if (eterm) (loop) #t ))) )) (vz (lambda () (or (match ’+) (match ’-)) )) (eterm (lambda () (and (vz)(term)))) (term (lambda () (and (fact) (let loop () (if (efact) (loop) #t ))) )) (efact (lambda () (and (fz)(fact)))) (fz (lambda () (or (match ’* )(match ’/ )) )) (fact (lambda () (or (match ’ident) (match ’number) (kexpr) (error 1) ))) (kexpr (lambda () (and (match ’lparen ) (expr) (or (match ’rparen) (error 2))) )) ; lokale Hilfsfunktionen: (error (lambda (x) (write ‘(error!! ,x)) #f)) (match (lambda (c) (and (eq? symbol c) (Getsym)))) ) (Getsym) (expr) ))) Erläuterung zu match: Zur Bereitstellung eines Lexems wird die parameterlose Prozedur Getsym aufgerufen. (Getsym) liefert immer true, wenn ein Lexem bereitgestellt werden kann. Liefert das 1. Argument des (and ... ) -Ausdruckes true, d.h. es handelt sich um das genannte Eingabezeichen, so liefert in diesem Fall auch der gesamte Ausdruck true. Bottom-up-Analyseverfahren arbeiten tabellengesteuert und werden nicht von Hand programmiert. Das Erstellen der Tabellen (Aktionstabelle und Sprungtabelle) ist sehr aufwändig. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 3.3 73 MOF Die von der OMG definierte Meta Object Facility (MOF) ist das Metamodell der UML, selbst also ein Metametamodell. Die UML wird von der OMG als Metamodell standardisiert. Die UML ist eine Instanz der MOF. Sowohl die MOF als auch die UML basieren auf der UML 2.0 Superstructure. 3.4 Domänenspezifische Sprachen Eine Domänenspezifische Sprache (DSL) ist eine Programmiersprache, die in der Regel für ein begrenztes Wissensgebiet bestimmt ist. Eine DSL ist nach [SMSH07] eine in der Regel eingeschränkte und Turing-unvollständige Sprache. Eine DSL ist dadurch von universell einsetzbaren Programmiersprachen - wie Java oder C++ - abgegrenzt. Beispiele für DSLs sind LaTex, SQL oder das find in Shell-Sprachen. Eine DSL soll Sprachelemente enthalten, die sich auf die Domäne beziehen und mit denen die Experten der Domäne möglichst intuitiv umgehen können. Domänenspezifische Sprachen (DSL) definieren • ein Metamodell mit abstrakter Syntax und statischer Semantik (Constraints) • die konkrete Syntax (und damit auch die Werkzeuge) zur Erstellung, Modifikation und Speicherung von Programmen (Modellen). • die dynamische Semantik (formal oder informal) Häufig wird dabei die grafische Modellierung mit der UML favorisiert. In jedem Fall benötigt man ein Sprachverarbeitungssystem (Parser + Interpreter, evtl. mit Compiler). Der Aufwand zur Entwicklung einer DSL muss sich lohnen. Zur Findung einer DSL wird zuerst die Domäne untersucht. Dabei werden Konzepte identifiziert und in Form eines Metamodells in Zusammenhang gebracht. Erst danach wird für das definierte Metamodell eine Syntax festgelegt. Kategorisierung von DSLs: • Eine interne DSL ist eine Sprache, die in eine Wirtsssprache (Host-Sprache) eingebettet ist, d.h. sie wird mit Mitteln der Hostsprache unter Nutzung ihrer Erweiterungskonzepte beschrieben. Hostsprachen sind typischerweise dynamisch getypte Sprachen wie Ruby oder LISP. Einige Werkzeuge, die für die Wirtssprache vorhanden sind, können auch für die interne DSL genutzt werden (z.B. die Wiederverwendbarkeit von Editoren und Parsern der Wirtssprache, auch von Sprachunterstützungen wie Auto-Vervollständigung, Syntax-Highlighting u.a.). KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 74 • Eine externe DSL ist nicht in eine andere Sprache eingebettet, sondern wird von Grund auf neu definiert. Sie macht einen speziell für sie entwickelten Parser erforderlich. • grafische DSLs: Es kann mehrere Sichten auf verschiedene Teile eines Modells geben. • textuelle DSLs: Unterstützung der Tastaturbedienung und der Teamarbeit sind wichtige Aspekte. • architekturzentrierte DSLs: Es handelt sich um eine architekturzentrierte Domäne, es werden Aspekte der Softwarearchitektur mit der DSL beschrieben. Ein in einer DSL geschriebenes Programm soll in wesentlichen Teilen automatisiert in ein ausführbares Programm transformiert werden können. 3.5 Plattformen Der aus einem formalen Modell generierte Code verwendet üblicherweise Programmbibliotheken, Middleware-Komponenten usw., um seine Aufgaben erfüllen zu können. Entsprechende Bausteine können als Third-Party-Produkte „von außen” kommen oder im Projekt selbst entwickelt werden. Eine Plattform hat die Aufgabe, die Umsetzung der Domäne zu stützen. Eine DSL der Domäne beschreibt den Problemraum, eine Plattform beschreibt den Lösungsraum. Transformationen sind das Bindeglied zwischen Modellierung und Plattform. Es gibt Modell-zu-Code-Transformationen (M2C) und Modell-zu-Modell-Transformationen (M2M). 3.6 Werkzeuge zur Metamodellierung: EMF Es gibt spezielle IDEs zur Unterstützung der Metamodellierung. Konkret wird die Definition von Metamodellen, Bedingungen, der konkreten Syntax von DSLs unterstützt. Außerdem werden Werkzeuge zur Verwendung der DSLs zur Verfügung gestellt. Das sind in erster Linie Editoren (z.B. GMF), aber auch andere Werkzeuge. Das Eclipse Modeling Framework (EMF) unterstützt die Definition von Metamodellen und damit auch die Entwicklung von domänenspezifischen Sprachen in der EclipseIDE. Das EMF legt als Metametamodell Ecore zugrunde, d.h. das entsprechende EMFPlug-in bringt Ecore mit. Ecore ist eine vereinfachte Untermenge der MOF. Ecore lässt KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 75 sich gleichzeitig mit den Mitteln der UML (welche ja durch die MOF beschrieben ist) ausdrücken und kann daher auch als UML-Dialekt aufgefasst werden. Das Metametamodell ist in einer Datei .ecore abgelegt. Diese enthält eine XMLbasierte Beschreibung der Metamodellelemente und der Beziehungen zwischen ihnen. Es existiert als EMF-Werkzeug ein Generator, der aus der .ecore-Datei Java-Klassen erzeugt. Diese beschreiben ebenfalls das Metametamodell (vgl. Abb. 3.6.1). Abbildung 3.6.1: Ecore-Klassenhierarchie Das Eclipse-UML-2-Projekt definiert das UML-2-Metamodell mit den Mitteln des Ecore-Metametamodells [SMSH07]. 3.6.1 Einführungsbeispiel Wir wollen den Einstieg in die Nutzung des EMF anhand der offiziell zur Verfügung stehenden Tutorials und der mit EMF mitgelieferten Beispiele vornehmen. Die Tutorials „Generating an EMF Model“ und „Generating an Extended EMF Model“ beschreiben die Modellierung einer Bibliothek und sind Bestandteil der OnlineHilfe des EMF. Innerhalb von Eclipse findet man sie unter Help → Help Contents → EMF Developer Guide → Tutorials. Da die Tutorials jeden Schritt vollständig KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 76 beschreiben, sollen im Folgenden nur die wichtigsten Aspekte herausgearbeitet werden. Die Adresse des Tutorials “Generating an EMF Model” ist: http://help.eclipse.org/ganymede/index.jsp?topic=/org.eclipse.emf.doc/tutorials/clibmod/clibmod.ht Die zu modellierende Bibliothek (Library) soll - wie in Abb. 3.6.2 dargestellt Buchautoren (Writer) und Bücher (Book) umfassen. Außerdem sollen Bücher einer Kategorie zugeordnet werden können. In einer Aufzählung sind die verfügbaren Buchkategorien (BookCategory) enthalten (es ist zu betonen, dass es sich tatsächlich um ein Metamodell handeln soll, im „UML-Turm” der Metamodellebenen lässt sich das Klassendiagramm auch auf der Ebene M1 verorten). Abbildung 3.6.2: Klassendiagramm zum Beispiel „Bibliothek” Das Projekt Bezugspunkt ist das Tutorial “Generierung eines EMF-Modells” (siehe oben). Das nachfolgende Beispiel demonstriert die Erstellung eines Metamodells auf der Basis von Java-Quellcode und entspricht genau dem Tutorial. Es umfasst folgende Schritte: • Step 0: Vorbereitungen • Step 1: Definieren eines EMF-Modells unter Nutzung von Annotated Java (alternativ kann ein Modell auch importiert werden) • Step 2: Generierung des Codes für das EMF-Modell • Step 3: Generierung eines syntaxgesteuerten Editors aus dem EMF-Modell • Step 4: Ausführen des generierten syntaxgesteuerten Editors KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 77 Step0 Die Vorbereitungen umfassen die oben beschriebene Bereitstellung des EMF in Eclipse (mittels Update Manager). Step 1 Es muss zunächst zur Realisierung des Bibliotheks-Projektes ein neues EMF-Projekt (Empty EMF Project) kreiert werden: File →New →Project... (vgl. Abb. 3.6.3) Abbildung 3.6.3: EMF-Projekt kreieren Mittels des Wizards wird ein Name für das Bibliotheks-Projekt festgelegt (z.B. de.htwdd.sf.library). Nach Beendigung des Wizards existiert eine Projektstruktur (vgl. Abb. 3.6.4). Die Verzeichnisse src und model werden erzeugt, sind aber noch leer. Danach werden per Hand Quelltexte für die Java-Interfaces und Klassen erzeugt (Ablage in de.htwdd.sf.library/src, über Kontextmenü des src-Verzeichnisses → New Java Interface ... ), die den Ausgangspunkt der Modellerstellung bilden (drei Interfaces und eine Klasse, vgl. Abb. 3.6.5 bis 3.6.8). Der Code ist jeweils mit @model-Tags in Javadoc-Kommentaren annotiert. Achtung: Die Interfaces und die Klasse sind einem package zugeordnet! Hier in diesem Beispiel ist der Quelltext der Ausgangspunkt der Modellerstellung. Alternativ wäre es auch möglich, z.B. von UML-Klassendiagrammen auszugehen. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 78 Abbildung 3.6.4: EMF-Projektstruktur nach dem Erzeugen eines Projekts, es existiert noch kein Modell Ecore-basierte Modelle werden in XMI-Dateien serialisiert, wodurch eine Weitergabe entlang einer Werkzeugkette unterstützt wird. package de . htwdd . s f . l i b r a r y ; import j a v a . u t i l . L i s t ; /∗ ∗ ∗ @model ∗/ public i n t e r f a c e L i b r a r y { /∗ ∗ ∗ @model ∗/ S t r i n g getName ( ) ; /∗ ∗ ∗ @model t y p e =" Writer " co n t ai n m en t =" t r u e " ∗/ L i s t <Writer> g e t W r i t e r s ( ) ; /∗ ∗ ∗ @model c o n t ai n m en t =" t r u e " ∗/ L i s t <Book> getBooks ( ) ; } Abbildung 3.6.5: Library.java KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG package de . htwdd . s f . l i b r a r y ; /∗ ∗ ∗ @model ∗/ public i n t e r f a c e Book { /∗ ∗ ∗ @model ∗/ String getTitle ( ) ; /∗ ∗ ∗ @model d e f a u l t ="100" ∗/ int getPages ( ) ; /∗ ∗ ∗ @model ∗/ BookCategory g e t C a t e g o r y ( ) ; /∗ ∗ ∗ @model o p p o s i t e =" b o o k s " ∗/ W r i t e r getAuthor ( ) ; } Abbildung 3.6.6: Book.java package de . htwdd . s f . l i b r a r y ; /∗ ∗ ∗ @model ∗/ public i n t e r f a c e W r i t e r { /∗ ∗ ∗ @model ∗/ S t r i n g getName ( ) ; /∗ ∗ ∗ @model o p p o s i t e =" a u t h o r " ∗/ j a v a . u t i l . L i s t <Book> getBooks ( ) ; } Abbildung 3.6.7: Writer.java 79 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG package de . htwdd . s f . l i b r a r y ; /∗ ∗ ∗ @model ∗/ public c l a s s BookCategory { /∗ ∗ ∗ @model name="Mystery " ∗/ public s t a t i c f i n a l i n t MYSTERY = 0 ; /∗ ∗ ∗ @model name=" S c i e n c e F i c t i o n " ∗/ public s t a t i c f i n a l i n t SCIENCE_FICTION = 1 ; /∗ ∗ ∗ @model name=" Bio graphy " ∗/ public s t a t i c f i n a l i n t BIOGRAPHY = 2 ; } Abbildung 3.6.8: BookCategory.java 80 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 81 Das Erzeugen des EMF-Modells (vgl. Abb. 3.6.9) erfolgt wiederum mit Hilfe eines Wizards. Es ist - ausgehend vom Kontextmenü des model-Verzeichnisses - “EMF Generator Model” auszuwählen (vgl. Abb. 3.6.10). AndroMDA Abbildung 3.6.9: Erzeugen eines neuen EMF-Modells Im nächsten Schritt wird der Dateiname library.genmodel für das Modell festzulegen (vgl. Abb. 3.6.11). Danach wird „Annotated Java” als Typ der Quelle ausgewählt (vgl. Abb. 3.6.12). Nach der Wahl des bereitgestellten Packages (vgl. Abb. 3.6.13) wird der Wizard beendet. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG Abbildung 3.6.10: Generieren eines EMF-Modells Abbildung 3.6.11: Festlegung des Dateinamens 82 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG Abbildung 3.6.12: Auswahl „Annotated Java” Abbildung 3.6.13: Wahl des Packages 83 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 84 Durch den Wizard sind ein Ecore-Modell (library.ecore) und ein GeneratorModell (library.genmodel) erzeugt worden (vgl. Abb. 3.6.14 ). Das Generator-Modell dient zur Steuerung der Codegenerierung. Eine View, die dieses Modell zeigt, wird nach Beenden des Wizards automatisch geöffnet. Das Wurzelobjekt repräsentiert das gesamte Modell. Durch Expandieren können seine Elemente angezeigt werden (packages, classifier, attributes etc., siehe unten). Über Kontextmenü → Show Properties View können die Eigenschaften eingesehen und geändert werden. Abbildung 3.6.14: Ecore- und Generator-Modell Ein EMF-Projekt besteht aus mehreren Ordnern: • src enthält im Verzeichnis de.htwdd.sf.library die Java-Quelltexte der Interfaces und Klassen für die Modellerzeugung (die später durch die Codegenerierung um Codebestandteile ergänzt werden) und später auch die generierten Java-Quellen für den Modell-Editor, • model enthält die .ecore-, .ecorediag- und .genmodel-Quelldateien, • Das Verzeichnis META-INF. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 85 Step 2 Vom Generator-Modell aus erfolgt jetzt die Code-Generierung für das EMF-Modell: Das Generator-Modell besitzt ein Wurzelobjekt, das das gesamte Modell umfasst. In Abb. 3.6.15 ist das Modell expandiert (d.h. „aufgeklappt”). Abbildung 3.6.15: Das library.genmodel Das Domänenmodell library.ecore enthält xml-Code des Modells. Abb. 3.6.16 zeigt den xml-Code für das vorliegende Beispiel (Datei mit Texteditor geöffnet). Über EClass, EDataType usw. wird ein Bezug zum Ecore-Framework hergestellt. Über die „Properties”-Einstellungen im Kontextmenü kann das Verhalten des CodeGenerators gesteuert werden. Zum Beispiel kann festgelegt werden, ob für einen Knoten Kindknoten eingefügt werden können. Durch Rechtsklick auf ein Modell-Objekt wird die Art des zu generierenden Codes ausgewählt (vgl. Abb. 3.6.17). Zunächst wird der Code für das Modell erzeugt. Nach der Generierung sind neue Klassen erzeugt und bestehende Klassen um Code ergänzt worden (vgl. Abb. 3.6.18). Ein neues Paar von Interfaces ist erzeugt worden, für das Package selbst und für die Factory. Es gibt außerdem zwei neue Packages mit den Suffixen .impl und .util. Und es gibt neue Dateien plugin.xml und MANIFEST.MF. Step 3 In diesem Schritt erfolgt die Generierung eines Editors für das Modell: Es werden drei neue Plug-ins generiert: KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 86 • das edit-Plug-in enthält Adapter und unterstützt ein Command-basiertes Editieren. • das editor-Plug-in enthält die GUI für den Editor und den Wizard. • das tests-Plug-in enthält Skelette (Templates) für Testfallspezifikationen für JUnit. Die Generierung des entsprechenden Quellcodes wird über das Kontextmenü des library.genmodel angestoßen („Generate Edit Code”, ”Generate Editor Code”, „Generate Test Code” einzeln oder „Generate All” für alle zusammen). Es werden drei neue Projekte (Plug-ins) erzeugt, die im Package-Explorer angezeigt werden: Die Körper der Skelette im tests-Plug-in dienen der Vorbereitung von JUnit-Tests und müssen vom Entwickler selbst ausgefüllt werden. Das tests-Plug-in enthält auch eine Beispiel-Klasse, die zeigt, wie ein Modell in einer Standalone-Anwendung geladen und validiert werden kann. Der Generierte Code sollte automatisch compiliert werden (Alternative: manuelles Build durch „Build All”). KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG <?xml version=" 1 . 0 " e n c o d i n g="UTF−8" ?> <e c o r e : E P a c k a g e x m i : v e r s i o n=" 2 . 0 " xmlns:xmi=" h t t p : //www. omg . o r g /XMI" x m l n s : x s i=" h t t p : //www. w3 . o r g /2001/XMLSchema−i n s t a n c e " x m l n s : e c o r e=" h t t p : //www. e c l i p s e . o r g / emf /2002/ Ecore " name=" l i b r a r y " nsURI=" h t t p : /// de /htwdd/ s f / l i b r a r y . e c o r e " n s P r e f i x=" de . htwdd . s f . l i b r a r y "> < e C l a s s i f i e r s x s i : t y p e=" e c o r e : E C l a s s " name=" Book "> <e S t r u c t u r a l F e a t u r e s x s i : t y p e=" e c o r e : E A t t r i b u t e " name=" t i t l e " eType=" ecore:EDataType h t t p : //www. e c l i p s e . o r g / emf /2002/ Ecore#// E S t r i n g " /> <e S t r u c t u r a l F e a t u r e s x s i : t y p e=" e c o r e : E A t t r i b u t e " name=" p a g e s " eType=" ecore:EDataType h t t p : //www. e c l i p s e . o r g / emf /2002/ Ecore#//EInt " d e f a u l t V a l u e L i t e r a l=" 100 " /> <e S t r u c t u r a l F e a t u r e s x s i : t y p e=" e c o r e : E A t t r i b u t e " name=" c a t e g o r y " eType=" #//BookCategory " /> <e S t r u c t u r a l F e a t u r e s x s i : t y p e=" e c o r e : E R e f e r e n c e " name=" a u t h o r " eType=" #//W r i t e r " e O p p o s i t e=" #//W r i t e r / books " /> </ e C l a s s i f i e r s> < e C l a s s i f i e r s x s i : t y p e=" ecore:EEnum " name=" BookCategory "> < e L i t e r a l s name=" Mystery " /> < e L i t e r a l s name=" S c i e n c e F i c t i o n " v a l u e=" 1 " /> < e L i t e r a l s name=" Biography " v a l u e=" 2 " /> </ e C l a s s i f i e r s> < e C l a s s i f i e r s x s i : t y p e=" e c o r e : E C l a s s " name=" L i b r a r y "> <e S t r u c t u r a l F e a t u r e s x s i : t y p e=" e c o r e : E A t t r i b u t e " name=" name " eType=" ecore:EDataType h t t p : //www. e c l i p s e . o r g / emf /2002/ Ecore#// E S t r i n g " /> <e S t r u c t u r a l F e a t u r e s x s i : t y p e=" e c o r e : E R e f e r e n c e " name=" w r i t e r s " upperBound="−1" eType=" #//W r i t e r " c o n t a i n m e n t=" t r u e " r e s o l v e P r o x i e s=" f a l s e " /> <e S t r u c t u r a l F e a t u r e s x s i : t y p e=" e c o r e : E R e f e r e n c e " name=" books " upperBound="−1" eType=" #//Book " c o n t a i n m e n t=" t r u e " r e s o l v e P r o x i e s=" f a l s e " /> </ e C l a s s i f i e r s> < e C l a s s i f i e r s x s i : t y p e=" e c o r e : E C l a s s " name=" W r i t e r "> <e S t r u c t u r a l F e a t u r e s x s i : t y p e=" e c o r e : E A t t r i b u t e " name=" name " eType=" ecore:EDataType h t t p : //www. e c l i p s e . o r g / emf /2002/ Ecore#// E S t r i n g " /> <e S t r u c t u r a l F e a t u r e s x s i : t y p e=" e c o r e : E R e f e r e n c e " name=" books " upperBound="−1" eType=" #//Book " e O p p o s i t e=" #//Book/ a u t h o r " /> </ e C l a s s i f i e r s> </ e c o r e : E P a c k a g e> Abbildung 3.6.16: xml-Code in der Datei library.ecore 87 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG Abbildung 3.6.17: Library - Code-Generierung Abbildung 3.6.18: EMF-Modell nach der Code-Generierung 88 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 89 Step 4 Der generierte Modell-Editor liegt in Form von Plug-ins vor. Um die neu erstellten Plug-ins zu testen bzw. zu erproben, muss eine weitere Eclipse-Instanz erzeugt werden (Auswahl des Plug-ins im Projekt-Manager, dann Run As → Eclipse-Application). Die Plug-ins laufen dann in dieser Umgebung. Abbildung 3.6.19: Kontrolle, dass die erzeugten Plug-ins auch verfügbar sind Als nächstes können Modell-Instanzen mittels des generierten syntaxgesteuerten Editors erstellt werden. Der Model-Wizard kann benutzt werden, um eine neue Instanz des Modells zu kreieren (über File →New →Project..., „General Project”). Das Projekt muss noch einen Namen erhalten (z.B. librarytest). Über das Kontextmenü des angelegten Projektes librarytest kann eine neue Library-Modell-Instanz erzeugt werden. „Library Model” wird mit angeboten (vgl. Abb. 3.6.20). Der Bibliotheksname kann präzisiert werden, in dem für das Attribut Name ein Wert festgelegt wird: KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 90 Abbildung 3.6.20: Wizard zum Erzeugen einer „Library Model” - Instanz Änderungen, die mit dem Editor vorgenommen wurden, werden meist erst nach einem „Refresh” (im Kontextmenü enthalten) sichtbar. Alternativ zu textuellen Editoren gibt es die Möglichkeit, mittels GEF und GMF grafische Modell-Editoren zu erstellen. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 3.6.2 91 Erstellung von EMF-Modellen aus UML-Diagrammen Anstelle von annotierten Java-Interfaces/Klassen können auch UML-Diagramme als Ausgangspunkt für die Modellerstellung dienen. Erprobt wurde die Modellerstellung auf der Basis von Diagrammen, die mittels der UML2-Tools erstellt wurden. Auch Topcased-UML-Modelle können verwendet werden. Abb. 3.6.21 zeigt die Bereitstellung der UML2-Tools. Abbildung 3.6.21: Plug-ins der UML2-Tools Die Erstellung eines UML-Diagramms soll beispielhaft mit Topcased vorgenommen werden. Nach der Fertigstellung eines UML-Klassendiagrammes ist es möglich, ein GeneratorModell aus diesem zu erzeugen. Dazu wird mittels New → Other oder STRG+N das „EMF Generator Model“ (Ordner Eclipse Modeling Framework) erstellt. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 92 Es folgt die Auswahl des zu importierenden Modells (Model Importer). Wir nutzen das erstellte UML Diagramm und wählen hier UML model. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 93 Danach wird die UML-Datei importiert. Unter „Browse Workspace“ ist im passenden Ordner die *.uml-Datei auszuwählen. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 94 Als letzter Schritt erfolgt die Paketauswahl. Dort wählen wir die passenden Pakete (hier: „student“ und „ecore“) aus und bestätigen mit „Finish“. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 95 Nun hat das System ein .genmodel angelegt. Per Rechtsklick auf „Student“ in der student.genmodel-View ist es jetzt möglich, „Edit Code“ und „Editor Code“ zu generieren (vgl. Abschnitt 3.6.1, Step 3). 3.6.3 Erstellen von EMF-Modellen mit Hilfe des Ecore-Editors Mittels des Wizards kann verlangt werden, den Ecore-Editor zur Erstellung eines Ecore-Modells zu nutzen. KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 96 KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 97 Ein so erstelltes .ecore-Modell kann anschließend importiert werden: 3.7 Modellaustausch Die MOF-Spezifikation definiert ein serialisierbares Modellformat, das XML Metadate Interchange (XMI). Die Unterstützung des XMI-Formates durch die derzeit auf dem Markt erhältlichen Modellierungswerkzeuge ist teilweise noch mangelhaft. Abb. 3.7.1 zeigt eine Klasse in XMI-Darstellung. EMF serialisiert Ecore-basierte Modelle in XMI-Dateien und ermöglicht damit KAPITEL 3. MODELLGETRIEBENE SOFTWAREENTWICKLUNG 98 Abbildung 3.7.1: Klasse C1 in XMI-Darstellung ebenso wie MOF das Weiterreichen von Modellen entlang einer Werkzeugkette, wobei EMF die Integration in die Eclipse-Plattform in den Vordergrund stellt. Kapitel 4 Werkzeuge zur Unterstützung der MDSD Nachfolgend werden Werkzeuge betrachtet, die Java-basiert sind. Das bedeutet nicht, dass auch die Zielsprache Java sein muss. Es gibt Projekte im EMF-Umfeld, die das Erstellen von textuellen und grafischen Editoren für Ecore-basierte Metamodelle weiter vereinfachen. Diese Werkzeuge sollen nachfolgend vorgestellt werden. 4.1 Überblick Graphical Modeling Framework Das Graphical Modeling Framework (GMF) unterstützt die Entwicklung grafischer Editoren und basiert auf dem Eclipse Modeling Framwork (EMF) und dem Graphical Editing Framework (GEF). Zum Erstellen eines Editors sind folgende Schritte erforderlich: 1. Erstellen eines EMF-Metamodells (als Instanz von Ecore), 2. Erstellen von EMF-Konfigurationsmodellen, 3. Generieren des Editors, 4. Hinzufügen von Funktionalität an dafür vorgesehenen Erweiterungspunkten (optional). Beispiel. Editor für Klassendiagramme • Es wird ein EMF-Projekt erstellt 99 KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 100 • Zum Projekt wird ein Ecore-Modell hinzugefügt Ein Klassendiagramm wurde wie in Abb. 4.1.1dargestellt beschrieben. Als Quelle des Modellimports wird das erstellte Ecore-Model ausgewählt. Abbildung 4.1.1: Ecore-Modell eines Klasseneditors Anschließend wird ein Plug-in-Projekt für den grafischen Editor erstellt. Werkzeuge aus dem Projekt openArchitectureWare Das Projekt openArchitectureWare ist ein Unterprojekt von Eclipse-GMT. Es ist wie folgt charakterisiert: • Werkzeugsuite auf Basis eines Generatorframeworks • Framework, Bereitstellung einer Infrastruktur zur Entwicklung von Generatoren • Einbindung in Eclipse • oAW kann beliebige Modellformate, Metamodelle und Ausgabeformate verarbeiten, keine Angebote für bestimmte Zielarchitekturen. Bestandteile: KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 101 1. Workflow-Engine 2. Typsystem und Expression Language 3. Templatesprache Xpand Die Workflowengine ermöglicht die Ausführung, d.h. die sequentielle Abarbeitung vordefinierter Komponenten (z.B. Modellinstanziierung, Modellvalidierung, Modelltransformation). Der Workflow wird in einer XML-Datei festgelegt (ähnliche Syntax wie Apache Ant). Konzepte wie das Definieren von Eigenschaften, das Referenzieren weiterer Workflow-Dateien sind aus Ant bekannt. Die Ausführung eines oAW-Workflows kann angestoßen werden: • aus einem Programm über das Workflow-API • einem Ant-Skript • die Eclipse-Oberfläche • Kommandozeilenaufruf Das oAW-eigene Typsystem ist eine Abstraktionsschicht über die verschiedenen Metamodelle, die als Eingabe für die Generierung verwendet werden können. Bei der Instantiierung eines Metamodells wird dieses in das Typsystem umgesetzt. In der oAWDistribution sind Adaptionen für einige Metamodelle enthalten: EMF, ... Mit der Templatesprache Xpand lassen sich Modelltransformationen beschreiben. 4.2 Xtext Das Framework Xtext dient zur Definition von textuellen DSLs [xte] durch Angabe von Grammatiken. Xtext stellt als Notationsmittel für Grammatiken eine vereinfachte EBNF-Notation zur Verfügung (sog. Xtext-Grammatiksprache). Damit können sowohl abstrakte als auch konkrete Syntax einer DSL definiert werden. Aus einer Xtext-Grammatik werden Werkzeuge und andere Artefakte generiert. Dazu gehören: • ein Metamodell, welches die einzelnen AST-Typen repräsentiert • ein Parser • ein Eclipse-basierter Texteditor mit einer Menge von DSL-spezifischen Features: Syntax Highlighting, Code Completion, Validierung, Code Folding, Outline View. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 102 Ein generierter Parser verarbeitet den Text einer DSL-Instanz und erzeugt eine ObjektGraph-Struktur, die eine Instant des EMF-Modells (Metamodell) ist. Bei der Generierung des Metamodells wird ein EPackage erzeugt, das EClasses, EDataTypes und EEnums enthält. Mit der Grammatiksprache von Xtext können nicht alle Programmiersprachen beschrieben werden, sie ist spezifisch auf die Belange von DSLs zugeschnitten. Die XtextGrammatiksprache wird im Abschnitt 4.2.4 behandelt. Das Xtext-Framework nutzt intern den Parser-Generator Antlr. Antlr ist ein objektorientierter Top-down-Parser-Generator, der Lexer/Parser für LL(k)-Grammatiken erzeugt. Antlr ist in Java implementiert. 4.2.1 Installation Das Xtext-Framework (in der Version 2.2.0) wird wie in Abb. 4.2.1 beschrieben mit Hilfe des Update-Managers von der Adresse http://download.eclipse.org/modeling/tmf/xtext/updates/composite/releases/ bereitgestellt. Abbildung 4.2.1: Installierung von Xtext Nach der Installation können Xtext-Projekte angelegt werden. In der Installation sind bereits Beispiele zur Xtext-Anwendung enthalten (vgl. Abb. 4.2.2). Über das HELP-Menü von Eclipse steht eine Xtext 2.1-Dokumentation zur Verfügung. 4.2.2 Erstes Anwendungsbeispiel Tatsächlich kann der Menüpunkt Xtext Project from Existing Ecore Models ausgewählt werden. Beispielsweise werden drei bisher in Projekten im Workspace er- KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 103 Abbildung 4.2.2: Wizard zur Erstellung von Xtext-Projekten stellte Modelle angeboten (vgl. Abb. 4.2.3). Für das Library.genmodel wird nach Bestätigen mit OK folgender Code erzeugt. Der Code ist in der Datei c:\Dokumente und Einstellungen\fritzsch \workspace\org.xtext.example.mydsl1\src\org\xtext\example\mydsl1\ enthalten. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD Abbildung 4.2.3: Auswahl eines Metamodells Abbildung 4.2.4: Xtext-generierter Code 104 KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 4.2.3 105 Zweites Anwendungsbeispiel Das Beispiel ist an ein Tutorial angelehnt, das in der Xtext 2.1 Documentation enthalten ist. Es wird zunächst ein Xtext-Projekt angelegt: File → New → Project... → Xtext → Xtext Project. Im Wizard werden festgelegt: Projektname: de.htwdd.sf.domainmodel DSL-Name: de.htwdd.sf.domainmodel.Domainmodel DSL-File-Extension: dmodel Der Wizard ist mit „finish” zu beenden. Nach Beenden des Wizards befinden sich drei neue Projekte im Workspace: de.htwdd.sf.domainmodel - enthält die Grammatikdefinition und alle LaufzeitKomponenten de.htwdd.sf.domainmodel.tests - Platz, um JUnit-Tests zu spezifizieren de.htwdd.sf.domainmodel.ui - Eclipse-basierter Editor und Funktionalität, die auf die Workbench bezogen ist. Jetzt ist die Grammatik anzugeben. Die die Grammatik enthaltende Datei Domainmodel.xtext (allgemein <DSL-Name>.xtext) wird nach Abschluss des Wizards automatisch als Eclipse-Editor geöffnet und kann editiert werden. Nach dem Öffnen ist zunächst eine „Hello World” - Grammatik enthalten, die zu ersetzen ist. Wir tragen folgende Grammatik für unsere Sprache ein: grammar de . htwdd . sf . domainmodel . Domainmodel with org . eclipse . xtext . common . Terminals generate domainmodel " http :// www . htwdd . de / sf / domainmodel / Domainmodel " Domainmodel : elements += Type * ; Type : DataType | Entity ; DataType : KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 106 ’ datatype ’ name = ID ; Entity : ’ entity ’ name = ID ( ’ extends ’ superType = [ Entity ])? ’{ ’ features += Feature * ’} ’ ; Feature : many ?= ’ many ’? name = ID ’: ’ type = [ Type ] ; Die erste Zeile (grammar ...) definiert den Namen der Sprache. Als Name ist jeder gültige „Java-Qualifier” erlaubt. Er entspricht dem Dateinamen, dem noch die Endung .xtext angehängt ist. Es wird außerdem eine andere Sprachdefinition einbezogen, hier org.eclipse.xtext.common.Terminals. Die generate-Anweisung legt fest, dass ein Ecore-Modell erzeugt wird. domainmodel ist darin der EPackage-Name. Alternativ könnte auch ein bestehendes Ecore-Modell verwendet werden. Die Startregel ist eine Parser-Regel und besagt, dass das Domänenmodell Domainmodel eine beliebige Anzahl von Types besitzt, die zu einem elements genannten Feature hinzugefügt werden können. Type ist wiederum durch eine Parser-Regel usw. Liegt die Grammatik-Definition vollständig vor, ist der Xtext-Language-Generator (eine „Workflow Engine”) auszuführen, der die verschiedenen Sprachkomponenten aus der Grammatik-Definition ableitet. Die Aktivierung der „Workflow Engine” erfolgt über das Kontextmenü der Datei GenerateDomainModel.mwe2 im Package de.htwdd.sf.domainmodel (vgl. Abb. 4.2.5). Der Generator erzeugt den Parser, den Serializer und einigen weiteren InfrastrukturCode. Nunmehr ist die Integration in die Eclipse-IDE zu testen. Mittels Run → Run Configurations ist eine neue Eclipse-Applikation zu erzeugen. In der erzeugten EclipseWorkbench sind die neu entwickelten Plug-ins verfügbar. In dieser Eclipse-Instanz kann ein neues Java-Projekt (z.B. Sample) erzeugt werden. In dem generierten Ordner src wird nachfolgend eine Datei erzeugt, die eine Endung entsprechend der obigen Festlegung haben muss (hier: .dmodel). Die nachfolgende Frage nach der „Xtext nature” wird erwartet und ist mit „Yes” zu bestätigen. Mit dem erzeugten Editor kann nun gearbeitet werden (vgl. Abb. 4.2.7). Mit dem „content assistent” (Ctrl+Space) können Einträge ausgewählt werden. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 107 Abbildung 4.2.5: Aktivierung des Xtext-Language-Generators Abbildung 4.2.6: Abfrage beim Erzeugen einer .dmodel-Datei Es gibt zusätzlich eine entsprechende Outline-View. Abbildung 4.2.8 zeigt eine mit dem generierten Editor erstellte Instanz dmtest.dmodel zur DSL. 4.2.4 Die Xtext-Grammatiksprache de Spezifikation einer Xtext-Grammatik beginnt mit einem Kopf, der die Eigenschaften der Grammatik beschreibt. Terminalregeln Aufgabe ist es, aus einer Folge von Zeichen der Eingabe Token zu erkennen. Die Namen der Terminalregeln werden mit Großbuchstaben geschrieben. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 108 Abbildung 4.2.7: Nutzung des generierten DSL-Editors Abbildung 4.2.8: Beispiel-Instanz zur DSL „Domainmodel” Parserregeln Parserregeln bilden den Bauplan zur Konstruktion von EObject-Objekten, aus denen der abstrakte Syntaxgraph eines Programms (AST) aufgebaut wird. Der Typ des jeweils aktuellen Objekts wird durch den Rückgabe-Typ der Parser-Regel spezifiziert. Es wird implizit angenommen, dass der Typname dem Regelnamen entspricht. Actions und Assignments werden benutzt, um Typen abzuleiten und die semantischen Objekte entsprechend zu initialisieren. Assignments dienen der Zuweisung von Informationen zu einem Feature (dem aktuell produzierten Objekt). Syntax: name = Regelaufruf | Schlüsselwort | Cross-Reference| Der Typ des Features name wird durch den rechtsseitig notierten Ausdruck bestimmt. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 109 Der Operator += erwartet ein mehrwertiges Feature und fügt den rechtsseitigen Wert zu einer Liste hinzu. Der Operator ?= wird für Features vom Typ Boolean (d.h. EBoolean) verwendet. Eine Cross-Reference ist ein Link innerhalb der Grammatik. Solche Links werden vom Programmverbinder (Linker) verarbeitet. Syntax: Cross-Reference = ’[’ type = TypeRef ( ’|’ t̂erminal-CrossreferenceableTerminal)? ’]’ Actions Das Objekt, das bei der Verarbeitung einer Parser-Regel zurückgegeben wird, wird gewöhnlich von der ersten Zuweisung (Assignment) erzeugt. Der Typ wird implizit durch den Rückgabetyp der Parser-Regel bestimmt. Mittels Actions kann der Rückgabetyp explizit gemacht werden. Es werden Simple Acions und Assigned Actions unterschieden. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 4.3 110 Xtend Wir wollen in diesem Abschnitt beschreiben 1. welche Charakteristika die Sprache Xtend besitzt, 2. wozu Xtend im Rahmen von Xtext-Projekten verwendet wird und 3. ein Beispiel: Verarbeitung von Expressions der Spache PL/0 durch einen Kellerautomaten. 4.3.1 Die Sprache Xtend Xtend ist eine statisch getypte Sprache, die auf der JVM läuft. Xtend erfordert Eclipse 3.5 oder höher und ein Java SDK Version 5 oder höher. So entspricht die STruktur von Xtend-Programmen der von Java-Programmen, bzgl. der Notation gibt es Einsparungen bzw. Verkürzungen. Es gibt z.B. keine Semikolons am Ende von Anweisungen (auch package- und import-Anweisungen) und keine explizite Angabe von Rückgabetypen. Jede Xtend-Klasse ist implizit public. Parametrisierte Klassen werden unterstützt. Xtend-Konstruktor-Deklarationen enthalten keinen Klassennamen, also nur new( paramtype param){ ... }. Instanzvariablen (Fields) werden wie in Java gehandhabt, zusätzlich gibt es sog. extension methods. Assignments sind Expressions, die den zugewiesenen Wert zurückgeben. Xtend-Metoden werden innerhalb einer Klasse deklariert und in entsprechende Java-Methoden transformiert. 4.3.2 Entwicklung eines Code-Generators mit Xtend Bei einem Xtext-Projekt wird im Runtime-Projekt der DSL ein Stub (Quelltext) eines Code-Generators als Xtend-Klasse erzeugt. Die Datei dslnameGenerator.xtend im Package dslname .generator des src-Verzeichnisses enthält diese (rudimentäre) Xtend-Klasse, die benutzt werden kann, um Code für Modelle zu generieren. Nachdem der Quellcode in dieser Datei entsprechend der Aufgabenstellung angepasst wurde, kann eine neue Eclipse-Applikation für das Xtext-Projekt erzeugt werden. Darin ist zunächst von Hand ein Source-Verzeichnis src-gen anzulegen. Der Generator wird durch einen Builder (org.eclipse.xtext.builder.IXtextBuilderPerticipant) aufgerufen, wenn das File gespeichert wird, das die DSL-Instanz enthält. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 111 Grundlage für die nachfolgenden Darstellungen zur Nutzung des Codegenerators ist das Xtext-Tutorial „15 Minutes Tutorial - Extended” (vgl. Abb. 4.3.1). Abbildung 4.3.1: Lernen von Xtend mittels Eclipse → Help → Xtext-Dokumentation Die Datei dslnameGenerator.xtend nimmt den Generator-Code (formuliert mit Xtend) auf. Diese Xtend-Klasse (z.B. DomainmodelGenerator im Tutorial) wird verwendet, um Code zu generieren: class DomainmodelGenerator implements IGenerator { override void doGenerate(Resource resource, IFileSystemAccess fsa) { } } Die Methode doGenerate wird ausgeführt, wenn von dem syntaxgesteuerten Editor eine DSL-Instanz gespeichert wird. Innerhalb des Körpers der Methode doGenerate kann die Erzeugung einer TextDatei programmiert werden (Anwendung der Methode generateFile auf das Parameterobjekt fsa): fsa.generateFile("KAData.java", code) In einem hier code genannten String wird zuvor der Text-Inhalt der Datei zusammengestellt, die hier den Namen KAData.java bekommt. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 112 Die nachfolgende Schleife ist innerhalb von doGenerate zu platzieren und erlaubt den Zugriff auf alle Objekte des angegebenen Typs (hier vom Typ Ident) im Syntaxbaum. for(e:resource.allContents.toIterable.filter(typeof(Ident))) { // Zugriff auf resourcen und Generierung von code-Strings, // hier für Objekte des Typs "Ident" } Auf die Objekte e des angegebenen Typs können nun Methoden angewandt werden, die innerhalb der Klasse zu definieren sind, z.B. e.traversiere. Schleifen werden wie folgt behandelt (Beispiel sind hier die Expressions von PL0): def traversiere(Term t) { System::out.println("traversiere Term!") if(t.facte != null) t.facte.traversiere if(t.efacte != null) for(allEFacte:t.efacte) allEFacte.traversiere } Wenn es einen Fact gibt (facte ist der Feature-Name), wird zunächst auf diesen die Funktion traversiere angewendet. Wenn es Efact-Objekte gibt, wird anschließend auf diese sukzessive die Funktion traversiere angewendet. Die Definition einer solchen Methode kann auch mittels Template-Code efolgen (s.u.). 4.3.3 Beispiel Gegeben ist die Grammatik G2 für Ausdrücke in PL/0 (vgl. Abb. 3.2.5). Angenommen, es wurde zur Grammatik G2 folgende Xtext-DSL erstellt: grammar de.htwdd.sf.pl0v3.PL0v3 with org.eclipse.xtext.common.Terminals generate pL0v3 "http://www.htwdd.de/sf/pl0v3/PL0v3" Pl0v3 : pl0=Expr ; Expr returns Expr: (vz=Vz)? terme=Term eterme+=(Eterm)* ; Eterm returns Eterm: vze=Vz terme=Term ; Term: facte=Fact efacte+=(Efact)* ; KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 113 Efact: fze=Fz facte=Fact ; Fact: elemf = (Ident | Number | Kexpr) ; Kexpr: lpar=Lparen ex=Expr rpar=Rparen ; Vz: vz=("+" | "-") ; Fz: fz=("*" | "/") ; Ident : name=ID ; Number : wert=INT ; Lparen: lp=’(’ ; Rparen: rp=’)’ ; Es soll für eine DSL-Instanz (einen Ausdruck) automatisch eine Postfix-Notation erstellt werden. Es soll ferner Code für eine Kellermaschine generiert werden. Templates Da durch den auszuführenden Xtend-Code wesentlich Code durch String-Verkettung erzeugt wird, der zu weiten Teilen aus dem Xtend-Code übernommen wird, bietet Xtend eine vereinfachte Schreibweise (Template Expressions) an: def compile(Entity e)”’ package public class e.name{ } ”’ Ein Template wird umschlossen von drei einfachen Quotes. Der Templatetext kann durch ein Paar französischer Klammern („guillemets”, «... », einfügen erfolgt über das Kontextmenü) unterbrochen werden. In « » eingeschlossene Textteile werden ausgewertet. Ein Template ist ein Ausdruck und kann überall stehen, wo ein Ausdruck stehen kann. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 4.4 114 Xpand Xpand ist eine Sprache, die mit EMF-basierten Metamodellen umgehen kann. Mittels Xpand können Modelle weiter verarbeitet werden (Transformationen), die mit dem Xtext-Generator erzeugt wurden. Mit Xpand können domänenspezifische Sprachen in bekannte Programmiersprachen übersetzt werden. Xpand greift auf den abstrakten Syntaxbaum zu. Xpand-Template-Datei Algorithmus 4.1 Grundgerüst IMPORT EXTENSION Xpand kann durch die funktionale Sprache Xtend um zusätzliche Logik erweitert werden. Xtend kennt wie Xpand alle Knotentypen des abstrakten Syntaxbaumes. KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 4.5 Aspektorientierte Programmierung Zuerst wird ein AspectJ-Projekt angelegt: AOPDemo wird als Klasse angelegt: Tracing wird als Aspect angelegt: 115 KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD Die Ausführung: Ergebnis der Ausführung: 116 KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 4.6 117 Grafische Beschreibung einer DSL Die konkrete Syntax einer DSL kann auch grafisch beschrieben werden. Die grafische Notation wird in der Praxis oft durch UML-Diagramme realisiert. Beispiel: Entwicklung einer grafischen DSL für Ontologie-Darstellungen. 4.6.1 GMF Das Graphical Modeling Framework (GMF) basiert auf dem EMF. Es unterstützt die Generierung von grafischen Editoren aus EMF-Metamodellen mit Hilfe von Wizards. Zum Erstellen eines Editors sind folgende Schritte erforderlich, die in der EclipseView „GMF-Dashboard” dargestellt sind: 1. Erstellen eines Metamodells mit EMF. 2. Erstellen von GMF-Konfigurationsmodellen. 3. Generieren des Editors 4. Optional an dafür vorgesehenen Erweiterungspunkten Funktionalität hinzufügen (Java) Abbildung 4.6.1: GMF Dashboard GMF basiert auf dem Graphical Editing Framework (GEF). Das GEF [GEF]ist ein Framework zur Erstellung grafischer Editoren und gehört zum Eclipse Modeling Project. Es stellt u. a. folgende Funktionen zur Verf¨ugung: • Figuren und Formen, die sich miteinander verbinden lassen KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 118 • Ein Überblicksfenster zur schnellen Navigation • Eine Werkzeugleiste für die Erstellung und Markierung von Figuren • Grafische und hierarchische Visualisierung • Druckerausgabe Als Zielarchitektur für den GMF-Generator dient das Graphical Editing Framework (GEF). 4.6.2 Beispiel Anlegen eines Plug-in-Projekts und Erstellen eines grafischen Editorfensters. In der Manifest-DAtei müssen folgende Abhängigkeiten festgelegt werden: org.eclipse.ui org.eclipse.core.runtime 4.6.3 Beispiel: Erstellen eines grafischen Klasseneditors Es wird zunächst in Eclipse ein Ecore-Modell erstellt. Abbildung 4.6.2: Ecore-Modell KAPITEL 4. WERKZEUGE ZUR UNTERSTÜTZUNG DER MDSD 4.7 119 AndroMDA AndroMDA ist ein Framework für modellgetriebene Softwareentwicklung gemäß dem MDA-Paradigma. AndroMDA ist in Java implementiert und quelloffen. AndroMDA unterstützt die Erzeugung von Quellcode aus Plattform-unabhängigen Modellen (PIM). Als Modellierungssprache wird nur die UML unterstützt. 4.7.1 Beispiel Kapitel 5 Software Factories Der Inhalt dieses Kapitels basiert weitgehend auf der Diplomarbeit von S. Bley an der HTW Dresden [Ble08]. 5.1 Der Begriff „Software Factory” Der Begriff „Software Factories” stammt aus der Microsoft Software-Factory-Initiative und wird von Greenfield und Short in [GS06] erklärt. Es existiert ein enger Bezug zu „Product Line Engineering”. In einer Produktlinie (= Produktfamilie) werden ähnliche Softwareprodukte in einer einheitlichen Softwareentwicklungsumgebung hergestellt, die dynamisch an die Besonderheiten der einzelnen Produkte angepasst werden kann. „Software Factory” nach Bley [Ble08]: 1. Das gemeinsame Konzept der Produktfamilie ist in einer Domäne zusammengefasst 2. Festlegung definierter Punkte, an denen sich die Produkte unterscheiden Ein Generator erzeugt aus dem Modell der gemeinsamen Domäne die Artefakte für alle Familienmitglieder. Mit einer Software Factory können verschiedene Produkte einer Produktfamilie erzeugt werden. Zum Beispiel kann es sich bei der Produktfamilie um Java-EnterpriseAnwendungen handeln (vgl. [Ble08]). Eine Softwarefabrik ist eine für eine bestimmte Domäne angepasste IDE. Es kommen Wizards, Patterns, Frameworks, Templates, DSLs und dafür angepasste Editoren zum Einsatz. 120 KAPITEL 5. SOFTWARE FACTORIES 5.2 121 Anforderungen an eine Factory Die fachlichen Belange einer Domäne sind unabhängig von der vorgesehenen Zieltechnologie vom Anwendungsentwickler in einer DSL zu formulieren, die DSL muss für die Beschreibung der Fachlichkeit geeignet sein. Spezifika der Zieltechnologie (z.B. Plattformen, verwendete Frameworks) sollen für ein konkretes Produkt individuell auswählbar sein. Zieltechnologiespezifische Artefakte sollen dann aus dem fachlichen Modell generiert werden können. Eine „Cartridge” enthält die Funktionalität, die für die automatische Codeerzeugung aus Modellen notwendig ist. Die Erweiterung um neue Cartridges soll mit geringem Aufwand möglich sein. 5.3 Ein Fallbeispiel: Architektur von Java-Enterprise-Applikationen Das gemeinsame Merkmal der Produkte, die im folgenden Fallbeispiel mit der Software Factory erstellt werden, liegt darin, dass sie (Java-) Enterprise-Anwendungen sind. Das heißt, es handelt sich um verteilte Anwendungen, in denen Daten verarbeitet und persistent gespeichert werden, und die in der Regel eine Benutzerschnittstelle anbieten. Daraus ergibt sich die Domäne der Software Factory: die Architektur von Java-Enterprise-Anwendungen. Eine Besonderheit dieses Fallbeispiels besteht darin, dass viele Aspekte von JavaEE-Anwendungen bereits durch die Eclipse-IDE abgedeckt werden. Es bietet sich deshalb an, die Factory in die Eclipse-IDE zu integrieren. Ausgangspunkt der Betrachtungen ist das Domänenmodell einer Enterprise-Anwendung, nach E. Evans [Eva03]. Abb. 5.3.1 zeigt dieses Modell. Entitäten repräsentieren Objekte einer Domäne. Entitäten können über die Laufzeit des Systems hinaus fortbestehen. Wertobjekte (Value Objecs) besitzen keine Objektidentität und sollen unveränderlich sein. Services beschreiben domänenspezifisches Verhalten, das nicht Objektklassen in Methoden zugeordnet ist. Die Domäne wird in Module unterteilt, die hauptsächlich Funktionen gruppieren. Module sind untereinander lose gekoppelt. Darüber hinaus haben sich Muster etabliert, die sich mit der Lebenszyklusverwaltung von Objekten befassen. Die Muster Aggregat, Fabrik und Repository adressieren diese Problematik. Aggregate gewährleisten die Datenintegrität. Umfangreiche Erzeugungslogik wird in eigene Objekte - die Fabriken (Factories) - ausgelagert. Repositories kapseln den Zugriff auf persistierte Objekte. KAPITEL 5. SOFTWARE FACTORIES 122 Abbildung 5.3.1: Domänenmodell nach E. Evans 5.3.1 DSL Stefan Bley legt für die Entwicklung einer Factory für Enterprise-Applikationen die in Abb. 5.3.2 dargestellte DSL zugrunde. Es handelt sich um eine „architekturzentrierte” DSL. Eine Entität enthält eine Menge von Attributen. Die Beziehungen zwischen Entitäten werden durch Referenzen ausgedrückt. Attribute und Referenzen sind unter einer gemeinsamen Oberklasse Entity Feature zusammengefasst. Entit¨aten können auch Operationen enthalten, jedoch sollten diese sich nicht über den Bereich der Entität hinaus auswirken. Abbildung 5.3.2: Domänenmodell (= Metamodell) „Domain” von S. Bley Die statische Semantik des Metamodells beinhaltet Zusicherungen, die für ein Modell gelten müssen, damit es als gültig angesehen werden kann. In Abb. 5.3.4 sind solche Zusicherungen zusammengefasst. KAPITEL 5. SOFTWARE FACTORIES Abbildung 5.3.3: Vererbung Abbildung 5.3.4: Statische Semantik des Metamodells 123 KAPITEL 5. SOFTWARE FACTORIES 5.3.2 124 Konzept Ein Kern-Plug-in (Core) stellt die Basis des Systems dar (vgl. Abb. 5.3.5). Es übernimmt die Steuerung. Das Kern-Plug-in definiert Extension-Points, an die sich die Cartridges andocken. Eine GUI-Komponente realisiert die Integration in die grafische Benutzeroberfläche von Eclipse. Eine weitere Komponente beinhaltet die („Domain” genannte) DSL. Die DSL umfasst das Metamodell und die konkrete Syntax zur Modellierung des Domänenwissens. Cartridges besitzen das „Wissen”, wie aus den Modellen Zielartefakte generiert werden. Die Ablaufsteuerung der CArtridge wird über einen konfigurierbaren Workflow organisiert. Bei der Konfiguration wird die Ablaufreihenfolge der Workflowkomponenten festgelegt. Abbildung 5.3.5: Konzept der Software Factory 5.3.3 Implementierung Unterschiede zwischen den von einer Factory erzeugten Produkten liegen in der Fachlichkeit sowie in der Wahl der Technologie, mit der sie implementiert werden. Dabei dient die Java-Enterprise-Plattform als Basis. Die weiteren für eine Software verwendeten Technologien sind jedoch meist durch projektspezifische Rahmenbedingungen bestimmt und somit nicht für alle Produkte der Software Factory gleich. Diese variablen Eigenschaften sind in Bausteinen zusammengefasst, die Cartridges genannt KAPITEL 5. SOFTWARE FACTORIES 125 werden. Die als Beispiel realisierte Software Factory stellt eine Entwicklungsumgebung zur Verfügung, indem sie die IDE Eclipse durch Plugins erweitert. Dadurch muss kein weiteres Werkzeug in den Softwareentwicklungsprozess eingebunden werden. Die Cartridges werden ebenfalls als Eclipse-Plugins in die Software Factory integriert. Im Beispiel ist eine Cartridge ein Eclipse-Plug-in, das den Extension-Point com.saxsys.cartridge erweitert, der vom Software-Factory-Kern bereitgestellt wird. Verlangt wird: • Cartridge-ID • eine Workflow-Datei, die den Ablauf der Komponenten festlegt, • Angabe von weiteren Cartridges: – Erforderliche (requires) Cartridges müssen vor der betreffenden Cartridge ausgeführt werden und – eingeschlossene (advices) Cartridges werden während der Ausführung der betreffenden Cartridge von ihr aufgerufen. Über Schnittstellen können Cartridges Wissen austauschen. Es gibt verschiedene Ansätze für Schnittstellen: • Metamodell-Extensions, • Aspektorientierte Templates, • Java-Code. Cartridges sind oft auf die Funktionalität anderer Cartridges angewiesen (use). Metamodell-Extensions definieren zusätzliche Eigenschaften und Hilfsmethoden für Metamodellelemente. Sie bilden eine Programmierschnittstelle für andere Codebestandteile. So kann gewährleistet werden, dass mehrfach gebrauchter Code zentral gehalten wird. Mittels aspektorientierter Programmierung (AOP) ist es möglich, dass eine Cartridge zusätzliche Informationen in ein Artefact generieren kann, das bereits von einer anderen Cartridge erstellt wurde. Xtend stellt einen AOP-Mechanismus zur Verfügung (vgl. [Asp15]). Zur Arbeit mit AspectJ in Eclipse können die AspectJ Development Tools (AJDT) als Plug-in genutzt werden. Abb. 5.3.6 zeigt die Installation der notwendigen Plug-ins. Eher selten wird von der Möglichkeit Gebrauch gemacht, dass eine Cartridge JavaCode einer anderen Cartridge referenziert. Genutzt werden kann diese Möglichkeit zum Beispiel, um in den Workflow einer Cartridge Workflow-Komponenten anderer Cartridges einzubeziehen. KAPITEL 5. SOFTWARE FACTORIES 126 Abbildung 5.3.6: AJDT - update-Site Verwendete Hilfs-Plug-ins Bestimmte Plug-ins sind keine Cartridges, werden aber von Cartridges verwendet. So enthält ein spezielles Plug-in die in Check formulierten Validierungsregeln für Modelle der Domäne „Domain”. Diese werden z.B. aus der POJO-Creater-Cartridge heraus geprüft. Exemplarische Cartridges Module Project Creator ist eine Cartridge zur Erstellung von Projekten im EclipseWorkspace. Die Cartridge erstellt ein Java-Projekt (genauer: ein AJDT-Projekt (AspectJ Development Tools)) für jeden „Domain”-Modul. Nachfolgende Cartridges können Ihre Artefakte in dieses Projekt hinein speichern. Es werden Unterverzeichnisse für manuell erzeugte und für generierte Artefakte angelegt und in den classpath eingetragen. Der Module Project Creator erstellt außerdem ein Java-Projekt, welches alle Bibliotheken aus Cartridges enthält, die im Extension Point classpathContribution angegeben KAPITEL 5. SOFTWARE FACTORIES 127 werden. Artefakte werden nur generiert, wenn sie noch nicht vorhanden sind. POJO-Creator erzeugt Java-Klassen und AspectJ-Aspekte für die Elemente eines Domain-Modells. Generierte Klassen sind sog. Plain Old Java Objects (POJOs), die dadurch gekennzeichnet sind, dass sie keine weiteren Abhängigkeiten von Klassenbibliotheken oder Frameworks besitzen. Dadurch unterscheiden sie sich z.B. von Entity Beans (EJB). Die Cartridge prüft Zusicherungen, modifiziert das Modell und generiert Code-Artefakte. JPA Annotation Creator generiert Artefakte für das Persistenzframework JPA (Java Persitence API ). Es stellt eine einheitliche Schnittstelle für die Verwendung von objekt-relationalen Mappern bereit. Data Access Object Generator Der Zugriff auf persistente Objekte erfolgt über einheitliche Datenzugriffsschnittstellen (DAO), die für den jeweiligen Persistenzmechanismus implementiert werden müssen. Die Cartridge erstellt diese Schnittstelle für alle Entitäten des Domain-Moduls. JPA Data Access Object Generator Der Generator ist für die Implementation der mittels Data Access Object Generator erzeugten Schnittstellen zuständig. Spring 2.0 Service Beans Generator Die Cartridge erstellt Artefakte für das Spring-Framework. Durch die Verwendung von Dependency Injection (DI) können Abhängigkeiten zwischen Objekten „von außen” verwaltet werden, sie müssen nicht schon zur Übersetzungszeit festgelegt werden. 5.3.4 Installation der Factory Zur Installation sind zunächst die Plugins über den Update-Manager in Eclipse bereitzustellen. Es ist ein Softwareentwicklungsprojekt im Workspace anzulegen. Im Unterverzeichnis models ist das Domänenmodell bereitzustellen. Welche Cartridges beim Build angewendet werden, ist in den Software-Factory-Einstellungen festgelegt. KAPITEL 5. SOFTWARE FACTORIES 128 Literaturverzeichnis [Asp15] ; Xerox Corporation (Veranst.): The AspectJTM Programming Guide. https://eclipse.org/aspectj/doc/released/progguide/index. html. Version: 2015, Abruf: 09.06.2015 [Ble08] Bley, S.: Konzeption und Entwicklung einer Software Factory für JavaEnterprise-Anwendungen basierend auf der Eclipse-Plattform, Hochschule für Technik und Wirtschaft Dresden, Fakultät Informatik/Mathematik, Diplomarbeit, 2008 [CR09] Clayberg, E. ; Rubel, D.: Eclipse Plug-ins. Third Edition. AddisonWesley, 2009 [Dau08] Daum, Berthold: Rich-Client-Entwicklung mit Eclipse 3.3. 3., aktualisierte und erweiterte Auflage. dpunkt.verlag, 2008 [Ecl] Eclipse Project Site. URL: http://www.eclipse.org, [Eva03] Evans, E.: Domain-Driven Design: Tackling Complexity in the Heart of Software. Amsterdam : Addison-Wesley Longman, 2003 [GEF] Graphical Editing Framework Project Site. www.eclipse.org/gef, Abruf: 2.1.2008 [GS06] Greenfield, J. ; Short, K.: Software Factories - Moderne SoftwareArchitekturen mit SOA, MDA, Patterns und agilen Methoden. mitp-Verlag, 2006 www.softwarefactories.com [MOF05] Meta Obect Facility (MOF) Specification. (OMG), 2005 [Pop06] Object Management Group Popp, G.: Konfigurationsmanagement mit Subversion, Ant und Maven Grundlagen für Softwarearchitekten und Entwickler. dpunkt.verlag, 2006 129 LITERATURVERZEICHNIS 130 [SMSH07] Stahl, T. ; M.Völter ; S.Efftinge ; Haase, A.: Modellgetriebene Softwareentwicklung - Techniken, Engineering, Management. 2., aktualisierte und erweiterte Auflage. dpunkt.Verlag, 2007 [Som07] Sommerville, I.: Software Engineering. Addison-Wesley, 2007 [Ste88] Stetter, Franz: Theoretische Informatik. Springer-Verlag, 1988 [xte] Xtext - Open Source Framework für die Entwicklung von Programmiersprachen und domänenspezifischen Sprachen. http://www.eclipse.org/Xtext Index A abstrakte Syntax, 65 Activator-Klasse, 20 Agile Softwareentwicklung, 9 AndroMDA, 119 ANT, 8 Antlr, 102 AOP, 125 AOP-Mechanismus, 125 Assignment, 108 Export-Wizards, 36 B Build, 19 I IDE, 11 interne DSL, 73 C Cartridge, 124 CASE-Tools, 10 Chomsky-Hierarchie, 63 Class-Loader, 17 classpath, 126 D DSL, 73 E Eclipse, 11 Eclipse Update Manager, 43 Eclipse-Applikation, 106 Ecore, 74 EMF, 13, 74, 99 Entitäten, 121 Entity Beans, 127 Equinox, 17 F Feature, 43 Feature-Manifest-Editor, 43 Feature-Projekt, 43 G GEF, 99, 117 GMF, 99, 117 Grammatik, 62 J JFace, 12 JLex, 70 JPA, 127 K Konfigurationsmanagement, 8 konkrete Syntax, 65 kontextsensitiv, 65 L LISP, 73 M M2C, 74 M2M, 74 MANIFEST.MF, 17 Maven, 8 MDSD, 60 131 INDEX Mercurial, 8 Metametamodell, 73 Metamodell-Extensions, 125 Model Driven Architecture, 60 Module Project Creator, 126 N Nichtterminal, 63 O openArchitectureWare, 100 OSGi-Bundle, 17 P PDE, 19 PIM, 119 Plug-in-Loader, 16 Plug-ins, 11 plugin.xml, 17 POJO-Creator, 127 Produktionsregeln, 63 Programming, 9 R Regelgrammatik, 63 Rich Client Application, 51 Rich Client Platform, 16 Roundtrip Engineering, 9 Ruby, 73 S Semantik, 65 Services, 121 SEU, 10, 11 site.xml, 47 Softwareentwicklungsumgebungen, 10 Sprache, formale, 62 SQL, 73 SWT, 12 Syntax, 65 132 T Terminal, 63 Terminalsymbol, 63 tests-Plug-in, 86 Token, 107 TOPCASED, 11 Topcased, 12 Turing-unvollständig, 73 U Update Manager, 77 Update Site Project, 47 V ε-Sonderregel, 65 W Wirtsssprache, 73 X Xpand, 114 Xtend, 110, 114 Xtext, 101 Xtext-Language-Generator, 106 Xtext-nature, 106