• Keine Ergebnisse gefunden

6.3 Umsetzung

6.3.1 Tabellarischer Editor für CPL

Die wichtigsten Schritte bei der Implementierung des tabellarischen Editors waren:

1. Erstellen der Ecore-Version des CPL-Meta-Modells (cpl.ecore).

2. Ableitung des Generator-Modells (cpl.genmodel).

3. Generieren der obsetool.cpl.metamodel-, obsetool.cpl.metamodel.edit-und obsetool.cpl.metamodel.editor-PlugIns.

4. Anpassungen an dem generierten Code.

Die Notwendigkeit des ersten Schrittes hängt damit zusammen, dass die Grundlage des EMF -Frameworks Ecore-Modelle bilden. Ecore kann als eine Vereinfachung von UML angesehen werden, bei der nur ausgewähl-te Sprachkonstrukausgewähl-te übernommen wurden. Diese Auswahl wurde vor al-lem mit Blick auf eziente Generierung vom Java-Code getroen. Die für die Entwicklung des tabellarischen Editors notwendige Konvertierung des CPL-Meta-Modells zu dem entsprechenden Ecore-Modell konnte wegen der Nähe von Ecore und UML problemlos durchgeführt werden. Lediglich bi-direktionale Assoziationen und Assoziationsklassen, die unter Ecore nicht unterstützt werden, müssen in zwei unidirektionale bzw. normale Klassen umgewandelt werden. Ansonsten unterscheidet sich das entstandene Eco-re-Modell inhaltlich20 nicht von dem im Kapitel 4.1.2 präsentierten CPL-Meta-Modell.

Im zweiten Schritt wird ein Generator-Modell erstellt, das sich im we-sentlichen aus Einstellungen des Generators und einer Verknüpfung auf das im ersten Schritt erzeugte Ecore-Modell für die Sprache CPL zusam-mensetzt. Das Generator-Modell ist nützlich, da es während der Editor-Entwicklung durchaus vorkommen kann, dass die Generierung vom Code wiederholt ausgeführt wird. In diesem Fall müssen die Einstellungen für den Generierungsvorgang nicht jedes Mal neu eingegeben werden. Dazu gehö-ren zum Beispiel Präxe der zu generiegehö-renden Pakete, Pfade und Schalter,

20Was sich noch unterscheidet aber für den Informationsgehalt des Modells keine Rolle spielt, ist die abweichende Benennung der Sprachelemente in Ecore. So wird eine Klasse in Ecore mit EClass statt Class bezeichnet.

die bestimmte Funktionalität in dem generierten Code erlauben oder un-terdrücken.

Die Code-Generierung im dritten Schritt ist ein vollautomatisierter Vorgang. EMF erstellt deutlich mehr Code als die konventionellen Genera-toren der UML-Werkzeuge. Nicht nur Code für die statische Struktur wird erstellt, sondern auch Code für das Anlegen, Bearbeiten und Darstellen von Modell-Elementen im Rahmen einer RCP-Anwendung. Zunächst wird für jede Klasse des CPL-Meta-Modells ein Interface und die zugehörige Imple-mentierung als Java-Klasse angelegt. Für einen Dingtypen sind das zum Beispiel ThingType und ThingTypeImpl (siehe Beispiel in dem Listing 6.1).

Für die weitere Verwendung in den Editoren ist es wichtig, dass diese Klassen indirekt von EObject EMF -Pedant für java.lang.Object abge-leitet sind. Diese Klasse ist wiederum von dem Interface Notier abgeabge-leitet (siehe Zeile 6). Das hat zur Folge, dass die Modell-Elemente entsprechend dem Observer-Entwurfsmuster registrierte Beobachter informieren, wenn Änderungen an diesen durchgeführt wurden. Das ist ein für OBSE-Tool unverzichtbares Verhalten. So werden Änderungen in einem Editor vom anderen wahrgenommen. Dieser Editor kann auf diese Änderungen reagie-ren und seine Anzeige aktualisiereagie-ren. Die Darstellung eines Modells in beiden Editoren bleibt so konsistent.

Mit dem Interface CplFactory und seiner Implementierung CplFacto-ryImpl wird eine Vereinheitlichung der Vorgehensweise bei der Erzeugung von Modellelementen erreicht. Realisiert wird dies mit Hilfe des Factory-Entwurfsmusters, was die Flexibilität des generierten Codes erhöht und möglichen späteren Änderungen an dem zu Grunde liegenden Ecore-Modell entgegenkommt.

1 public interface Thingtype extends ModelingElement ...

2

3 public class ThingtypeImpl extends ModelingElementImpl

4 implements Thingtype ...

5

6 public interface EObject extends Notier ...

7

8 public interface CplFactory extends EFactory ...

9

10 public class CplFactoryImpl extends EFactoryImpl

11 implements KcpmmFactory ...

12 }

Listing 6.1: Einblick in die generierte Code-Struktur des tabellarischen Editors

Viele Hilfsfunktionen wie Änderungen rückgängig machen, Kopieren und Einfügen, drag and drop werden ebenfalls in den generierten Code integriert21. Ist der CPL-Editor nach der Generierung voll einsetzbar? Die-se Frage kann mit ja beantwortet werden, allerdings ist dieDie-ser Editor gene-risch und berücksichtigt die Besonderheiten einer Sprache nicht. Es ist zwar möglich, Elemente anzulegen und baumartig über das Modell zu navigie-ren, jedoch fehlt die für die Sprache CPL wichtige tabellarische Darstellung noch in diesem Stadium.

Damit der Editor Anpassungen im generierten Code bei einer erneuten Generierung nicht überschreibt, besitzen Methoden eine spezielle Annota-tion. Standardmäÿig wird das Schlüsselwort @generated verwendet, um den automatisch entstandenen Code zu kennzeichnen. Wird eine Methode an-gepasst, reicht es mit @generated NOT zu signalisieren, dass sie bei der nächsten Generierung nicht mehr verändert werden darf.

Im OBSE-Tool kommunizieren Editoren und Modell-Elemente nicht direkt miteinander, sondern über zwei spezielle Klassen: IContentProvider und ILabelProvider. Die erste wird benutzt, um über den Inhalt eines Modells zu navigieren und die zweite, um ein Modell-Element darzustellen (meistens als Name eines Elements versehen mit einem Symbol). Auf diese Art können analog zu dem Model-View-Controler-Entwurfsmuster mehrere Sichten auf ein CPL-Modell angeboten werden. Gleichzeitig ist die Implementierung eines neuen Providers der richtige Einstiegspunkt, um den generierten Code

21Für weiterführende Informationen zum EMF -generierten Code und seinem Design siehe [BSM+03].

zu erweitern.

1 tableViewerOfThingtype.setContentProvider

2 (new AdapterFactoryContentProvider(adapterFactory) {

3 public Object [] getElements(Object object){

4 return ((Model)object).getContain().toArray();

5 }

6 public void notifyChanged(Notication notication){

7 switch (notication .getEventType()){

8 case Notication .ADD:

9 case Notication .ADD_MANY:

10 if ( notication .getFeature() != CplPackage

11 .eINSTANCE.getModel_Contain()) return;

12 }

13 super.notifyChanged(notication);

14 }

15 });

16

17 tableViewerOfThingtype.setLabelProvider

18 (new AdapterFactoryLabelProvider(adapterFactory));

Listing 6.2: Registrierung neuer Provider für den tabellarischen Editor Die Listing 6.2 zeigt einen Ausschnitt der Methode createPages() aus der Klasse CplEditor, in dem der tabellarischen Darstellung (tableViewerOf-Thingtype) ContentProvider (Zeilen 2-16) und LabelProvider (Zeilen 18-19) zugewiesen werden. Als Beispiel wird an dieser Stelle die Aktivierung des Benachrichtigungsmechanismus beim Hinzufügen von neuen Elementen ge-zeigt (Zelen 6-14). Dadurch werden alle Observer beim Erzeugen von neu-en Modell-Elemneu-entneu-en (Bedingung in der Zeile 10) informiert. Ergänzneu-end dazu müssen noch viele weitere Anpassungen vorgenommen werden, um generierte ContentProvider von CPL-Modellierungselementen wie Dingtyp zu erweitern und die Spalten der Tabelle und ihre Inhalte festzulegen.

Diese Änderungen können anhand des beiliegenden Quellcodes des OB-SE-Tools verfolgt werden (qgenerated NOT-Methoden in den PlugIns obse-tool.cpl.metamodel, obsetool.cpl.metamodel.edit und obsetool.cpl.metamodel.-editor).