3D PLM Enterprise Architecture

Middleware Abstraction - ENOVIA Event Model

The ENOVIA Event Model

Important concepts about publishing events in ENOVIA V5
Technical Article

Abstract

This article describes, in the ENOVIA V5 event model context, the methodology to declare and raise events (Publisher side).


The Event Declaration

Each domain in ENOVIA (PRODUCT, CONFIG, etc.) declares its data strucutre in a XML file,named "DomainName".metadata.

In the same way, all the specific events that objects of that domain will raise are described in another XML file: "DomainName".event.

Note: By convention, the name of the event will be the same as the C++ method name in which the event is really raised.

Examples:

[Top]

What Does Event Declaration Mean?

When you want an object to raise event, you have to describe a set of attributes:

Added to those definitions, people may want to transmit additional information when an event is raised, or getting information from subscribers : this can be done by datastreams. The format of such entities is also described in the XML file,before declaration of events.

[Top]

Declaring Data Streams

A data stream is a set of ordered attributes which will be filled before raising the event in the C++ code. The declaration consists in a Name, then a list of attributes determined by their name and type.

Example: If you define an event "MoveFile", raised in a method MoveFile (moving a file from one directory to another, you want to send also 3 data:

This can be done by declaring a stream MoveFileStream which contains 3 string arguments FileName,SourceDir,TargetDir to the event the 3 data : name of the file to be moved, source directory and target directory, and then referencing that stream in the "MoveFile" event declaration.

[Top]

Format of XML Event Files

An event declaration file generally has the following format:

<Package Name="...">
  <DataStream Name="...">
    <DataStreamArg Name="..."
                   Type="...">
    </DataStreamArg>....
  </DataStream>
  <Class Name="..."
         Type="...">
    <Event Name="..." ...>
      <DataStreamRef Name="..."     <!-- if a stream is associated with the event -->
                     Type="..."
      </DataStreamRef>
    </Event>
  </Class>
</Package>

[Top]

Meaning of Tags, Values, and Attribute Values

[Top]

The Callback Interface Definition.

Basic Principles

The subscription of a client is done by calling one of the dedicated methods of the event manager associated with each session. The mandatory argument in those methods is a pointer on an interface, implemented by the client object. When the event occurs, the system calls,for each client which subscribed to that event, the right method of the interface associated with that event (see 2.2).

The Two Kinds of Callback Interfaces

Two kinds of "callback" interfaces are available:

  1. The "generic" interface delivered in standard ENOVISubscriberEvent.
    Inside you will find two methods onReceive(..) and onKO(...).
    A client class may implement this interface only,and use it for all its subscriptions. Each time one of the event it was subscribed to occurs, it will be called back on the onReceive method. then, it will have to decode the arguments to know which event is being emitted.
  2. The explicit interfaces, created and delivered by the domains defining events. Here the callback methods are totally explicit:

    for an event which has been declared with two steps.

    So the client object which implements such an interface knows exactly for which event and at which step it is called.

    The domains design the grouping of their event callback methods. They can choose to group all the methods in one single interface, or create several interfaces with a small number of events concerned with each interface.

[Top]

Declaring a Callback Interface

The rules are the following:

Note: A client object will always be able to subscribe to the event by implementing the generic interface ENOVISubscriberEvent.>

[Top]

How the Events are Raised by the Publishing Objects

The emission of events is rather simple to do, and based on Macros delivered by the event model. in each cpp file where there are "event" methods, you must insert an include :
#include ENOVEventFireMacro.h

Then,in each method which has to raise an event , you insert the macro EVENT_FIRE(...) 2 times, one at the beginning of the method, the second one at the end of the method.By doing that, at run time, the event will be raised in its step before when entering the method, and the step after will be sent when exiting the method.

Example

Let's take a class SamplePublisher which has declared a new event SampleEvent.
This event is declared before/after and the associated callback interface is SampleInterface.

In the cpp code SamplePublisher.cpp, there will be a method SampleEvent. The code could as follows.
#include ENOVEventFireMacro.h
...
HRESULT SamplePublisher::SampleEvent(...)
{
  HRESULT rc=S_OK,oNotify=S_OK;
  ENOVIStream_var spClientStream=NULL_var;

  //event [before step]
  EVENT_FIRE(SamplePublisher,SampleEvent,IID_SampleInterface,Before,spClientStream,oNotify);
  // code of the method
  ...
  // event [after step]
  EVENT_FIRE(SamplePublisher,SampleEvent,IID_SampleInterface,After,oStream,oNotify);
  return rc;
}

The arguments of the macro are:

If the event is declared with a reference on a publisher data stream, this stream must be filled before the first macro EVENT_FIRE insertion.

To do that , use the DATA_EVENT_INIT macro, which gives back a smart pointer on ENOVIStream, already dimensioned according to the data stream definition in the XML declaration file. Then, the code fills the stream using the methods of the ENOVIStream interface. When the event is raised, the system automatically associates the stream and the event.

Example

Let's take the same example as above. The method has 3 string arguments iA iB iC, and a stream SamplePStream,declared with 3 string arguments "Arg1" "Arg2" "Arg3" was associated with event SampleEvent.

In the cpp code SamplePublisher.cpp, the code could be as follows.

#include ENOVEventFireMacro.h
...
HRESULT SamplePublisher::SampleEvent(const CATUnicodeString& iA,
                                     const CATUnicodeString& iB,
                                     const CATUnicodeString& iC)
{
  HRESULT rc=S_OK,oNotify=S_OK;
  ENOVIStream_var spPublihStream=NULL_var,spClientStream=NULL_var;

  // instantiation of a well dimensionned stream, according to
  // the declaration in XML event files...

  EVENT_DATA_INIT(SamplePSStream,spPublishStream);

  ...// checks the smart pointer...

  //fill the stream will the data
  sPublishStream->AddArgumentValue("Arg1",iA);
  sPublishStream->AddArgumentValue("Arg2",iB);
  sPublishStream->AddArgumentValue("Arg3",iC);

  //raise the event. The stream is automatically linked with the event
  EVENT_FIRE(SamplePublisher,SampleEvent,IID_SampleInterface,Before,spClientStream,oNotify);
  ...
}

[Top]


The two main ways to subscribe

The Event Model use cases accompanying this technical article illustrate the 2 different mechanisms for automatic subscription at the creation of an ENOVIA login session.

  1. The first way implies the implementation of ENOVIEventPlugin interface (see details in the corresponding use case documentation). The ENOVIA session automatically instantiates it and calls the unique method (Init) of ENOVIEventPlugin. In this method, a subscription to event CreateLoginSession step After is performed for a customer-provided listener class that implements ENOVISessionEvent. In the callback method onAfterCreateLoginSession of this listener class, the customer is finally free to subscribe to any event of interest.
  2. The second way implies the usage of a generic mechanism of the ENOVIA  session : each domain of ENOVIA (PRODUCT, ACTION, DOCDIR, ...) is associated with a late type INFO_<<NameOfDomain>>; when such a domain is loaded during the session initialization, the session asks if there is an extension of that late type which implements ENOVISessionEvent interface, let's call it the listener, and if so, makes this listener subscribe to event CreateLoginSession step After. Hence once the login session is created, the listener is called back and the customer is finally free to subscribe to any event of interest in method onAfterCreateLoginSession.
Method
Use case
1. CAAVpiAutomaticSubscription
1. CAAVpiAutomaticSubscription2
2. CAAVpiPackageSubscription

[Top]


In Short

In this article you have learned how the events are declared and raised, from the publisher point of view, and how it's able to subscribe to those events and be called back when an event occurs.

[Top]


History

Version: 1 [Oct 2001] Document created
[Top]

Copyright © 2001, Dassault Systèmes. All rights reserved.