3D PLM Enterprise Architecture |
Middleware Abstraction |
The Send/Receive Communication ProtocolSending notifications from command to command |
Technical Article |
AbstractTo convey end user intents to the object that can do the requested job, CAA V5 uses specific objects called commands that build a tree structure. Events issued by the end user are converted into CAA V5 notifications that are sent from command to command upwards in the command tree structure until a command executes the job. A given command can send notifications, and when receiving one, it can either be transparent to, enrich, or process the received notification, depending on the notification type and the command purpose. |
The send/receive communication protocol uses the SendNotification
,
AnalyseNotification
, and ReceiveNotification
methods
of the CATCommand class, and sends notifications along the command tree
structure to perform the event propagation from the command that detected the
event to the command that can process it.
The command 1 receives the system event as a CAA V5 notification, instance of
the CATNotification class. It sends the notification to its father, the command
2, using the CATCommand's SendNotification
method:
SendNotification(MyFather, Notification); |
Each command knows its father by means of a pointer stored as a private data member and passed as an input parameter of the command constructor.
This command 2 is not designed to process events, that is it does not
override the AnalyseNotification
method. Thus the CATCommand's AnalyseNotification
method is used and returns CATNotifTransmitToFather
to the command
1 which then resends the notification to the command 3, father of the command 2
in the command tree structure. This command 3 is designed to process such events
and overrides the AnalyseNotification
method to catch that expected
notification by returning CATNotifDontTransmitToFather
to the
sending command 1 which stops the event propagation. Otherwise, it returns CATNotifTransmitToFather
,
thus leaving this notification goes on propagating. Depending on what the
command 3 developer intends to do, two possibilities exist:
SendCommandSpecificObject
method
can be overridden, and used possibly several times, to query about the
object(s) involved.SendNotification
first parameter allows for this. In this case, pay attention to a possible
loop between the sending command and the target command.If no command is found, the root command is reached. This root command, a CATCommandSelector instance, plays a specific role. When it receives a notification, meaning that no command below in the command tree structure path, from the command which first receives the event and the CATCommandSelector instance, has been able to process the event, it sends back the notification to the active dialog command. This active dialog command can then decide what to do. The figure below shows the command tree structure and the event propagation along it.
Once the appropriate receiving command is reached, a dialog can begin between
this receiving command and the sending command, to get more information about
the event, that is generally which object is concerned with the event. In its AnalyseNotification
method, the receiving command requests the sending command for that object,
beginning with the expected type(s). The sending command returns that object if
the type is matched, or NULL
otherwise. The receiving command can
then loop on all the types it expects until whether an object is returned, or
the type list end is reached.
The CATCommand's SendObject
method is used by the receiving
command against the sending command to ask for an object type, and this SendObject
method calls the sending command's SendCommandSpecificObject
method, if this one exists, to return the expected object, or returns NULL
otherwise.
Below is an OMT-like figure that shows the main objects and methods used.
[Top]
As soon as you intend to create a command, you should know if your command is transparent for notifications, that is leave notifications pass through it, is a sending command, process some of the possible notifications that can reach it, and/or enrich some of them.
[Top]
This is the case, for example, of some intermediate dialog objects that contains others, such as a frame in a window that contains a graphic viewer. The frame is an instance of a class which derives from CATCommand, as well as the viewer it contains, and as well as the window that contains both. The frame is there to accommodate the viewer, but has no real possibilities regarding the user intents, and is thus transparent for notifications.
In this case, you have nothing to do. The CATCommand class instance created
when your command is instantiated provides your command with this transparent
behavior, takes care of receiving the notifications, and replies always CATNotifTransmitToFather
to the sending command.
[Top]
Your command detects a user intent, and plays the role of converting the
system event into a CAA V5 notification. This notification is sent thanks to the
CATCommand's method SendNotification
you can use as is.
In this case, you have nothing to do. The CATCommand class instance created
when your command is instantiated provides your command with this transparent
behavior, takes care of receiving the notifications, and replies always CATNotifTransmitToFather
to the sending command.
SendNotification(MyFather, Notification); |
But this is generally not enough. If the user intent is valid in the current
context, that is can be turned into a task that an available command can
perform, and if this command is reached by the notification, sure this command
will request more information from your sending command using the SendObject
method. To reply, your sending command must override the SendCommandSpecificObject
method called by the SendObject
method. This method should return a
pointer to the object belonging to the requested class and managed by your
command, and NULL
otherwise.
void * SendCommandSpecificObject( const char * ClassOfExpectedObject, CATNotification * Notification) { if (TheObjectIManage->IsAKindOf(ClassOfExpectedObject) return ((void *) TheObjectIManage); else return NULL; } |
Of course, you can loop on the different objects you command manages, if any.
[Top]
Your command is there to process some user intents, and you need to code what to do when the end user asks to do what your command expects. Two ways are offered:
AnalyseNotification
method to code or call the
appropriate methods that perform the jobAddAnalyseNotificationCB
method.Both can be used in the same command, but not for the same notification, since the callback is searched for first.
[Top]
You simply need to catch the notifications you expect, and resend the others.
A skeleton for such a overridden AnalyseNotification
method could
be:
CATNotifPropagationMode MyCommand::AnalyseNotification (CATCommand* SendingCommand, CATNotification* ReceivedNotification) { if (ReceivedNotification->IsAKindOf( // Catch expected notifications ExpectedNotification::ClassName()) { // provide here the code to process the notification return (CATNotifDontTransmitToFather); } else // Resend the others return (CATNotifTransmitToFather); } |
In this skeleton, SendingCommand
is the command that sends the
notification named ReceivedNotification
. If this ReceivedNotification
is an instance of the ExpectedNotification class, or of one of its derived
classes, then you can process ReceivedNotification
, and stops the
notification propagation by returning CATNotifDontTransmitToFather
.
Otherwise, leave the notification propagation goes on by returning CATNotifTransmitToFather
.
[Top]
You can set a callback for each expected notification, for example in the command constructor, as follows:
... AddAnalyseNotificationCB( // Set the callback for the ExpectedSendingCommand, // expected notifications ExpectedNotification, (CATCommandMethod)&MyCommand::MethodToCallBack, PointerToUsefulData); ... MyCommand::MethodToCallBack( // Code the callback CATCommand* ExpectedSendingCommand, CATNotification * ExpectedNotification, CATCommandClientData PointerToUsefulData) { // provide here the code to process the notification } ... |
Setting a callback, and providing the method for the callback, stops the notification propagation along the command tree structure.
[Top]
If your command requests input from the end user, such as the object selected
under the mouse, use the SendObject
method to request the sending
command, which should know this object, to send it to your command, as follows:
... SendObject(ClassOfExpectedObject, Notification); ... |
where ClassOfExpectedObject
is the class from which the object
you expect is an instance, and Notification
the notification which
reaches your command.
[Top]
You may want to add information to a received notification without processing
it by your command. In this case, you can either override the AnalyseNotification
method, or set a callback, as described above, but instead of processing the
notification, you instantiate a new notification and you send it to the
appropriate command, generally the father of your command.
The following code should then be inserted in the code skeleton above in place of the comment for processing the notification.
... MyEnrichedNotification = new CATEnrichedNotification(); SendNotification(Father, MyEnrichedNotification); ... |
[Top]
This example relies on the following command tree:
The command 1 detects an end user intent and converts it as a notification sent along the command tree structure. The command 2 is transparent for notifications, and the notification reaches the command selector which resends it to the active dialog command. This command expects such notification, and request from the sending command 1 an expected object to be sent.
The first step is for the command 1 to send the notification. This is coded as follows in the appropriate method, that is the one which turns the system event into a CAA V5 notification:
... CATNotification* NotifToSend = new MyNotification(); SendNotification (GetFather(), NotifToSend); ... |
The appropriate notification is instantiated, and sent to the command's
father. Note that this father can be retrieved using the GetFather
method.
Then the notification goes along the command tree structure. It meets the
command 2 which has not overridden the AnalyseNotification
method
and which uses the CATCommand's AnalyseNotification
method to
return CATTransmitToFather
to the command 1. Since this father is
the command selector, the notification propagation stops and is sent by this
command selector to the command 3, the active dialog command. This command has
overridden the AnalyseNotification
method as follows:
CATNotifPropagationMode Command3::AnalyseNotification (CATCommand* SendingCommand, CATNotification* ReceivedNotification) { if (ReceivedNotification->IsAKindOf( ExpectedNotification::ClassName()) { ExpectedObject* TheExpectedObject = (ExpectedObject*) SendingCommand->SendObject( ExpectedObject::ClassName(), ReceivedNotification); if (TheExpectedObject) return (CATNotifDontTransmitToFather); else return (CATNotifTransmitToFather); } else return (CATNotifTransmitToFather); } |
The active command knows the notification it expects, and the method compares
its class to the one of the received notification. If the two classes match, it
creates an expected object instance and request from the sending command to such
object using the SendObject
method. If the expected object is
returned, the method returns successfully with CATNotifDontTransmitToFather
,
and with CATNotifTransmitToFather
otherwise.
The sending command should have overridden the SendCommandSpecificObject
as follows:
void *Command1::SendCommandSpecificObject( const char * ExpectedObject, CATNotification* ReceivedNotification) { if ( _TheHandledObject->IsAKindOf(ExpectedObject) && (ReceivedNotification == _NotifSent) ) return ((void *) _TheHandledObject); else return (NULL); } |
The SendCommandSpecificObject
method has the same arguments than
the SendObject
method. The sending command has keep track of the
notification sent, for example in the _NotifSent
data member, and
handles _TheHandledObject
instance. If the class of which _TheHandledObject
is an instance is a kind of the ExpectedObject class, that is the two classes
are the same or _TheHandledObject
's class derives from the
ExpectedObject class, _TheHandledObject
is returned, and is also
returned by the calling SendObject
command as TheExpectedObject
pointer to the active dialog command, which can now uses it appropriately.
Otherwise, NULL
is returned.
[Top]
The CAA V5 commands build a tree structure whose root command is the CATCommandSelector instance. The Send/Receive communication protocol enables a notification sent by one of these commands to propagate up to the appropriate command, that is the command able to execute the job requested by the notification.
Each command on top of the sending command can in turn either participate to the notification propagation or process the notification. If the root command is reached, it sends the notification to the active command which can decide to process the notification, or to stop its propagation.
[Top]
[1] | xxx |
[Top] |
Version: 1 [Jan 2000] | Document created |
[Top] |
Copyright © 2000, Dassault Systèmes. All rights reserved.