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