Thema 4 Acceleo- Sprachmittel und Generator- · Templates - Details Templates haben keinen...

Preview:

Citation preview

Thema 4 Acceleo- Sprachmittel und Generator- struktur

SE – Vertiefung Beuth-Hochschule Berlin

1. ACCELEO-PRAXIS

(c) schmiedecke 14 SE3 2

Abgeguckt bei Obeo UmlToJava

Es gibt zwei Generatorprojekte UmltoJava

UmlToJava (Helios)

einfach über den Marketplace installieren

(überschaubarer, hier überwiegend verwendet)

UmlToJava (Kepler)

über das Obeo-Network von Github herunterladen

(Anspruchsvoll, Projekt wird fortgeführt)

(c) schmiedecke 14 SE3 3

Templating-Sprache

Ein Generator besteht aus Templates

(+ Queries + Properties)

(mind.) ein Template wird als Main Template

ausgezeichnet

Die Ausgabe erfolgt in die Datei, die im File-Block

angegeben ist

Mehrere File-Blöcke sind möglich, aber nur nacheinander

(c) schmiedecke 14 SE3 4

Beispiel 1

[comment encoding = UTF-8 /]

[module generateUmlToJava('http://www.eclipse.org/uml2/4.0.0/UML')]

[template public generate(aClass : Class)]

[comment @main/]

[file (aClass.name.concat('.java'), false)]

public class [aClass.name.toUpperFirst()/] {

[for (p: Property | aClass.attribute) separator('\n')]

private [p.type.name/] [p.name/];

[/for]

[for (p: Property | aClass.attribute) separator('\n')]

public [p.type.name/] get[p.name.toUpperFirst()/]() {

return this.[p.name/];

}

[/for]

}

[/file]

[/template]

(c) schmiedecke 14 SE3 5

Beispiel 1a

[module generateJava('http://www.eclipse.org/uml2/3.0.0/UML')/]

[import common/]

[import interfaceBody/]

[import

org::eclipse::acceleo::module:.example::uml2java::helios::common::classBody/]

[template public generateClass(c : Class)]

[comment @main /]

[file (c.getFullPathFile().trim(), false)]

[_commentFileBlock()/]

[c.packageBlock()/]

[importBlock()/]

[_commentBodyBlock()/]

[c.generateClassBody()/]

[/file]

[/template]

(c) schmiedecke 14 SE3 6

Beispiel 1b – zweites Main Module und zweites File

[template public generateInterface(i : Interface)]

[comment @main /]

[file (i.getFullPathFile().trim(), false)]

[_commentFileBlock()/]

[i.packageBlock()/]

[importBlock()/]

[_commentBodyBlock()/]

[i.generateInterfaceBody()/]

[/file]

[/template]

[query public getJavaFileName (name : String) : String =

name.concat('.java')

/]

(c) schmiedecke 14 SE3 7

Templates - Details

Templates haben keinen Rückgabetyp,

sie erzeugen Output (String)

Templates haben Parameter,

die Typen sind Metamodell-Elemente

Ein Template-Aufruf wird nur ausgeführt, wenn der

Parameter "passt" (bzw. die Parameter passen)

Bei Anwendung auf eine Menge von Elementen wird

das Template wiederholt angewendet

(s. Folgefolie)

Templates realisieren Polymorphie

sie werden je nach Parameter-(Sub-)Typ ausgewählt

(s. Folgefolie) (c) schmiedecke 14 SE3 8

Beispiel 2a: Schleife und Typ-Switch Quelle: Acceleo Best Pracitces

[template public classSwitchTemplate(eClass : Eclass)

[for (eNamed : ENamendeElement | eClass .eAllContents(ENamedElement))]

[if (eNamed.oclIsKindOf(ETypedElement))]

do something for ETypedElement

[elseif (eNamed.oclIsKindOf(EStructuralFeature))]

do something for EStructuralFeature

[elseif (eNamed.oclIsKindOf(EAttribute))]

do something for Eattribute

[/if]

[/for]

[/template]

(c) schmiedecke 14 SE3 9

Beispiel 2b: Menge und Polymorphie

[template public polymorphicClassTemplate(eClass : EClass)]

[eClass.eAllContents(ENamedElement).doSomething()/]

[/template]

[template private doSomething(arg : ETypedElement)]

do something for ETypedElement

[/template]

[template private doSomething(arg : EStructuralFeature)]

do something for EStructuralFeature

[/template]

[template private doSomething(arg : EAttribute)]

do something for EAttribute

[/template]

[template private doSomething(arg : ENamedElement)] [/template]

(c) schmiedecke 14 SE3 10

Navigieren im Modell

Navigieren im Modell erfolgt anhand des Metamodells

Zu den Attributen

– liefert typischerweise einfache Werte [c.name/]

Über die Assoziationen des Metamodells

– liefert typischerweise Mengen!! [c.superClass/]

Über die Funktionen des EMF-GenModels

Über die Acceleo-Operationen auf EObject

– eAllContents

– eContainer

– ancestors

– siblings

– followingSiblings ...

(c) schmiedecke 14 SE3

11

Navigieren mithilfe des

EMF-GenModels der UML

(c) schmiedecke 14 SE3 12

Beispiel 3 – Navigieren im Modell

[template public generateClassBody(c : Class)]

public

[if (c.isAbstract)] abstract

[/if]

class [c.name.toUpperFirst()/]

[for (superC : Class | c.superClass) before(' extends ')

separator(',')] [superC.name/]

[/for]

[for (interf : Interface | c.getImplementedInterfaces()) before('

implements ') separator(',')] [interf.name/]

[/for]

(c) schmiedecke 14 SE3 13

...erreichbar über die Acceleo-Vorhersage

(c) schmiedecke 14 SE3 14

Beispiel 4

[for (p : Property | c.getAllAttributes())]

[if (p.upper = -1 or p.upper > 1)]

private List<[p.type.name/]> [p.name/];

[else]

private [p.type.name/] [p.name/];

[/if]

[/for]

(c) schmiedecke 14 SE3 15

Navigieren mithilfe des

EMF-Genmodels der UML

(c) schmiedecke 14 SE3 16

... erreichbar über die Acceleo-Vorhersage

(c) schmiedecke 14 SE3 17

Beispiel 5

[template public packagePath(cl : Classifier)]

[cl.getNearestPackage().normalizeName()/]

[/template]

(c) schmiedecke 14 SE3 18

Acceleo-

Operationen

wiki.eclipse/

Acceleo/

Acceleo_Operations

_Reference

(c) schmiedecke 14 SE3 19

Parametrisierte Operationen (Acceleo und Genmodel)

Die meisten mengenliefernden Acceleo-Operationen

können durch einen Parameter eingeschränkt werden

z.B.:

(c) schmiedecke 14 SE3 20

Beispiel 6 – Parametrisierte Operationen

[template public genPackagePath(anElement : Element)]

[if (anElement.ancestors(Component)->size() > 0)]

[anElement.ancestors(Component)

->first().genComponentPath()/]

[else][anElement.reqGetDefaultProjectName()/]

[/if]

/[anElement.reqGetSourceFolderPath()/]

/[anElement.genPackageDeclaration().substituteAll('.', '/').concat('/')/]

[/template]

(c) schmiedecke 14 SE3 21

Templates können eingeschränkt und mit post nachbearbeitet werden

(c) schmiedecke 14 SE3 22

"? (Bedingung)" im Template-Tag schränkt die

Gültigkeit ein

"post" ermöglicht abschließende Bearbeitung des

Outputs

Beispiel 7 – Template-Einschränkung

(c) schmiedecke 14 SE3 23

[template private getterAndSetter(aProperty : Property) ?

(aProperty.upper = 1)]

public [if(aProperty.isStatic)]

static

[/if]

[aProperty.reqTypeName()/]

get[aProperty.genName().toUpperFirst()/]()

{

return [if(not aProperty.isStatic)]this.[/if]

[aProperty.genName()/];

}

...

Beispiel 8 – Template-Nachbearbeitung

[template private normalizeName(anElement : NamedElement) post(trim())]

[if ((anElement.name = 'package') or (anElement.name = 'interface') or

(anElement.name = 'class'))]

[anElement.name.concat('_')/]

[else]

[anElement.name/]

[/if]

[/template]

(c) schmiedecke 14 SE3 24

Operationsanwendung

Operationen (Acceleo, EMF, OCL) werden angewendet

Mit "." auf einfache Werte

[anElement.genPackageDeclaration().substituteAll('.',

'/').concat('/')/]

Mit "->" auf Mengen und Folgen

[if (anElement.ancestors(Component)->size() > 0)]

(c) schmiedecke 14 SE3 25

Let-Blöcke

Mit dem let-Tag können Variablen mit der Gültigkeit

des Let-Blocks definiert werden

Der Let-Block wird nur dann ausgeführt, wenn die

Variablen-Zuweisung typkompatibel ist (also

"funktioniert")

[let x : Type = myExpression] | x.dosomething() [/let]

Ist gleichbedeutend mit

[if (myExpression.oclIsKindOf(Type))]

[myExpression.oclAsType(Type).dosomething()/]

[/if]

(c) schmiedecke 14 SE3 26

Beispiel 9 – Let-Block Wird nur ausgeführt, falls aClass einen Wert hat

[template private genClassifierBody(aClassifier : Classifier) overrides genClassifierBody]

[let aClass : Class = aClassifier.oclAsType(Class)]

[aClass.declaration()/] {

[aClass.attributes()/]

[aClass.constructor()/]

[aClass.operations()/]

[for (aProperty : Property | aClass.ownedAttribute

->union(aClass.reqOutgoingNavigableOwnedEnd()))]

[aProperty.accessors()/]

[/for]

[/let]

[/template]

(c) schmiedecke 14 SE3 27

Mengenkonstruktion

Die Navigation durch Metamodell liefert immer wieder

Mengen

Viele Acceleo- und OCL-Operationen dienen der

Bearbeitung von Mengen

– Filtern

– Vereinigen

– Zu Sequenzen machen – oder wieder zu Mengen

– Unterstrukturen auflösen (flatten)

Vieles lässt sich mit Mengenoperationen eleganter

ausdrücken als mit Schleifen ÜBEN

(c) schmiedecke 14 SE3 28

Beispiele 10 - Mengenoperationen

[template public genPackageDeclaration(anElement : Element)]

[anElement.packagePath().normalizeName()->reverse()->sep('.')/]

[/template]

[for (aParameter : Parameter | ownedParameter

->select(param : Parameter |

param.direction = ParameterDirectionKind::return)

->first())]

...

(c) schmiedecke 14 SE3 29

OCL-

Operationen

wiki.eclipse.org/Acceleo/

OCL_Operations

_Reference

Ähnlich wie Acceleo-Ops,

andere Typen

(c) schmiedecke 14 SE3 30

Queries

Queries sind Expressions, d.h. Sie liefern ein Ergebnis

Zweck: Kapselung / Wiederverwendung komplexer

Abfragen

++Ergebnis wird gecached (Effizienzgewinn)

Typischerweise, aber nicht zwingend, OCL

(c) schmiedecke 14 SE3 31

Beispiele 11

[query public getJavaFileName (name : String) : String =

name.concat('.java')

/]

[query private packagePath(anElement : Element) : Sequence(Package) =

Sequence{anElement.getNearestPackage()}

->union(anElement.getNearestPackage().ancestors()->filter(Package))

->select(pack : Package | pack.oclIsTypeOf(Package))

/]

[query private allDocumentation(anElement : Element) : Sequence(String) =

anElement.eAnnotations.details->select(entry | entry.key = 'documentation')

->collect(entry | entry.value)

/]

(c) schmiedecke 14 SE3 32

Queries als Java Wrapper Services

EMF liefert das Modell als Java-Objektbaum

und ein Traversierungs-API (GenModel)

Alle Abfragen lassen sich auch in Java formulieren

Dort, wo das leichter ist, kann Java-Code geschrieben

und innerhalb einer Query mit "invoke" gerufen werden

(s. Getting-Started-Tutorial)

(c) schmiedecke 14 SE3 33

Konstanten

Konstanten können als Property-Datei hinterlegt

werden

Syntax:

– Schlüssel = Text

(c) schmiedecke 14 SE3 34

ACCELEO –

BEST PRACTICES

(c) schmiedecke 14 SE3 35

Best practices: Naming Conventions

A. Naming conventions

Project (eclipse plugin):

<domain><project name (optional)><kind of input

(optional)><input metamodel name>gen<output language

name>

Example: com.mydomain.myproject.pim.uml.gen.java

Modules, variables

camel case names, avoid acceleo or ocl keywords:

Acceleo keywords: module, import, extends, template, query,

public, private, protected, guard, init,overrides, each, before,

after, for, if, elseif, else, let, elselet, trace, macro,file, mode,

text_explicit, code_explicit, super, stdout

OCL keywords: and, body, context, def, derive, else, end, if,

endpackage, false, if, implies, in, init, inv, invalid, let, not, null,

or, package, post, pre, self, static, then, true, xor

(c) schmiedecke 14 SE3 37

BP: Package Structure

Root package should share the same name of the project.

Example: com.mydomain.myproject.pim.uml.gen.java

Subpackages

main

all modules with main templates and their matching launcher class

files

all modules that will generate a file

common

all utility modules

request / query

all modules that contains utility requests (queries) on the input model

services

all modules wrapping Java classes

properties

all properties files

(c) schmiedecke 14 SE3 38

BP: Package Structure

(c) schmiedecke 14 SE3 39

BP: Package Export

B. 3. Exporting packages

The main package, the properties package and the

service package need to be exported.

Java services will not work when the generator is

deployed if the package containing those package is

not exported in the MANIFEST.MF (runtime tab).

It is recommended to export all other packages but to

keep them "hidden from all plugins".

(c) schmiedecke 14 SE3 40

Der Rest ist ÜBEN

und ABGUCKEN...

Recommended