Sending events
Introduction
We are now going to work with the "PatternEventSource" package. We will thus be able to create events on an attribute and on an association.
The "PatternEventSource" package contains:
· a "Source" class containing a "name" attribute and a "data" association to which we will apply the pattern
· a "Data" class, the target of the data association
· a "SpyApplet" which generalizes Applet and which will allow us to visualize the pattern's action
· an "InnerSpy" class, internal class of "SpyApplet", which will act as subscriber to the events that we will have created
In Java, events are grouped into event classes. Therefore in Java you have the following basic event classes: "Window", "Mouse" and "Key".
The event sending pattern follows the same principle.
Initial model of the Source class

Figure 37. Calling the pattern on the "name" attribute
We are going to run the event creation pattern on the "name" attribute of the Source class.

Figure 38. Creating events on the "name" attribute
A dialog box, used to create new events, opens.
We are going to create a "NameChanged" event to be launched each time the value of an attribute is modified. We are also going to create an "EmptyName" event aimed at being launched when the attribute takes an empty string as its value.
To do this, carry out the following actions:
1. Enter "Name" in the "Event class" field.
2. Enter "NameChanged" in the "New event" field.
3. Click on the "Add" button.
4. Enter "EmptyName" in the "New event" field.
5. Click on the "Add" button.
6. Click on the "OK" button.

Figure 39. Dialog box for creating events
Model of the source class after the first transformation

Figure 40. Transformed model
Summary of the elements created during the first transformation
New elements appear in our project:
· an "event" package in the "PatternEventSource" package
· a "NameEvent" class, which generalizes the JDK's "EventObject" class, in the "event" package. This class represents the "Name" type event class we have just created. Objects with this type will be created each time a "Name" type event occurs, in other words, the changing of a name or an empty name.
|
The
class contains ... |
function
... |
|
a "name" attribute |
designed to contain the new value of the attribute after the event has occurred. |
|
a "NAME_CHANGED" constant |
represents the name change event. |
|
an "EMPTY_NAME" constant |
represents the empty name event. |
|
two constants, "NAME_FIRST" and "NAME_LAST" |
allows you to enumerate the events of the "Name" class. |
|
an "id" attribute |
designed to take the value of one of the constants representing the events, i.e. "NAME_CHANGED" or "EMPTY_NAME". |
|
a constructor |
takes the event's source object, the type of event and the new value of the "name" attribute as parameters. |
· a "NameListener" interface in the "event" package. This interface defines the methods to be redefined to react to the "Name" type events. It contains a "nameChanged" method linked to the name change event and an "emtpyName" method linked to the empty name event.
· a "NameAdapter" class in the "event" package. This class implements the "NameListener" interface and defines the "nameChanged" and "emptyName" methods that have no effect. A class such as this is defined each time an event class contains at least two events. Indeed, the subscription is carried out through an event class and not through one event after the other. However, sometimes we are not interested in all the events of an event class. In this way, instead of implementing the interface, a listener can generalize this class and only define the methods corresponding to the events to which it wants to react.
Furthermore, the "Source" class has been enriched with the following elements:
· an instance association towards the "NameListener" interface described above. It will allow an instance of the "Source" class to find out which objects have subscribed to the "Name" type events it produces
· a "getName" accessor used to recover of the current value of the "name" attribute
· a "setName" mutator used to modify of the value of the "name" attribute and the notification of the subscribers to the events of the "Name" class on the current instance
· a {JavaNoAccessor} tagged value on the "name" attribute indicating to the generator that it should not generate accessors, as they have already been created by the pattern
· a "notifyNameChanged" method that tells the subscribers to the "Name" type events of the current instance that the name has changed
· a "notifyEmptyName" method that tells the subscribers to the "Name" type events of the current instance that the name is emtpy
· a "addNameListener" method that allows an object to subscribe to "Name" type events on the current instance
· a "removeNameListener" method that allows an object to be removed from the list of subscribers to the "Name" type events of the current instance
Modifying the mutator
We are now going to look at the "setName" method of the "Source" class. The method created by the pattern must be modified.
The pattern does not know the semantics of the events. We can see that the "setName" method systematically notifies the name change event, which is correct, but also gives the empty name event, which is not correct.
Therefore, a test needs to be added.

Figure 41. Modifying the "setName" method
Calling the pattern on the "data" association
We are going to run the event creation pattern on the "data" association of the "Source" class.

Figure 42. Creating events on the "data" association
Creating events on the "data" association
A dialog box opens which allows the creation of new events.
We are going to create a "DataChanged" event that will be launched each time data are added or removed.
To do this, carry out the following actions:
1. Enter "Data" in the " Event Class" field.
2. Enter " DataChanged" in the "New event" field.
3. Click on the "Add" button.
4. Click on the "OK" button.
Model of the source class following the second transformation

Figure 43. Transformed model
Summary of the elements created during the second transformation
New elements appear in our project:
· a "DataEvent" class, which specializes the JDK's "EventObject" class, in the "event" package. This class represents the "Data" type event class we have just created. Objects with this type will be created each time a "Data" type event occurs.
|
The class contains ... |
which ... |
|
a "data" association with the same cardinality as the one of the Source class |
contains the image of the object's association after the event has occurred |
|
a "DATA_CHANGED" constant |
represents the name change event |
|
two constants "DATA_FIRST" and "DATA_LAST" |
enumerates the events of the "Name" class |
· an "id" attribute designed to take the value of one of the constants representing the events, i.e. "DATA_CHANGED" only
· a constructor that takes the event's source object, the type of event and the new value of the "data" association as its parameters
· a "DataListener" interface in the "event" package. This interface defines the methods to be redefined to react to "Data" type events. It contains a "dataChanged" method linked to the association's modification event.
Furthermore, the Source class has been enriched with the following elements:
· an instance association towards the "DataListener" interface described above. It will allow an instance of the "Source" class to find out which objects have subscribed to the "Data" type events it produces
· a "getData" accessor allowing the recovery of the Data type object which has the "data" association data rank
· a "setData" mutator allowing you to modify the value of the Data type object with the "data" association data rank and to notify the subscribers to the "Data" class events on the current instance
· a {JavaNoAccessor} tagged value on the "data" association indicating to the generator that it should not generate accessors. Indeed, the pattern created them
· a "notifyDataChanged" method that tells the subscribers to the "Data" type events of the current instance that the name has changed
· a "addDataListener" method allowing an object to subscribe to "Data" type events on the current instance
· a "removeDataListener" method allowing an object to be removed from the list of subscribers to the "Data" type events of the current instance
Subscription to the "InnerSpy" class
It is first necessary to create an implementation link from the "InnerSpy" class towards the "NameListener" interface and another towards the "DataListener" interface. The pattern for creating methods to be implemented on the "InnerSpy" class is then run.

Figure 44. Creating methods to react to events
Steps:
1. Right-click on "InnerSpy".
2. Run the "Create the methods to be implemented" command from the Java Developer context menu.
The "nameChanged", "emptyName" and "dataChanged" methods have been created in "InnerSpy". You now have to enter the code of these methods. In the example, we are simply going to display traces in the applet's text zone.
"nameChanged" method:
getConsole().append ( "The new name is " +
evt.getName() + "\n" );
"emptyName" method:
getConsole().append ( "Warning ! Non identified element !\n" );
"dataChanged" method:
getConsole().append ( "The current data is
:\n" );
for ( int i = 0 ; i < evt.getData().size(); i++ )
{
getConsole().append
( " - " +
evt.getData().get(i).getContent() + "\n" );
}
Generating code
You now have to generate. Follow the steps below:
1. Generate the code of the "PatternEventSource" package's classes.
Note: If the "Automatically generate" parameter is active, it is not necessary to carry out these steps. For more information on this parameter, please see "Objecteering Java Developer parameters".
Execution
We are now going to be able to launch the applet. You simply have to click on the ‘Run the Applet’ button of the Java tab for the "SpyApplet" class.

Figure 45. Executing the applet
The applet runs a scenario that creates a "Source" class object, subscribes to its "Name" and "Data" type events and modifies the "name" attribute and the "data" association of this object. The result is as follows:

Figure 46. Result of the applet execution