In this assignment, you will become a bit more accquainted with GMF and,
in particular, the way of extending an automatically generated GMF editor.
Moreover, you will learn how to add programmed Java contraints to the editor.
To this end, your will be provided with a simple GMF editor for defining
modules in a graphical way — this editor has the capability of showing
the module instances insided module instances, which we call "inlining". But
this inlining is not done automatatically, yet. The task of this assignment
is to extend this editor, so that when the reference to a module definition is set for
a module instance, the ports corresponding to the module definition are
created automatically. Moreover, when the attribute "inlined" is set to
true by the user, the definition should be inlined graphically.
Up to now, the GMF editor for modules will allow the user creating connection (definitions)
which would not make any sense (inside of module instances). Therefore, as
a part of this tutorial, you will add Java constraints to the editor, which
make sure that this does not happen.
This tutorial is relevant for those students who plan to do project 1.
Below, the major steps for these extensions are outlined (assuming that you have
Eclipse installed as described here already):
- Download the Eclipse project with the graphical editor from ATSE-Project1-GMF-experiment.template.zip and import the
projects to your Eclipse workbench. Note that, in these projects, all places where
you need to do some programming for extending the programme are marked with
TODO .
Before you start programming, start the runtime workbench of your Eclipse and check
whether the editor is working properly. To this end, you can use an example
project with some module definitions from
ATSE-Project1-GMF-experiment.example.zip; download it and import it to the runtime
workspace.
You can create module definitions and create module instances inside the
module definitions and also inside module instances; and you can create connection definitions and connection inlines.
But all of this editing needs to be done manually.
- In a first step, extend the editor in such a way, that whenever the user selects
a module definition for a module instance (in the property view) or unselects it,
in the module instance, a number of input and output port instances should be
created for this instance, which correspond to the port definitions in the
respective module definition.
To this end, there is a listener installed on every module instance, which
calls the static method notifyChanged() in class
HandleModuleInstanceUpdate in project
dk.dtu.compute.atse.f14.project1.experiment.diagram . There is some
code there already, with two positions marked with a TODO .
The first TODO is where you need add code for
creating the respective number of input and output ports for the instance.
Note that you only need to add the model elements, the graphics "magically"
will be updated by the graphical editor itself, once the new ports are added
to the model. Note that the underlying model has some additional attributes for
the port instances refering to the respective port definitions in the module
definition. You need to set them properly here too. The model of these modules
package will be discussed in the tutorial session.
After you have implemented this part, start the runtime workbench again, and
check whether the ports are now added automatically when the definition of a
module instance is set (and deleted when the definition is set to null).
- In a second step, add the code that inlines a copy (!) of the complete definition
of a module into a module instance. The place where to add this code is marked
with the second
TODO in the notifyChanged() method
of the class HandleModuleInstanceUpdate .
You can use a method for cloning a single instance of a module. Note that
this method has a mapping parameter that keeps track of how ports of the
original map to the ports of the clone. You will need this mapping in
the end when you also clone the connections between the different instances.
After you have implemented this part, start the runtime workbench again, and
check whether the definition of the module is properly inlined (it is very likely
that it will have some flaws initially). In case you cannot spot the problem right away, start the
runtime workbench in debug mode and set a break point in you code, so that
you can see what is going on.
- At last, implement two constraints for this model in the package
modules.validation
of project dk.dtu.compute.atse.f14.project1.experiment .
The first constraint is defined by class ConnectionDefsOnTopLevelOnly which basically is
empty again. Here you need to add code that returns ctx.createFailureStatus(new Object[] {connection}) in case the connection definition is a non-top-leve connection. This
means the connection connects port instances that do not belong to a top-level instance
of the module or port definitions that do not belong to the module itself (this will be
discussed in the tutorial).
The second constraint is defined by class ConnectionInstReflectedByDefinition ,
which should guarantee that each inlined constraint properly reflects a connection definition
in the module definition. Technically, this is done in the same way as the first constraint;
getting this conceptually right is a bit more involved, however.
- Test whether your implementation of the constraints is correct by starting the runtime
workbench again. The first constraint is registered as a live constraint, which means
that the editor now will automatically reverse the addition of connection definitions that
are not on the top-level. The second constraint is installed as batch constraint, which
means the validation needs to be invoked manually (Edit -> Validate) when the editor
is open. If there are inlined connections that are invalid, they will be marked with
a problem marker (you can easily add invalid inlined connections with the graphical editor
manually for testing whether your validation works properly).
- At last, have a look into how the notification mechanism is hooked into the GMF editor
so that the module instances are properly inlined. Also have a look into how the
constraints are installed (in the
plugin.xml ).
|