Das GeneSEZ Generator Framework
Transcription
Das GeneSEZ Generator Framework
Das GeneSEZ Generator Framework Draft Das GeneSEZ Generator Framework Copyright © 2006 - 2012 GeneSEZ Research Group Draft Draft Draft Table of Contents I. Getting Started ......................................................................................................................................... 1 1. Hintergrund und Idee von GeneSEZ ................................................................................................. 2 1.1. MDA und MDSD in Kürze ...................................................................................................... 2 1.2. Idee des GeneSEZ Ansatzes ................................................................................................. 3 1.3. Überblick des GeneSEZ Ansatzes .......................................................................................... 4 2. Installation von GeneSEZ ................................................................................................................. 6 2.1. Konfiguration des Workspace ................................................................................................. 6 2.2. Art der Installation ................................................................................................................. 6 2.2.1. Installation des GeneSEZ Plug-Ins .............................................................................. 6 2.2.2. Plattform-Projekte im Workspace ................................................................................. 6 2.2.3. Metamodell und Plattform-Projekte im Workspace ........................................................ 7 2.3. GeneSEZ Eclipse Plug-In ...................................................................................................... 7 2.4. Abhängigkeiten zu anderen Eclipse Plug-Ins ........................................................................... 7 2.4.1. GeneSEZ 1.7 ............................................................................................................. 8 2.4.2. GeneSEZ 2.x ............................................................................................................. 8 2.5. GeneSEZ Repository ............................................................................................................. 9 2.6. GeneSEZ Eclipse Plug-In Projekte ......................................................................................... 9 3. GeneSEZ: Just Try It Out ............................................................................................................... 11 3.1. Checkout Beispielprojekt ...................................................................................................... 11 3.2. Projektstruktur ..................................................................................................................... 11 3.2.1. Generatorprojekt ....................................................................................................... 11 3.2.2. Anwendungsprojekt ................................................................................................... 12 3.3. Ausführen des Workflows .................................................................................................... 12 3.3.1. Hinweis GeneSEZ Version 1.6.0 ................................................................................ 12 3.4. Workflow Details .................................................................................................................. 13 3.5. Generierter Quellcode .......................................................................................................... 13 II. Benutzer-Referenz .................................................................................................................................. 14 4. Das GeneSEZ-Logging-Konzept ...................................................................................................... 16 4.1. Java .................................................................................................................................... 16 4.2. Skripten + Templates ........................................................................................................... 16 4.3. Konfiguration ....................................................................................................................... 16 5. GeneSEZ Workflow Komponenten .................................................................................................. 17 5.1. Allgemeine Workflow Komponenten ...................................................................................... 17 5.1.1. Uml2GeneSEZ .......................................................................................................... 17 5.1.2. Validator ................................................................................................................... 18 5.1.3. Serializer .................................................................................................................. 18 5.1.4. Generator ................................................................................................................. 19 5.2. Plattformspezifische Workflow Komponenten ......................................................................... 20 5.2.1. Java Generator ......................................................................................................... 20 5.2.2. PHP Generator ......................................................................................................... 20 5.2.3. C# Generator ........................................................................................................... 21 6. Generierung von Zugriffsfunktionen ................................................................................................. 22 6.1. Spezifikation im Modell ........................................................................................................ 22 6.2. Auswertung ......................................................................................................................... 22 6.3. Konfiguration der Modelltransformation ................................................................................. 24 6.4. Beispiel ............................................................................................................................... 24 7. Externe Typen im Metamodell ........................................................................................................ 25 7.1. Definition im UML-Modell ..................................................................................................... 25 7.2. Definition im Workflow ......................................................................................................... 25 7.3. Umgang in xPand-Templates ............................................................................................... 25 7.4. Beispiel ............................................................................................................................... 25 7.4.1. Verwendung eines Stereotypes zur Annotation einer Klasse ........................................ 26 7.4.2. Verwendung eines Stereotypes zur Annotation eines Packages ................................... 26 7.4.3. Verwendung der Namen von Packages ..................................................................... 26 7.4.4. Mapping aller Klassen, die direkt im Modell enthalten sind ........................................... 26 8. Type Mapping ................................................................................................................................ 27 8.1. Konzept des Type-Mapping .................................................................................................. 27 iii Draft Das GeneSEZ Generator Framework Draft 8.2. Aufbau einer Type-Mapping Datei ........................................................................................ 8.2.1. Includes .................................................................................................................... 8.2.2. Multi-Value Types ..................................................................................................... 8.2.3. Primitive Types und External Types ........................................................................... 8.2.4. Kontexte ................................................................................................................... 8.3. Verwendung des Type-Mappings .......................................................................................... 8.4. Zusammenhang Type-Mapping + Naming Conventions .......................................................... 9. Statistik-Komponente ...................................................................................................................... 9.1. Funktionsumfang ................................................................................................................. 9.2. Workflow-Konfiguration ........................................................................................................ 9.3. Logging ............................................................................................................................... 9.4. Hinweis zu den Diagrammen in der Statistik ......................................................................... 9.5. Statstik-Übersicht am Beispiel .............................................................................................. 10. GeneSEZ UML Profil .................................................................................................................... III. Plattform Projekte .................................................................................................................................. 11. PHP Plattform Projekt ................................................................................................................... 11.1. Beispielprojekte ................................................................................................................. 11.2. Modellierung für PHP ......................................................................................................... 11.3. PHP5 ................................................................................................................................ 11.4. QuickForm ......................................................................................................................... 11.4.1. Erstellen von QuickForm Objekten ........................................................................... 11.4.2. Konvertierung von Formularen zu Domain Objekten .................................................. 11.4.3. Benutzerspezifische Definitionen .............................................................................. 11.4.4. Spezielle Attribute ................................................................................................... 11.4.5. Beispielcode ........................................................................................................... 11.5. Weitere Frameworks .......................................................................................................... 11.6. MDSD für das Dynamic Data Model (DDM) ........................................................................ 11.6.1. Erstellung eines UML Modells .................................................................................. 11.6.2. Mapping von UML Datentypen auf DDM Typen ........................................................ 11.6.3. Mapping von UML Klassen auf DDM Klassen ........................................................... 11.6.4. Mapping von UML Attribute auf DDM Attribute .......................................................... 11.6.5. Mapping von UML Assoziationen auf DDM Assoziationen .......................................... 11.6.6. Workflow Definition ................................................................................................. 12. Java Plattform Projekt .................................................................................................................. 12.1. Beispielprojekte ................................................................................................................. 12.2. Modellierungshinweise zur Verwendung der Plattform-Erweiterungen .................................... 12.2.1. Automatische Quellcode-Ergänzung ......................................................................... 12.3. JPA (Java Persistence API) ............................................................................................... 12.3.1. Das UML-Profil "jpa" ............................................................................................... 12.3.2. Eine Einführung - Die (Persistent) Entity ................................................................... 12.4. EJB 3 (Enterprise JavaBeans) ............................................................................................ 12.5. Seam 2 ............................................................................................................................. IV. Weitere GeneSEZ Projekte .................................................................................................................... 13. metaframework ............................................................................................................................. 13.1. Yet Another PHP Framework? ........................................................................................... 13.2. Anwendungsarchitektur ...................................................................................................... 13.3. Gliederung einer Anwendung ............................................................................................. 13.4. Infrastruktur-Konzepte ........................................................................................................ 13.4.1. Plug-Ins .................................................................................................................. 13.4.2. Service Registry ...................................................................................................... 13.4.3. Plug-In Registry, Interceptor Registry, Extension Registry .......................................... 13.4.4. Resolver ................................................................................................................. 13.4.5. Locator ................................................................................................................... 13.5. Konzepte zur Anwendungsentwicklung ................................................................................ 13.5.1. Request Handler ..................................................................................................... 13.5.2. Datentransferobjekte ............................................................................................... 13.5.3. Rendering ............................................................................................................... 13.5.4. Interceptors ............................................................................................................. 13.5.5. Extensions und Contributions ................................................................................... 13.6. Weitere Konzepte zur effektiven Anwendungsentwicklung .................................................... iv 28 28 28 29 29 30 31 32 32 32 33 33 34 37 38 39 39 39 40 41 41 41 42 42 42 43 43 44 44 45 45 45 46 47 47 47 48 48 49 50 52 52 53 55 55 55 56 56 57 57 58 58 59 59 59 60 61 61 61 62 Draft Das GeneSEZ Generator Framework Draft 13.6.1. Composite-Struktur bei Request Handlern ................................................................ 62 13.6.2. Delegate- und Decorator-Pattern bei Request Handlern ............................................. 63 v Draft Draft List of Figures 1.1. Vereinfachte Darstellung generativer, modellgetriebener Ansätze ............................................................. 2 1.2. Schematischer Überblick des GeneSEZ Ansatzes ................................................................................... 4 6.1. Plattformunabhängige Teil des GeneSEZ UML Profils ........................................................................... 22 6.2. Auswertung der Modellierungsmöglichkeiten ......................................................................................... 23 6.3. Auswertung des Stereotyps accessor ................................................................................................. 23 8.1. Das GeneSEZ Typ-System .................................................................................................................. 27 9.1. Übersicht zur Quellcode Zusammensetzung .......................................................................................... 34 9.2. Details zu den einzelnen Quellcodedateien ........................................................................................... 35 9.3. Zusammensetzung Quellcodeverzeichnis .............................................................................................. 35 9.4. Statistik zum Quellcode ohne Tests ...................................................................................................... 36 11. Übersicht zur aktuellen Plattformunterstützung ....................................................................................... 38 11.1. UML Profil für die PHP Plattform ........................................................................................................ 40 11.2. UML Profil für das DDM .................................................................................................................... 44 12.1. Mapping des Stereotypen "jpaPersistent" auf die Annotationen "@Entity" .............................................. 48 12.2. UML-Profil der Java Plattform-Erweiterung JPA ................................................................................... 49 12.3. Persistent Entity mit den Stereotypen "jpaPersistentEntity" und "jpaPrimaryKey" .................................... 50 12.4. Persistent Entity mit unique-Attribut und ohne jpaPrimaryKey ............................................................... 51 12.5. Persistent Entity ohne technischen Primärschlüssel ............................................................................. 52 13.1. Architektur einer Anwendung basierend auf dem metaframework ......................................................... 55 13.2. URL-Pattern zur Gliederung einer Anwendung .................................................................................... 56 13.3. UML Modell der Klasse Context ......................................................................................................... 56 13.4. UML Modell des Plug-In Konzepts ...................................................................................................... 57 13.5. UML Modell der Service Registry ....................................................................................................... 58 13.6. UML Modell der Plug-In, Interceptor und Extension Registry ................................................................ 58 13.7. UML Modell des Resolvers ................................................................................................................ 59 13.8. UML Modell des Locators .................................................................................................................. 59 13.9. UML Modell der Request Handler ....................................................................................................... 60 13.10. UML Modell der Datentransferobjekte ............................................................................................... 60 13.11. UML Modell des Rendering .............................................................................................................. 61 13.12. UML Modell der Interceptoren .......................................................................................................... 61 13.13. Definition der Composite-Struktur von Request Handlern in UML ........................................................ 63 13.14. UML Modell des Decorate Request Handlers .................................................................................... 64 vi Draft Draft List of Tables 11.1. PHP Plattform Features ..................................................................................................................... 39 11.2. Unterstützung der Abbildung von UML Konzepten in PHP ................................................................... 40 12.1. Java Plattform-Erweiterungen ............................................................................................................. 47 vii Draft Draft Part I. Getting Started In Chapter 1, Hintergrund und Idee von GeneSEZ wird etwas Hintergrundwissen zu modellgetriebenen Ansätzen und GeneSEZ vermittelt. Für einen praktischen Einstieg kann direkt zu Chapter 2, Installation von GeneSEZ gesprungen werden. Draft Draft Chapter 1. Hintergrund und Idee von GeneSEZ Nach einem kleinen Einblick in modellgetriebene Ansätze wird die Idee des GeneSEZ Ansatzes beschrieben, gefolgt von einem kleinen Überblick von GeneSEZ. 1.1. MDA und MDSD in Kürze Die modellgetriebenen Ansätze beschäftigen sich allgemein mit der effektiven Nutzung von Anwendungsmodellen in der Softwareentwicklung. Effektiv meint hier die Nutzung, die über Dokumentation und Überblick der Software hinaus geht. Dafür gibt es zwei unterschiedliche Ansätze: interpretativ Modelle werden zur Laufzeit der Anwendung interpretiert. generativ Modelle werden zur Entwicklungszeit genutzt und es wird ein Teil der Software automatisch aus den Modellen abgeleitet. Wir beschränken uns hier auf die generativen Ansätze. Die MDA (Model Driven Architecture) ist eine Sammlung von Spezifikationen [http://www.omg.org/mda/specs.htm] ist ein Ansatz zur teilautomatisierten Softwareentwicklung der OMG (Object Managment Group [http://www.omg.org/]). Die MDSD (Model Driven Software Development, englisch für Modellgetriebene Softwareentwicklung) bezeichnet die pragmatische Vorgehensweise zur Generierung von Softwareartefakten aus Modellen. Die Modelle müssen nicht zwingend formal sein. Sie müssen lediglich deterministisch auswertbar sein. Dies wird meist durch ein Metamodell sichergestellt. Die Figure 1.1, “Vereinfachte Darstellung generativer, modellgetriebener Ansätze” zeigt eine vereinfachte Darstellung generativer modellgetriebener Ansätze. Figure 1.1. Vereinfachte Darstellung generativer, modellgetriebener Ansätze Anwendungsmodelle werden durch Transformationen in Quellcode transformiert. Dabei können Transformationen in vorgelagerten Schritten Modelle verändern oder Modelle aus anderen erstellen. Im Kontext der MDA werden Modelltransformationen auch Mapping Functions genannt. Die MDA führt weiterhin die Begriffe Platform Independent Model (PIM) und Platform Specific Model (PSM) ein, lässt die konkrete Definition sowie die Unterscheidung dieser aber offen als Matter of Degree. Als Ziele generativer, modellgetriebener Ansätze werden meist die Wiederverwendung von Architekturen, die gleichbleibend hohe Qualität des Quellcodes sowie die Steigerung der Entwicklungsgeschwindigkeit genannt. In einem generativen, modellgetriebenen Entwicklungsprozess entsteht eine nicht zu verachtende Menge an Quellcodeartefakten (z.B. Transformationsbeschreibungen (Quellcodeschablonen/Templates, Skripte), Komponenten) zur automatisierten Generierung von Quellcode aus Modellen. Die Erstellung dieser Artefakte ist meist aufwändiger, als die manuelle Implementierung des Quellcodes den diese Artefakte erzeugen. Um die oben genannten Ziele zu erreichen, sollten die Quellcodeartefakte des Entwicklungsprozesses eine hohe Wiederverwendung aufweisen. Der projektübergreifende Einsatz sollte daher angestrebt werden. Da alle Quellcodeartefakte eines generativen, modellgetriebenen Entwicklungsprozesses von dem verwendeten Metamodell abhängig sind, ist der Stellenwert der im Entwicklungsprozess genutzten Metamodelle relativ hoch. 2 Draft Hintergrund und Idee von GeneSEZ Draft 1.2. Idee des GeneSEZ Ansatzes In der MDA/MDSD Vorgehensweise zur Softwareentwicklung werden erstellte Anwendungsmodelle automatisch durch Modelltransformationen in Quellcode überführt. Eine MDSD-Plattform stellt hierfür die folgenden Modelltransformationen unterstützen: Modell-zu-Modell Transformationen Zur Erstellung neuer Modelle mit der Möglichkeit verschiedene Modellierungssprachen als Quelle und Ziel zu nutzen Modellmodifikationen Verändern ein Modell, meist um Informationen abzuändern oder weitere hinzuzufügen Modell-zu-Text Transformationen Werden genutzt um Quellcode und andere notwendige Dateien für eine Software zu generieren Modell-zu-Modell Transformationen und Modellmodifikationen stellen eine Vorverarbeitung von Modellen sicher während letztlich Modell-zu-Text Transformationen den Quellcode einer Software erzeugen. Das Transformationsziel ist meist eine objektorientierte Programmiersprache. Je ähnlicher die Konzepte der Programmiersprache mit der in Modellierungssprachen verankerten sind, desto einfacher lassen sich Modelltransformationen erstellen, die beide Konzepte aufeinander abbilden. Weiterhin werden die Modelltransformationen dadurch intuitiver und wartbarer. Bei den Modellierungssprachen für MDSD-Plattformen sind UML sowie DSLs weit verbreitet. Die UML stellt objektorientierte Modellierungskonzepte zur Verfügung und bietet die richtige Abstraktionsebene zur Quellcodegenerierung. Leider entwickelte sich die UML mit einer steigenden Anzahl von Modellierungskonzepten zu einer für Modelltransformationen ungeeigneten Modellierungssprache: • sie wurde ziemlich komplex • sie enthält Informationen die für die Programmcodegenerierung uninteressant ist • es gibt keinen Überblick von dem UML Metamodell aus dem hervorgeht wie auf bestimmte Informationen zugegriffen werden kann • sie enthält Informationen über die grafische Darstellung von Modellelementen, z.B. den Bildern von Stereotypen • viele Ansätze zeigen auf, das nur ein Teil der UML sinnvoll für MDA/MDSD-Plattformen nutzbar ist (u.a. Stephen J. Mellor and Marc Balcer. Executable UML: A Foundation for Model-Driven Architectures. Addison-Wesley Longman Publishing Co., Inc., Boston, MA, USA, 2002. Foreword by Ivar Jacoboson. und Paul Baker, Zhen Ru Dai, Jens Grabowski, Øystein Haugen, Ina Schieferdecker, and Clay Williams. Model-Driven Testing: Using the UML Testing Profile. Springer-Verlag New York, Inc., Secaucus, NJ, USA, 2007.) Durch die komplexe und normalisierte Struktur des Metamodells ist UML relativ ungeeignet für Modelltransformationen. Erschwerend kommt hinzu das selbst die UML Spezifikation keine Übersicht des Metamodells bereit stellt. Neben der UML gibt es die DSLs welche Konzepte eines Anwendungsbereich oder technische Aspekte zur Beschreibung von Modellen nutzen. Dabei sind vor allem die fachlichen DSLs interessant, da die Modelle mit den Experten der Anwendungsbereiche diskutiert werden können. Solche Modellierungssprachen vergrößern jedoch den Unterschied zwischen Modellierungskonzepten und den Konzepten der Programmiersprachen. Dies führt einerseits zu komplexeren Modelltransformationen und andererseits zu Modelltransformationen die anwendungsbereichspezifisch sind. Von der Perspektive der Abbildung führt dies bei verschiedenen Modellierungssprachen zur kontinuierlichen Neuerstellung von Modelltransformationen für die selbe Programmiersprache da von verschiedenen Modellierungssprachen aus transformiert wird. Basierend auf den Konsequenzen des Einsatzes von UML bzw. DSLs war die Idee bei GeneSEZ nicht direkt die Metamodelle mit denen die Modelle erstellt wurden auszuwerten sondern ein separates Metamodell für eine MDSD-Plattform zu erstellen und dieses auszuwerten. Dessen Struktur sollte geeignet für die Auswertung durch Modelltransformationen sein und nur Informationen beinhalten die für die Quellcodegenerierung von Interesse sind. 3 Draft Hintergrund und Idee von GeneSEZ Draft Dies führt zu einem Metamodell welches speziell für die letzten Modelltransformationsschritte in Quellcode geeignet ist. Für die MDSD-Plattform bedeutet dies eine stabile, wiederverwendbare und investitionssichere Basis für die Quellcodegenerierung. Mit den Begriffen der MDA kann das GeneSEZ Metamodell als abstracting mapping klassifiziert werden, da viele Informationen in der UML uninteressant für die Quellcodegenerierung sind. Mit den Konzept der DSLs kann es als DSL für Modelltransformationen, speziell von Modell-zu-Text Transformationen gesehen werden. In Bezug zu UML ergibt sich ein einfacheres und knapperes Metamodell für Modelltransformationen. Mit Bezug auf fachliche DSLs wird ein Zwischenschritt in Modelltransformationen eingeführt welche das anwendungsbereichspezifische Metamodell auf das GeneSEZ Metamodell abbildet und dieses dann in einem weiteren Schritt in Quellcode abgebildet wird. Dadurch werden komplexere direkte Abbildungen in Quellcode vermieden und die Modelltransformationen des GeneSEZ Metamodells in Quellcode werden über verschiedene Anwendungsbereiche hinweg wiederverwendbar. 1.3. Überblick des GeneSEZ Ansatzes Basierend auf dem GeneSEZ Metamodell entstand eine MDSD-Plattform die in Figure 1.2, “Schematischer Überblick des GeneSEZ Ansatzes” schematisch dargestellt ist. Figure 1.2. Schematischer Überblick des GeneSEZ Ansatzes Dabei sind für den Hauptbestandteil die folgenden Konzepte charakteristisch: • Das GeneSEZ Core Metamodell als zentraler Bestandteil welches die Informationen zur Quellcodegenerierung in aufbereiteter Form zur Verfügung stellt und für Modelltransformationen genutzt wird. • Modelladapter werden genutzt um GeneSEZ Modelle mit Informationen aus Anwendungsmodellen zu erstellen. • Die GeneSEZ Komponenten als Funktionsbibliothek sowie als gemeinsame Basis für die Erzeugung von Quellcode für verschiedene Programmiersprachen. • Die Plattformprojekte stellen Quellcodeschablonen (Templates) für die jeweiligen Programmiersprachen, sowie Libraries und Frameworks zur Quellcodegenerierung bereit. 4 Draft Hintergrund und Idee von GeneSEZ Draft Anwendungsmodelle können dabei unabhängig von der MDSD-Plattform erstellt und ausgearbeitet werden. Durch Modelladapter werden die für die Quellcodegenerierung notwendigen Informationen aus den Anwendungsmodellen extrahiert und in GeneSEZ Modelle überführt. Basierend auf diesen GeneSEZ Modellen können weitere Modelltransformationen erfolgen bis letztendlich eine Modell-zu-Text Transformation die Quellcodegenerierung durchführt und automatisch Quellcodeartefakte erzeugt. Meist kann der Quellcode nicht sinnvoll vollständig erzeugt werden, wodurch dieser mit manueller Implementierung noch vervollständigt wird. Dabei ist es nicht notwendig diese Schritte nacheinander abzuarbeiten. Ist eine erste Version des Anwendungsmodells verfügbar so kann dieses in ein GeneSEZ Modell überführt werden und anschließend Quellcode erzeugt werden. Dieser kann auch bereits mit manueller Implementierung ergänzt werden. Während das Anwendungsmodell weiter ausgearbeitet wird, kann dieses regelmäßig in Quellcode transformiert werden wobei die manuelle Implementierung erhalten bleibt. Dieses iterative Vorgehen erlaubt den Rückfluss an Informationen die aus der Implementierung entstehen zur Anwendungsmodellierung wo diese zur Verbesserung des Anwendungsmodells beitragen können. Ein wesentlicher Vorteil bei der Entwicklung von Modelltransformationen ist die Möglichkeit das GeneSEZ Metamodell auf zwei A4 Seiten vollständig auszudrucken und als Übersicht zu nutzen, wie auf bestimmte Informationen zugegriffen werden kann. 5 Draft Draft Chapter 2. Installation von GeneSEZ GeneSEZ basiert auf der Eclipse IDE und benötigt mindestens Version 3.3. Es können sowohl Eclipse Distributionen von der Eclipse Homepage [http://www.eclipse.org/downloads/], von der GeneSEZ Website [http:// www.genesez.org/wordpress/download/], dem GeneSEZ Build Server [http://download.genesez.org/] oder bereits vorhandene genutzt werden. Die GeneSEZ Eclipse Distributionen des GeneSEZ Build Servers [http://download.genesez.org/] bieten einen schnellen Einstieg, da diese bereits alle notwendigen Plug-Ins enthalten. 2.1. Konfiguration des Workspace Für GeneSEZ Projekte sollte der Workspace UTF-8 als Standard Encoding nutzen. Dies kann über Window » Preferences, General » Workspace in der Gruppe Text file encoding eingestellt werden. Weiterhin müssen openArchitectureWare bzw. XTend/XPand mit den zu verwendenten Metamodellen konfiguriert werden. Diese sollten über Window » Preferences, dann openArchitectureWare bzw. XTend/XPand in der folgenden Reihenfolge eingestellt sein: • EMF Metamodels (aktiviert) • UML2 Profiles (aktiviert) • JavaBeans Metamodel (aktiviert) Alle anderen werden nicht benötigt und müssen somit nicht aktiviert werden. 2.2. Art der Installation Die Installation von GeneSEZ kann einiges an zeitlichen Aufwand verursachen, daher sollte die Intention vorher festgelegt werden: • Änderungen am GeneSEZ Metamodell • Änderungen an Templates und Skripten zur Quellcodegenerierung, die nicht sinnvoll mit XPand AOP [http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.m2t/org.eclipse.xpand/doc/org.eclipse.xpand.doc/ html/xpand_reference.html?root=Modeling_Project&view=co] durchgeführt werden können Treffen die beiden Punkte nicht zu, genügt die Installation des GeneSEZ Plug-Ins. Trifft nur der letzte Punkt zu, kann durch Nutzung des Metamodells aus dem GeneSEZ Plug-In einiges an Aufwand eingespart werden. Treffen beide Punkte zu sollte GeneSEZ komplett in dem Workspace liegen. 2.2.1. Installation des GeneSEZ Plug-Ins Für eine Installation von GeneSEZ in ein vorhandenes Eclipse mit dem Eclipse Update Manager die notwendigen Features der Eclipse Plug-Ins unter Section 2.4, “Abhängigkeiten zu anderen Eclipse Plug-Ins” sowie das GeneSEZ Eclipse Plug-In installieren. Bei GeneSEZ Eclipse Distributionen des GeneSEZ Build Servers [http://download.genesez.org/] ab Eclipse Version 3.4 wird das dropins Verzeichnis genutzt. Das GeneSEZ Plug-In befindet sich im Verzeichnis dropins/ genesez und die für GeneSEZ notwendigen Plug-Ins im Ordner dropins/prerequisites. Soll GeneSEZ in ein vorhandenes Eclipse ab Version 3.4 installiert werden, können einfach diese beiden Verzeichnisse in das dropins Verzeichnis der jeweiligen Eclipse kopiert werden. (Die Namen der Verzeichnisse genesez und prerequisites können natürlich beliebig umbenannt werden!). 2.2.2. Plattform-Projekte im Workspace Voraussetzung hierfür ist die Installation des GeneSEZ Plug-Ins. Zusätzlich werden die gewünschten PlattformProjekte (alle Plug-In Projekte mit de.genesez.platforms im Namen) aus dem GeneSEZ Repository 6 Draft Installation von GeneSEZ ausgecheckt. Ist das Ziel Java Quellcode, betrifft es das Projekt das Projekt de.genesez.platforms.common. Draft de.genesez.platforms.java und optional Wichtig ist hierbei die Wahl einer passenden Version der Plattform-Projekte zum GeneSEZ Plug-In. Daher sollten Tag oder Branch-Versionen genutzt werden. 2.2.3. Metamodell und Plattform-Projekte im Workspace Bei dieser Art der Installation ist GeneSEZ komplett als Quellcode im Workspace vorhanden. Dazu müssen die folgenden Schritte ausgeführt werden. 1. Checkout der benötigten GeneSEZ Eclipse Plug-In Projekte aus dem GeneSEZ Repository (Tag oder BranchVersionen sollten bevorzugt werden) 2. Konfiguration von Verzeichnispfaden, siehe Section 2.2.3.1, “Konfiguration der environment.properties” 3. Erstellung der GeneSEZ Metamodell-Implementierung, siehe Section 2.2.3.2, “Erstellung der MetamodellImplementierung” 2.2.3.1. Konfiguration der environment.properties Im Projekt de.genesez.build im Ordner build muss die Datei environment.properties angelegt werden. Hierzu kann die Datei environment.properties.template als Vorlage genutzt werden, welche sich im selben Verzeichnis befindet. Die folgenden Eigenschaften sind obligatorisch: ECLIPSE_HOME spezifiziert das eclipse home directory, d.h. dort wo eclipse.exe bzw. eclipse als ausführbare Datei liegt MAGICDRAW_DIR spezifiziert das MagicDraw home directory, d.h. das Verzeichnis wo MagicDraw installiert oder entpackt wurde Die anderen Eigenschaften können ignoriert werden und nicht nicht notwendig, um das Metamodell zu erstellen. 2.2.3.2. Erstellung der Metamodell-Implementierung Die Generierung der Implementierung des GeneSEZ-Metamodells erfolgt mit Hilfe von EMF. Dazu muss das BuildSkript build.xml im build-Ordner des Metamodell-Projektes de.genesez.metamodel ausgeführt werden. Zum Ausführen den Menüpunkt Run As » Ant Build... wählen und im Tab JRE den Punkt Run in same JRE as the workspace wählen. Hinweis: Zeigt die Umgebungsvariable JAVA_HOME auf eine JRE und nicht auf einen JDK, können die ANT Skripte nicht ausgeführt werden, da diese den Java Compiler aufrufen. Nachdem die Metamodell-Implementierung generiert wurde, sollte sich das GeneSEZ-Framework genauso nutzen lassen, wie wenn die Plug-Ins installiert worden wären. 2.3. GeneSEZ Eclipse Plug-In Homepage http://www.genesez.org/ Update Site http://updatesite.genesez.org/site.xml Abhängigkeiten EMF, EMF UML, openArchitectureWare 2.4. Abhängigkeiten zu anderen Eclipse Plug-Ins An dieser Stelle muss zwischen der GeneSEZ Version 1.7 und 2.x unterschieden werden. Während die Versionen 1.7 auf openArchitectureWare (oAW) basieren, wird in den Versionen 2.x die im Eclipse Modeling Framework (EMF) integrierten Modeling Workflow Engine (MWE) verwendet. 7 Draft Installation von GeneSEZ Draft 2.4.1. GeneSEZ 1.7 2.4.1.1. Eclipse Modeling Framework (EMF) Homepage http://www.eclipse.org/modeling/emf/ Update Site http://download.eclipse.org/modeling/emf/updates/releases/ Version 2.3.x benötigte Features • Eclipse Modeling Framework (EMF) Runtime + End-User Tools (Identifier: org.eclipse.emf.feature.group) 2.4.1.2. EMF UML Homepage http://www.eclipse.org/modeling/mdt/?project=uml2 Update Site http://download.eclipse.org/modeling/mdt/updates/releases/ Version 2.1.x benötigte Features • UML2 End-User Features (Identifier: org.eclipse.uml2.feature.group) Abhängigkeiten EMF 2.4.1.3. openArchitectureWare Homepage http://openarchitectureware.org/ Version 4.3.1 benötigte Features • openArchitectureWare libraries (Identifier: org.openarchitectureware.lib.feature.feature.group) • openArchitectureWare core (Identifier: org.openarchitectureware.core.feature.feature.group) • openArchitectureWare plugins (Identifier: org.openarchitectureware.plugins.feature.feature.group) • openArchitectureWare uml2 adapter (Identifier: org.openarchitectureware.uml2.adapter.feature.group) Abhängigkeiten EMF, EMF UML 2.4.2. GeneSEZ 2.x Die einfachste Art und Weise die benötigten Plugins für GeneSEZ 2.x zu installieren ist die Verwendung von Eclipse Helios oder neuer. In diesen Versionen können die benötigten Plugins über die Update-Seite des jeweiligen Releases (http://download.eclipse.org/releases/[releaseName]) installiert werden. GeneSEZ funktioniert sowohl mit 8 Draft Installation von GeneSEZ Draft 32Bit- als auch 64Bit-Versionen von Eclipse und/oder Java. Ab der Version 2.1 wird Java in der Version 7 vorausgesetzt. 2.4.2.1. Modeling Workflow Engine (MWE) Homepage http://www.eclipse.org/projects/project.php?id=modeling.emf.mwe unterstützte Versionen 1.0.x, 1.1.x, 2.0.x benötigte Features • MWE SDK (Identifier: org.eclipse.emf.mwe.sdk.feature.group) • MWE 2 language SDK (Identifier: org.eclipse.emf.mwe2.language.sdk.feature.group) • MWE 2 runtime SDK (Identifier: org.eclipse.emf.mwe2.runtime.sdk.feature.group) 2.4.2.2. Xpand Homepage http://www.eclipse.org/modeling/m2t/?project=xpand unterstützte Versionen 1.0.x, 1.1.x benötigte Features • Xpand SDK (Identifier: org.eclipse.xpand.sdk.feature.group) 2.5. GeneSEZ Repository Der Quellcode des GeneSEZ-Frameworks wird in einem Subversion-Repository verwaltet. Repository URL http://svn.genesez.org/genesez/ Im Repository wird das Standard-Repository-Layout von Subversion mit trunk, branches und tags genutzt. Alle stabilen Releases sind als Tag verfügbar. Die branches sind die Entwicklungspfade, die die Releases hervorbringen. Im trunk befinden sich dann alle Projekte, also auch solche, die noch zu keinem Release gehören. Neben diesem Standard-Subversion-Repository Layout gibt es im GeneSEZ Repository zwei weitere Top-Level Verzweigungen: examples Hier befinden sich alle GeneSEZ Beispielprojekte für die verschiedenen Plattformen. projects Hier befinden sich weitere GeneSEZ Projekte, die nicht direkt etwas mit dem GeneSEZ Generator Framework zu tun haben müssen. Hier befindet sich aber beispielsweise die PHP Bibliothek zum Assoziationshandling. 2.6. GeneSEZ Eclipse Plug-In Projekte Das GeneSEZ Framework besteht aus einem Set von Eclipse-Projekten. Die folgenden Projekte sind für die Benutzung des GeneSEZ-Frameworks erforderlich: de.genesez.build Enthält ANT-Build-Skripte, die von den anderen Projekten referenziert werden. de.genesez.metamodel Enthält das GeneSEZ-Metamodel. 9 Draft Installation von GeneSEZ Draft de.genesez.platforms.common Enthält allgemeine Komponenten und Skripte, die von den Plattform-Projekten genutzt werden. Weiterhin ist für die Benutzung des GeneSEZ-Frameworks noch mindestens eines der folgenden Plattformprojekte erforderlich, je nachdem für welche Plattform Quellcode generiert werden soll: de.genesez.platforms.java Notwendig um Java-Quellcode zu generieren. de.genesez.platforms.dotnet Notwendig um C#-Quellcode zu generieren. de.genesez.platforms.cpp Notwendig um C++-Quellcode zu generieren. de.genesez.platforms.php Notwendig um PHP-Quellcode zu generieren. Die weiteren Projekte sind für die Nutzung von GeneSEZ nicht unbedingt notwendig: de.genesez.features Das Eclipse Projekt welches GeneSEZ als Eclipse-Feature zur Verfügung stellt. de.genesez.updatesite Das Eclipse Projekt um GeneSEZ auf einer Update-Site zu publizieren. de.genesez.manual Die Dokumentation zu GeneSEZ. de.genesez.core Ist ein Projekt zur besseren Integration in die Eclipse IDE, u.a. mit Wizzards. Hinweis: Einige Plattform-Projekte haben Abhängigkeiten zu diesem Projekt und werden fehlerhaft markiert, wenn dieses Projekt nicht vorhanden ist. Dennoch ist dieses Projekt nicht unbedingt erforderlich und GeneSEZ funktioniert ohne dieses. 10 Draft Draft Chapter 3. GeneSEZ: Just Try It Out Dieser Artikel verdeutlicht die Funktionweise und Anwendung des GeneSEZ-Frameworks an einem kleinen Beispiel. Dazu wird ein Projekt aus dem GeneSEZ-Repository ausgecheckt, die Projektstruktur erläutert und ein vorhandenes UML-Modell in Quellcode transformiert. 3.1. Checkout Beispielprojekt Um das Beispielprojekt aus dem GeneSEZ-Repository auszuchecken, muss zuerst die GeneSEZ-Repository Location konfiguriert werden. Dies wird genauer unter GeneSEZ Source Control Management beschrieben. Anschließend kann das Beispielprojekt de.genesez.example.java.forms sowie das zugehörige Generatorprojekt de.genesez.example.java.forms.generator ausgecheckt werden. 3.2. Projektstruktur Für ein Softwareprojekt wird eine Aufteilung in mindestens zwei Projekte vorgeschlagen. Dies ist zum Einen ein so genanntes Generatorprojekt, welches Konfigurationen, Bibliotheken und weitere spezifische Artefakte für den modellgetriebenen Entwicklungsprozess beinhaltet. Neben diesem existiert mindestens noch ein weiteres Projekt welches den anwendungsspezifischen Quellcode beinhaltet. Durch diese Aufteilung sind in jedem Projekt nur die Artefakte enthalten, die für das jeweilige Projekt relevant sind. 3.2.1. Generatorprojekt Das Generatorprojekt ist ein openArchitectureWare-Projekt, welches wiederum ein Eclipse-Plug-In-Projekt ist. Dadurch können die benötigten Bibliotheken für den Generator einfach als Eclipse-Plug-Ins referenziert werden. Neben den spezifischen Verzeichnissen und Dateien von Eclipse-Plug-In-Projekten existieren die folgenden Verzeichnisse: * config * model-exp * model-gen Das Verzeichnis config enthält den Workflow, welcher die einzelnen Schritte beschreibt, die notwendig sind, um ein Modell in Quellcode zu transformieren. Weiterhin kann optional noch die Datei log4j.properties enthalten sein, welche das von GeneSEZ und openArchitectureWare genutzte Logging-Framework Log4J konfiguriert. Im Verzeichnis model-exp befindet sich das Modell der Anwendung im XMI-Format des Eclipse UML2-Projektes. Im Falle des Beispielprojektes wurde das Modell mit dem Modellierungswerkzeug Magic Draw erstellt und als Eclipse UML2-Modell exportiert. Daraus ergibt sich auch der Name des Verzeichnisses model-exp, der für "exportiertes Modell" steht. Dieses Modell dient als Ausgangspunkt der Codegenerierung. Der Ordner model-gen enthält ein serialisiertes GeneSEZ-Modell, welches durch den Workflow erzeugt wurde. Sich dieses Modell einmal näher anzusehen, kann z.B. nützlich sein, um zu überprüfen, ob Modellmodifikationen korrekt funktionieren. Die XMI-Datei kann mit Hilfe des Sample Reflective Ecore Model Editor geöffnet werden. Dieser stellt das Modell in einer Baumstruktur dar, ähnlich wie der UML Model Editor für Eclipse UML2-Modelle. Weiterhin können sich noch weitere Dateien und Verzeichnisse wie z.B. projektspezifische Type-Mapping-Dateien und Artefakte für die Anpassung des Generators im Generator-Projekt befinden. 11 Draft GeneSEZ: Just Try It Out Draft 3.2.2. Anwendungsprojekt Bei größeren Projekten ist es sinnvoll, mehrere Anwendungsprojekte zu erstellen (z.B. wenn neben einer Desktopoberfläche eine Weboberfläche entwickelt wird). Ansonsten ist ein Anwendungsprojekt in der Regel ausreichend. Das Anwendungsprojekt kann ein Eclipse-Projekt der entsprechenden Zielplattform sein: ein JavaProjekt, ein PHP-Projekt oder ein Web-Projekt (je nachdem, welche Eclipse-Nature am besten geeignet ist). Es kann sich aber genauso gut um ein Projekt einer anderen Entwicklungsumgebung handeln (z.B. ein Visual Studio-Projekt für die C#-Entwicklung). Für den modellgetriebenen Entwicklungsprozess an sich ist lediglich ein Verzeichnis im Dateisystem notwendig (siehe unten), jedoch sollte dies sinnvoll in einer Projektstruktur eingegliedert sein. Die Verzeichnisstruktur ist sehr vom verwendeten Projekt abhängig. Deshalb werden hier nur die wichtigsten Verzeichnisse kurz vorgestellt. Im Falle des Beispielprojektes handelt es sich um ein Java-Projekt, das die folgenden Verzeichnisse enthält: * src * src-gen * lib * model Die Verzeichnisse src und src-gen enhalten den Quellcode des Projektes. Der generierte Quellcode befindet sich dabei im Verzeichnis src-gen und der manuell erstellte in src. Im lib-Verzeichnis sind die Bibliotheken für das Projekt enthalten. Im Beispielprojekt ist hier die Bibliothek zum Assoziations-Handling enthalten. Der model-Ordner enthält das Modell, welches mit der eingesetzten Modelliersoftware erstellt wurde. Dieses Modell ist dem Anwendungsprojekt zugeordnet, da aus diesem Modell Teile des Quellcodes automatisch erzeugt werden, wodurch das Modell selbst zum Quellcode wird. 3.3. Ausführen des Workflows 3.3.1. Hinweis GeneSEZ Version 1.6.0 Durch einen Bug im GeneSEZ-Plug-In müssen bei Version 1.6.0 im Beispiel-Generator-Projekt noch folgende PlugIn-Abhängigkeiten und -Bibliotheken hinzugefügt werden: * openArchitectureWare UML2 Adapter * GeneSEZ Metamodell * dom4j Bibliothek Dazu im Ordner META-INF die Datei MANIFEST.MF öffnen und im Tab Dependencies unter Required PlugIns die beiden Plug-Ins de.genesez.metamodel und org.openarchitectureware.uml2.adapter hinzufügen. Die Bibliothek dom4j.jar wird über den Build Path hinzugefügt: Rechtsklick auf das Projekt und » Build Path » Configure Build Path... wählen und dann im Tab Libraries auf Add External JARs... klicken. Nun kann die Datei dom4j-1.6.1.jar aus dem GeneSEZ-Plug-In-Verzeichnis gewählt werden (z.B. ...\eclipse-extensions\genesez\eclipse \plugins\de.genesez.platforms.common_1.6.0). Um den Workflow zu starten, einfach Rechtsklick auf die Datei workflow.oaw im Verzeichnis config und Run As » oAW Workflow wählen. In der Konsole sollte bei erfolgreicher Ausführung in den letzten Zeilen die folgende Ausgabe erscheinen: 12 Draft GeneSEZ: Just Try It Out Draft Im Verzeichnis src-gen des Anwendungsprojektes sollte nun der aktuelle generierte Quellcode vorhanden sein. 3.4. Workflow Details Der Workflow kann mit einem Doppelklick geöffnet werden. Die Definition des Workflows ist ähnlich der von ANTBuild-Skripten. In der ersten Hälfte sind Properties definiert. Dies sind projektspezifische Einstellungen wie Pfad und Dateiname des Modells sowie Standardwerte für die Workflow Komponenten. In der zweiten Hälfte des Workflows sind die Workflowkomponenten definiert, die die Transformationsschritte vom Modell bis zum Quellcode definieren: 1. Die erste Workflowkomponente liest ein UML2-Modell ein, validiert es und transformiert es in ein GeneSEZ-Modell 2. Danach wird das GeneSEZ-Modell mit allgemeinen Regeln auf Korrektheit überprüft 3. Als drittes wird das GeneSEZ-Modell auf Java-Konformität überprüft 4. Die vierte Workflowkomponente serialisiert das GeneSEZ-Modell in eine Datei 5. Als letztes wird das GeneSEZ-Modell mit Hilfe der Java-Templates in Java-Quellcode transformiert Die Parameter der einzelnen Workflow Komponenten sind in der Workflow-Referenz erklärt: GeneSEZ Workflow Referenz. 3.5. Generierter Quellcode Wesentlich für die Akzeptanz der MDSD ist, dass der generierte Quellcode den Coding-Guidelines der Entwickler entspricht. Um dies zu erreichen, stehen mehrere Möglichkeiten bereit. Die Workflowkomponente zur Durchführung einer Modell-zu-Text-Transformation stellt Parameter bereit, um das Aussehen des generierten Quellcodes zu beeinflussen. Dazu wird hier auf die Referenz dieser Workflowkomponente verwiesen: GeneSEZ Modell-zu-Text Workflow Komponente Größere änderungen an der Struktur des Quellcodes können mit Hilfe des Customization Guide erreicht werden: GeneSEZ Customization Guide? Für Informationen, wie die GeneSEZ-Templates Modellinformationen in Quellcode umsetzen, wird auf die GeneSEZGenerator-Pattern verwiesen. 13 Draft Draft Part II. Benutzer-Referenz Draft Draft Table of Contents 4. Das GeneSEZ-Logging-Konzept .............................................................................................................. 4.1. Java ............................................................................................................................................ 4.2. Skripten + Templates ................................................................................................................... 4.3. Konfiguration ............................................................................................................................... 5. GeneSEZ Workflow Komponenten .......................................................................................................... 5.1. Allgemeine Workflow Komponenten .............................................................................................. 5.1.1. Uml2GeneSEZ .................................................................................................................. 5.1.2. Validator ........................................................................................................................... 5.1.3. Serializer .......................................................................................................................... 5.1.4. Generator ......................................................................................................................... 5.2. Plattformspezifische Workflow Komponenten ................................................................................. 5.2.1. Java Generator ................................................................................................................. 5.2.2. PHP Generator ................................................................................................................. 5.2.3. C# Generator ................................................................................................................... 6. Generierung von Zugriffsfunktionen ......................................................................................................... 6.1. Spezifikation im Modell ................................................................................................................ 6.2. Auswertung ................................................................................................................................. 6.3. Konfiguration der Modelltransformation ......................................................................................... 6.4. Beispiel ....................................................................................................................................... 7. Externe Typen im Metamodell ................................................................................................................ 7.1. Definition im UML-Modell ............................................................................................................. 7.2. Definition im Workflow ................................................................................................................. 7.3. Umgang in xPand-Templates ....................................................................................................... 7.4. Beispiel ....................................................................................................................................... 7.4.1. Verwendung eines Stereotypes zur Annotation einer Klasse ................................................ 7.4.2. Verwendung eines Stereotypes zur Annotation eines Packages ........................................... 7.4.3. Verwendung der Namen von Packages ............................................................................. 7.4.4. Mapping aller Klassen, die direkt im Modell enthalten sind .................................................. 8. Type Mapping ........................................................................................................................................ 8.1. Konzept des Type-Mapping .......................................................................................................... 8.2. Aufbau einer Type-Mapping Datei ................................................................................................ 8.2.1. Includes ........................................................................................................................... 8.2.2. Multi-Value Types ............................................................................................................. 8.2.3. Primitive Types und External Types ................................................................................... 8.2.4. Kontexte ........................................................................................................................... 8.3. Verwendung des Type-Mappings .................................................................................................. 8.4. Zusammenhang Type-Mapping + Naming Conventions ................................................................. 9. Statistik-Komponente .............................................................................................................................. 9.1. Funktionsumfang ......................................................................................................................... 9.2. Workflow-Konfiguration ................................................................................................................ 9.3. Logging ....................................................................................................................................... 9.4. Hinweis zu den Diagrammen in der Statistik ................................................................................. 9.5. Statstik-Übersicht am Beispiel ...................................................................................................... 10. GeneSEZ UML Profil ............................................................................................................................ 15 16 16 16 16 17 17 17 18 18 19 20 20 20 21 22 22 22 24 24 25 25 25 25 25 26 26 26 26 27 27 28 28 28 29 29 30 31 32 32 32 33 33 34 37 Draft Draft Chapter 4. Das GeneSEZ-Logging-Konzept In diesem Artikel soll in aller Kürze das GeneSEZ-Logging-Konzept-beschrieben werden. Dabei wird auf das Logging in Java-Code, in Skripten und in Templates sowie auf die Konfiguration eingegangen. GeneSEZ basiert auf dem Framework openArchitectureWare, welches die Logging-API des Apache Commons Logging Frameworks nutzt und als Implementierung log4j verwendet. Das GeneSEZ-Framework nutzt ebenfalls das Apache Commons Logging Framework. 4.1. Java Das Logging von Java-Code aus unterscheidet sich nicht von der gewöhnlichen Nutzung der Logging-API. Zuerst wird eine Referenz auf ein Log-Objekt benötigt: Dann kann dieses Log-Objekt genutzt werden, um Log-Ausgaben zu realisieren:Weitere Informationen befinden sich im Manual zu log4j: log4j 1.2 Manual 4.2. Skripten + Templates Für Log-Ausgaben aus den openArchitectureWare-Artefakten steht als Frontend im Common-Projekt unter dem Namespace de.genesez.platforms.common.log das eXtend-Skript Log.ext zur Verfügung. Die Funktionen dieses Skriptes rufen Methoden der Java Klasse GenesezLogger auf, welche die Apache Commons Logging-API nutzen. Sollen Log-Ausgaben erfolgen, so sollte zuerst ein benannter Logger ausgewählt werden, damit die Ausgaben später im Log einem Artefakt zugeordnet werden können: Die weiteren Funktionen des Skripts dienen zum Logging von Nachrichten mit dem jeweiligen Log-Level: 4.3. Konfiguration Zur Konfiguration der verwendeten Implementierung log4j hat openArchitectureWare bereits standardmäßig die Datei log4j.properties im Classpath, die dementsprechend auch standardmäßig genutzt wird. Das GeneSEZFramework stellt ebenfalls eine log4j.properties im Namespace de.genesez.platforms.common.log bereit. log4j sucht den kompletten Classpath nach dieser Datei ab und nutzt die erste Datei dieses Namens, die gefunden wird. Daher wird i.d.R. die von openArchitectureWare genutzt, da diese im Classpath eher gefunden wird. Soll die Log-Konfiguration angepasst werden, so kann die vom GeneSEZ-Framework bereitgestellte als Vorlage genutzt werden. Dazu wird diese in das Konfigurationsverzeichnis des aktuellen Generator-Projekts kopiert (siehe GeneSEZ Projektstruktur). Zur detaillierten Erklärung der Inhalte der Konfigurationsdatei sei auf das log4j Manual verwiesen: log4j 1.2 Manual 16 Draft Draft Chapter 5. GeneSEZ Workflow Komponenten Die GeneSEZ Workflow Komponenten sind Wrapper um die Workflow Komponenten von openArchitectureWare um deren Handhabung einfach zu gestalten und für einige Einstellungen Standardwerte bereitzustellen. Die allgemein nutzbaren Workflow Komponenten sind im Package de.genesez.platforms.common.workflow enthalten, die in anderen Plattform-Projekten spezialisiert werden können. Dies Betrifft insbesondere den Generator zur Ausführung von Modell-zu-Text Transformationen. Unbedingt erforderliche Parameter werden fett dargestellt und als erste aufgeführt. Parameter die mehrmals angegeben werden können sind mit multi-value gekennzeichnet, Parameter die nur einmal angegeben werden können mit single-value. Bei Parametern mit Standardwerten sind die Standardwerte mit angegeben. 5.1. Allgemeine Workflow Komponenten 5.1.1. Uml2GeneSEZ Diese Workflow Komponente dient zur Ausführung der gleichnamigen UML-zu-GeneSEZ Transformation. Diese Transformation besteht aus folgenden Schritten: • Einlesen eines UML Modells (Eclipse UML2 kompatibles XMI Format) • Validieren des UML Modells um die Transformation in ein GeneSEZ Modell sicherzustellen • Transformation des UML Modells in ein GeneSEZ Modell Dabei sind folgende Parameter möglich: model der Dateiname inklusive des Dateipfades zur UML Modell Datei profile, multi-value dient zur Angabe von UML Profilen, die zusätzlich zum UML2 Metamodell als Metamodell registriert werden. Hiermit müssen alle bei der Modellierung verwendeten UML Profile angegeben werden, sofern sie in eigenständigen Dateien hinterlegt sind und nicht in der UML Modell Datei. ignoreValidationErrors, single-value, Standard: false ein boolscher Wert der angibt, ob Validierungsfehler des UML Modells die Transformation beenden oder nicht. excludePackage, multi-value, Standard: UML Standard Profile kann genutzt werden um ein UML Package im UML Modell mit qualifiziertem Namen anzugeben, welches bei der UML-zu-GeneSEZ Transformation ausgeschlossen werden soll. excludePackages, multi-value, Standard: UML Standard Profile hat die gleiche Bedeutung wie exclude package mit dem Unterschied das als Wert eine Komma separierte Liste mit UML Packages angegeben werden kann. mapClassesInModelToExternal, single-value, Standard: false gibt an ob Classifier die direkt im Wurzel-Element des UML Modells abgelegt sind in externe Typen des GeneSEZ Modells transformiert werden. externalPackage, multi-value wird genutzt um UML Packages mit qualifiziertem Namen anzugeben die als Container für externe Typen genutzt werden. Diese UML Packages werden dann nicht in GeneSEZ Packages transformiert und alle enthaltenen Classifier werden in externe Typen transformiert. externalPackages, multi-value hat die gleiche Bedeutung wie external package mit dem Unterschied das als Wert eine Komma separierte Liste mit UML Packages angegeben werden kann. 17 Draft GeneSEZ Workflow Komponenten Draft externalStereotype, multi-value, Standard: external wird genutzt um Namen von UML Stereotypen anzugeben, die entweder Classifier als externe Typen im UML Modell markieren oder aber UML Packages, die als Container für externe Typen dienen. externalStereotypes, multi-value hat die gleiche Bedeutung wie external stereotype mit dem Unterschied das als Wert eine Komma separierte Liste mit Namen von Stereotypen angegeben werden kann. umlCheckScript, multi-value, Standard: de::genesez::adapter::uml2::uml2constraints dient zur Angabe von Check-Skripten die zur Validierung des UML Modells genutzt werden. uml2GenesezScriptCall, single-value, Standard: de::genesez::adapter::uml2::uml2genesez::transform(uml2model) dient zur Angabe einer Skript-Funktion welche die UML-zu-GeneSEZ Transformation durchführt. Siehe auch uml slot. umlSlot, single-value, Standard: uml2model dient zur Angabe des Namens des Slots, welcher das instanziierte UML Modell speichert. slot, single-value, Standard: genesezModel dient zur Angabe des Names des Slots auf welchem das erstellte GeneSEZ Modell gespeichert wird. 5.1.2. Validator Wird zur Überprüfung von GeneSEZ Modellen mit Hilfe eines Check-Skriptes eingesetzt. Folgende Parameter können verwendet werden: script, multi-value wird genutzt um mind. 1 Check-Skript anzugeben welches genutzt wird um das GeneSEZ Modell zu validieren. scripts, multi-value hat die gleiche Bedeutung wie script mit dem Unterschied das als Wert eine Komma separierte Liste mit CheckSkripten angegeben werden kann. abortOnError, single-value, Standard: true kann genutzt werden um den Transformations-Lauf nicht abzubrechen wenn das Check Skript Fehler meldet. Standardmäßig wird abgebrochen. slot, single-value, Standard: genesezModel kann genutzt werden um den Name des Slots zu setzen, welches das zu validierende Modell beinhaltet. Zusätzlich stehen die Parameter der CheckComponent von openArchitectureWare bereit. Hierzu zählt u.a. warnIfNothingChecked das standardmäßig auf false steht. Auf true gesetzt bewirkt es das eine Warnung in dem Workflow Log erscheint, wenn das Check Skript keine Modellelemente überprüft hat. 5.1.3. Serializer Wird zur Serialisierung von instanziierten GeneSEZ Modellen in eine Datei genutzt. Es können folgende Parameter angegeben werden: file, single-value dient zur Angabe der Datei in welcher ein instanziiertes Modell gespeichert wird. slot, single-value, Standard: genesezModel dient zur Angabe des Names des Slots welches das zu serialisierende GeneSEZ Modell beinhaltet. Weiterhin können die Parameter der Writer Komponente von openArchitectureWare angegeben werden. • Die boolesche Option OPTION_SCHEMA_LOCATION_IMPLEMENTATION standardmäßig auf false gesetzt um die serialisierten Dateien auch mit dem Sample Reflective Ecore Model Editor öffnen zu können. • Die boolesche Option cloneSlotContents kann genutzt werden um instanziierte Modelle, die bereits mit einer Ressource verbunden sind (also bereits serialisiert sind) noch einmal in eine andere Datei zu serialisieren. 18 Draft GeneSEZ Workflow Komponenten • Weitere boolesche Optionen sind: multipleResourcesInCaseOfList, useSingleGlobalResourceSet Draft OPTION_SCHEMA_LOCATION, 5.1.4. Generator Der Generator dient zur Ausführung von Modell-zu-Text Transformationen. Die folgenden Parameter werden angebogen, jedoch ist es von der durch template spezifizierten Modell-zu-Text Transformation abhängig, welche Parameter tatsächlich von der Transformation genutzt werden. Normalerweise sollte der Generator als Basisklasse für Modell-zu-Text Transformationen genutzt werden. template, single-value dient zur Angabe des XPand Templates sowie dem Namen des Define-Blockes, welcher zur Modell-zu-Text Transformation aufgerufen wird. outputDir, single-value dient zur Angabe des Verzeichnisses welches den generierten Quellcode enthält bzw. enthalten soll. Ist das Verzeichnis nicht vorhanden, wird es erstellt. proRegDir, single-value, Standard: Wert von outputDir dient zur Angabe des Verzeichnisses welches Quellcode mit Protected Regions enthält die in der aktuellen Transformation erhalten werden sollen. typeMappingFile, multi-value dient zur Angabe der Type-Mapping Dateien, welche bei der Modell-zu-Text Transformation genutzt werden sollen. basePackage, single-value kann genutzt werden um ein Package anzugeben welches als Basis für die Modell-zu-Text Transformation genutzt wird. Alles wird dann in dieses Package generiert. useModelNameAsBasePackage, single-value, Standard: false hiermit kann angegeben werden das der Name des Modell-Elementes (das Wurzel-Element des GeneSEZ Modells) als base package verwendet werden soll. generateSectionComments, single-value, Standard: true dient zur Angabe das einzeilige Kommentare generiert werden, welche den Quellcode in Bereiche untergliedern. accessorsForStereotypes, optional, single-value, Standard: entity spezifiziert eine Komma- separierte Liste mit Namen von Stereotypen welche die Generierung von Get- und Set- Methoden implizieren accessorStereotype, optional, single-value, Standard: accessor dient zur Angabe des Namens des Stereotyps accessor. Standardwert ist der Name des Stereotyps im GeneSEZ UML Profil. Wird ein anderer Name angegeben, muss dieser Stereotyp mindestens über die gleichen Tags des Stereotyps accessor aus dem GeneSEZ Profil verfügen (sofern die Auswertungslogik für Zugriffsfunktionen nicht ersetzt/erweitert wird). usePropertyVisibilityForAccessors, single-value, Standard: false hiermit kann festgelegt werden, das Attribute immer mit der Sichtbarkeit private generiert werden und die zugewiesene Sichtbarkeit der Attribute für die Zugriffsfunkionen (Getter und Setter) verwendet wird. excludePackage, multi-value dient zur Angabe von GeneSEZ Packages per qualifizierten Namen, die bei der Modell-zu-Text Transformation ausgeschlossen werden sollen. excludePackages, multi-value, Standard: UML Standard Profile hat die gleiche Bedeutung wie exclude package mit dem Unterschied das als Wert eine Komma separierte Liste mit qualifizierten Namen von GeneSEZ Packages angegeben werden kann. aspectTemplate, multi-value dient zur Angabe von XPand Templates mit Around Anweisung mit deren Hilfe Advices für Template-DefineAnweisungen definiert werden. 19 Draft GeneSEZ Workflow Komponenten Draft aspectTemplates, multi-value hat die gleiche Bedeutung wie aspect template mit dem Unterschied das als Wert eine Komma separierte Liste mit XPand-Templates angegeben werden kann. aspectScript, multi-value dient zur Angabe von XTend Skripten around Anweisung mit deren Hilfe Advices für XTend Funktionen definiert werden. aspectScripts, multi-value hat die gleiche Bedeutung wie aspect script mit dem Unterschied das als Wert eine Komma separierte Liste mit XTend-Skripten angegeben werden kann. slot, single-value, Standard: genesezModel dient zur Angabe des Names des Slots welcher das GeneSEZ Modell für die Modell-zu-Text Transformation beinhaltet. prExcludes, single-value, Standard: .svn dient zur Angabe von Auschlüssen von Dateien und Verzeichnissen, welche keine Protected Regions enthalten. prDefaultExcludes, single-value, Standard: false hiermit können die Standard Datei-Ausschlüsse für den Protected Region Resolver definiert werden. Welche genau dazu gehören verrät die openArchitectureWare Dokumentation. Alle Dateien mit diesen Endungen werden nicht auf Protected Regions hin überprüft. fileEncoding, single-value, Standard: utf-8 dient zur Angabe der Kodierung der Templates. Weiterhin besitzt der Generator alle Parameter der XPand-Generator Komponente von openArchitectureWare. 5.2. Plattformspezifische Workflow Komponenten Die plattformspezifischen Generator- Workflow Komponenten zur Modell-zu-Text Transformation bieten ebenfalls alle Paramter des Generators. Zusätzlich verfügen diese aber über weitere Standardwerte (speziell template und typeMappingFile) und eventuell weiterer plattformspezifischer Transformations-Parameter. Somit reduziert sich die Anzahl der notwendigen Transformations-Parameter auf einen: outputDir. 5.2.1. Java Generator Der Java Generator transformiert standardmäßig ein GeneSEZ Modell in Java 5 kompatiblen Quellcode. template, single-value, Standard: de::genesez::platforms::java::java5::templates::Root::Root XPand-Template zur Modell-zu-Java Transformation. typeMappingFile, multi-value, Standard: de/genesez/platforms/java/typemapping/typemapping.xml Standard Java Type-Mapping Datei. formatterConfig, single-value, Standard: de/genesez/platforms/java/workflow/ eclipse.java.formatter.settings.xml spezifiziert die Datei mit Konfigurationseinstellungen des Java Beautifiers. Aktuell wird der in Eclipse integrierte Formatter genutzt. 5.2.2. PHP Generator Der PHP Generator transformiert standardmäßig ein GeneSEZ Modell in PHP5 kompatiblen Quellcode. template, single-value, Standard: de::genesez::platforms::php5::templates::Root::Root XPand-Template zur Modell-zu-PHP Transformation. typeMappingFile, multi-value, Standard: de/genesez/platforms/php/typemapping/typemapping.xml Standard PHP Type-Mapping Datei. 20 Draft GeneSEZ Workflow Komponenten Draft generateIncludes, single-value, Standard: true spezifiziert ob die PHP Anweisung require_once zur Einbindung benötigter anderer PHP Quellcodedateien generiert wird relativeIncludes, single-value, Standard: false spezifiziert ob benötigte PHP Quellcodedateien per relativen oder absoluten Dateisystempfad eingebunden werden includeBase, single-value, Standard: (leerer String) spezifiziert einen Standard Include Pfad der als Ausgangsverzeichnis für alle absolut referenzierten PHP Quellcodedateien genutzt wird accessorStyle, single-value, Werte: magic, api, Standard: magic spezifiziert wie Zugriffsfunktionen für Attribute generiert werden, ob per magic get und set Funktion oder per get und set Funktion für jedes Attribut. propertyAccess, single-value, Werte: setter, attribute, array, Standard: setter spezifiziert für die QuickForm Unterstützung wie auf die Attribute des Domain Objektes zugegriffen werden soll, wenn Daten aus HTML Formularen gesetzt werden müssen 5.2.3. C# Generator Der C# Generator generiert C# Quellcode. template, single-value, de::genesez::platforms::dotnet::csharp::templates::Root::Root XPand-Template zur Modell-zu-C# Transformation. typeMappingFile, multi-value, Standard: typemapping.xml Standard C# Type-Mapping Datei. Standard: de/genesez/platforms/dotnet/csharp/typemapping/ 21 Draft Draft Chapter 6. Generierung von Zugriffsfunktionen Je nach Plattform werden Zugriffsfunktionen, d.h. Get- und Set- Methoden für Attribute unterschiedlich stark eingesetzt und auf verschiede Art implementiert. Die Logik zur Auswertung ist jedoch plattformunabhängig definiert. 6.1. Spezifikation im Modell Aktuell werden drei Möglichkeiten bereit gestellt um die Generierung von Zugriffsfunktionen auf unterschiedlich granularen Ebenen anzugeben: 1. Verwendung von Stereotypen die Klassen zugewiesen werden und die Generierung einer Get und SetMethode für deren Attribute implizieren 2. Verwendung des Stereotyps accessor für Klassen um für alle ihre Attribute die Generierung von Get- und Set- Methoden zu steuern 3. Verwendung des Stereotyps accessor für Attribute um die Generierung von Get- und Set- Methoden detailliert zu steuern Die Stereotypen für die Möglichkeit 1 werden in der Modelltransformation angegeben. Der Stereotyp accessor ist im GeneSEZ Profil enthalten. Jedoch kann auch jeder andere Stereotyp genutzt und in der Modelltransformation konfiguriert werden, der die Tags getter und setter mit boolschen Werten besitzt. In Abbildung Figure 6.1, “Plattformunabhängige Teil des GeneSEZ UML Profils” ist der plattformunabhängige Teil des GeneSEZ UML Profils mit dem Stereotyp accessor dargestellt. Figure 6.1. Plattformunabhängige Teil des GeneSEZ UML Profils 6.2. Auswertung Die Auswertungen der Modellierungsmöglichkeiten wird vom speziellen über Fallbacks auf die allgemeingültigen bis hin zum Standardfall, das keine Zugriffsfunktionen generiert werden, durchgeführt. Für jedes Attribut wird die in Abbildung Figure 6.2, “Auswertung der Modellierungsmöglichkeiten” mit einem UML Aktivitätsdiagramm dargestellte Auswertung durchgeführt. 22 Draft Generierung von Zugriffsfunktionen Draft Figure 6.2. Auswertung der Modellierungsmöglichkeiten Zuerst wird der konfigurierte Stereotyp accessor am Attribut überprüft. Ist dieser vorhanden wird dieser ausgewertet und entsprechend eine Get und/oder Set Methode generiert. Diese Auswertung ist in Abbildung Figure 6.3, “Auswertung des Stereotyps accessor” dargestellt. Figure 6.3. Auswertung des Stereotyps accessor Ist der Stereotyp nicht vorhanden, wird geprüft ob die Klasse den konfigurierten Stereotyp accessor aufweist. Wenn ja, dann wird dieser ausgewertet. Ist dies nicht der Fall, wird geprüft ob die Klasse einen Stereotyp zugewiesen hat, der sich in der konfigurierten Liste der Stereotypen für Zugriffsfunktionen befindet. Ist dies der Fall, werden eine Get- und eine Set- Methode generiert. Falls nicht, wird keine Zugriffsfunktion für das Attribut generiert. Die konfigurierten Stereotypen für Klassen haben somit Modellweite Gültigkeit. Der Stereotyp accessor an Klassen hat Klassenweite Gültigkeit und am Attribut nur lokale. Weiterhin können die globalen Möglichkeiten durch die lokalen eingeschränkt werden. 23 Draft Generierung von Zugriffsfunktionen Draft 6.3. Konfiguration der Modelltransformation Zur Auswertung der Zugriffsfunktionen weisen die Generator-Komponenten für die Modell-zu-Text Transformation alle die gleichen Workflow-Parameter auf: accessorsForStereotypes, optional, single-value, Standard: entity spezifiziert eine Komma- separierte Liste mit Namen von Stereotypen welche die Generierung von Get- und Set- Methoden implizieren accessorStereotype, optional, single-value, Standard: accessor dient zur Angabe des Namens des Stereotyps accessor. Standardwert ist der Name des Stereotyps im GeneSEZ UML Profil. Wird ein anderer Name angegeben, muss dieser Stereotyp mindestens über die gleichen Tags des Stereotyps accessor aus dem GeneSEZ Profil verfügen (sofern die Auswertungslogik für Zugriffsfunktionen nicht ersetzt/erweitert wird). usePropertyVisibilityForAccessors, optional, single-value, Standard: false spezifiziert ob die Sichtbarkeit der Attribute stets private sein soll und die zugewiesene Sichtbarkeit der Attribute im Modell für die Zugriffsfunkionen (Get- und Set Methode) verwendet werden soll. 6.4. Beispiel Am besten direkt mit einem unserer Beispielprojekte ausprobieren! 24 Draft Draft Chapter 7. Externe Typen im Metamodell Mit dem Metamodellelement MExternal ist ein Konzept im GeneSEZ-Metamodell vorhanden, welches in dieser Form nicht zur UML gehört. Als externe Typen werden in diesem Zusammenhang im Modell verwendete Typen (Klassen, Interfaces, Enumerations) bezeichnet, die selbst nicht im Modell vorhanden sind. Sie befinden sich stattdessen z.B. in Standard-Bibliotheken der Programmiersprache oder in anderen Bibliotheken, die verwendet werden sollen. 7.1. Definition im UML-Modell Im zugrunde liegenden UML-Modell werden externe Typen als Klassen (bzw. Interfaces oder Enumerations) definiert und speziell gekennzeichnet. Dazu gibt es mehrere Möglichkeiten: * Verwendung eines Stereotypes * Verwendung eines separaten Packages * Ablage des Typs direkt im Modell (der Typ hat eine Containment-Beziehung zum Modell-Element und befindet sich nicht in einem Package) Die verschiedenen Möglichkeiten haben spezifische Vor- und Nachteile. Die Annotation der einzelnen Klassen mit einem Stereotyp ist jedoch allgemein zu bevorzugen, da hier in den Modellen und verschiedenen Diagrammen die Semantik einer externen Klasse am deutlichsten zum Ausdruck kommt. Beispiele dazu sind weiter unten zu finden. 7.2. Definition im Workflow Je nachdem, wie externe Typen im UML-Modell definiert wurden, muss dies auch im Workflow angegeben werden. Dazu werden die folgenden drei Parameter der Workflow-Komponenten makeGenesezModel bzw. makeGenesezModelProfile genutzt: * mapClassesInModelToExternal » Der Parameter kann als Wert true oder false annehmen und gibt an, ob Typen, die direkt im Modell abgelegt sind und somit zu keinem Package gehören, zu externen Typen transformiert werden (true) oder normal behandelt werden (false). Standardmäßig ist der Wert false. * externalPackages » Als Wert für den Parameter kann eine mit Komma (oder für eine bessere Lesbarkeit eine mit Komma und Leerzeichen) separierte Liste mit Namen von Packages angegeben werden, welche Container für externe Typen darstellen. Die angegebenen Packages selbst werden ebenfalls nicht in ein GeneSEZ-Package transformiert. Standardmäßig ist der Wert ein leerer String. * externalStereotypes » Als Wert kann eine mit Komma (oder für eine bessere Lesbarkeit eine mit Komma und Leerzeichen) separierte Liste mit Namen von Stereotypen angegeben werden. Diese Stereotypen können im UMLModell sowohl Typen als auch Packages zugewiesen werden. Ist einer dieser Stereotypen einem Typ zugewiesen, so wird dieser in einen externen Typ transformiert. Ist ein Stereotyp einem Package zugewiesen, so wird dieses als Container für externe Typen betrachtet und wird selbst nicht transformiert. Alle in dem betreffenden Package enthaltenen Typen werden zu externen Typen. Standardmäßig ist der Wert ein leerer String. 7.3. Umgang in xPand-Templates Innerhalb von Templates ist es unwesentlich, ob ein Typ ein externer Typ ist oder nicht. Diese Zuordnung wird durch das GeneSEZ Type-Mapping realisiert. 7.4. Beispiel Es folgen einige Beispiele, die den Einsatz der vorgestellten Möglichkeiten zur Definition von externen Typen zeigen. Wie in den Modellen deutlich wird, ist die Verwendung eines Stereotypes zur Annotation von Klassen am ausdrucksstärksten. 25 Draft Externe Typen im Metamodell 7.4.1. Verwendung eines Stereotypes zur Annotation einer Klasse Zugehörige Parameter in der Workflow Konfiguration: 7.4.2. Verwendung eines Stereotypes zur Annotation eines Packages Zugehörige Parameter in der Workflow Konfiguration (identisch mit dem ersten Beispiel): 7.4.3. Verwendung der Namen von Packages Zugehörige Parameter in der Workflow Konfiguration: 7.4.4. Mapping aller Klassen, die direkt im Modell enthalten sind Zugehörige Parameter in der Workflow Konfiguration: 26 Draft Draft Draft Chapter 8. Type Mapping Die Type-Mapping-Komponente dient dazu, im Modell verwendete Typen auf Typen in einer Programmiersprache abzubilden. Die Abbildung Figure 8.1, “Das GeneSEZ Typ-System” zeigt eine Übersicht der möglichen Typen: Figure 8.1. Das GeneSEZ Typ-System MClassifier bezeichnet selbst erstellte Typen im Modell. MGeneric stellt einen generischen Typ dar und wird verwendet, um eine Klasse mit einem oder mehreren Typen zu parametrisieren. MPrimitiveType stellt die primitiven Typen der jeweiligen Programmiersprache dar. Dabei handelt es sich meist um Hardware-nahe Typen, die in der Regel ohne include- oder import-Anweisung verwendbar sind. MExternal stellt die Typen einer Programmiersprache dar, die durch Standardbibliotheken oder andere verwendete externe Bibliotheken verfügbar gemacht werden. 8.1. Konzept des Type-Mapping Das Type-Mapping realisiert zwei verschiedene Aufgaben. Zum einen werden mit einem Namens-Mapping die Namen der Typen im Modell auf die zu verwendenden Namen in der jeweiligen Zielsprache abgebildet. Bei MClassifier und MGeneric wird beim Aufruf der Funktion mapName() kein Namens-Mapping durchgeführt, da es sich ja um selbst modellierte Typen handelt, deren Namen nicht abgebildet werden müssen. Hier wird der name bzw. die specification zurück gegeben. Die zweite Aufgabe ist ein Typ-Mapping, welches die Typ-Modifikatoren auswertet und gegebenenfalls den im Modell verwendeten Typ ersetzt. Typ-Modifikatoren werden im Modell nicht am Typ selbst festgelegt, sondern bei dem Modellelement, welches den Typ aufweist (also z.B. bei einem Attribut). Die Funktion mapType() realisiert das TypMapping. Folgende Typ-Modifikatoren werden ausgewertet: multiplicity Anzahl der zu speichernden Objekte eines Typs (d.h. ob der Typ an sich ausreicht oder eine Collection oder ein Array des Typs verwendet werden muss) unique gibt an, ob ein Objekt mehrmals vorkommen kann, wenn die multiplicity größer als 1 ist ordered gibt an, ob die Objekte geordnet abgelegt werden 27 Draft Die Typ-Modifikatoren unique und multiplicity größer als 1 ist. Type Mapping Draft ordered beziehen sich auf multi-value Typen, d.h. Typen, deren Die Abbildungsvorschriften für das Namens- und Typ-Mapping werden in einer XML-Datei festgelegt. Weiterhin sind für die Auswahl des passenden Typs oft die im Quellcode angestrebte Verwendung bzw. die vorliegenden Rahmenbedingungen wesentlich. Hierzu können Kontexte definiert werden, die ein spezielles Mapping für eine bestimmte Situation/Verwendung darstellen. 8.2. Aufbau einer Type-Mapping Datei Eine Type-Mapping Datei besteht aus 4 Abschnitten: include Angabe einer oder mehrerer Type-Mapping Dateien die eingebunden bzw. erweitert werden soll multiValuedTypes Angabe wie Type-Modifikatoren behandelt werden primitiveTypes Angabe wie primitive Typen gemappt werden externalTypes Abbildung von externen Typen Das folgende Listing zeigt den schematischen Aufbau der Type-Mapping Datei. <?xml version="1.0" encoding="UTF-8"?> <tns:typeMapping xmlns:tns="http://www.genesez.de/typemapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <tns:include> <tns:file> de/genesez/platforms/common/typemapping/typemapping.xml </tns:file> </tns:include> <tns:multiValuedTypes> ... </tns:multiValuedTypes> <tns:primitiveTypes> ... </tns:primitiveTypes> <tns:externalTypes> ... </tns:externalTypes> </tns:typeMapping> Für die Type-Mapping Dateien gibt es ein XML Schema [https://server.genesez.de/trac/browser/trunk/ de.genesez.platforms.common/common/de/genesez/platforms/common/typemapping/typemapping.xsd] welches zur Validierung genutzt wird. Das Schema wird immer automatisch aus dem Classpath (Ressource: de/genesez/ platforms/common/typemapping/typemapping.xsd) geladen und muss nicht explizit in der XML Datei per schemaLocation angegeben werden! 8.2.1. Includes Angabe einer oder mehrerer Type-Mapping Dateien mit einem Identifier der genutzt wird um die referenzierten TypeMapping Dateien aus dem Classpath zu laden. Alle in dieser Datei definierten Mappings werden eingebunden. <tns:include> <tns:file> de/genesez/platforms/common/typemapping/typemapping.xml </tns:file> </tns:include> 8.2.2. Multi-Value Types In diesem Abschnitt wird definiert, wie Typen unter Berücksichtigung der Typ-Modifikatoren abgebildet werden. Dazu stehen die beiden optionalen Attribute unique und ordered bereit. 28 Draft Type Mapping Draft <tns:multiValuedType ordered="true" unique="true"> <tns:default>java.util.Set</tns:default> </tns:multiValuedType> Die beiden Attribute sind optional da in der UML Standardwerte festgelegt sind: unique == true und ordered == false. Eine andere Möglichkeit der Angabe für das obige Mapping unter Nutzung der Standardwerte ist die folgende: <tns:multiValuedType ordered="true"> <tns:default>java.util.Set</tns:default> </tns:multiValuedType> Für den Typ-Modifikator unique ist kein Wert angegeben wodurch der Standartwert aus der UML genutzt wird. Da dieser true ist entsteht ein identisches Mapping wie bei der Angabe beider Modifikatoren. 8.2.3. Primitive Types und External Types Um Mappings für primitive und externe Typen zu erstellen wird die gleiche Syntax genutzt: <tns:type from="boolean"> <tns:to> boolean </tns:to> </tns:type> Das Element type steht für eine Type-Mapping Definition. Mit dem from Attribut wird der im Modell verwendete Name des abzubildenden Typs angegeben. Mit dem Element to wird der Name des Typs in der Zielsprache angegeben auf den der Typ abgebildet wird. Im Beispiel oben wird der im UML-Metamodell enthaltene primitive Typ Boolean auf den Typ boolean der Zielprogrammiersprache abgebildet. 8.2.4. Kontexte Kontexte werden genutzt um die verschiedenen Verwendungsmöglichkeiten von Typen in der Zielsprache zu adressieren. Es können beliebig viele Kontext-Mappings für einen Typ angegeben werden. Jedes Kontext-Mapping stellt einen bestimmten Bereich bzw. Situation dar, in welcher ein Typ im Xpand-Template gemappt wird. Diese Kontexte werden also nicht im Modell angegeben, sondern bei dem Aufruf des Type-Mappings im Xpand-Template. Zur Verringerung der Kopplung in Quellcode werden z.B. Attributen mit dem Interface-Typ definiert und nur in deren Initialisierung die gewünschte konkrete Implementierung verwendet. Um solche Probleme zu Adressieren können die Standardmappings mit Kontext-bezogenen Mappings erweitert werden. 8.2.4.1. Kontexte und Multi-Value Typen Das folgende Beispiel zeigt ein Multi-Value Type-Mapping, das zwischen Interface-Typ und konkreter Implementierung unterscheidet: <tns:multiValuedType ordered="true"> <tns:default> java.util.Set </tns:default> <tns:context name="Implementation"> java.util.LinkedHashSet </tns:context> </tns:multiValuedType> In der Programmiersprache Java könnte das obige Mapping in folgendem Quellcode resultieren: java.util.Set<String> strings = new java.util.LinkedHashSet<String>(); Für den Typ der Variablen wird der Standardtyp (Interface-Typ) genutzt. Nur bei der Initialisierung der Variablen wird die konkrete Implementierung verwendet. Dies resultiert in einer geringeren Kopplung zu genutzten Implementierung. 8.2.4.2. Kontexte und Primitive Typen Kontexte können darüber hinaus auch in Primitive Type und External Type Mappings verwendet werden. Ein Kontext kann bei Java z.B. dazu genutzt werden um die Primitiven Typen auf ihre Wrapper-Typen in Java abzubilden: 29 Draft Type Mapping Draft <tns:type from="boolean"> <tns:to>boolean</tns:to> <tns:context name="Wrapper">Boolean</tns:context> </tns:type> Dadurch ist es möglich bei einer speziellen Verwendung des Typs Boolean auf den Wrapper Typ Boolean zu mappen anstatt auf den Primitiven Typ boolean. Notwendig ist dies z.B. bei Multi-Value Typen: java.util.Set<Boolean> bs = new java.util.LinkedHashSet<Boolean>(); Der Primitive Typ boolean kann in Java nicht als generischer Parameter verwendet werden. Deshalb muss sein Wrapper Typ genutzt werden. 8.2.4.3. Kontexte und Externe Typen Für External Type Mappings sind Kontexte u.a. in Bezug auf die Generierung von import bzw. include Statements sinnvoll: <!-- container is the base class for custom authentication providers from the 'PEAR::Auth' package --> <tns:type from="Auth_Container"> <!-- default mapping is to the class name --> <tns:to>Auth_Container</tns:to> <!-- used to generate imports --> <tns:context name="import">Auth/Container.php</tns:context> </tns:type> Standardmäßig wird der Typ in dem Beispiel auf den Klassennamen abgebildet. Wird jedoch der Kontext import angegeben, wird der benötigte Teil für die PHP include Anweisung zurückgegeben. 8.3. Verwendung des Type-Mappings Das Type-Mapping kann in Xpand-Templates einfach durch das Einbinden des Type-Mapping Xtend-Skriptes genutzt werden: «REM» use the type mapping «ENDREM» «EXTENSION de::genesez::common::typemapping::TypeMapping» Das Xtend-Skript stellt prinzipiell zwei verschiedene Funktionen bereit, bei denen jeweils optional noch ein KontextParameter angegeben werden kann: mapName() bildet den als Parameter übergebenen Typ auf den Namen des Typs in der Zielsprache ab mapType() wertet die Typ-Modifikatoren (des Metamodellelementes) aus und gibt die entsprechenden Multi-Value-Typen zurück Als Beispiel hier die Deklaration von Attributen in Java: «IF isSingleValuedType() -» «EXPAND _Modifier -» «type.mapName().asTypeName()» \ «EXPAND Type::Generics» «asAttribute()» «EXPAND _DefaultValue»; «ELSE -» «EXPAND _Modifier -» «mapType() -» \ <«type.mapName().asTypeName()»> \ «asAttribute()» = new «mapType("Implementation")» \ <«type.mapName().asTypeName() -»>(); «ENDIF -» Bei einem normalen, single-value Typen ( multiplicity == 1) wird lediglich der verwendete Typ auf den zu verwendenden Namen in der Zielsprache gemappt. Ist der übergebene Typ ein MClassifier oder ein MGeneric, 30 Draft Type Mapping Draft so wird das eigentliche Type-Mapping nicht durchgeführt sondern lediglich der übergebene Typ unverändert wieder zurückgegeben. Bei MExternal und MPrimitiveType werden die Informationen aus der Type-Mapping-Datei ausgewertet und der Typ als String zurückgegeben. Der Aufruf von asTypeName() wird zur Anwendung der Naming Conventions durchgeführt. Bei multi-value Typen ( multiplicity > 1) wird zuerst der Typ gemappt. Im obigen Beispiel wird dazu als Parameter ein MAttribute übergeben. Das Type-Mapping wertet dann die Typ-Modifikatoren unique und ordered aus und gibt den entsprechenden Multi-Value-Typ zurück. Der eigentlich verwendete Typ im Modell wird auf den Namen in der Zielsprache gemappt und als Typ-Parameter der Collection angegeben. 8.4. Zusammenhang Type-Mapping + Naming Conventions Wie bereits im letzten Abschnitt aufgezeigt wird nur das Type-Mapping aufgerufen, welches dann selbst anhand des übergebenen Typs entscheidet, ob die Informationen der Type-Mapping-Datei ausgewertet werden müssen oder nicht. Im Folgenden nun ein Beispiel zur Generalisierung: extends «generalization.first().mapName().asTypeName() -» Hier wird nach dem Schlüsselwort extends die (erste) Basisklasse generiert. Diese Basisklasse kann vom Typ MClass oder auch vom Typ MExternal sein. Ist die Basisklasse vom Typ MClass ist es eine modellierte Klasse (des Domain-Modells) und muss daher den Naming Conventions unterworfen werden. Ist es ein MExternal, muss lediglich das Type-Mapping durchgeführt werden. Um die Xpand-Templates nicht unnötig mit dem Test, um welchen Meta-Typ es sich handelt, zu verkomplizieren, wurden die Funktionen für die Namensgebung so definiert, dass sie diese Aufgabe erledigen. Die Funktion mapName() liefert bei Typen, bei denen kein Type-Mapping durchgeführt werden muss, den Typ unverändert wieder zurück (z.B. MClassifier, MGeneric). Wird bei MPrimitiveType oder MExternal ein Type-Mapping durchgeführt, liefert die Funktion einen String zurück. Die Funktion asTypeName() für die Namensgebung erkennt am übergebenen Parameter (Typ oder String), ob das Type-Mapping durchgeführt wurde oder nicht. Wird ein String übergeben, wird dieser unverändert zurückgegeben, da das Type-Mapping den Typ bereits ermittelt hat. Wird ein Typ übergeben, werden die Naming Conventions angewandt und ein String zurückgegeben. Somit werden auf elegante Weise beide Aspekte behandelt. 31 Draft Draft Chapter 9. Statistik-Komponente Im Umfeld der modellgetriebenen Softwareentwicklung wird meist nach Informationen und Zahlen verlangt die Aufschluß darüber geben sollen, ob sich der Einsatz von MDSD lohnt oder nicht. Zu den Informationen gehört dann oft wiederkehrender Quellcode sowie die Persistenzschicht und bei Zahlen lässt man sich zu prozentualen Schätzungen bringen - die manchmal daneben liegen können. Die Statistik-Komponente kann dazu genutzt werden, um die prozentualen Schätzungen zu unterstützen und einen Einblick in die Quellcode-Zusammensetzung zu erlangen. Bewust auf wesentliche Informationen reduziert und sie für Entscheider nutzbar zu machen. 9.1. Funktionsumfang Die Statistik-Komponente kann für ein Software-Projekt mit mehreren Quellcodeverzeichnissen konfiguriert werden. Für alle Quellcodedateien werden die Anzahl der Quellcodezeilen (Lines of Code) für die folgenden Kategorien ermittelt: • generierte Quellcodezeilen • manuell implementierter Quellcode • Dokumentation • Kommentare Leerzeilen werden beim zählen nicht mit berücksichtigt. Die Werte werden getrennt für die einzelnen Quellcodedateien, für die Quellcodeverzeichnisse sowie für das Projekt gesamt angegeben. Dokumentationskommentare und Kommentare werden separat aufgeführt, da sie das Verhältnis zwischen generierten und nicht-generierten Quellcode sehr beeinflussen können. Kommentare sind meist manuell geschrieben, Dokumentationskommentare dagegen meist aus dem Modell generiert. Die manuellen und generierten Quellcodezeilen enthalten keine Kommentare und umfassen demnach (meist) nur Programmanweisungen. 9.2. Workflow-Konfiguration Um die Statistik-Komponente zu nutzen, muss lediglich eine Workflow Komponente hinzugefügt werden: <component id="statistics" class="de.genesez.platforms.common.workflow.Statistics"> ... </component> Die Statistik Workflow Komponente ist von der Generator Workflow Komponente abgeleitet und kann dadurch mit den selben Parametern konfiguriert werden. Die wichtigsten geerbten Parameter sind folgende: outputDir, mandatory, single-value spezifiziert das Ausgabeverzeichnis für die Statistik-Datei, siehe hier template, mandatory, single-value, Standard: de::genesez::platforms::common::statistic::Root::Root spezifiziert das Template welches die Statistik-Datei generiert. Soll das Aussehen der Statistik-Datei geändert werden, kann hier ein anderes Template spezifiziert werden oder der Parameter aspectTemplate genutzt werden. slot, mandatory, single-value, Standard: statisticModel die Statistik-Komponente ändert den Standartwert des Slot-Parameters zur Ablage des Statistik-Modells Die Workflow Komponente selbst bietet folgende Paramete: name, optional, single-value, Standard: Statistic der Name der Statistik-Datei 32 Draft Statistik-Komponente Draft projectName, optional, single-value, Standard: Statistic Der Names des Projekts, für das die Statistik-Datei generiert wird. codeDetails, optional, single-value, Standard: true boolscher Wert der angibt, ob Statistiken über die einzelnen Packages und Dateien generiert werden withDate, optional, single-value, Standard: false boolscher Wert der angibt ob der Name der Statistik-Datei um einen Zeitstempel ergänzt werden soll generatedDir, optional, multi-value ein Quellcodeverzeichnis mit generierten Quellcode, d.h. die Quellcodedateien wurden vom Generator erzeugt und innerhalb Protected Regions wurde manuel implementiert generatedDirs, optional, multi-value gleiche Bedeutung wie generatedDir , jedoch kann als Wert eine mit Komma oder Semikolon getrennte Liste mit Quellcodeverzeichnissen angegeben werden manualDir, optional, multi-value ein Quellcodeverzeichnis das ausschließlich manuellen Quellcode enthält, d.h. die Quellcodedateien wurden manuell erzeugt und enthalten keinerlei generierten Quellcode manualDirs, optional, multi-value gleiche Bedeutung wie manualDir , jedoch kann als Wert eine mit Komma oder Semikolon getrennte Liste mit Quellcodeverzeichnissen angegeben werden excludes, optional, single-value, Standard: .svn, .cvs spezifiziert die Namen für den Dateifilter der Dateien und Verzeichnisse mit diesen Namen von der Statistik ausschließt comments, optional, single-value spezifiziert die Kommentarzeichen um die Quellcodezeilen auszuwerten. Die Kommentarzeichen werden mit einer Objektdefinition angegeben. Folgend die Standardwerte: <comments class="de.genesez.platforms.common.statistic.CommentSign"> <singleLineComment value="//" /> <multiLineCommentStart value="/\\*" /> <multiLineCommentEnd value="\\*/" /> <multiLineCommentLine value="\\*" /> <multiLineDocCommentStart value="/\\*\\*" /> </comments> Standardmäßig beginnen Einzeilenkommentare mit //, Mehrzeilenkommentare mit Dokumentationskommentare mit /**. Mehrzeilen- und Dokumentationskommentare enden mit Kommentarzeilen innerhalb Mehrzeilen- und Dokumentationskommentaren beginnen mit *. /*, */. 9.3. Logging Die Statistik-Komponente nutzt das Logging-Konzept. Sollten zuviel unerwünschte Log-Ausgaben im Workflow erscheinen, so kann in einer log4j.properties Datei der entsprechende Logger auf ein höheres Log-Level gestellt werden: log4j.logger.de.genesez.platforms.common.statistic = INFO Weitere Informationen zum Logging und zur Konfiguration siehe GeneSEZ Logging Konzept. 9.4. Hinweis zu den Diagrammen in der Statistik Die Diagramme in der Statistik werden aktuell von der Google Chart API [http://code.google.com/intl/de-DE/apis/ chart/] generiert. Dies ist ein Web-Service der die Diagramme als Bilder für eine URL mit den Daten liefert. Daher muss aktuell beim Betrachten der Statistik-Webseite eine Internetverbindung bestehen um die Diagramme sehen zu können! 33 Draft Statistik-Komponente Draft 9.5. Statstik-Übersicht am Beispiel Das Beispiel nutzt das metaframework als Software-Projekt. Die Statistik-Komponente ist im Workflow wie folgt definiert: <component id="statistics" class="de.genesez.platforms.common.workflow.Statistics"> <name value="metaframework" /> <outputDir value="../de.genesez.platforms.php.metaframework/reports/ statistics" /> <generatedDir value="../de.genesez.platforms.php.metaframework/src" /> <manualDir value="../de.genesez.platforms.php.metaframework/tests" /> <comments class="de.genesez.platforms.common.statistic.CommentSign"> <singleLineComment value="//" /> <multiLineCommentStart value="/\\*" /> <multiLineCommentEnd value="\\*/" /> <multiLineCommentLine value="\\*" /> <multiLineDocCommentStart value="/\\*\\*" /> </comments> </component> Das Zielverzeichnis des Generators ist hier als generatedDir angegeben. Das Verzeichnis mit den JUnit Tests ist ein Verzeichnis mit komplett manuell erstelltem Quellcode. Nach Ausführung des Workflows ist im Ausgabe-Verzeichnis die Datei metaframework.html zu finden, welche die Statistik-Übersicht enthält: Figure 9.1. Übersicht zur Quellcode Zusammensetzung 34 Draft Statistik-Komponente Draft Ganz oben findet sich die Projekt-Statistik sowie zwei Diagramme welche die Quellcodezeilen je Kategorie aufzeigen. Wie an den Quellcodezeilen erkennbar ist würde das Verhältnis zwischen generiertem und manuell implementierten Quellcode sehr verzerrt werden, wenn die Dokumentationszeilen zu den generierten Programmcodezeilen gerechnet werden würden (würde 59% statt 40% generierten Quellcode ergeben). Weiter unten folgen die konfigurierten Quellcodeverzeichnisse. Mit Klick auf den Button sind die Details der Quellcodedateien zu sehen: Figure 9.2. Details zu den einzelnen Quellcodedateien Es gibt auch eine Zusammenfassung für jedes Quellcodeverzeichnis: Figure 9.3. Zusammensetzung Quellcodeverzeichnis Werden die komplett manuell erstellten Tests aus der Statistik ausgeklammert wirken die Zahlen noch positiver ;-) 35 Draft Statistik-Komponente Figure 9.4. Statistik zum Quellcode ohne Tests 36 Draft Draft Draft Chapter 10. GeneSEZ UML Profil Um Konzepte des GeneSEZ-Metamodells in UML zu modellieren sowie nützliche und fachlich relevante Informationen zur Umsetzung im Modell zu hinterlegen, wurde ein GeneSEZ-UML-Profil eingeführt. Dieses ist prinzipiell plattformunabhängig, jedoch müssen nicht alle Aspekte, die das UML-Profil enthält, auch von den plattform-spezifischen Template-Sets ausgewertet werden. Welche Aspekte die plattformspezifischen Templates unterstützen, ist in der Dokumentation zu den jeweiligen Plattformen zu finden. source:trunk/de.genesez.docs/GeneSezProfile/genesez.profile.png Folgend werden die einzelnen Stereotypen und ihre Bedeutung näher erläutert. 37 Draft Draft Part III. Plattform Projekte Das GeneSEZ Framework stellt aktuell Modelltransformationen für die folgenden Plattformen bereit: Java Die Programmiersprache Java in Version 4 und 5 sowie darauf aufbauenden Technologien und Frameworks PHP Die Programmiersprache PHP in Version 5 sowie Unterstützung von Frameworks dot.net Die Programmiersprache C# C++ Die Programmiersprache C++ In Abbildung Figure 11, “Übersicht zur aktuellen Plattformunterstützung” sind die unterstützten Plattformen grafisch dargestellt. Figure 11. Übersicht zur aktuellen Plattformunterstützung Draft Draft Chapter 11. PHP Plattform Projekt GeneSEZ unterstützt PHP als Programmiersprache mit dem folgenden Umfang: Table 11.1. PHP Plattform Features Feature Beschreibung PHP5 Objektorientierter PHP5 konformer Quellcode DDM Generierung der Definitionen des dynamischen Datenmodells aus UML Modellen metaframework Unterstützung der metaframework Plug-In Entwicklung QuickForm Generierung von Adaptern zwischen Domainobjekten und HTML Formular Doctrine Ansatz zur Generierung der Doctrine ORM Definitionen Smarty Ansatz zur Generierung von Smarty Templates zur Darstellung der Domainobjekte Seasar Typemapping für den Dependency Injection Container Sesar Die Unterstützung für Assoziationsklassen fehlt bislang noch in PHP5 sowie in der Bibliothek zum Assoziationshandling für PHP. Die Unterstützung von Doctrine und Smarty ist vorerst nur als Ansatz zu sehen, wie solch eine Unterstützung realisiert werden kann. 11.1. Beispielprojekte Die folgenden Projekte sind mit der GeneSEZ PHP Plattform entwickelt und eignen sich sehr gut um die GeneSEZ PHP Unterstützung auszuprobieren. Geometrische Formen Ein einfaches Beispielprojekt welches die Klassendefinitionen geometrischer Formen aus einem UML Modell generiert. metaframework Ein anderer Ansatz für ein Webframework - ein Framework über Frameworks. metaframework plug-ins Die von GeneSEZ bereit gestellten Plug-Ins für das metaframework wurden ebenfalls mit der GeneSEZ PHP Plattform erstellt. Aktuell sind dabei die QuickForm Adapter ausgenommen. GeneSEZ Assoziationshandling Die GeneSEZ PHP Bibliothek zur Implementierung von Assoziationen. Das Beispiel zu geometrischen Formen eignet sich gut zur Erweiterung und weiterem Ausprobieren der PHP Plattform. Die letzten drei Projekte generieren Infrastruktur Quellcode, der im Falle der Bibliothek zum Assoziationshandling von der GeneSEZ PHP Plattform selbst genutzt wird. 11.2. Modellierung für PHP Für Modellierung von PHP Anwendungen mit UML steht ein GeneSEZ PHP UML Profil zur Verfügung und ist in Abbildung Figure 11.1, “UML Profil für die PHP Plattform” dargestellt. 39 Draft PHP Plattform Projekt Draft Figure 11.1. UML Profil für die PHP Plattform Darin sind einige der PHP Klassen und Schnittstellen enthalten, zwei weitere Klassen welche für die für Modellierung einer PHP Anwendung sinnvoll sind und zwei Instanzspezifikationen, die als Standardwerte für Parameter oder Attribute verwendet werden können. 11.3. PHP5 Die Basis der PHP Plattform stellt die Abbildung der Konzepte der UML in PHP dar: Table 11.2. Unterstützung der Abbildung von UML Konzepten in PHP Konzept Unterstützung Hinweis Klassen ja Interfaces ja Enumerations ja Attribute ja Assoziationen teilweise Enumerations werden von PHP nicht nativ unterstützt. Assoziationsklassen werden noch nicht unterstützt Konstanten ja Operationen ja Konstruktoren ja Destruktoren ja Zugriffsfunktionen ja auf Attribute sowie auf Assoziationen Dokumentation ja die Definitionen von phpDocumentor [http://phpdoc.org/index.php] werden unterstützt Enumerations und Assoziationen werden in PHP nicht nativ unterstütz. Die Umsetzung von Enumerations in Quellcode erfolgt aktuell mit einer final Klasse, die Enumeration-Literale werden zu Konstanten. Die Umsetzung von Assoziationen erfolgt sehr kompakt mit einer PHP Bibliothek. 40 Draft PHP Plattform Projekt Draft 11.4. QuickForm Im PEAR Namespace des PHP Plattform-Projektes befindet sich die Unterstützung für das Erstellen und Auswerten von HTML Formularen auf Basis des Paketes PEAR::HTML_QuickForm. Das QuickForm Template generiert für jede Klasse eine spezielle Form Klasse mit 3 statischen Methoden: create dient der Erstellung von QuickForm Formular Objekten, siehe Section 11.4.1, “Erstellen von QuickForm Objekten” build... dient der Erstellung von Domain Objekten aus QuickForm Objekten, siehe Section 11.4.2, “Konvertierung von Formularen zu Domain Objekten” addCustomDefinition dient der Möglichkeit Anpassungen und Ergänzungen an dem QuickForm Objekt innerhalb eines geschützten Bereiches durchzuführen, siehe Section 11.4.3, “Benutzerspezifische Definitionen” 11.4.1. Erstellen von QuickForm Objekten Mit der create Methode werden QuickForm Objekte erstellt die ein Formular repräsentieren. Die Methode hat einen Parameter defaultValues um den Formularfeldern Standardwerte zuzuweisen. Dem Formular Objekt werden neben versteckten Feldern für jedes Attribute der Klasse ein Feld hinzugefügt. Weiterhin wird für jedes Attribut ein trim Filter hinzugefügt. Am Ende wird die Methode addCustomDefinitions aufgerufen, welche einen geschützten Bereich für manuelle Implementierungen bereitstellt, um weitere Formulardefinitionen hinzuzufügen oder vorhandene abzuändern. 11.4.2. Konvertierung von Formularen zu Domain Objekten Mit der Methode build... kann aus QuickForm Formular Objekten wieder ein Domain Objekt erstellt werden. Dazu hat die Methode 2 Parameter: form spezifiziert das notwendige QuickForm Objekt <klassenname> spezifiziert ein optionales Domain Objekt Wird der zweite Parameter nicht genutzt, wird einfach ein neues Domain Objekt mit dem Standardkonstruktor erstellt. Für jedes Attribut der Domain Klasse wird der Wert von dem Formular exportiert und dem Domain Objekt als Attributwert zugewiesen. Je nach verwendetem Persistenzframework kann sich die Art des Zugriffs auf Attribute unterschieden, weshalb die QuickForm Unterstützung mit dem Workflow Parameter propertyAccess die folgenden drei Möglichkeiten bereit stellt: setter, (Standard) Nutzung einer set Methode $object->setAttribtue($form->exportValue('attribute')); attribute Setzen der Attributwerte mit direkten Zugriff auf die Attribute (bei nicht sichtbaren Attributen wird hier die magic set methode aufgerufen) $object->attribute = $form->exportValue('attribute'); array Setzen der Attributwerte als wäre das Objekt ein Array 41 Draft PHP Plattform Projekt Draft $object['attribute'] = $form->exportValue('attribute'); Standardmäßig wird die Nutzung einer set Methode angenommen. Zum Schluss wird das Domain Objekt zurückgegeben. 11.4.3. Benutzerspezifische Definitionen Die Methode addCustomDefinition ist lediglich ein Methoden-Stub mit einem Parameter form, der das QuickForm Objekt enthält. Innerhalb der geschützten Bereichen können weitere Einstellungen am Formular Objekt vorgenommen werden, weitere Felder hinzugefügt oder vorhandene Einstellungen geändert werden. 11.4.4. Spezielle Attribute Neben dem oben beschriebenen Standard Pattern wird aktuell eine Ausnahme unterstützt: Attribute mit dem Stereotyp html, dem Tag type und dem Tagged Value PASSWORD versehen sind. Für Passwörter werden in der create Methode 2 Formularfelder generiert sowie eine Validierungsregel welche die Gleichheit beider Formularwerte mit dem Validierungskonzept von QuickForm prüft. Weiterhin wird in der build... Methode der Wert des Passwortfeldes nur exportiert, wenn dieser kein leerer String ist. 11.4.5. Beispielcode Da die Klassen automatisch aus anderen Klassen erstellt werden und die Methoden ebenfalls automatisch erzeugt werden ist der generierte Quellcode natürlich bereits dokumentiert. Im folgenden Listing ist der PHP Quellcode für eine Klasse xyz abgebildet. <?php require_once 'HTML/QuickForm.php'; /** * Support class for dealing with QuickForm form definitions * * It provides two methods for converting an object into a form definition and vise versa. * An additional method is used to add some custom definitions to the form object. * * @see http://pear.php.net/manual/en/package.html.html-quickform.php * @author dreamer */ class XyzForm { /** * creates a QuickForm form definition for a Xyz * @param array $defaultValues default form values * @return HTML_QuickForm form definition for a Xyz * @see http://pear.php.net/manual/en/package.html.html-quickform.htmlquickform.setdefaults.php */ public static function create($defaultValues = array()) { $form = new HTML_QuickForm('xyzForm'); $form->setDefaults($defaultValues); $form->addElement('hidden', '...'); $form->addElement('text', '...', '...:'); $form->addElement('password', 'password', 'password:'); $form->addElement('password', 'passwordRepeat', 'Repeat password:'); $form->addElement('submit', 'save', 'save'); $form->addRule( array('password', 'passwordRepeat'), 'The passwords you entered does not match!', 'compare'); 42 Draft PHP Plattform Projekt Draft $form->applyFilter('...', 'trim'); self::addCustomDefinition($form); return $form; } /** * sets the values of the form object to the Xyz object * if the Xyz object is obmitted, a new instance is created * @param HTML_QuickForm a form, submitted by the user * @param Xyz an object to which the values of the form are set * @return Xyz the object with the submitted values */ public static function buildXyz($form, $xyz = null) { if ($xyz === null) { $xyz = new Xyz(); } $xyz->... = $form->exportValue('...'); if ($form->exportValue('password') != "") { $xyz->password = $form->exportValue('password'); } return $xyz; } /** * method to add custom definitions to the form object * @generated method stub for further implementation * @param HTML_QuickForm the created form for further adjustments * @see create() */ private static function addCustomDefinition($form) { /* PROTECTED REGION ID(pear.quickform.custom.definitions._14_0_b6f02e1_1206538020843_168097_254) ENABLED START */ // TODO: further form definitions for class 'XyzForm' /* PROTECTED REGION END */ } } ?> 11.5. Weitere Frameworks Für das ORM Framework Doctrine ist ein Ansatz enthalten der aufzeigt, wie die Unterstützung ausgebaut werden kann. Dies umfasst bisher aber nur Klassen und single-valued Attribute. Multi-Valued Attribute und Assoziationen werden noch nicht unterstützt. Für die Smarty Template Engine ist ein Ansatz enthalten wie auf Basis von Klassen ein Smarty Template für ListViews basierend auf einer Tabelle für Objekte der Klasse generiert werden kann. Die Unterstützung für das metaframework bezieht sich auf Plug-Ins welche mit UML modelliert werden können. Diese können sowohl in separaten UML Modellen enthalten sein, als auch in einem als separate Packages. Weiterhin wird die Erstellung und Implementierung der getId() Methode der Plug-In Klassen abgenommen. Für den Dependency Injection Container Seasar ist aktuell eine Typemapping Definition enthalten. 11.6. MDSD für das Dynamic Data Model (DDM) Für das dynamische Datenmodell kann mit dem GeneSEZ PHP Platform Projekt eine PHP Datei mit DDM Definitionen generiert werden. Die in einem UML Modell enthaltenen Datentypen, Klassen, Attribute sowie Assoziationen werden auf Basis des DDM definiert. 43 Draft PHP Plattform Projekt Draft 11.6.1. Erstellung eines UML Modells Für die Modellierung einer Anwendung die auf der Basis des DDM entwickelt werden soll gibt es ein UML Profil, welches in Abbildung Figure 11.2, “UML Profil für das DDM” dargestellt ist. Alle UML Klassen werden zu DDM Klassen und alle UML Datentypen werden zu DDM Typen. Attribute und Assoziationen werden analog abgebildet. Figure 11.2. UML Profil für das DDM Das Profil stellt fünf Stereotypen bereit. Die Stereotypen type und class sind optional. Zur Definition eines DDM Typs ist jedoch einer der drei Basistypen erforderlich. Dabei ist bewust keine Vererbungsbeziehung zwischen den Stereotypen type sowie den Stereotypen boolean, integer und string spezifiziert. Dies hat die folgenden Konsequenzen: • soll ein constraint für einen Typ angegeben werden muss zusätzlich der Stereotyp type zugewiesen werden • ist kein constraint erforderlich, kann auf den Stereotyp type verzichtet werden • Soll der Name des Datentyps als constraint verwendet werden, so muss lediglich der Stereotyp type zugewiesen werden, ohne einen Tagged Value für constraint anzugeben Mit Vererbungsbeziehung müsste jedes nicht notwendige constraints explizit als leerer String modelliert werden. 11.6.2. Mapping von UML Datentypen auf DDM Typen Der Stereotyp type ist bei der Abbildung von UML Datentypen auf DDM Typen optional, jedoch muss ein Stereotyp zur Angabe des Basistyps angegeben werden. Es werden die folgenden Eigenschaften berücksichtigt: • das Attribtue name eines DDM Typs ist durch den Namen des UML Datentyps gegeben • die description eines DDM Typs ist durch die Kommentare des UML Datentyps gegeben • das Attribut editable wird aus dem negierten Wert der UML Eigenschaft isLeaf gebildet. Im GeneSEZ Metamodell ist dieser Wert bereits negiert dem Attribut final zugewiesen • der basetype ergibt sich aus dem Namen des zugewiesenen Stereotypen: boolean, integer oder string • der Wert für constraint ergibt sich wie folgt: • ist der Stereotyp type nicht zugewiesen, ist der Wert ein leerer String • ist der Stereotyp type zugewiesen, aber kein Wert für den Tagged Value constraint vergeben, so wird der Name des UML Datentyps als Wert genutzt • ist der Stereotyp type zugewiesen sowie ein Tagged Value constraint vergeben, so wird der Wert des Tagged Values genutzt 44 Draft PHP Plattform Projekt Draft Bei der Abbildung werden die auf die Werte von name und basetype noch Namenskonventionen angewendet die standardmäßig den Name mit einem Großbuchstaben beginnen lassen und den basetype komplett in Großbuchstaben konvertieren. 11.6.3. Mapping von UML Klassen auf DDM Klassen Der Stereotyp class ist bei der Abbildung von UML Klassen auf DDM Klassen optional. Die Eigenschafen beider Konstrukte werden wie folgt aufeinander abgebildet: • das Attribtue name ist durch den Namen der UML Klasse gegeben • die description ist durch die Kommentare der UML Klasse gegeben • das Attribut editable wird aus dem negierten Wert der UML Eigenschaft isLeaf gebildet. Im GeneSEZ Metamodell ist dieser Wert bereits negiert dem Attribut final zugewiesen • als parent wird die erste Basisklasse genutzt • der Wert für view ergibt sich wie folgt: • ist der Stereotyp class nicht zugewiesen, wird der Name der UML Klasse genutzt • ist der Stereotyp class zugewiesen, aber kein Wert für den Tagged Value view vergeben, so wird der Name der UML Klasse genutzt • ist der Stereotyp class zugewiesen sowie ein Tagged Value view vergeben, so wird der Wert des Tagged Values genutzt Bei der Abbildung werden auf die Werte von name und view noch Namenskonventionen angewandt die standardmäßig beide Werte mit einem Großbuchstaben beginnen lassen. 11.6.4. Mapping von UML Attribute auf DDM Attribute Die Abbildung von UML Attributen auf DDM Attribute ist ohne zusätzliche Informationen möglich. Dabei werden die Informationen aus dem UML Modell wie folgt genutzt: • das Attribtue name ist durch den Namen des UML Attributes gegeben • die description ist durch die Kommentare des UML Attributes gegeben • das Attribut column ergibt sich wie folgt: • ist kein Standardwert des UML Attributes angegeben oder ist ein leerer String als Standardwert angegeben, so wird der Name des UML Attributes genutzt • ist ein Standardwert des UML Attributes angegeben der kein leerer String ist, wird dieser genutzt • als type wird der modellierte UML Datentyp genutzt • als class wird die modellierte UML Klasse genutzt Bei der Abbildung werden auf die Werte name und view noch Namenskonventionen angewandt die standardmäßig beide Werte mit einem Großbuchstaben beginnen lassen. 11.6.5. Mapping von UML Assoziationen auf DDM Assoziationen Die Abbildung von UML Assoziationen auf DDM Assoziationen ist ebenfalls ohne zusätzliche Informationen möglich. Dabei werden die Informationen des UML Modells wie folgt genutzt: • der name ist durch den Namen der UML Assoziation gegeben 45 Draft PHP Plattform Projekt Draft • die description ist durch die Kommentare der UML Assoziation gegeben • das erste von beiden Assoziationsenden wird die from Seite • die to Seite ist durch die UML Klasse gegeben welche als Typ des ersten Assoziationsendes gesetzt ist • die to cardinality wird aus der multiplicity des ersten Assoziationsendes gesetzt • die from cardinality wird aus der multiplicity der Gegenseite gesetzt, welche im GeneSEZ Metamodell als oppositeMultiplicity des ersten Assoziationsendes zugänglich ist Auf den Wert von name wird noch eine Namenskonvention angewandt die den Wert mit einem Großbuchstaben beginnen lässt. 11.6.6. Workflow Definition Bei der Uml2GeneSEZ Transformation sollte das GeneSEZ DDM UML Profil als Metamodell mit angegeben werden: <component id="uml2genesez" class="de.genesez.platforms.common.workflow.Uml2GeneSEZ"> <model value="<model name>" /> <profile value="model/genesez.php.ddm.profile.uml" /> </component> Zur Model-zu-Text Transformation kann ein PHP Generator genutzt werden, der de::genesez::platforms::php::ddm::templates::Definition::Root ausführt: das Template <component id="model2php" class="de.genesez.platforms.php.workflow.PhpGenerator"> <outputDir value="src-gen" /> <template value="de::genesez::platforms::php::ddm::templates::Definition::Root" /> </component> Danach wird im angegebenen Verzeichnis eine PHP Datei mit den DDM Definitionen erstellt. Standardmäßig ist diese ddm.definitions.php genannt. Die Datei enthält am Anfang eine Protected Region um die Datenbankverbindung sowie Doctrine initialisieren zu können bevor mit der Erstellung des DDM Modells begonnen wird. 46 Draft Draft Chapter 12. Java Plattform Projekt GeneSEZ kann sowohl Java 1.4 als auch Java 5 konformen Quellcode erzeugen. Darüber hinaus sind die folgenden Plattform-Erweiterungen verfügbar: Table 12.1. Java Plattform-Erweiterungen Plattform-Kurzbeschreibung Erweiterung JPA Generierung von Annotationen der Java Persistence API (Version 1.0) sowie automatische Codeergänzungen zur Verringerung des Modellierungsaufwands EJB 3 Generierung von Annotationen der Enterprise JavaBeans (Version 3.0) sowie automatische Codeergänzungen zur Verringerung des Modellierungsaufwands Seam 2 Generierung von Annotationen des Webframworks Seam (Version 2.1.2 GA) sowie automatische Codeergänzungen zur Verringerung des Modellierungsaufwands JWS Generierung von Annotationen des Java WebServices (JWS) Die Plattform-Erweiterungen JPA, EJB 3, Seam 2 und JWS ergänzen den "normalen" Java 5-Code. Dies bedeutet, dass der Java 5-konforme Code um die entsprechenden Code-Schnipsel, meistens Annotationen, ergänzt wird. Eine Erweiterung des Java 1.4-konformen Quellcodes ist nicht möglich. Zum besseren Verständnis der PlattformErweiterungen wird empfohlen Section 12.2, “Modellierungshinweise zur Verwendung der Plattform-Erweiterungen” zu lesen und sich mit dem Bank-Beispielprojekt vertraut zu machen. 12.1. Beispielprojekte Die folgenden Projekte sind mit der GeneSEZ Java Plattform entwickelt und eignen sich sehr gut um die GeneSEZ Java Unterstützung auszuprobieren. Geometrische Formen Ein einfaches Beispielprojekt, welches die Klassendefinitionen geometrischer Formen aus einem UML-Modell generiert (je ein Beispiel für Java 1.4 und 5). Auto Ein einfaches Beispielprojekt, welches die Eigenschaften und Beziehungen von Autos und deren Besitzer aus einem UML-Modell generiert (je ein Beispiel für Java 1.4 und 5). Time Budget Planing Ein einfaches Beispielprojekt, welches ein rudimentäres Time Budget Planing-System aus einem UML-Modell generiert. Bank Ein Beispielprojekt, welches die Verwaltung von Bankengruppen mit ihren Banken, Konten und Kunden aus einem UML-Modell generiert. Dieses Beispiel wird zur Erklärung der Plattform-Erweiterungen JPA, EJB 3, Seam 2 und JWS verwendet. 12.2. Modellierungshinweise zur Verwendung der Plattform-Erweiterungen Die Plattform-Erweiterungen ergänzen den "normalen" Java 5-konformen Quellcode um einige Code-Schnipsel, meistens Annotationen. Die dazu notwendigen Informationen kann der Modellierer über Stereotypen modellieren. Dabei entsprechen die Stereotypen mit ihren TaggedValues meist den in den verschiedenen Spezifikationen definierten Annotationen mit ihren Attributen. Dabei wurde auch das in den JavaEE-Spezifikationen verwendete Prinzip der "Convention over Configuration" berücksichtigt. Die Standard-Werte der TaggedValues entsprechen denen der Annotations-Attribute. Das folgende Bild zeigt dies am Beispiel des Stereotypen "jpaPersistentEntity". 47 Draft Java Plattform Projekt Draft Figure 12.1. Mapping des Stereotypen "jpaPersistent" auf die Annotationen "@Entity" Diese Abbildung der Stereotypen mit ihren TaggedValues auf die Annotationen mit ihren Attributen erlaubt eine intuitive Verwendung der Stereotypen, falls der Modellierer die Sicht des Programmierers einnimmt. Er kann anhand der verwendeten Stereotypen sehen wie der generierte Quellcode aussehen wird und gegebenenfalls Schlußfolgerungen ziehen welche Informationen im Modell noch fehlen. Die Einnahme der Sicht eines Programmierers bei der Modellierung hat Vor- und Nachteile. Dem oben genannten Vorteil steht die "Vertechnologisierung" des Modells entgegen. Damit ist die Anreicherung des Modells mit technologiespezifischen Informationen gemeint. Unter Umständen werden einige Informationen auch redundant modelliert. Der folgende Ansatz erlaubt dem Modellierer sich ein paar Schritte von der Programmier-Sicht zu entfernen. Der Rückweg steht ihm dabei aber jederzeit offen. 12.2.1. Automatische Quellcode-Ergänzung Die automatische Quellcode-Ergänzung verringert den Aufwand des Modellierers ein vollständiges Modell für eine bestimmte Technologie zu erstellen. Dabei übernimmt GeneSEZ die Aufgabe bereits im Modell vorhandenen oder logisch herleitbare Informationen in die Generierung des Quellcodes einfließen zu lassen. Der Modellierer muss keine redundanten Informationen oder technologiespezifischen Elemente (z.B. Interfaces, Klassen, Attribute oder Methoden) modellieren. Die notwendigen Informationen für die Codegenerierung können GeneSEZ im Allgemeinen auf drei verschiedene Weisen zur Verfügung gestellt werden: • vollautomatisch (Informationen ergeben sich vollständig durch die Metadaten des Modells), • halbautomatisch (Informationen ergeben sich aus Stereotypen und den Metadaten des Modells) oder • manuell (Informationen ergeben sich ausschließlich aus den verwendeten Stereotypen). Dieses Konzept ermöglicht dem Modellierer seinen Aufwand auf ein Minimum zu senken und das Modell frei von technologiespezifischen Elementen zu halten. Er kann aber jederzeit die automatische Quellcode-Ergänzung durch die Verwendung von Stereotypen beeinflussen (halbautomatisch) oder überschreiben (manuell). GeneSEZ setzt einen mündigen Modellierer voraus, der weiß was er modelliert. Die manuellen Informationen haben bei der Codegenerierung die höchste Priorität. 12.3. JPA (Java Persistence API) Die Java Plattform Erweiterung JPA ermöglicht dem Modellierer das Modell mit persistenzspezifische Informationen auf Basis der Java Persistence API (JPA) in der Version 1.0 [http://java.sun.com/javaee/technologies/ persistence.jsp] zu versehen. GeneSEZ erzeugt aus diesen Informationen die entsprechenden Annotationen und fügt sie dem Quellcode hinzu. Die Generierung von XML-Konfigurationsdateien wird nicht unterstützt. Es wird ein grundlegendes Verständnis der JPA-Technologie vorausgesetzt. Im nächsten Abschnitt wird das UML-Profil für die Java Plattform-Erweiterung JPA vorgestellt. Danach wird am Beispiel einer Persistent Entity gezeigt was ausgewählte Stereotypen bewirken und wie die automatische QuellcodeErgänzung den Modellierer unterstützt. Die nachfolgenden Abschnitte beschreiben das Verhalten von Stereotypen, welche die automatische Quellcode-Ergänzung verwenden. Sie können unabhängig voneinander gelesen werden. Als Beispiel dient durchgängig das Bank-Projekt. 48 Draft Java Plattform Projekt Draft 12.3.1. Das UML-Profil "jpa" Figure 12.2. UML-Profil der Java Plattform-Erweiterung JPA Figure 12.2, “UML-Profil der Java Plattform-Erweiterung JPA” zeigt das UML-Profil für die Java PlattformErweiterung JPA. In dem Profil sind die verschiedenen Stereotypen mit ihren TaggedValues und den dazugehörigen Enumerations enthalten. Die Enumerations werden als Datentypen einiger TaggedValues verwendet, falls diesen fest definierte Werte zugewiesen werden müssen. Dadurch werden dem Modellierer direkt die möglichen Werte (am besten durch das Modellierungstool) vorgegeben und Tippfehler vermieden. 49 Draft Java Plattform Projekt Draft 12.3.2. Eine Einführung - Die (Persistent) Entity Eine normale UML-Klasse wird zu einer (Persistent) Entity, indem der Modellierer diese mit Hilfe des Stereotyps "jpaPersistentEntity" als solche charakterisiert. Jede Persistent Entity benötigt einen Primärschlüssel, der durch das Anhängen des Stereotyps jpaPrimaryKey an ein Attribut oder eine Methode (field oder property access, siehe auch Kapitel über field/property access-Umschaltung) festgelegt wird (siehe Figure 12.3, “Persistent Entity mit den Stereotypen "jpaPersistentEntity" und "jpaPrimaryKey"”). Figure 12.3. Persistent "jpaPrimaryKey" Entity mit den Stereotypen "jpaPersistentEntity" und GeneSEZ erzeugt aus dieser Klasse folgenden Quellcode (ohne die automatisch erzeugten getter und setterMethoden): @Entity @Table(name = "tbl_Bank") public class Bank implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int sortCode; private String name; @Version private int version; public Bank { } [...] } Die Generierung der Annotationen @Entity sowie @Id lassen sich durch die beiden verwendeten Stereotypen erklären. Woher kommen aber die anderen Stereotypen, das Attribut version, der Standardkonstruktor und das Interface Serializable? Die Antwort lautet automatische Quellcode-Ergänzung. Gehen wir die verschiedenen Punkte der Reihe nach durch: • @Table(name = "tbl_bank"): Diese Annotation entsteht durch die Verwendung des Stereotyps jpaPersistentEntity. Dies ist auch der Grund warum jpaPersistentEntity kein 1:1 Mapping der Annotation @Entity ist und auch nicht genauso benannt wurde. Er enthält zusätzlich die TaggedValues der Annotation @Table. Für die Zusammenfassung der beiden Annotationen zu einem Stereotyp spricht vor allem, dass diese nicht getrennt verwendet werden. Aufgrund der "convention over configuration" ist die Angabe von @Table zwar optional, es können aber bei bestimmten Klassennamen, welche Schlüsselworte in Datenbanken sind, Probleme entstehen. Aus diesem Grund wird automatisch ein Prefix (Standard "tbl_") vor den Klassennamen gesetzt und somit ein Tabellenname erzeugt, welcher Probleme mit reservierten Schlüsselworten in Datenbanken verhindert. • Serializable: Die Implementierung dieses Interfaces ermöglicht die Serialisierung der Klasse, was beispielsweise bei der Übertragung über ein Netzwerk benötigt wird. Der Programmierer hat durch die Implementierung dieses Interfaces keinerlei Mehraufwand. Durch die automatische Quellcode-Ergänzung muss die Implementierung dieses Interfaces nicht modelliert werden. Das Modell wird frei von technologiespezifischen Elementen gehalten. • @GeneratedValue(strategy = GenerationType.AUTO): Wie im Klassendiagramm zu sehen ist dem TaggedValue generatedValue des Stereotyps jpaPrimaryKey der Wert true zugewiesen worden (Default-Wert: 50 Draft Java Plattform Projekt Draft false). Wie bei jpaPersistentEntity verbergen sich auch hinter jpaPrimaryKey mehrere Annotationen, weshalb der Stereotyp auch nicht jpaId genannt wurde. Die Begründung ist analog zu jpaPersistentEntity. Die Annotation @GeneratedValue wird nur in Verbindung mit @Id verwendet. Durch die convention over configuration wird die Standard-Generierungsstrategie der Datenbank überlassen. Dies spiegelt sich im TaggedValue strategy wieder, der als Datentyp die Enumeration jpaGenerationType mit dem Standardwert AUTO besitzt. Bei diesem Beispiel wurden GeneSEZ die notwendigen Informationen zur Generierung manuell vom Modellierer vorgegeben. Es wurden keine Werte logisch hergeleitet oder automatisch ergänzt. Die Vorgabe der Standardstrategie basiert auf der JPA-Spezifikation. • @Version und das Attribut "version": Die automatische Quellcode-Ergänzung erzeugt für jede Persistent Entity, die über kein Attribut mit @Version verfügt, dieses Attribut und die dazugehörige Annotation für das optimistische Locking. Es handelt sich wiederum um ein technologiespezifisches Element, welches nicht modelliert werden muss. • Standardkonstruktor: Zur Erzeugung von JavaBeans durch den Container ist ein parameterloser Standardkonstruktor notwendig. Dieser muss bei einer JavaBean (also auch SessionBeans, MessageDrivenBeans oder Seam-Komponenten) explizit vorhanden sein. Auch um diese technologiespezifische Eigenheit kümmert sich die automatische Quellcode-Ergänzung. Bei dieser Klasse gibt es bezüglich des Primärschlüssels zwei notwendige Anmerkungen. Da mit der Bankleitzahl (sortCode) nicht gerechnet werden soll, ist die Wahl des Datentyps String hier dem int vorzuziehen. Aus Performanzgründen empfiehlt die JPA-Spezifikation aber auf Primärschlüssel mit dem Datentyp String zu verzichten. Hinzu kommt noch, dass die Vermischung von fachlichen und technischen Merkmalen nicht besonders guter Programmierstil ist. Aus diesem Grund wird dem Attribut sortCode mit Hilfe des Stereotyps jpaColumn eine UniqueBeschränkung verpasst (fachlicher Primärschlüssel) und als technischer Primärschlüssel wird das Attribut id mit dem Datentyp int hinzugefügt. Für das nächste Beispiel (siehe Figure 12.4, “Persistent Entity mit unique-Attribut und ohne jpaPrimaryKey” und ???) wird noch ein Attribut mit dem Namen index hinzugefügt, welches den Platz der Bank in einem fiktiven Bewertungsindex repräsentiert. Figure 12.4. Persistent Entity mit unique-Attribut und ohne jpaPrimaryKey GeneSEZ erzeugt aus dieser Klasse folgenden Quellcode (ohne die automatisch erzeugten getter und setterMethoden): @Entity @Table(name = "tbl_Bank") public class Bank implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; @Column(name = "sortCode", unique=true, nullable=false) private String sortCode; private String name; @Column(name = "bank_index") private String index; @Version private int version; public Bank { } [...] 51 Draft Java Plattform Projekt Draft } Auch in diesem Beispiel war die automatische Quellcode-Ergänzung wieder am Werke. Wir schauen uns die Punkte genauer an: • @Id und @GeneratedValue(strategy = GenerationType.AUTO): GeneSEZ hat diese Annotationen automatisch an das Attribut id generiert, weil ein Attribut mit diesem Namen in der Java Plattform-Erweiterung JPA für einen Primärschlüssel reserviert ist, sofern kein anderes Attribut den Stereotyp jpaPrimaryKey besitzt. Nur unter bestimmten Umstände wird diese automatische Quellcode-Ergänzung unterlassen (siehe jpaInheritance). Bei diesem Beispiel hat GeneSEZ alle notwendigen Informationen durch das Modell erhalten (ein Attribut mit dem Namen id und dem Datentyp int existiert und gleichzeitig besitzt kein anderes Attribut dieser PersistentEntity den Stereotyp jpaPrimaryKey). Es hat eine vollautomatische Ergänzung stattgefunden. • @Column(name = "sortCode", unique=true, nullable=false): Die Beschränkung unique verlangt, dass der Wert des entsprechende Attributs ungleich null ist. Leider reicht das Setzen des Annotation-Attributs unique auf den Wert true nicht aus, um diese Folgebedingung zu erfüllen. GeneSEZ sorgt in diesem Fall vollautomatisch für das Setzen des Annotation-Attributs nullable auf den Wert false und lässt eine Kombination unique=true, nullable=false bei der Generierung auch nicht zu. • @Column(name = "bank_index"): Der Name dieses Attributs ist ein reserviertes Schlüsselwort in der Datenbank MySQL. Damit es nicht zu Problemen kommt, sorgt GeneSEZ dafür, dass ein anderer Spaltenname verwendet wird (Klassenname + "_" + Attribut-Name). Eine Festlegung des Spaltennamens durch den Modellierer hat natürlich eine höhere Priorität. Es wird dabei von einem mündigen Modellierer ausgegangen, der über die Problematik von Schlüsselwortkonflikten Bescheid weiß. Schließlich treten die Konflikte nicht mit jeder verwendeten Datenbank auf. Figure 12.5. Persistent Entity ohne technischen Primärschlüssel Ein Ziel der Java Plattform-Erweiterung JPA ist das Modell möglichst frei von technologiespezifischen Elementen zu halten. Dies wird nicht immer gelingen, aber bei der Persistent Entity lässt sich noch etwas verbessern. Der technische Primärschlüssel ist ein technologiespezifisches Element und hält man sich an die Trennung von fachlichen und technischen Merkmalen, dann läuft es in den meisten Klassen auf ein zusätzliches Attribut hinaus. Um das Modell von technologiespezifischen Elementen freizuhalten und den Arbeitsaufwand des Modellierers zu verringern, sorgt die automatische Quellcode-Ergänzung dafür, dass jede Persistent Entity einen technischer Primärschlüssel bekommt (Name: id, Datentyp: int), sofern der Modellierer kein anderes Attribut als Primärschlüssel definiert hat. Figure 12.5, “Persistent Entity ohne technischen Primärschlüssel” zeigt die Klasse Bank ohne technischen Primärschlüssel. Am generierten Quellcode ändert sich gegenüber dem letzten Beispiel nichts. 12.4. EJB 3 (Enterprise JavaBeans) Beschreibung folgt. 12.5. Seam 2 Beschreibung folgt. 52 Draft Draft Part IV. Weitere GeneSEZ Projekte Draft Draft Table of Contents 13. metaframework ..................................................................................................................................... 13.1. Yet Another PHP Framework? ................................................................................................... 13.2. Anwendungsarchitektur .............................................................................................................. 13.3. Gliederung einer Anwendung ..................................................................................................... 13.4. Infrastruktur-Konzepte ................................................................................................................ 13.4.1. Plug-Ins .......................................................................................................................... 13.4.2. Service Registry .............................................................................................................. 13.4.3. Plug-In Registry, Interceptor Registry, Extension Registry .................................................. 13.4.4. Resolver ......................................................................................................................... 13.4.5. Locator ........................................................................................................................... 13.5. Konzepte zur Anwendungsentwicklung ....................................................................................... 13.5.1. Request Handler ............................................................................................................. 13.5.2. Datentransferobjekte ....................................................................................................... 13.5.3. Rendering ....................................................................................................................... 13.5.4. Interceptors ..................................................................................................................... 13.5.5. Extensions und Contributions .......................................................................................... 13.6. Weitere Konzepte zur effektiven Anwendungsentwicklung ............................................................ 13.6.1. Composite-Struktur bei Request Handlern ........................................................................ 13.6.2. Delegate- und Decorator-Pattern bei Request Handlern .................................................... 54 55 55 55 56 56 57 57 58 58 59 59 59 60 61 61 61 62 62 63 Draft Draft Chapter 13. metaframework 13.1. Yet Another PHP Framework? Die Idee basiert auf der Beschreibung fundamentaler Aspekte einer Webanwendung. Dabei werden zur Beschreibung Schnittstellen eingesetzt wobei jede Schnittstelle ein Konzept mit einer bestimmten Aufgabe impliziert. Diese Aufgaben sind entweder notwendig oder sinnvoll innerhalb eines Request-Response Zykluses einer Webanwendung. Zu den Schnittstellen gibt es auch Standard-Implementierungen. Diese können bereits vorhandene und weit verbreitete Frameworks und Bibliotheken nutzen. Das metaframework selbst hat allerdings keine Abhängigkeiten zu anderen Frameworks und Bibliotheken - it's just that good. Bisherige Frameworks basieren meist auf dem Model-View-Controller- (MVC) Pattern wodurch ein großteil der Architektur einer Webanwenung vordefiniert ist. Eine Klasse (Model) beschreibt Daten, die in einer Datenbanktabelle gespeichert werden. Ein Controller bietet mit Methoden (Actions) Zugriff auf die Objekte dieser Klasse. Views stellen die Objekte der Klassen dar. Dabei wird meist eine fixe URL Struktur nach dem Muster /controller/ action festgelegt. Durch diese Art der Beschreibung entstehen Technologieabhängigkeiten: Die Notwendigkeit der Betrachtung des objektrelationalen Mappings bzw. des Datenbankzugriffs oder die Art der View Technologie. Einige Frameworks verfolgen Plug-In Ansätze zur Austauschbarkeit der Technologien, jedoch sind solche Plug-In Schnittstellen auf relativ tiefer technischer Ebene nicht einfach zu beschreiben. Das metaframework nutzt im Gegensatz zur Beschreibung einer Webanwendung keine technologischen Konzepte - man könnte die Konzepte mit einer höheren Abstraktionsebene vergleichen. Dadurch werden konkrete Realisierungspattern wie das MVC ausgeklammert. Jedoch können solche MVC Architekturen mit dem Framework nachgebildet werden - sie sind aber kein muss. Es geht auch flexibler. 13.2. Anwendungsarchitektur Das metaframework selbst besteht aus Schnittstellen und Klassen die Standardimplementierungen liefern. Durch die Verwendung von Schnittstellen können die Standardimplementierungen einfach an die eigenen Bedürfnisse angepasst werden oder andere Frameworks und Schnittstellen nutzen. Weiterhin basiert das Framework auf einem Plug-In Konzept. Dies erlaubt eine modulare Anwendungsentwicklung wie in Abbildung Figure 13.1, “Architektur einer Anwendung basierend auf dem metaframework” zu sehen ist. Das Framework selbst nutzt ebenfalls das Plug-In Konzept. Notwendig um das Framework einzusetzen ist ein Core PlugIn welches die Implementierungen der Schnittstellen bereitstellt und die Objekte entsprechend verknüpft. Figure 13.1. Architektur einer Anwendung basierend auf dem metaframework 55 Draft metaframework Draft Die Anwendung basiert dabei auf vorhandenen Frameworks und Bibliotheken. Das Core Plug-In sowie andere technische Plug-Ins stellen mit Adaptern die Implementierung der Schnittstellen des metaframeworks sicher. Die Frameworks und Bibliotheken die als Basis der Anwendung dienen können somit frei gewählt werden und bleiben austauschbar. Die Anwendung besteht aus Plug-Ins die gegenseitig Abhängigkeiten definierten können. Das metaframework stellt eine Art Laufzeitumgebung für die Plug-Ins bereit. 13.3. Gliederung einer Anwendung Webanwendungen nutzen URLs um ihre Funktionalität zur Verfügung zu stellen. Der Zugriff auf eine bestimmte URL mit eventuell optionalen Parametern (Request) hat eine bestimmte Anwort (Response) zur Folge. Die Antwort könnte eine HTML Webseite sein oder aber auch JSON oder XML (wie bei AJAX oder SOAP). Die URLs stellen somit die Eingabedaten dar die mit der Funktionalität auf Ausgabedaten abgebildet werden. Sinnvollerweise werden URLs in aussagekräftiger Weise strukturiert und aufgebaut werden. Viele MVC-Frameworks nutzen die /controller/action Struktur. Einige bieten für größere Webanwendungen noch einen optionalen Moduleintrag an: /module/controller/action. Dabei impliziert der controller häufig eine Klasse und die action eine Methode. Das metaframework stellt zur Strukturierung der Webanwendung die Klasse Context bereit. Mit den Objekten dieser Klasse kann mit der Assoziation nestedContext eine Baumstruktur nach dem Pattern in Abbildung Figure 13.2, “URL-Pattern zur Gliederung einer Anwendung” aufgebaut werden. Figure 13.2. URL-Pattern zur Gliederung einer Anwendung Die Klasse Context ist in Abbildung Figure 13.3, “UML Modell der Klasse Context” als UML Modell dargestellt. Sie definiert ein Attribut name welches in der URL dargestellt wird. Das Attribut handler ist ein Identifikator für die Funktionalität die ausgeführt werden soll. Figure 13.3. UML Modell der Klasse Context Definiert ein Kontext keinen handler so tritt ein Fallback Mechanismus ein und der handler eines parent Kontextes wird genutzt. Ein Handler kann auf den URL-Teil der zusätzlich zu seinem Kontext angegeben wurde zugreifen und diesen auswerten. Da Kontext Definitionen ohne handler wenig Sinn ergeben ist die Kontext-Struktur in der zugreifbaren URL-Struktur enthalten, beide sind aber nicht gleich. Somit sind an das REST-Pattern angelehnte URLStrukturen möglich. 13.4. Infrastruktur-Konzepte Im folgenden werden die Konzepte des metaframeworks erläutert, welche die Infrastruktur für eine Anwendung darstellen. 56 Draft metaframework Draft 13.4.1. Plug-Ins Das metaframework selbst ist relativ einfach aufgebaut und stellt lediglich eine Ablaufumgebung bereit. Durch Plug-Ins kann eine Webanwendung basierend auf dem metaframework mit Leben gefüllt werden. In Abbildung Figure 13.4, “UML Modell des Plug-In Konzepts” ist das UML Modell der Plug-In Definition dargestellt. Figure 13.4. UML Modell des Plug-In Konzepts Das metaframework unterscheidet dabei zwei Arten von Plug-Ins: PlugIn Mit Plug-Ins kann eine Webanwendung modular aufgebaut werden. Jedes Plug-In stellt dazu einen zugreifbaren Kontext sowie die Request-Handler bereit um URL Anfragen zu beantworten. CorePlugIn Aktuell kann es nur ein Core Plug-In geben. Es stellt alle notwendigen Standard-Implementierungen der metaframework Schnittstellen bereit. Daher verfügt es über eine zusätzliche Methode welche die Initialisierung eventuell genutzter Frameworks oder Bibliotheken sicher stellt. Weiterhin stellt das Core Plug-In die Service Registry bereit über die zentral auf Infrastruktur-Objekte zugegriffen werden kann. Weiterhin gibt es eine Standardimplementierung PlugInBase die als Basis für eigene Plug-Ins genutzt werden kann und die zu implementierenden Methoden auf eine ( getId()) reduziert. 13.4.2. Service Registry Die Service Registry verwaltet zentral alle Infrastruktur-Objekte, d.h. alle Instanzen der Implementierugnen der metaframework Schnittstellen. Dies umfasst die PlugInRegistry, ExtensionRegistry, InterceptorRegistry, Resolver, Locator, Rendering sowie die von den Plug-Ins definierten RequestHandler und Interceptoren. Die Abbildung Figure 13.5, “UML Modell der Service Registry” zeigt die UML Definition der Service Registry sowie die im metaframework enthaltene Standard-Implementierung. 57 Draft metaframework Draft Figure 13.5. UML Modell der Service Registry Um die gegenseitigen Referenzen der Objekte untereinander elegant zu lösen bietet sich als Implementierung ein Dependency Injection [http://martinfowler.com/articles/injection.html] Container an. Siehe dazu metaframework Plug-Ins. 13.4.3. Plug-In Registry, Interceptor Registry, Extension Registry Diese drei Registries werden genutzt um Plug-Ins, Interceptor-Definitionen sowie Contributions auf Extensions zu verwalten. Die PlugInRegistry und die InterceptorRegistry werden nur von der Klasse Metaframework genutzt, während die ExtensionRegistry vom Anwendungscode genutzt wird. In Abbildung Figure 13.6, “UML Modell der Plug-In, Interceptor und Extension Registry” ist das UML Klassendiagramm der drei Registries dargestellt. Figure 13.6. UML Modell der Plug-In, Interceptor und Extension Registry Bei der Plug-In Registry werden alle Plug-Ins verwaltet sowie die Abhängigkeiten zwischen ihnen geprüft. Bei fehlenden Plug-Ins wird die Abarbeitung durch das Framework gestoppt. Die Interceptor-Registry verwaltet die Interceptoren mit den zugehörigen URL-Pattern für welches sie ausgeführt werden. Die Extension-Registry verwaltet die Contributions von Plug-Ins zu Extensions. Das Extension-Contrubution Konzept wird hier näher erläutert. 13.4.4. Resolver In Abschnitt Section 13.3, “Gliederung einer Anwendung” wurde das Kontext-Konzept vorgestellt um eine Anwendung zu gliedern. Kontexte können dabei mit einem Identifikator auf einen RequestHandler verweisen. Die Aufgabe des Resolvers ist es einen Aufruf der Anwendung auf die Kontext-Struktur abzubilden und KontextInformationen über den aktuellen Request zu ermitteln. Diese Informationen werden in einem HandlerInfo Objekt zusammengefasst und zurückgeliefert. Abbildung Figure 13.7, “UML Modell des Resolvers” zeigt die Definition des Resolvers in UML. 58 Draft metaframework Draft Figure 13.7. UML Modell des Resolvers Neben der Schnittstelle ist auch eine Implementierung für Webanwendungen vorhanden, welche die aufgerufene URL auf die Kontext-Struktur abbildet. 13.4.5. Locator Basierend auf den Informationen des HandlerInfo Objektes ermittelt der Loctor den RequestHandler welcher den aktuellen Request bearbeiten kann. Abbildung Figure 13.8, “UML Modell des Locators” zeigt das UML Klassenmodell des Locators und einer Standardimplementierung. Figure 13.8. UML Modell des Locators Die Standardimplementierung nutzt die Service Registry um eine Referenz auf den RequestHandler zu erlangen. Neben der Service Registry ist auch eine Instanziierung per Reflection denkbar, wie sie bei vielen MVC-Frameworks eingesetzt wird. 13.5. Konzepte zur Anwendungsentwicklung In diesem Abschnitt werden die Konzepte erläutert die wesentlich für das entwickeln von Anwendungen sind. 13.5.1. Request Handler Die Funktionalität einer Anwendung wird von Request Handlern bereitgestellt. Diese bearbeiten einen Request und sammeln alle benötigten Daten für die Response. Die UML Definition der Request Handler ist in Abbildung Figure 13.9, “UML Modell der Request Handler” dargestellt. 59 Draft metaframework Draft Figure 13.9. UML Modell der Request Handler Die Abarbeitung wird durch die Methode handle initiiert die durch den übermittelten Parameter Zugriff auf KontextInformationen des aktuellen Requests hat. Der Rückgabewert der Methode ist ein Datentransferobjekt oder der boolsche Wert true. Der Wert true impliziert das die Antwort bereits generiert wurde wodurch das Rendering nicht durchgeführt wird. Die Standardimplementierung RequestHandlerBase bietet nützliche Funktionen u.a. zur Erstellung von Links / URLs. Neben der Standardimplementierung gibt es eine weitere Implementierung welche den Controller des MVCKonzepts realisiert. Dieser bildet eine zentrale Stelle zur Implementierung der CRUD-Funktionalität und verfügt über nützliche Methoden für Redirects und Link-Erstellung. Alle Aktionen (wie create, edit, retrieve, ...) des Controllers sind über die Assoziation zur Klasse Action modelliert und somit erweiterbar. 13.5.2. Datentransferobjekte Die Daten für die Response werden in Datenobjekten verpackt die als Container dienen. Dieses Konzept findet sich in den Pattern Value Object oder Data Transfer Object wieder. Das UML Klassenmodell für die Datentransferobjekte ist in Abbildung Figure 13.10, “UML Modell der Datentransferobjekte” zu sehen. Figure 13.10. UML Modell der Datentransferobjekte Jedes Datentransferobjekt kennt seinen View durch den es dargestellt wird. Die Standardimplementierung erbt von der PHP Klasse ArrayObject wodurch auf einfache Weise Daten gespeichert werden können. 60 Draft metaframework Draft 13.5.3. Rendering Die Aufgabe des Rending ist es die Daten die Request Handler zusammentragen in geeigneter Form zu rendern. Das UML Modell des Rendering ist in Abbildung Figure 13.11, “UML Modell des Rendering” dargestellt. Figure 13.11. UML Modell des Rendering Es fällt auf das vom metaframework keine Standardimplementierung bereitgestellt wird da das Rendering optional ist. In den metaframework Plug-Ins gibt es eine Implementierung auf Basis der Smarty Template Engine [http:// www.smarty.net/]. 13.5.4. Interceptors Für Aufgaben wie die Authentifizierung und Autorisierung die sich über weite Bereiche einer Anwendung erstrecken sind Request Handler nur bedingt geeignet da in jedem Request Handler die Berechtigungen geprüft werden müssten. Für solche Aufgaben gibt es die Interceptoren welche einen Request abfangen und entscheiden können, wie dieser fortgesetzt werden soll. Die Definition in UML ist in Abbildung Figure 13.12, “UML Modell der Interceptoren” zu sehen. Figure 13.12. UML Modell der Interceptoren Für Interceptoren wird eine Schnittstelle mit einer Methode vorgegeben. Diese hat über den Parameter handlerInfo Zugriff auf Kontext-Informationen zum Request und muss einen boolschen Wert zurückgeben der angibt ob der Request abgefangen wurde oder nicht. Der Wert true bedeutet das der Request abgefangen wurde und die Response vom Interceptor erzeugt wird. Bei false wird das Request Processing wie gehabt durchgeführt. 13.5.5. Extensions und Contributions Ein Problem von modularen Anwendungen kann eine Abhängigkeit zwischen Modulen oder hier Plug-Ins sein. Beispielsweise betrifft dies das Menü. Auf die Funktionalität einiger Plug-Ins soll durch Menü-Einträge direkt zugegriffen werden können. Sind die Plug-Ins aber nicht registriert (vorhanden), so sollen diese Menü-Einträge nicht erscheinen. Solch ein indirekter Informationsaustausch ist über das Extension-Contribution Konzept realisierbar (welches von Eclipse Extension Points inspiriert wurde). Im Gegensatz zu den anderen Konzepten gibt es hier kein UML Modell - die einzige Definition ist die Extension Registry in Abbildung Figure 13.6, “UML Modell der Plug-In, Interceptor und Extension Registry” . Mit der Plug-In Schnittstelle können Plug-Ins beliebige Contributions für Extensions bereitstellen: public function getExtensions() { return array( 'de.example.navigation.simple' => array('name' => 'Datenmodell', 'link' => '/ddm', 'image' => 'images/ddm.png'), 'de.example.navigation.complex' => new Menu_MenuBar(array( new Menu_Menu('class', '/class', array( new Menu_MenuItem('create new', '/class/create'), new Menu_MenuItem('list', '/class/list') )), ... 61 Draft metaframework Draft )) ); } Im Beispiel ist die Contribution eines Arrays auf die Extension de.example.navigation.simple sowie eine Objektstruktur auf de.example.navigation.complex zu sehen. Wie der Name der Extension vermuten lässt handelt es sich beide male um Navigationseinträge für das Menü. Der letztere wird bei einer komplexen Menüdarstellung genutzt, der erste bei einem einfachen Menü. Die Contributions aller Plug-Ins werden durch die Extension Registry zusammengefügt. Der Zugriff auf die Extension Registry ist über die Service Registry während des Request Processing jederzeit aus möglich. So können die Contributions für bestimmte Extensions abgefragt und genutzt werden: $extensionRegistry = $this->serviceRegistry->getComponent('extensionRegistry'); $contributions = array(); if ($extensionRegistry->hasContributions('de.example.navigation.simple')) { $contributions = $extensionRegistry>getContributions('de.example.navigation.simple'); } Dabei ist es Aufgabe des Entwicklers sicherzustellen, das die Contributions von einem Datentyp sind, mit dem die zugreifende Logik etwas anfangen kann. 13.6. Weitere Konzepte zur effektiven Anwendungsentwicklung Bei der Entwicklung von Anwendungen trifft man häufig auf wiederkehrende Probleme für die es meist nicht nur eine Lösung gibt, sondern auch ein Design-Pattern. In diesem Abschnitt werden solche Lösungen die das metaframework mit Klassen bereits unterstützt erläutert. Diese sind nicht notwendig für das Verständnis des metaframeworks, aber sinnvoll für die Anwendungsentwicklung mit diesem. 13.6.1. Composite-Struktur bei Request Handlern Blickt man auf Anwendungen oder Webanwendungen so fällt auf das diese meist gegliedert sind. Es gibt einen Header, ein Menü zur Navigation, häufig eine Sidebar, eine große Fläche für den eigentlichen Inhalt und eventuell einen Footer. Technisch betrachtet möchte man diese Dinge auch trennen, was in einem separaten Request Handler für jeden Bereich resultiert. Jeder Request Handler liefert dann ein Datentransferobjekt mit Daten für seinen Bereich. Nun stellt sich die Frage wie diese Datentransferobjekte kombiniert und einem View zum Rendern übergeben werden können. Hierfür unterstützt das metaframework eine Composite-Struktur für Request Handler wie in Abbildung Figure 13.13, “Definition der Composite-Struktur von Request Handlern in UML” dargestellt ist. 62 Draft metaframework Draft Figure 13.13. Definition der Composite-Struktur von Request Handlern in UML Der CompositeRequestHandler ist ebenfalls ein Request Handler und besitzt eine qualifizierte Assoziation zu RequestHandler, d.h. der Zugriff auf einen nestedRequestHandler ist nur durch einen Wert vom Typ String möglich. Mit der Standardimplementierung CompositeRequestHandlerBase können Request Handler im Konstruktor übergeben werden (als assoziatives Array) sowie über die qualifizierte Assoziation eingefügt werden: $this->nestedRequestHandler->insert('header', $this->serviceRegistry>getComponent('header.handler')); $this->nestedRequestHandler->insert('footer', $this->serviceRegistry>getComponent('footer.handler')); Hier werden von der Service Registry ein Header- und Footer Handler geholt und diese in die qualifizierte Assoziation eingefügt. Die Implementierung der Methode handle delegiert das Request Processing einfach an alle Request Handler und kombiniert die Datentransferobjekte in einem, wobei der qualifier als Schlüssel genutzt wird - analog zu den Request Handlern. $header = $compositeDto->header; $footer = $compositeDto->footer; Obiges Programmlisting zeigt den Zugriff auf die Daten der einzelnen Request Handler über das zurückgegebene Datentransferobjekt des Composite Request Handlers. 13.6.2. Delegate- und Decorator-Pattern bei Request Handlern Häufig tritt bei der Entwicklung einer Anwendung auch der Fall auf, das man prinzipiell etwas wiederverwenden könnte, jedoch kleine Anpassungen notwendig sind. Da etwas ändern und etwas anderes hinzufügen. Solche Anwendungsfälle sind u.a. durch das Decorator-Pattern beschrieben, das vorhandene Funktionalität ausschmücken kann. Im metaframework wird das Decorator-Pattern kombiniert mit dem Delegate-Pattern durch eine spezielle 63 Draft metaframework Draft Basisklasse für Request Handler unterstützt. In Abbildung Figure 13.14, “UML Modell des Decorate Request Handlers” ist das zugehörige UML Modell zu sehen. Figure 13.14. UML Modell des Decorate Request Handlers Im Konstruktor der Klasse DecorateRequestHandler ist zu erkennen das der Delegate-Teil optional ist - dieser wird ebenfalls durch den CompositeRequestHandler unterstützt. Die Methode handle ruft zuerst die Methode handle des dekorierten Request Handlers auf. Anschließend wird das erhaltene Datentransferobjekt mit den Datentransferobjekten der Delegate Request Handlern kombiniert, analog Abschnitt Section 13.6.1, “CompositeStruktur bei Request Handlern” . Zum Schluss wird die Methode decorate aufgerufen und das von dieser Methode erhaltene Datentransferobjekt als Rückgabewert der Methode handle genutzt. Durch diesen Ablauf kann die Methode decorate alle Daten des Datentransferobjektes beliebig dekorieren. Ein weiterer Vorteil ist das nur eine loose Kopplung zur Schnittstelle RequestHandler existiert. Dadurch besteht die Möglichkeit zum Layering von Dekorierern, d.h. DecorateRequestHandler können wiederum dekoriert werden. Eine Alternative kann allerdings die Verwendung der Vererbung sein. Hier muss genau definiert werden, was erreicht werden soll. Eine Vererbung hat eine viel stärkere Kopplung als das Decorator- oder Delegate Pattern, da bei den beiden Pattern nur eine Kopplung zur Schnittstelle RequestHandler existiert. Bei Vererbung besteht eine direkte Kopplung zum konkreten Typ, allerdings ist dadurch auch der Zugriff auf alle nicht privaten Member und Methoden möglich. Als Beispiel kann eine einfache Webanwendung herangezogen werden. Das Layout einer Webanwendung ist meist komplett oder für größere Bereiche einer Webanwendung gewollt gleich, d.h. es gibt einen Header, Footer, Sidebar, etc. Der eigentliche Inhaltswechsel findet im Haupt-Anzeigebereich statt, wo der Inhalt von unterschiedlichen Request Handlern bereitgestellt wird. Die Inhaltsänderungen in den angliedernden Bereichen (Header, Footer, Sidebar, etc.) ist meist geringer. Für solch ein Szenario kann ein Composite Request Handler genutzt werden, der die Request Handler für die einzelnen Bereiche zusammenfasst. Die Request Handler der Haupt-Anzeigebereiche werden DecorateRequestHandler und dekorieren den Request des Composite Request Handler. Somit kann auf einfache Weise ein einheitliches Design einer Webanwendung erreicht werden. 64