ProFLOW Tutorial

Werbung
ProFLOW Tutorial
Dieses Dokument soll dazu dienen, die Installation, Benutzung und Erweiterungsmöglichkeiten des ProFLOW Frameworks zu erklären.
1.
Installation ............................................................................................... 2
2.
Benutzung ................................................................................................ 4
Anlegen eines neuen Projekts ...................................................................................... 4
Erzeugen eines neuen Diagramms ............................................................................... 4
Editieren eines Diagramms .......................................................................................... 5
Weitere Features .......................................................................................................... 6
3.
Erweiterung ............................................................................................. 7
Learning from Examples.............................................................................................. 7
Anlegen einen neuen Plug-In Projects ......................................................................... 8
Erzeugen eines neuen Prozesses .................................................................................. 9
Starten einer Runtime Workbench ............................................................................. 11
Erzeugen eines neuen Prozesselements ..................................................................... 12
Erzeugen einer neuen Transition................................................................................ 16
Erzeugen einer neuen Annotation .............................................................................. 17
Definieren der Editorpalette....................................................................................... 20
Registrieren von zusätzlichen Attributen ................................................................... 22
Registrieren von Process Actions............................................................................... 25
Registrieren von Model Object Actions..................................................................... 27
Verwendung von Commands..................................................................................... 29
Deployen des Plug-Ins ............................................................................................... 31
1. Installation
ProFLOW wurde mit und für Eclipse 3.2 entwickelt. Das Eclipse 3.2 Release steht unter
folgendem Link zur Verfügung:
http://download.eclipse.org/eclipse/downloads/
Zur Installation von Eclipse muss lediglich die heruntergeladene .zip-Datei in einen
gewünschten Zielordner entpackt werden.
Außerdem benötigt man noch das Graphical Editing Framework (GEF) in der entsprechenden Version 3.2. Dieses ist unter dem folgenden Link verfügbar:
http://download.eclipse.org/tools/gef/downloads/index.php
Die hierzu gehörende .zip-Datei muss ebenfalls lediglich in den Eclipse-Ordner entpackt
werden. Dabei werden die Unterordner /features und /plugins um einige Dateien und Ordner
erweitert.
Abschließend muss nun noch das ProFLOW Framework installiert werden. Hierzu muss
ebenfalls lediglich die gegebene .zip-Datei in den Eclipse-Ordner entpackt werden, sodass die
Unterordner /features und /plugins mit den notwendigen Dateien erweitert werden.
Abschließend müssen sie nun nur noch die beiden Frameworks GEF und ProFLOW in
Eclipse aktivieren. Führen sie hierfür folgende Schritte aus:
1. Starten sie Eclipse (Ausführen der eclipse.exe im Eclipse-Ordner)
2. Aktivieren sie die beiden Frameworks unter Help Æ Software Updates Æ Manage
Configuration
3. Aktivieren sie den dritten Schalter in der Toolbar-Leiste "Show Disabled Features"
und aktivieren sie die deaktivierten Frameworks GEF und ProFLOW (auswählen und
"enablen" … siehe Abbildung 1-1)
4. Schließen und Starten sie Eclipse neu
Die Installation ist somit abgeschlossen und sie können ihre ersten ProFLOW Diagramme
erstellen. Außerdem ist es nun auch möglich, neue Eclipse Plug-ins zu entwickeln, welche auf
ProFLOW aufbauen und das Framework um weitere Diagrammtypen erweitern. Hierauf soll
nun in den folgenden Kapiteln eingegangen werden.
Abbildung 1-1
2. Benutzung
In diesem Kapitel soll nun kurz darauf eingegangen werden, wie sie mittels ProFLOW
Diagramme erstellen können.
Anlegen eines neuen Projekts
ProFLOW Diagramme müssen einem Projekt zugeordnet sein. Somit benötigen sie, bevor sie
ein ProFLOW Diagramm erstellen möchten, zunächst ein Projekt. Es genügt, wenn sie ein
einfaches Projekt anlegen. Starten sie hierfür den Menupunkt: File Æ New Æ Project.. Es
erscheint somit der Project Creation Wizard. Hier wählen sie den Eintrag Project im Ordner
General aus. Natürlich können sie hier auch jeden anderen Projekttyp auswählen.
Erzeugen eines neuen Diagramms
Haben sie ein neues Projekt erstellt, können sie in diesem ein neues ProFLOW Diagramm
erzeugen. Rechtsklicken sie auf ihr neu angelegtes Projekt und starten sie den folgenden
Kontextmenueintrag: New Æ Other.. In dem erscheinenden Creation Wizard wählen sie nun
den Eintrag ProFLOW Diagram im Other Ordner aus und drücken sie Next. In der
folgenden Wizard Page können sie den Diagrammtyp auswählen. Hier können sie zwischen
allen registrierten Diagrammtypen wählen. Das Description-Feld liefert die Beschreibung zu
dem ausgewählten Diagrammtyp. Haben sie sich für einen Diagrammtyp entschieden, müssen
sie in der folgenden Wizard Page nun nur noch den Namen und den Dateinamen des zu
erstellenden Diagramms definieren. ProFLOW Diagramm Dateien müssen mit der Extension
.proFLOW enden. Schließt man den Creation Wizard mit Finish wird die erzeugte .proFlowDatei mit dem grafischen ProFLOW Editor geöffnet.
Editieren eines Diagramms
In dem geöffneten ProFLOW Editor können sie nun ihr Diagramm erzeugen. Hierfür müssen
sie lediglich ein gewünschtes Element in der Palette auswählen und in der Zeichenfläche
platzieren. Das Cursor-Feedback zeigt dabei an, ob das Hinzufügen eines Elementes bzw. das
Verbinden zweier Elemente miteinander über eine Transition zulässig ist. Die Palette des
jeweiligen Editors beinhaltet immer die Elemente des jeweiligen Diagrammtyps sowie alle
FLOW Elemente. Außerdem stehen immer die Paletteneinträge Select und Marquee zum
Auswählen von Elementen zur Verfügung sowie der Eintrag Text zum Hinzufügen einfacher
Text-Labels.
Die erzeugten Elemente lassen sich frei auf der Zeichenfläche positionieren. Sie können
zudem (soweit zulässig) auch in einem fest vorgeschriebenen Bereich vergrößert bzw.
verkleinert werden. Das Routing einer Transition kann zudem mittels Bendpoints verändert
werden.
Der Name eines Elements kann mittels Doppelklick mit einem TextCellEditor verändert
werden. Der Name sowie weitere registrierte Attribute eines selektierten Elements können
auch über die Properties View geändert werden. Sollte die Properties View nicht sichtbar sein,
öffnen sie diese mittels Window Æ Show View Æ Other.. Æ General Æ Properties.
Der ProFLOW Editor verfügt über eine Undo/Redo Funktionalität, sodass alle Veränderungen
auch wieder rückgängig gemacht werden können.
Weitere Features
•
Zoom: Über die Kontextmenueinträge Zoom In und Zoom Out des ProFLOW Editors
sowie über den entsprechenden Toolbar Eintrag ist es möglich, die Editor Zeichenfläche zu zoomen.
•
Drucken: Über den Menueintrag File Æ Print.. ist es möglich, den Inhalt des aktuellen ProFLOW Editors auszudrucken.
•
Process Actions: Im Kontextmenü, in der Symbolleiste oder in dem Hauptmenü des
ProFLOW Editors können zudem (falls vorhanden) registrierte Diagramm-spezifische
Actions gestartet werden.
o Eine Process Action, welche für alle Diagramm-Typen zur Verfügung steht, ist
beispielsweise die Action Export as Plain XML… Diese Action ermöglicht
einen XML-Export, wobei anders als beim normalen Speichern in der
.proFlow-Datei keine Layout-Informationen mit abgespeichert werden.
o Eine weitere Process Action, welche für alle Diagramm-Typen zur Verfügung
steht, ist die Action Export as Image File… Hiermit kann man das aktuelle
Diagramm als Bilddatei (.jpg oder .bmp) abspeichern.
•
ModelObject Actions: Abhängig von der Definition der registrierten Actions, können
im Kontextmenu, in der Symbolleiste oder in dem Hauptmenü des ProFLOW Editors
auch Actions auf Diagrammelementen ausgeführt werden.
•
Alignment und Match Actions: In der zugehörigen Toolbarleiste des ProFLOW
Editors werden noch einige Actions zur Verfügung gestellt, womit selektierte Diagrammelemente ausgerichtet werden können oder deren Größe angeglichen werden
können.
3. Erweiterung
Es ist möglich, das bestehende ProFLOW Framework um neue Diagrammtypen zu erweitern.
Hierfür ist es notwendig, ein neues Eclipse Plug-in zu entwickeln, welches auf den ProFLOW
Plug-ins ProFLOW.core und ProFLOW.ui aufbaut.
Learning from Examples
Bevor im Folgenden Schritt für Schritt erklärt werden soll, wie sie ein eigenes Plug-in mit
einem eigenen neuen Diagrammtyp entwickeln können, wollen wir einen kurzen Blick in
bereits bestehende Diagramm-Implementationen werfen. Wie sie sicherlich schon im vorigen
Kapitel bemerkt haben, existieren bereits zwei Diagrammtypen mit der erweiterten
ereignisgesteuerten Prozesskette (eEPK) und dem Aktivitätsdiagramm. Diese beiden
Diagrammtypen sind ebenfalls als eigenständige Plug-ins, welche auf den angesprochenen
ProFLOW Plug-ins aufbauen, realisiert. Es lohnt sich also sicherlich, dort erst einmal ein
wenig „rumzustöbern“, um sich einen Überblick zu verschaffen, wie schwer unser
Unterfangen wohl werden wird. Die Frage die sich nun natürlich gleich stellt ist, wie komme
ich an den Source-Code der angesprochenen Plug-ins? Ganz einfach. Alle Plug-ins, welche in
ihrer Eclipse Umgebung installiert/registriert sind, können sich in Eclipse auch angezeigt
werden. Sofern diese registrierten Plug-ins auch den Source-Code mitliefern (was bei den
angesprochenen ProFLOW Plug-ins der Fall ist), können sie auf einfache Weise diese als
Source Projects in den Workspace von Eclipse laden. Gehen sie hierfür nun wie folgt vor:
•
•
•
•
Öffnen sie die Plug-in Development Perspective
Öffnen sie die Plug-ins View
Markieren sie die ProFLOW Plug-ins
Führen sie den Kontextmenueintrag Import as Æ Source Project aus
Wenn sie nun einen Blick in den Package Explorer werfen, sehen sie, dass die ausgewählten
Plug-ins sich nun in ihrem Workspace befinden. Wenn sie sich die einzelnen DiagrammImplementierungen in den Plug-ins ProFLOW.eepk und ProFLOW.activity anschauen,
werden sie bemerken, dass die Realisierung eines neuen Diagramms pro Element, Transition
oder Annotation lediglich eine Model-Klasse und eine UI-Klasse benötigt. Also alles doch gar
nicht so schwer. Fangen wir doch am besten gleich mit einem einfachen eigenen Diagramm
an, um mit dem Framework besser vertraut zu werden.
Anlegen einen neuen Plug-In Projects
Bevor wir uns in die konkrete Implementierung unseres neuen Diagramms stürzen können,
müssen wir jedoch zunächst noch ein neues Plug-in Project erzeugen. Führen sie dafür
folgenden Menueintrag aus: File Æ New Æ Project.. Im erscheinenden Project Creation
Wizard wählen sie den Eintrag Plug-in Project und drücken sie Next.
In der folgenden Wizard Page müssen sie nun lediglich den Namen des neuen Projekts
festlegen, in unserem Fall ProFLOW.example. In der darauf folgenden Wizard Page können
sie nun noch den Plug-In Namen verändern bzw. weitere Informationen zu Provider, Version,
etc. angeben. In unserem Beispiel haben wir lediglich den Namen des Plug-Ins und der
Activator-Klasse verändert. Der Rest bleibt unverändert.
Nach dem Drücken des Finish Buttons wird das neue Plug-In Project in ihrem Workspace
angelegt. Das neue Plug-In Project enthält an für uns interessanten Dateien zunächst nur die
Manifest.MF-Datei in dem META-INF-Ordner. Diese Datei ist auch von Beginn an im PlugIn Editor geöffnet. Die Dateien Manifest.MF, build.properties und die später erzeugte
plugin.xml bilden den Kern eines jeden Plug-In Projects. Hier werden sämtliche Plug-Inspezifischen Einstellungen getroffen. Diese drei Dateien werden im Plug-In Editor verwaltet.
Zu Beginn werden wir die Abhängigkeiten (Dependencies) unseres neu erstellten Plug-In
Projects setzen. Wechseln sie hierfür zur Dependencies Page des Plug-In Editors. Hier sind
schon zwei Abhängigkeiten gesetzt: org.eclipse.ui und org.eclipse.core.runtime. Um in
unserem Projekt auf die beiden ProFLOW Plug-Ins ProFLOW.core und ProFLOW.ui
zugreifen zu können, müssen wir diese beiden Plug-Ins nun ebenfalls zu den Abhängigkeiten
aufnehmen. Außerdem benötigen wir noch eine Abhängigkeit zu dem Plug-In org.eclipse.gef,
welches im Plug-In ProFLOW.ui verwandt wird (s. Abbildung 3-1).
Bevor wir nun mit der konkreten Implementierung beginnen, führen sie am besten gleich
noch eine saubere Packagestruktur ein. Analog zu den beiden Beispiel-Plug-Ins
ProFLOW.eepk und ProFLOW.activity erstellen wir somit die Packages
proFlow.example.model und proFlow.example.ui.editParts.
Abbildung 3-1
Erzeugen eines neuen Prozesses
Nachdem wir nun ein neues Plug-In Project angelegt haben und auch die benötigten
Abhängigkeiten gesetzt sind, können wir nun mit der Implementierung unseres neuen
Diagramm- bzw. Prozesstyps beginnen.
Um einen neuen Prozesstyp zu erstellen, müssen wir zunächst eine neue Klasse erzeugen,
welche die Klasse ProFLOW.core.model.Process erweitert. Erstellen wir nun also die Klasse
ExampleProcess im Package proFlow.example.model. In dieser müssen wir nun lediglich die
Methode getTypeID():String implementieren. Die TypeId stellt den eindeutigen Identifier für
diesen Prozesstyp dar, welcher zur eindeutigen Identifizierung ihres Prozesstypen im
ProFLOW Framework benötigt wird. In unserem Beispiel wählen wir als TypeId den String
„ProFLOW.example.Process“. Der Code für unsere Prozess-Model-Klasse sieht also wie
folgt aus:
public class ExampleProcess extends Process {
public String getTypeID() {
return "ProFLOW.example.Process";
}
}
Im Anschluss müssen wir nun noch den neu erstellten Prozess dem ProFLOW Framework
bekannt machen. Dies wird mittels Extension Points (dem Erweiterungsmechanismus von
Eclipse) realisiert. Hierbei unterscheiden wir gezielt in Core- und UI-Extension Points unseres
Frameworks. Die Core-Extension Points sind dabei verantwortlich für das Class Loading und
die Persistenz wohingegen die UI-Extension Points die grafische Repräsentation definieren.
Für einen neu erstellten Prozesstyp müssen Extensions für die Extension Points
ProFLOW.core.processes und ProFLOW.ui.processes definiert werden. Gehen sie hierbei wie
folgt vor:
•
•
•
Öffnen sie den Plug-In Editor (Öffnen der Datei Manifest.MF)
Wechseln sie zur Extensions Page des Plug-In Editors
Fügen sie mittels Add eine Extension des Typs ProFLOW.core.processes hinzu
•
•
•
Rechtsklicken sie auf die neu erstellte Extension und führen sie den Kontextmenueintrag New Æ process aus
Spezifizieren sie nun das neu erstellte Extension Element process auf der rechten Seite
des Editors wie folgt:
o id: Hier muss der eindeutige Identifier für den zu registrierenden Prozess angegeben werden. Der Identifier entspricht dem bereits in der Process-Klasse
verwandten Identifier, in unserem Beispiel also ProFLOW.example.Process.
o class: Hier muss die Klasse angegeben werden, welche die Framework-Klasse
ProFLOW.core.model.Process erweitert, also in unserem Beispiel die gerade
implementierte Klasse ProFLOW.example.model.ExampleProcess.
Fügen sie nun noch analog eine Extension des Typs ProFLOW.ui.processes hinzu,
erstellen sie ebenfalls ein process Extension Element und spezifizieren sie dieses wie
folgt:
o id: Hier muss derselbe Identifier angegeben werden, wie schon in der CoreExtension und der implementierenden Process-Klasse, in unserem Beispiel also wieder ProFLOW.example.Process.
o name: Hier muss der Name angegeben werden, mit welchem dieser Prozess in
dem ProFLOW Diagram Creation Wizard aufgeführt werden soll.
o description: Hier kann eine Beschreibung zu dem Prozess mit angegeben werden, welche ebenfalls in dem Creation Wizard erscheint.
o defaultName: Der optionale Default-Name wird im Creation Wizard als Default Datei- und Diagrammname verwandt.
o icon: Hier kann noch ein Icon angeben werden, welches im Creation Wizard
neben dem Namen dargestellt werden soll.
Wie sie evtl. schon bemerkt haben, ist mit dem Definieren der Extensions ein weitere Datei in
ihrem Plug-In Project erstellt worden – die plugin.xml. Sie haben über die beschriebene
grafische Schnittstelle der Extensions Page lediglich diese Datei editiert. Sie können sich den
erstellten XML-Code auch in dem Plug-In Editor ansehen indem sie zu dem plugin.xml Reiter
wechseln. Natürlich ist es auch möglich die plugin.xml auf herkömmlichen Wege, anstatt über
die grafischen Schnittstelle, zu verändern. Die plugin.xml-Datei sollte nun folgendermaßen
aussehen:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
<extension
point="ProFLOW.core.processes">
<process
id="ProFLOW.example.Process"
class="proFlow.example.model.ExampleProcess"/>
</extension>
<extension
point="ProFLOW.ui.processes">
<process
id="ProFLOW.example.Process"
name="Example Process"
description="A simple example process to demonstrate the
extension mechanism."
defaultName="example_process"
icon="icons/sample.gif"/>
</extension>
</plugin>
Starten einer Runtime Workbench
Bevor wir nun weitere Elemente für unseren neu erstellten Prozesstyp implementieren wollen,
lassen sie uns erst einmal ansehen, was wir mit unserer derzeitigen Arbeit schon erreicht
haben. Um ein Plug-In Project ausprobieren zu können, ist es in Eclipse möglich ein weitere
„innere“ Eclipse-Instanz aus Eclipse heraus zu starten – eine sog. Runtime Workbench.
Gehen sie hierbei wie folgt vor:
•
•
•
•
•
Starten sie den Menueintrag: Run Æ Run.. (bzw. Run Æ Debug.. wenn sie ihr Projekt
Debuggen wollen)
Erzeugen sie eine neue Eclipse Application (Eclipse Application auswählen und New
Button drücken)
Geben sie ihrer neu erstellten Configuration einen passenden Namen (z.B. ProFLOW
Example) und ändern sie ggf. die Runtime Workspace Location
Vergewissern sie sich nochmals, dass im Plug-ins Reiter ihr Plug-In
ProFLOW.example mit ausgewählt ist
Starten sie die Runtime Workbench mit Run
Es wird daraufhin eine neue Eclipse-Instanz gestartet in der ihr Plug-In schon integriert ist.
Wenn sie nun wie oben beschrieben ein neues ProFLOW Diagramm in ihrer Runtime
Workbench erstellen möchten, werden sie sehen, dass unser gerade erstellter Prozess in dem
entsprechenden Wizard mit aufgeführt ist. Der in der Extension definierte Name, die
Beschreibung sowie das angegebene Icon werden hier ebenso verwandt, wie auf der
folgenden Wizard Page zur Dateierzeugung der angegebene Default-Name.
Drücken sie auf Finish, werden sie jedoch bemerken, dass außer den Paletteneinträgen Select
und Marquee zur Markierung und dem einfachen Textlabel noch keine weiteren Elemente in
dem geöffneten ProFLOW Editor zur Verfügung stehen.
Wie neue Elemente, Transitionen und Annotationen unserem Prozess hinzugefügt werden
können, soll nun im Weiteren genauer erläutert werden.
Erzeugen eines neuen Prozesselements
Um ein neues Prozesselement zu erstellen, müssen wir eine Klasse implementieren, welche
die Framework-Klasse proFlow.core.model.SimpleElement erweitert. In unserem Beispiel
erzeugen wir somit eine solche Klasse namens ExampleElement im entsprechenden ModelPackage proFlow.example.model.
Hier muss, wie auch schon bei unserer Process-Klasse, die Methode getTypeID():String
implementiert werden. Als eindeutigen Identifier für unseren Prozesselementtyp wählen wir
dieses Mal den String „ProFLOW.example.Element“.
Es ist zudem sinnvoll im Default-Konstruktor einige Werte unseres Prozesselements zu
initialisieren. So initialisieren wir im super-Konstruktoraufruf den Default-Namen des
Elements. Außerdem können hier auch gleich die aktuelle, maximale und minimale
Dimension gesetzt werden. Abhängig von diesen Werten ist dann das Vergrößern und
Verkleinern eines gezeichneten Elements möglich.
Achtung: Es ist wichtig, dass jedes Model-Object (also jeder Process, SimpleElement,
ContainerElement, Annotation oder Transition) einen Default-Konstruktor enthält, da es sonst
zu Problemen mit dem Class Loading kommt.
Der Code für unsere ExampleElement-Klasse sieht somit wie folgt aus:
public class ExampleElement extends SimpleElement {
public ExampleElement() {
super("Element");
setMaxDimension(new Dimension(200, 100));
setMinDimension(new Dimension(50, 30));
setDimension(new Dimension(100, 50));
}
public String getTypeID() {
return "ProFLOW.example.Element";
}
}
Damit unser neu erstelltes Element auch in unseren Prozess hinzugefügt werden darf, muss
noch die zuvor implementierte Klasse ExampleProcess ein wenig ergänzt werden. In dieser
Klasse müssen sie noch die Methode isValidChildElement(Element):boolean überschreiben.
In unserem Fall wird ein positiver instanceof-Check mit unserem neuen Prozesselement
hinzugefügt. Die Klasse ExampleProcess sieht danach wie folgt aus:
public class ExampleProcess extends Process {
public boolean isValidChildElement(Element element) {
return super.isValidChildElement(element)
|| element instanceof ExampleElement;
}
…
}
Nachdem wir nun die nötige Implementation auf Model-Ebene vollzogen haben, müssen wir
uns nun noch um die grafische Repräsentation unseres neuen Prozesselements kümmern.
Hierfür müssen wir eine weitere Klasse implementieren, welche die Framework-Klasse
proFlow.ui.editParts.ElementEditPart erweitert.
Info: Das ProFLOW Framework verfolgt, da es auf dem Graphical Editing Framework (GEF)
aufbaut, das MVC-Paradigma (Model-View-Controller). Die EditPart-Klassen stellen dabei
die Controller des Frameworks dar. Sie sind dafür zuständig, wie ein Model-Object grafisch
dargestellt wird und wie sich Modelländerungen grafisch auswirken. In einem GEF-basierten
Projekt stellen die View-Elemente die sog. Figures dar. Diese gilt es im Controller zu
erzeugen und zu verwalten.
Erzeugen sie nun also eine Klasse ExampleElementEditPart im Package
proFlow.example.ui.editParts, welche die Klasse ElementEditPart erweitert. Wie sie sehen,
müssen sie hier lediglich die Methode createFigure():IFigure implementieren. Ein Figure
kann dabei beliebig komplex gestaltet sein. Das ProFLOW Framework stellt jedoch schon
einige nützliche Figure-Implementationen bereit, welche für den Großteil der Anwendungsfälle ausreichen sollte. Die folgenden Figure-Implementation im ProFLOW.ui Plug-In sind
dabei verfügbar:
•
LabeledRoundedRectangle: Mit dieser Figure-Klasse können sie rechteckige
Formen erzeugen, welche mit einem editierbaren Label versehen sind. Abhängig von
der gesetzten Corner-Dimension, können die Ecken des Rechtecks abgerundet werden,
aber auch elliptische bis hinzu kreisförmige Formen erstellt werden. Nahezu alle Figures der Plug-Ins ProFLOW.activity und ProFLOW.eepk sind mit dieser Figure-Klasse
implementiert.
•
LabeledPolygon: Mit dieser Figure-Klasse können sie beliebig aufgebaute Polygone
erzeugen, welche ebenfalls mit einem editierbaren Label versehen sind. Abhängig von
der beliebig komplex gesetzten Punktliste, können hierbei beliebig geformte Polygone
erzeugt werden. Das Event-Figure des ProFLOW.eepk Plug-Ins sowie das Decision/Merge-Figure des ProFLOW.activity Plug-Ins sind mit dem LabeledPolygonFigure realisiert.
•
LabeledImage: Mit dieser Figure-Klasse lassen sich beliebige Images darstellen.
Zudem ist es möglich, das Image unterhalb mit einem editierbaren Label zu versehen.
Sämtliche FLOW-Figures sind mit dieser Figure-Klasse implementiert.
Unser Prozesselement soll in unserem Beispiel lediglich ein einfaches weißes Rechteck
darstellen, welches mit einem editierbaren Label versehen ist. Die ExampleElementEditPartKlasse sieht demnach wie folgt aus:
public class ExampleElementEditPart extends ElementEditPart {
protected IFigure createFigure() {
LabeledRoundedRectangle elementFigure =
new LabeledRoundedRectangle();
elementFigure.setCornerDimensions(new Dimension(0, 0));
elementFigure.setSize(
getCastedModel().getDimension().getWidth(),
getCastedModel().getDimension().getHeight());
elementFigure.setLocation(new Point(
getCastedModel().getLocation().getX(),
getCastedModel().getLocation().getY()));
elementFigure.setText(getCastedModel().getName());
return elementFigure;
}
public ILabelContainer getLabelContainer() {
return ((LabeledRoundedRectangle) getFigure())
.getLabelContainer();
}
}
Das Implementieren der Methode getLabelContainer():ILabelContainer, in der lediglich der
LabelContainer der Figure-Klasse weitergeleitet wird, ist notwendig, damit der Name des
erzeugten Elements im ProFLOW Editor über einen TextCellEditor editierbar ist. Überschreibt man diese Methode nicht, wie dies beispielsweise bei der Implementation der
Connector-Elemente der Fall ist, so wird der Name des Elements zwar dargestellt, er ist
jedoch nicht editierbar.
Nachdem wir nun sowohl die Model-Klasse als auch die EditPart-Klasse für unser neues
Prozesselement implementiert haben, müssen wir unser Element, wie dies schon bei unserem
neuen Prozesstyp der Fall war, nun nur noch unserem Plug-In bekannt machen. Für einen neu
erstellten Prozesselementtyp müssen Extensions für die Extension Points
ProFLOW.core.simpleElements und ProFLOW.ui.simpleElements im Plug-In Editor definiert
werden. Gehen sie dabei wie folgt vor:
•
•
Fügen sie eine Extension des Typs ProFLOW.core.simpleElements ein
Spezifizieren sie das neu erstellte Extension Element simpleElement wie folgt:
o id: Hier muss der eindeutige Identifier für das zu registrierende Prozesselement angegeben werden. Der Identifier entspricht dem bereits in der ModelKlasse verwandten Identifier, also ProFLOW.example.Element.
o class: Hier muss die Klasse angegeben werden, welche die Framework-Klasse
ProFLOW.core.model.SimpleElement erweitert, also in unserem Beispiel die
Klasse ProFLOW.example.model.ExampleElement.
•
•
Fügen sie nun noch eine Extension des Typs ProFLOW.ui.simpleElements hinzu
Erstellen sie ebenfalls ein simpleElements Extension Element und spezifizieren sie
dieses wie folgt:
o id: Hier muss derselbe Identifier angegeben werden, wie schon in der CoreExtension und der Model-Klasse, also ebenfalls ProFLOW.example.Element.
o name: Hier muss der Name angegeben werden, mit welchem dieses Prozesselement in der Editorpalette aufgeführt werden soll.
o editPart: Hier muss die Klasse angegeben werden, welche die FrameworkKlasse ProFLOW.ui.editParts.ElementEditPart erweitert, also in unserem Beispiel die Klasse ProFLOW.example.ui.editParts.ExampleElementEditPart.
o description: Hier kann eine Beschreibung zu dem Prozesselement mit angegeben werden, welche als Tooltip bei dem Editorpaletteneintrag erscheint.
o icon: Hier kann noch ein Icon angeben werden, welches beim Editorpaletteneintrag neben dem Namen dargestellt werden soll.
Die plugin.xml-Datei wurde somit um folgenden Code ergänzt:
<extension
point="ProFLOW.core.simpleElements">
<simpleElement
id="ProFLOW.example.Element"
class="proFlow.example.model.ExampleElement"/>
</extension>
<extension
point="ProFLOW.ui.simpleElements">
<simpleElement
id="ProFLOW.example.Element"
name="Element"
editPart="proFlow.example.ui.editParts.ExampleElementEditPart"
description="Create an Example Element"
icon="icons/element.gif"/>
</extension>
Erzeugen einer neuen Transition
Im Folgenden soll nun erläutert werden, wie sie eine neue Transition erzeugen können.
Hierfür müssen sie, wie schon beim Erzeugen eines neuen Prozesselements, eine ModelKlasse sowie eine EditPart-Klasse implementieren.
Die Model-Klasse unserer neuen Transition muss in diesem Fall die Framework-Klasse
ProFLOW.core.model.Transition erweitern. Erzeugen sie eine Klasse ExampleTransition im
Package proFlow.example.model. In dieser Klasse müssen sie lediglich neben der bereits
bekannten Methode getTypeID():String die Methoden isValidSourceElement(Element):
boolean und isValidTargetElement(Element):boolean implementieren.
Mit den beiden letzteren Methoden können sie definieren, welche Elemente gültige Start- und
Endpunkte dieser Transition darstellen dürfen. In unserem einfachen Beispiel gibt es mit
unserem zuvor erstellten ExampleElement lediglich ein gültiges Element für beide Methoden.
Unsere Transitions-Klasse sieht demnach wie folgt aus:
public class ExampleTransition extends Transition {
public boolean isValidSourceElement(Element source) {
return (source instanceof ExampleElement);
}
public boolean isValidTargetElement(Element target) {
return (target instanceof ExampleElement);
}
public String getTypeID() {
return "ProFLOW.example.Transition";
}
}
Um kompliziertere Transitionsregeln zu definieren, können sie neben den angesprochenen
Methoden noch die Methoden isValidTransition(Element, Element):boolean, canChangeSourceElement(Element):boolean und canChangeTargetElement(Element):boolean
überschreiben. Ein gutes Beispiel für eine komplexer gestaltete Transition ist die Transition
proFlow.eepk.model.EEPKTransition des ProFLOW.eepk Plug-Ins.
Nun müssen wir noch die EditPart-Klasse unserer Transition implementieren. Diese muss
eine Subklasse der Framework-Klasse proFlow.ui.editParts.TransitionEditPart sein. Die
Figure-Klasse einer Transition stellt eine einfache PolylineConnection dar. Diese können sie
noch modifizieren, indem sie die Methode createFigure():IFigure überschreiben. In unserem
Beispiel fügen wir dabei eine einfache Decoration hinzu:
public class ExampleTransitionEditPart extends TransitionEditPart {
protected IFigure createFigure() {
PolylineConnection connection =
(PolylineConnection) super.createFigure();
connection.setTargetDecoration(new PolygonDecoration());
connection.setLineStyle(SWT.LINE_SOLID);
return connection;
}
}
Abschließend müssen wir nun nur noch die implementierte Transition unserem Plug-In
bekannt machen. Analog zur Erstellung eines neuen Prozesselementtyps müssen sie für eine
Transitions lediglich Extensions für die Extension Points ProFLOW.core.transitions und
ProFLOW.ui.transitions im Plug-In Editor definiert werden. Die Spezifikation der Attribute
der entsprechenden Extensions ist dabei genauso definiert, wie schon zuvor bei den
Extensions eines neuen Prozesselements beschrieben. Die plugin.xml wird somit um
folgenden Einträge erweitert:
<extension
point="ProFLOW.core.transitions">
<transition
id="ProFLOW.example.Transition"
class="proFlow.example.model.ExampleTransition"/>
</extension>
<extension
point="ProFLOW.ui.transitions">
<transition
id="ProFLOW.example.Transition"
name="Transition"
editPart="proFlow.example.ui.editParts
.ExampleTransitionEditPart"
description="Create a new Transition"
icon="icons/transition.gif"/>
</extension>
Erzeugen einer neuen Annotation
Nachdem wir nun für unseren neuen Prozesstyp ein Prozesselement und eine Transition
implementiert haben, wollen wir nun noch ein letztes Element unserer Prozessdefinition
hinzufügen – eine Annotation. Annotationen können sowohl Prozesselementen als auch
Transitionen hinzugefügt werden.
Achtung: In der derzeitigen Version des ProFLOW Frameworks wird nur das Annotieren von
Prozesselementen unterstützt. Das Annotieren von Transitionen soll aber in späteren
Versionen ebenfalls mit zur Verfügung stehen.
Zum Erzeugen einer neuen Annotation müssen sie wieder eine Model-Klasse und dieses mal
sogar zwei EditPart-Klassen implementieren. Die Model-Klasse muss dabei die Framework-
Klasse proFlow.core.model.Annotation erweitern. Erstellen sie somit eine neue Klasse
ExampleAnnotation im Package proFlow.example.model.
Diese Klasse muss neben der bereits bekannten Methode getTypeID():String ebenfalls noch
die Methode isValidAnnotatableObject(AnnotatableObject):boolean implementieren. In der
letzteren Methode wird definiert, welchen Prozesselementen bzw. welchen Transitionen diese
Annotation hinzugefügt werden darf. In unserem Beispiel soll die neu erstellte Annotation
lediglich unserem ExampleElement hinzugefügt werden dürfen.
Wie schon bei der ExampleElement-Klasse bietet es sich bei einer Annotation-ModelImplementation an, im Default-Konstruktor den Default-Namen sowie die Dimensionswerte
zu initialisieren. Außerdem kann man hier auch noch die Orientierung der Annotation
initialisieren. Die Orientierung definiert, wo der Layout-Algorithmus beim Hinzufügen von
neuen Annotationen diese relativ zum annotierten Elemente platzieren soll.
Unsere ExampleAnnotation-Klasse sieht demnach wie folgt aus:
public class ExampleAnnotation extends Annotation {
public ExampleAnnotation() {
super("Annotation");
setMaxDimension(new Dimension(200, 100));
setMinDimension(new Dimension(50, 30));
setDimension(new Dimension(80, 40));
setOrientation(ALL_SIMPLE_ORIENTATIONS);
}
public boolean isValidAnnotatableObject(
AnnotatableObject annotatableObject) {
return (annotatableObject instanceof ExampleElement);
}
public String getTypeID() {
return "ProFLOW.example.Annotation";
}
}
Da sich eine Annotation grafisch aus zwei Elementen zusammensetzt, dem eigentlichen
Annotationselement und einer Kante zwischen dem Annotationselement und dem annotierten
Element, müssen sie auch zwei EditPart-Klassen erweitern.
Die EditPart-Klasse, welche die Darstellung des Annotationselements regelt, muss die
Framework-Klasse proFlow.ui.editParts.AnnotationEditPart erweitert. Erzeugen sie also eine
Klasse ExampleAnnotationEditPart im Package proFlow.example.ui.editParts. Die
Implementation dieser Klasse ähnelt stark unserer ExampleElementEditPart-Klasse. Die
Annotation stellt wieder ein editierbares weißes Rechteck dar, dieses mal jedoch mit
abgerundeten Ecken. Die Klasse sieht demnach wie folgt aus:
public class ExampleAnnotationEditPart extends AnnotationEditPart {
protected IFigure createFigure() {
LabeledRoundedRectangle annotationFigure =
new LabeledRoundedRectangle();
annotationFigure.setCornerDimensions(new Dimension(10, 10));
annotationFigure.setSize(
getCastedModel().getDimension().getWidth(), getCastedModel().getDimension().getHeight());
annotationFigure.setLocation(new Point(
getCastedModel().getLocation().getX(),
getCastedModel().getLocation().getY()));
annotationFigure.setText(getCastedModel().getName());
return annotationFigure;
}
public ILabelContainer getLabelContainer() {
return ((LabeledRoundedRectangle) getFigure())
.getLabelContainer();
}
}
Im Weiteren muss nun noch eine EditPart-Klasse implementiert werden, welche die Klasse
proFlow.ui.editParts.AnnotationConnectionEditPart erweitert. Diese ähnelt in der
Realisierung stark der Implementation einer TransitionsEditPart-Klasse. In unserem Beispiel
soll die Kante eine gepunktete schwarze Linie darstellen. Die Implementation der Klasse
ExampleAnnotationConnectionEditPart sieht demnach wie folgt aus:
public class ExampleAnnotationConnectionEditPart extends
AnnotationConnectionEditPart {
protected IFigure createFigure() {
PolylineConnection connection =
(PolylineConnection) super.createFigure();
connection.setLineStyle(SWT.LINE_DOT);
return connection;
}
}
Abschließend muss nun nur noch die neu erstellte Annotation dem Plug-In bekannt gemacht
werden. Erstellen sie hierfür, wie bereits bekannt, Extensions der Extension Points
ProFLOW.core.annotations und ProFLOW.zu.annotations. Die plugin.xml-Datei wird somit
um die folgenden Einträge erweitert:
<extension
point="ProFLOW.core.annotations">
<annotation
id="ProFLOW.example.Annotation"
class="proFlow.example.model.ExampleAnnotation"/>
</extension>
<extension
point="ProFLOW.ui.annotations">
<annotation
id="ProFLOW.example.Annotation"
name="Annotation"
editPart="proFlow.example.ui.editParts
.ExampleAnnotationEditPart"
connectionEditPart="proFlow.example.ui.editParts
.ExampleAnnotationConnectionEditPart"
description="Create a new Annotation"
icon="icons/annotation.gif"/>
</extension>
Definieren der Editorpalette
Wie sie vielleicht schon beim Starten der Runtime Workbench zum Ausprobieren ihres neuen
Diagrammtyps bemerkt haben, sind die neu erstellten Elemente noch nicht in der Editorpalette
des ProFLOW Editors mit aufgeführt. Keine Angst, sie haben nichts falsch gemacht. Damit
die neu erstellten Elemente in der Editorpalette erscheinen, müssen sie nur noch die
Editorpaletten-Einträge mit Hilfe des Extension Points ProFLOW.ui.processPaletteEntries
für ihren neuen Prozesstyp registrieren.
Info: Die Realisierung der Editorpaletten-Einträge mittels eines Extension Points wurde aus
dem Grunde gewählt, da sie so auch auf bereits in anderen Plug-Ins implementierte Elemente
zurückgreifen können, solange sie deren eindeutigen Identifier wissen.
Erstellen sie nun zunächst eine Extension des angesprochenen Extension Points im PluginEditor. Abhängig von der Art des Elements, welches sie in der Editorpalette registrieren
wollen, müssen sie ein Extension Element vom Typ paletteElement (für SimpleElements),
paletteContainer (für ContainerElements, Achtung: wird zurzeit noch nicht unterstützt),
paletteTransition (für Transitionen) oder paletteAnnotation (für Annotationen) erstellen. Bei
jedem dieser Elemente müssen sie nun lediglich den Identifier des Prozesstyps, den Identifier
des zu registrierenden Elements sowie den Identifier der Palettengruppe, in welche das
Element eingefügt werden soll, angeben.
In unserem Fall benötigen wir also Extension Elements für ein Prozesselement (SimpleElement), eine Transition und eine Annotation. Da wir außerdem noch die FLOW-Elemente in
unserem Diagramm nutzen möchten, müssen wir auch diese hier noch mit einem entsprechenden Extension Elements anbinden. Die plugin-xml-Datei wird somit um den folgenden
Eintrag erweitert.
<extension
point="ProFLOW.ui.processPaletteEntries">
<paletteTransition
transitionId="ProFLOW.example.Transition"/>
processId="ProFLOW.example.Process"
groupId="ProFLOW.ui.transitionPaletteGroup"
<paletteElement
elementId="ProFLOW.example.Element"
processId="ProFLOW.example.Process"/>
groupId="ProFLOW.ui.elementPaletteGroup"
<paletteAnnotation
annotationId="ProFLOW.example.Annotation"
processId="ProFLOW.example.Process"/>
groupId="ProFLOW.ui.annotationPaletteGroup"
<paletteElement
elementId="ProFLOW.flow.Document"
processId="ProFLOW.example.Process"/>
groupId="ProFLOW.ui.flowPaletteGroup"
<paletteElement
elementId="ProFLOW.flow.Documents"
processId="ProFLOW.example.Process"/>
groupId="ProFLOW.ui.flowPaletteGroup"
<paletteElement
elementId="ProFLOW.flow.Person"
processId="ProFLOW.example.Process"/>
groupId="ProFLOW.ui.flowPaletteGroup"
<paletteElement
elementId="ProFLOW.flow.Group"
processId="ProFLOW.example.Process"/>
groupId="ProFLOW.ui.flowPaletteGroup"
<paletteTransition
transitionId="ProFLOW.flow.Knowledge"/>
processId="ProFLOW.example.Process"
groupId="ProFLOW.ui.flowPaletteGroup"
<paletteTransition
transitionId="ProFLOW.flow.Experience"/>
processId="ProFLOW.example.Process"
groupId="ProFLOW.ui.flowPaletteGroup"
</extension>
In unserem Beispiel haben wir bei den Palettengruppen auf bereits im ProFLOW.ui Plug-in
definierte Gruppen zurückgegriffen. Es ist jedoch auch möglich, mit dem Extension Element
paletteGroup eigene Gruppen anzulegen. Bei einem solchen Extension Element musst du
dann lediglich den eindeutigen Identifier sowie den Namen der Gruppe definieren. Bzgl. der
Palettenstruktur hast du somit kompletten Handlungsfreiraum. Du kannst genau festlegen,
welche Elemente in die Palette aufgenommen werden sollen und wie diese strukturiert ist.
Wenn sie nun nochmals die Runtime Workbench starten, um unseren neu erstellten
Prozesstyp auszuprobieren, werden sie sehen, dass die neu erstellten Elemente nun auch in der
Editorpalette erscheinen. Sie können nun neue Diagramme ihres neuen Prozesstyps erstellen.
Registrieren von zusätzlichen Attributen
In den vorigen Kapiteln haben sie gelernt, wie sie mit Hilfe des ProFLOW Frameworks neue
Prozesstypen erstellen können. Sie haben dabei einen neuen Prozesstyp erstellt, welcher ein
Prozesselement, eine Transition und eine Annotation enthält. In diesem Kapitel soll nun
erläutert werden, wie sie ihr Modell und speziell die einzelnen Elemente ihres Prozesstyps
noch mit weiteren Attributen verfeinern können.
Es ist möglich, für sämtliche ModelObjects neue Attribute zu registrieren. Diese Attribute
sind dann über die Properties View, wie schon in Kapitel 2 zur Benutzung des Frameworks
beschrieben, anzeigbar und editierbar. Die Registrierung eines Attributes erfolgt dabei ganz
einfach auf Code-Ebene, sie müssen hierfür keine Extensions registrieren. Um ein neues
Attribut zu registrieren, müssen sie lediglich die Methode registerAttribute(String
attributeId, String name, String category, Object defaultValue, Object restriction)
ausführen.
Bevor im Folgenden einige Beispielattribute registriert werden sollen, hier noch eine kurze
Beschreibung der Parameter dieser Methode:
•
•
•
•
attributeId: Das Attribut muss mit einem eindeutigen Identifier registriert werden.
Dieser Identifier wird auch als PropertyKey in Benachrichtigungen über ModelChanges verwandt.
name: Geben sie hier den Namen für das Attribut an, welcher in der Properties View
verwandt werden soll.
category: Sie können neben dem Namen auch noch die Kategorie angeben, unter
welcher das neue Attribut in der Properties View angezeigt werden soll. Beim Übergeben keines Kategorienamens erscheint das neue Attribut per Default unter der General-Kategorie.
defaultValue: Hier müssen sie den Default-Wert ihres neuen Attributs angeben. Das
ProFLOW Framework unterstützt das Registrieren von Attributen der folgenden Ty-
•
pen: java.lang.String, java.lang.Integer, java.lang.Double, java.lang.Boolean, java.io.File, org.eclipse.swt.graphics.FontData und org.eclipse.swt.graphics.RGB.
restriction: Hier können sie noch optional Einschränkungen für ein definiertes
Attribut festlegen. Eingeschränkt werden können hierbei Integer-Attribute mit einer
Instanz der Klasse proFlow.core.properties.IntegerRange sowie Double-Attribute mit
einer Instanz der Klasse proFlow.core.properties.DoubleRange. Ein String-Attribut
kann ebenfalls auf eine bestimmte Menge von gültigen Strings beschränkt werden.
Hierfür müssen sie lediglich ein String-Array mit den gültigen String-Werten übergeben. Außerdem ist es noch möglich ein File-Attribut durch eine Instanz der Klasse
proFlow.core.properties.FileFilter einzuschränken bzw. das Verhalten des File Dialog
CellEditors zu beeinflussen.
Lassen sie uns nun ein paar einfache Attribute registrieren. Unserem Prozesstyp könnten wir
beispielsweise ein einfaches Description-Attribut hinzufügen. Erweitern sie somit also die
Klasse ExampleProcess um einen Default-Konstruktor-Implementation in der dieses Attribut
registriert wird:
public class ExampleProcess extends Process {
public static final String DESCRIPTION_ATTRIBUTE_ID =
"ProFLOW.example.Process.description";
public ExampleProcess() {
registerAttribute(DESCRIPTION_ATTRIBUTE_ID,
"Description", null, "", null);
}
…
}
In der Properties View erscheint somit das neue Attribut unter der General-Kategorie, wenn
sie ihren Prozess selektiert haben. Sie können dieses Attribut dabei einfach über einen
TextCellEditor editieren.
Lassen sie uns nun noch ein weiteres Attribut registrieren, dessen Wert sich, anders als beim
vorigen Attribut, auch grafisch widerspiegeln soll. Unserer Transition könnte beispielsweise
noch ein Farb-Attribut hinzugefügt werden. Abhängig von dem dort ausgewählten Wert soll
die Transition dann auch im Editor dargestellt werden. Erweitern sie hierfür nun zunächst die
Klasse ExampleTransition um eine entsprechende Attributregistrierung:
public class ExampleTransition extends Transition {
public static final String COLOR_ATTRIBUTE_ID =
"ProFLOW.example.Transition.color";
public ExampleTransition() {
registerAttribute(COLOR_ATTRIBUTE_ID,
"Color", "Layout", new RGB(0, 0, 0), null);
}
…
}
Das neue Attribut erscheint daraufhin nun auch in der Properties View, wenn sie eine
Transition ihres Diagrammtyps im Editor selektieren. Damit der im ColorDialog ausgewählte
Farbwert auch grafisch im Editor reflektiert wird, müssen sie nun noch die EditPart-Klasse
ihrer Transition folgendermaßen erweitern:
public class ExampleTransitionEditPart extends TransitionEditPart {
protected IFigure createFigure() {
PolylineConnection connection =
(PolylineConnection) super.createFigure();
connection.setTargetDecoration(new PolygonDecoration());
connection.setLineStyle(SWT.LINE_SOLID);
RGB rgb = (RGB) getCastedModel().getAttributeValue(
ExampleTransition.COLOR_ATTRIBUTE_ID);
if (rgb != null)
connection.setForegroundColor(new Color(null, rgb));
return connection;
}
public void notifyChange(Object object, Object property) {
super.notifyChange(object, property);
if (property.equals(ExampleTransition.COLOR_ATTRIBUTE_ID) &&
object instanceof RGB)
getFigure().setForegroundColor(
new Color(null, (RGB) object));
}
}
Abschließend wollen wir noch ein letztes Attribut registrieren, welches im nächsten Kapitel
noch eine Bedeutung spielen wird. Erweitern sie dafür die Klasse ExampleElement um ein
Integer-Attribut namens Counter:
public class ExampleElement extends SimpleElement {
public static final String COUNTER_ATTRIBUTE_ID =
"ProFLOW.example.Process.counter";
public ExampleElement() {
…
registerAttribute(COUNTER_ATTRIBUTE_ID,
"Counter", null, new Integer(0), null);
}
…
}
Registrieren von Process Actions
Wir haben an zwei einfachen Beispielen gesehen, wie sie ihr Modell mit der Registrierung
von neuen Attributen verfeinern können. Im Folgenden soll nun noch erläutert werden, wie
sie dem Kontextmenü, der Symbolleiste und dem Hauptmenü ihres ProFLOW Editors noch
weitere Actions, welche auf dem gesamten Prozess arbeiten, hinzufügen können.
Um solch eine neue Action zu definieren, müssen sie eine Subklasse der Klasse
proFlow.ui.actions.ProcessActionRunner implementieren. In unserem Beispiel wollen wir
eine einfache Action erstellen, welche die Anzahl der Prozesselemente (ausgenommen die
Text Labels) unseres Prozesses zählt und das Ergebnis in einem Dialog anzeigt.
Erstellen sie hierfür zunächst das Package proFlow.example.ui.actions und eine darin
enthaltene neue Klasse ElementCountAction, welche die angesprochene Framework-Klasse
erweitert. In dieser Klasse müssen sie nun lediglich die Methode run(Process, IWorkbenchPartSite) implementieren. Unsere Action-Klasse sieht demnach wie folgt aus:
public class ElementCountAction extends ProcessActionRunner {
protected void run(Process process, IWorkbenchPartSite site) {
int elementCount = 0;
for (Element currentElement : process.getAllElements()) {
if (!(currentElement instanceof TextNoteElement))
elementCount++;
}
MessageDialog.openInformation(site.getShell(),
"Element Count",
"Process: " + process.getName() +
"\n\nContains " + elementCount + " Elements. ");
}
}
Abschließend müssen sie die neue Process Action noch mittels des Extension Points
ProFLOW.ui.processActions registrieren. Erzeugen sie nun zunächst eine neue Extension
dieses Extension Points im Plug-In Editor und erzeugen sie ein neues Extension Element
processAction. Dieses müssen sie nun noch wie folgt spezifizieren:
•
id: Hier muss ein eindeutiger Identifier für die neue Process Action angegeben
werden, in unserem Fall wählen wir ProFLOW.example.actions.ElementCount.
•
•
•
•
•
•
•
name: Hier muss der Name angegeben werden, mit welchem diese Action im Kontextmenu des ProFLOW Editors erscheinen soll, wir wählen Element Count.
class: Hier muss die Klasse angegeben werden, welche die Framework-Klasse
proFlow.ui.actions.ProcessAction erweitert, also in unserem Beispiel die gerade implementierte Klasse proFlow.example.ui.actions.ElementCountAction.
icon: Hier kann optional noch ein Icon angegeben werden, welches neben dem Namen
im Kontextmenu erscheinen soll.
contextMenuGroup: Hier kann die Gruppe angegeben werden, unter welcher die
neue Action im Kontextmenu aufgeführt werden soll. Gültige Werte sind hier die folgenden Group-Identifier: org.eclipse.gef.group.copy, .edit, .find, .print, .rest, .save,
.undo und .view. Wir wählen in unserem Fall die Gruppe org.eclipse.gef.group.rest.
toolbarMenuGroup: Hier kann die Gruppe angegeben werden, unter welcher die
neue Action in der Symbolleiste (Toolbar) aufgeführt werden soll. Gültige Werte sind
hier die folgenden Group-Identifier: left_group, middle_group und right_group. Hier
wählen wir die Gruppe right_group.
menuGroup: Hier kann die Gruppe angegeben werden, unter welcher die neue Action
in dem Hauptmenü aufgeführt werden soll. Gültige Werte sind hier die folgenden
Group-Identifier: top_group, middle_group und bottom_group. Hier wählen wir die
Gruppe top_group.
processTypeId: Als letztes Attribut muss noch spezifiziert werden, für welchen
Prozesstyp diese Action ausgeführt werden darf. Hier muss entweder eine konkreter
Processtyp-Identifier angegeben werden oder der Default-Wert all. Da unsere Action
auf allen Prozesstypen ausgeführt werden kann, wählen wir in unserem Beispiel den
Default-Wert all.
Die plugin.xml-Datei wird somit um den folgenden Eintrag ergänzt:
<extension
point="ProFLOW.ui.processActions">
<processAction
id="ProFLOW.example.actions.ElementCount"
name="Element Count"
class="proFlow.example.ui.actions.ElementCountAction"
icon="icons/info.gif"
contextMenuGroup="org.eclipse.gef.group.rest"
toolbarGroup="right_group"
menuGroup="top_group"
processTypeId="all"/>
</extension>
Es steht ihnen frei, ob sie die Action im Kontextmenü, in der Symbolleiste und/oder in dem
Hauptmenü platzieren wollen.
Achtung: Wenn sie eine Action in der Symbolleiste platzieren möchten, müssen sie auch ein
Icon angeben, da die Action sonst nicht in der Symbolleiste angezeigt werden kann.
Wir haben somit auf einfache Weise eine neue Action registriert. Wenn sie nun die Runtime
Workbench starten, werden sie sehen, dass die neue erstellte Action im Kontextmenu des
ProFLOW Editors erscheint und in beschriebener Weise arbeitet.
Registrieren von Model Object Actions
Neben den zuvor beschriebenen Process Actions kann noch eine weitere Art von Actions
ProFLOW Editor hinzugefügt werden, die Model Object Actions. Diese Actions können auf
jeder Art von Modelobjekten (also SimpleElements, ContainerElements, Annotationen oder
Transitionen) definiert werden.
Im folgenden Beispiel wollen wir eine einfache Action definieren, welche auf einer beliebigen
Transition ausgeführt, das Source- und Target-Element in einem Dialog anzeigt. Die
Definition dieser Action ist dabei ähnlich der Definition der zuvor erläuterten Process Action.
Implementieren sie hierbei zunächst eine Subklasse der Klasse proFlow.ui.actions.ModelObjectActionRunner. Erzeugen sie also die Klasse TransitionInfoAction in dem bereits zuvor
erzeugten Package proFlow.example.ui.actions. In dieser Klasse müssen sie nun wie zuvor
lediglich die Methode run(List<ModelObject>, Process, IWorkbenchPartSite) vervollständigen. Unsere ActionRunner-Klasse sieht demnach wie folgt aus:
public class TransitionInfoAction extends ModelObjectActionRunner {
public void run(List<ModelObject> modelObjects, Process process,
IWorkbenchPartSite site) {
Transition t = (Transition) modelObjects.get(0);
MessageDialog.openInformation(site.getShell(),
"Transition Info",
"Source Element: " + t.getSourceElement() + "\n" +
"Target Element: " + t.getTargetElement());
}
}
Abschließend müssen sie die neue Model Object Action noch mittels des Extension Points
ProFLOW.ui.modelObjectActions registrieren. Erzeugen sie hierfür eine Extension dieses
Extension Points und erzeugen sie ein neues Extension Element modelObjectAction. Dieses
müssen sie nun noch wie folgt spezifizieren:
•
•
id: Hier muss ein eindeutiger Identifier für die neue Model Object Action angegeben
werden, in unserem Fall ProFLOW.example.actions.TransitionInfo.
name: Hier muss der Name angegeben werden, mit welchem diese Action im Kontextmenu des ProFLOW Editors erscheinen soll, wir wählen Transition Info.
•
•
•
•
•
•
•
class: Hier muss die Klasse angegeben werden, welche die Framework-Klasse
proFlow.ui.actions.ModelObjectActionRunner erweitert, also in unserem Beispiel die
gerade implementierte Klasse proFlow.example.ui.actions.TransitionInfoAction.
icon: Hier kann optional noch ein Icon angegeben werden, welches neben dem Namen
im Kontextmenu erscheinen soll.
contextMenuGroup: Hier kann die Gruppe angegeben werden, unter welcher die
neue Action im Kontextmenu aufgeführt werden soll. Gültige Werte sind hier die folgenden Group-Identifier: org.eclipse.gef.group.copy, .edit, .find, .print, .rest, .save,
.undo und .view. Wir wählen in unserem Fall die Gruppe org.eclipse.gef.group.rest.
toolbarMenuGroup: Hier kann die Gruppe angegeben werden, unter welcher die
neue Action in der Symbolleiste (Toolbar) aufgeführt werden soll. Gültige Werte sind
hier die folgenden Group-Identifier: left_group, middle_group und right_group.
menuGroup: Hier kann die Gruppe angegeben werden, unter welcher die neue Action
in dem Hauptmenü aufgeführt werden soll. Gültige Werte sind hier die folgenden
Group-Identifier: top_group, middle_group und bottom_group. Hier wählen wir die
Gruppe bottom_group.
modelObjectTypeId: Außerdem muss noch spezifiziert werden, für welchen Modelobjekttyp diese Action ausgeführt werden darf. Hier muss entweder eine konkreter
Modelobjekt-Identifier angegeben werden oder eines der reservierten Wörter all,
simpleElements, containerElements, annotations oder transitions abhängig von der
Art des gültigen Modelobjekts. Da unsere Action auf allen Transitionen ausgeführt
werden soll, wählen wir in unserem Beispiel den Wert transitions.
enablesFor: Abschließend muss noch angegeben werden, wieviele Modelobjekte
ausgewählt werden müssen, um eine die Action ausführen zu können. Hier stehen drei
Möglichkeiten der Definition zur Verfügung:
o n – Eine konkrete Anzahl von Modelobjekten muss ausgewählt werden.
o n+ – Mindestens die angebene Anzahl von Modelobjekten muss ausgewählt
werden.
o + – Eine beliebige Anzahl von Modelobjekten kann ausgewählt werden.
In unserem Beispiel soll die Action lediglich auf einer selektierten Transition ausgeführt werden können. Wir wählen also den Wert „1“.
Die plugin.xml-Datei wird somit um den folgenden Eintrag ergänzt:
<extension
point="ProFLOW.ui.modelObjectActions">
<modelObjectAction
id="ProFLOW.example.actions.TransitionInfo"
name="Transition Info"
class="proFlow.example.ui.actions.TransitionInfoAction"
contextMenuGroup="org.eclipse.gef.group.rest"
menuGroup="bottom_group"
modelObjectTypeId="transitions"
enablesFor="1"/>
</extension>
Die neu erzeugte Model Object Action erscheint nun im Kontextmenu des ProFLOW Editors.
Verwendung von Commands
Die in den obigen Kapiteln vorgestellte Implementation der Actions kann so leider nicht
immer verwendet werden. Sie ist nur zulässig, wenn man lediglich Berechnungen auf dem
Modell ausführt. Will man in Actions das zugrundeliegende Modell verändern, müssen
Commands verwendet werden.
Info: Verändert man das Modell ohne die Verwendung von Commands, so kann man die
grafische Darstellung des dargestellten Prozesses zwar mit Hilfe des Benachrichtigungsmechanismus aktualisieren. Das Problem hierbei ist jedoch, dass der ProFLOW-Editor selbst von
diesen Veränderungen nichts erfährt und somit den „Dirty State“ nicht aktualisiert und der
Editor dementsprechend nicht abspeicherbar ist.
Im Folgenden soll nun erklärt werden, wie man mit Hilfe von Commands diesem Problem
begegnen kann. Lassen sie uns eine Action implementieren, welche das Counter-Attribut der
Klasse ExampleElement hochzählt.
Hierfür müssen wir zunächst die EditPart-Klasse unseres ExampleElements um eine weitere
EditPolicy erweitern. EditPolicies definieren, wie EditParts verändert werden dürfen. Wir
fügen somit unserer Klasse ExampleElementEditPart eine Component-Role-EditPolicy hinzu:
public class ExampleElementEditPart extends ElementEditPart {
…
protected void createEditPolicies(){
super.createEditPolicies();
installEditPolicy(EditPolicy.COMPONENT_ROLE,
new ExampleElementEditPolicy());
}
}
Info: Es gibt eine Vielzahl verschiedener Arten von EditPolicies. Zum Verändern des
Modells bietet sich in den meisten Fällen jedoch die Component-Role-EditPolicy an.
In der EditPolicy müssen wir nun definieren, wie ein EditPart auf eine konkrete Anfrage
(Request) reagieren soll. Wenn ein EditPart eine Anfrage bearbeiten kann, so gibt sie eine
entsprechende Command zurück, welche die Anfrage bearbeitet. In unserem Fall gibt sie eine
Instanz der Command-Klasse IncrementCounterCommand zurück.
Achtung: Eine EditPart kann nur zu jeder Policy-Rolle eine EditPolicy zugewiesen
bekommen. Da die Superklasse ElementEditPart der Klasse ExampleElementEditPart bereits
eine Component-Role-EditPolicy besitzt, müssen wir diese in unserem Beispiel erweitern.
public class ExampleElementEditPolicy
extends ElementComponentEditPolicy {
public Command getCommand(Request request) {
Object model = getHost().getModel();
if (IncrementCounterAction.INCREMENT_COUNTER_REQUEST_TYPE
.equals(request.getType())
&& model instanceof ExampleElement) {
ExampleElement element = (ExampleElement) model;
return new IncrementCounterCommand(element);
}
return super.getCommand(request);
}
}
In der Command-Klasse können wir nun das Hochzählen unseres Counters implementieren.
Bei Commands ist es möglich, neben einer Methode execute() auch undo()- und redo()Methoden zu implementieren. Somit ist es im ProFLOW-Editor möglich, diese Veränderungen auch wieder rückgängig zu machen. Die Klasse IncrementCounterCommand sieht
demnach wie folgt aus:
public class IncrementCounterCommand extends Command {
private ExampleElement element;
private Integer oldCounter;
public IncrementCounterCommand(ExampleElement element) {
this.element = element;
this.oldCounter = (Integer) element.getAttributeValue(
ExampleElement.COUNTER_ATTRIBUTE_ID);
}
public void execute() {
elment.setAttributeValue(
ExampleElement.COUNTER_ATTRIBUTE_ID, oldCounter + 1);
}
public void undo() {
element.setAttributeValue(
ExampleElement.COUNTER_ATTRIBUTE_ID, oldCounter);
}
public void redo() {
execute();
}
}
Abschließend müssen wir nun noch die Command ansteuern. Dafür implementieren wir eine
neue ModelObjectAction, welche diese Command aufruft. In der Klasse ModelObjectActionRunner stehen hierfür die Hilfsmethoden executeCommand(ModelObject, Request) sowie
executeCommand(List<ModelObject>, Request) zur Verfügung. Da wir in unserem Fall
lediglich ein selektiertes Element verändern wollen, benutzen wir die erste Methode, um die
dazugehörige Command aufzurufen. Hierfür müssen wir lediglich das Element, dessen
Counter-Attribut hochgezählt werden soll, sowie einen Request mit dem entsprechenden Typ
übergeben:
public class IncrementCounterAction extends ModelObjectActionRunner {
public static final Object INCREMENT_COUNTER_REQUEST_TYPE =
new Object();
public void run(List<ModelObject> modelObjects, Process process,
IWorkbenchPartSite site) {
Element element = (Element) modelObjects.get(0);
executeCommand(element,
new Request(INCREMENT_ELEMENT_COUNTER_REQUEST_TYPE));
}
}
Info: Die Methode executeCommand(…) arbeitet dabei wie folgt. Es wird zunächst der zum
ModelObject dazugehörige EditPart ermittelt. Ausgehend von diesem EditPart wird der
Command erfragt, welcher den gegebenen Request bearbeiten kann. Dabei werden alle
registrierten EditPolicies des EditParts befragt. Abschließend wird die Command auf dem
CommandStack des ProFLOW-Editors abgesetzt und somit ausgeführt.
Info: Es ist natürlich möglich, die Klasse Request zu erweitern (also Subklassen dieser Klasse
zu bilden). Dies kann notwendig werden, wenn man Informationen in Form von Parametern
über die EditPolicy zu der entsprechende Command-Klasse weiterleiten möchte.
Abschließend müssen wir nun nur noch die obige Action registrieren. Hierfür müssen wir in
bereites bekannter Weise die plugin.xml um den folgenden Eintrag erweitern:
<extension
point="ProFLOW.ui.modelObjectActions">
<modelObjectAction
id="proFlow.example.ui.actions.IncrementElementCounterAction"
name="Increment Counter"
class="proFlow.example.ui.actions.IncrementCounterAction"
icon="icons/increment.gif"
contextMenuGroup="org.eclipse.gef.group.rest"
toolbarGroup="middle_group"
modelObjectTypeId="ProFLOW.example.Element"
enablesFor="1"/>
</extension>
Deployen des Plug-Ins
Die Definition unseres Example Plug-Ins wäre damit abgeschlossen. Abschließend soll nun
noch erläutert werden, wie sie ihr neu erstelltes Plug-In ausliefern können. Ausliefern
bedeutet in unserem Fall, dass sie eine .jar-Datei aus ihrem Plug-In Project erzeugen. Gehen
sie hierbei wie folgt vor.
Spezifieren sie zunächst die Build Configuration ihres Plug-Ins. Gehen sie hierfür auf die
Build Page ihres Plug-In Editors. Hier können sie festlegen, welche Dateien der Binary und
welche Dateien der Source Build enthalten sollen. Dem Binary Build müssen sie lediglich den
META-INF-Ordner, den icons-Ordner sowie die plugin.xml-Datei hinzufügen. Beim Source
Build, welchen wir im Folgenden erstellen wollen, wählen sie alle Dateien bis auf bin-Ordner.
Info: Wenn sie nichts dagegen haben, dass Nutzer ihres Plug-Ins auch ihren Source-Code
sehen dürfen, sollten sie immer einen Source Build erstellen – schließlich profitieren und
lernen sie selbst an vielen Stellen meist aus bereitgestelltem Source-Code.
Um die .jar-Datei ihres Plug-Ins zu erstellen, wechseln sie zu der Overview Page des Plug-In
Editors. Hier können sie rechts unten in der Exporting Section den Export Wizard starten. In
diesem müssen sie dann lediglich noch die Destination (also den Zielordner ihres Builds) und
die weiteren Optionen spezifizieren. Selektieren sie die ‚Include source code’ Checkbox, um
den Source Build auszuwählen. Nachdem sie auf den Finish-Button gedrückt haben, wird die
.jar-Datei im angegebenen Zielordner erstellt.
Sie können nun die neu erstellte .jar-Datei ihres Plug-Ins in den plugins-Ordner ihrer Eclipse
Version kopieren. Beim erneuten Ausführen von Eclipse müssen sie, damit die neue .jar-Datei
geladen wird, einmalig das Argument -clean mit übergeben. Anschließend können sie nun den
neu erstellten Diagrammtyp auch in ihrer „normalen“ Eclipse Workbench einsetzen.
Herunterladen