Menu

Seite4191

Anonymous Joerg Reichert
Attachments
Persistence-packages.png (28498 bytes)

4.1.9.1 Allgemeines

Allgemeines

Bevor sich intensiv der Vorgehensweis bei der Templatierung der Persistenzschicht gewidmet werden soll, müssen noch einige in allen Templates (auch in denen der anderen Schichten) verwendeten Prinzipien und Methoden näher erläutert werden.

Alle Templates-spezifischen Dateien sind unter dem Ordner src-templates im Generator-Projekt abgelegt und somit getrennt von der Generator-GUI (unter src) und statischen Dateien, die nicht generiert sondern nur generiert werden müssen (src-static).

Einige Operationen auf dem Modell sind in Extensions augelagert wurden. Zum einen soll so die Länge der Aufrufe in den Templates verkürzt werden, zum anderen hat man in den Extensions einen zentralen Punkt, wo Operationen geändert werden können, die sonst immer jeweils an den einzelnen Stellen in den Templates mühsehlig aufgesucht hätten werden müssen.

Im Paket de.uni_leipzig.dreirad.generator.templates.common unter src-templates sind alle Templates und Extensions abgelegt, die in (fast) allen Templates Verwendung finden bzw. keinen der Aufgabengebiete, die vier Ober-Template-Packages beschreiben, eindeutig zuzuordnen sind.

EmfTypes.ext

In EmfTypes.ext sind Methoden zum Abfragen verschiedener EMF-Datentypmengen definiert, z.B. die Menge aller Ganzzahltypen in EMF. Aus den Teilmengen werden auch größere Menge gebildet. So entsteht durch die Vereinigung aller Nicht-Zahlen- mit allen Zahlen-Datentypen die Menge aller EMF-Datentypen. Die Methoden werden später in den Templates benötigt, um z.B. spezielle Validatoren und Formatierer generieren zu können.

import ecore;

getAllTotalNumberEmfTypes() : {
    'EByte',
        ...
};

...

getAllEmfTypes() :
    getAllNonNumberEmfTypes()
    .union(getAllNumberEmfTypes());

TypeMapping.ext

Die Erweiterung TypeMapping ermöglicht es, für einen im Domänenmodell ausgelesenen EMF-Datentyp den richtigen Java-Datentypen zuzuordnen. Da bei uns Ecore auch im Domänenmodell verwendet wird, erfolgt in den Templates kein automatisches Typmapping.

import ecore;

getJavaType(EAttribute this) : getJavaType(eType.name.toString());

getJavaType(String name) :
    switch(name) {
        case 'EBigDecimal': 'java.math.BigDecimal'
        case 'EBigInteger': 'java.math.BigInteger'
        case 'EBoolean': 'Boolean'

                ...

        case 'EString': 'String'
        case 'ETreeIterator': 'java.util.Iterator'
        default: 'Object'
    };

Für weitere Informationen sei auf Umgang mit den Datentypen verwiesen.

Common.ext

In der Extension Common werden alle Methoden zusammengefasst, die sehr häufig verwendet werden.
So erfolgt hier der Zugriff auf die globale Variable PackageName, die durch Funktion von Object zu String gecastet wird, sowie eine Methode, die eine Package-Struktur in eine Ordner-Struktur konvertiert.
Des Weiteren werden Benamungskonventionen festgelegt. Bei Instanzen- und Attributnamen ist der erste Buchstabe stets klein, bei Klassennamen stets groß. Bei der Getter-Methoden-Benamung wird der Sonderfall bei Boolean (is statt get) beachtet. Bei der Vergabe von Pluralnamen wird in den Sonderfällen von Standardvorgehensweise des Anhängens eines s an den Singularnamen abgewichen.
Das Holen der Menge aller Oberklasse einer Klasse einschließlich der Ausgangs-Klasse selbst, der Holen der Menge aller Attribute bzw. aller Relationen einschließlich der in den Oberklassen definierten sind häufig benötigte Operation, die nach ausgelagert wurden.
Unter Verwendung der Methoden aus EmfType.ext (die dazu importiert wurde) werden spezielle Datentypmengen aus der Menge der im Modell verwendeten Datentypen geholt (also nicht aller überhaupt existierender EMF-Datentypen - sonst könnte man direkt die Methoden von EmfTypes.ext nutzen).

import ecore;
extension de::uni_leipzig::dreirad::generator::templates::common::EmfTypes;

String getPackageName() : GLOBALVAR PackageName;
String getAsPath(String this): replaceAll("\\.", "/");

getClassName(EClassifier this): name.toFirstUpper();
getClassName(EReference this): eType.name.toFirstUpper();
getInstanceName(EReference this): eType.name.toFirstLower();
getInstanceName(EClassifier this): name.toFirstLower();
getAttributeName(EAttribute this): name.toFirstLower();
getGetMethodName(EAttribute this): this.eType.name.matches('EBooleanObject') ? 'is' + name.toFirstUpper() : 'get'+name.toFirstUpper();
getSetMethodName(EAttribute this): 'set'+name.toFirstUpper();
getPluralName(String name): (name.endsWith('s') || name.endsWith('x')) ? name+'es' : name+'s';

getClassAndItsSuperClassesContents(EClass this) : this.eSuperTypes.add(this).eContents;
getAllAttributes(EClass this) : getClassAndItsSuperClassesContents().typeSelect(EAttribute);
getAllRelations(EClass this) : getClassAndItsSuperClassesContents().typeSelect(EReference);

getAllDataTypeNames(EPackage this) : eClassifiers.typeSelect(EClass).eContents.typeSelect(EAttribute).eType.name.toSet();
getAllNumberDataTypeNames(EPackage this) : getAllDataTypeNames().select(name|getAllNumberEmfTypes().contains(name));
getAllTotalNumberDataTypeNames(EPackage this) : getAllDataTypeNames().select(name|getAllTotalNumberEmfTypes().contains(name));
getAllDecimalNumberDataTypeNames(EPackage this) : getAllDataTypeNames().select(name|getAllDecimalNumberEmfTypes().contains(name));
getAllStringDataTypeNames(EPackage this) : getAllDataTypeNames().select(name|getAllStringEmfTypes().contains(name));
getAllBooleanDataTypeNames(EPackage this) : getAllDataTypeNames().select(name|getAllBooleanEmfTypes().contains(name));
getAllNonNumberDataTypeNames(EPackage this) : getAllDataTypeNames().select(name|getAllNonNumberEmfTypes().contains(name));

Logger.xpt

Im Template Logger.xpt ist die Definition des log4j-Loggers hinterlegt. Diese kann somit bei Bedarf in allen Templates aufgerufen werden.

«IMPORT ecore»
«EXTENSION de::uni_leipzig::dreirad::generator::templates::common::Common»

«DEFINE loggerDefinition(String className) FOR EPackage»
    «EXPAND loggerDefinition(className) FOR this.eClassifiers.typeSelect(EClass).get(0)»
«ENDDEFINE»


«DEFINE loggerDefinition(String className) FOR EClass»
    private static Logger LOGGER = Logger.getLogger(«className».class);
«ENDDEFINE»

Nun zu den Templates für die Persistenzschicht. Die folgende Abbildung zeigt, wie die Templates in Packages organisiert sind.

Es wurde die Aufgabe der Entitäten-Generierung von der Datenzugriffs-Generierung getrennt. Zudem existiert noch ein Package, in dem Templates für xml-Konfigurationsdateien liegen. In den Aufgaben-Packages erfolgt eine weitere Unterteilung in weitere Pakete, die Teilaspekte der Aufgabe darstellen. Zu den Aspekten gehört auch die konkrete technische Umsetzung der Aufgabe. Je nach Konfiguration werden Templates eines der Unter-Packages angewendet.

Im obersten Package liegt das Template PersistenceMain.xpt.

«IMPORT ecore»

«DEFINE persistenceMain FOR EPackage»

    «EXPAND entities::EntitiesMain::entitiesMain FOR this»
    «EXPAND data_access::DataAccessServiceMain::dataAccessServiceMain FOR this»

«ENDDEFINE»

Die Endung Main soll signalisieren, dass es sich hierbei um das WurzelTemplate in diesem Package handelt, dass von in einer Generator-Komponente eingebunden werden soll. Die Methode persistenceMain() des Templates kann dann in dieser Komponente im oAW-Workflow gerufen werden.

   <component class="oaw.xpand2.Generator" id="persistenceGenerator">
      <metaModel idRef="meta.model"/>
      <expand value="de::uni_leipzig::dreirad::generator::templates::persistence::PersistenceMain::persistenceMain FOR domainModel"/>
      <globalVarDef name="PackageName" value="'${package.name}'" />
      <outlet>
         <path value="${output.path}/src-gen" />
      </outlet>
      <fileEncoding value="ISO-8859-1"/>
      <beautifier class="oaw.xpand2.output.JavaBeautifier"/>
   </component>

persistenceMain ruft selbst weitere Templates auf, die die Teilaufgaben der Persistenzschicht abarbeiten. Sie werden in Templatierung der Entitäten und Templatierung des Datenzugriffs beschrieben.

Persistence.ext

Neben PersistenceMain.xpt befindet sich noch die Erweiterung Persistence.ext direkt im Package de.uni_leipzig.dreirad.generator.templates.persistence. Sie definiert Methoden, die in Templates innerhalb des Persistence-Packages zusätzlich zu den Methoden aus Common.ext benötigt werden. Neben dem Zugriff auf die globalen Datenbank-Variablen gehören auch zwei Hilfs-Methoden zur Generierung der toString-Methode für die Entität dazu.

import ecore;

String getJndiName() : GLOBALVAR JNDIName;
String getDriver() : GLOBALVAR Driver;
String getDialect() : GLOBALVAR Dialect;
String getDatabaseName() : GLOBALVAR DatabaseName;
String getUserName() : GLOBALVAR UserName;
String getPassword() : GLOBALVAR Password;
String getJdbcUrl() : GLOBALVAR JDBC_URL;

getToStringPart(EAttribute this): 'buffer.append("' + name.toFirstUpper() + ': ").append(' + name.toFirstLower() + ')';
getToStringPartWithComma(EAttribute this) : getToStringPart(this)+'.append(", ")';

weiter zu 4.2.3.2 Umgang mit den Datentypen
weiter zu 4.3 Templatierung der Geschäftslogikschicht
zurück zu 4.2.2 Erstellen des oAW-Workflows
zurück zu 4.2 Implementierung des Generators
zurück zu 4 Implementierung
zurück zu [FrontPage]


Related

Documentation: FrontPage
Documentation: Seite000
Documentation: Seite400
Documentation: Seite418
Documentation: Seite419
Documentation: Seite4192
Documentation: Seite4193
Documentation: Seite4194
Documentation: Seite41A
Documentation: Seite420