6. Code Generation

This section describes how to use the Vortex OpenSplice Modeler for generating DDS-compliant source code. The DDS code generated by the Vortex OpenSplice Modeler removes the need for programmers to manually write the DDS components of their applications; the Modeler does it for them using an easy-to-use, Eclipse-based graphical interface.

caution

The OpenSplice HDE (version 6.1 or above) must be installed and configured in order to generate code for OpenSplice from Vortex OpenSplice Modeler.

Vortex Lite (version 1.2 or above) must be installed and configured in order to generate code targeting Vortex Lite from Vortex OpenSplice Modeler.

The principal purpose of the Vortex OpenSplice Modeler is to generate DDS-compliant source code. The Modeler achieves this aim and is able to generate:

  • code for DDS data types, including
    • IDL specifications for Vortex OpenSplice DDS Data Types
    • Native language interfaces for Vortex OpenSplice Data Types (via the Vortex OpenSplice IDL Pre-Processor)
    • Typed interface code
  • Native Language code, in Java or C++, for Applications

The Modeler can generate code either at the Module or Application level. If a Module is exported, then this simply exports all Applications within the Module. This will automatically generate the Vortex OpenSplice IDL and typed interfaces for any data types used by that Application when generating code for an Application.

Code generation can be set to target either of the following DDS Implementations:

  • Vortex OpenSplice
  • Vortex Lite.

6.1. Saving to Eclipse Projects

The code generated by the Modeler can be saved to either a Java or C++ Project within the user’s workspace.

java These folders are created in Java-based projects:

src - an empty folder where users can place their own source code

generated - contains the generated DDS type and application code

caution The generated folder and its contents must not be edited by users.

idl - contains generated IDL specification files

cpp These folders are created in C++-based projects:

src - an empty folder where users can place their own source code

generated - contains the generated DDS type and application code

caution The generated folder and its contents must not be edited by users.

idl - contains generated IDL specification files

windows

Additionally for Windows, the code generated by the Modeler can be saved to a Visual Studio Project [1] .

The folders created are exactly the same as described above. However, additional Visual Studio-specific files are created that allow the project to be imported into Visual Studio. These files are:

  • For Visual Studio 2005 and 2008:

    <project_name>.vcproj
    OBJS.mak
    Makefile
    Makefile.release
  • For Visual Studio 2013:

    <project_name>.vcxproj
    <project_name>.vcxproj.filters

6.2. Exporting Applications

An application can be exported by:

Step 1

Right-clicking on the Application in the Project Explorer OR the Diagram Editor.

Step 2

Choosing Generate Application Code.

All of the Applications within a module can be exported by:

Step 1

Right-clicking on the Module containing the Applications to be exported.

Step 2

Choosing Export Module. The Export Application dialog will be displayed (whether one or more applications are selected for code exportation).

Export Application dialog

Export Application dialog

Step 3

The Project Name text box contains the name of the export project. Accept the default name or enter a new project name.

Step 4

Select the desired DDS target platform from the Target DDS Implementation drop-down menu.

Step 5

Select the desired target language from the Target Language drop-down menu.

Step 6

In the Contents panel, choose to create a new project, to merge with an exisiting project, or to overwrite an existing project.

caution Note that a ‘merge’ will only overwrite the generated folder, whereas an ‘overwrite’ will overwrite the whole project.

Step 7

When creating a project with a new name you can save the project in a location of your choice. Do this by using the Browse button or by directly changing the fields in the Directory text box.

Step 8

Check the Generate main method check box to generate a class containing a main method for the chosen language.

Step 9

The Language Options expandable gives additional options for the project creation.

Step 10

The IDL Options expandable enables you to export additional IDL Types that have not been associated with any entities in the model. To do this you must:

  1. Expand IDL Options
  2. Click the Add button
  3. Choose the IDL Types to be exported (supported Types are Struct, Constant, and Enum) in the Selection dialog
  4. Click the OK button.

Step 11

Click the Finish button to accept the options and export the Application.

6.3. Java Code Generation

java

The conditions and details relating to the generation of the Java source code for each model component is described in this section.

All generated entities (except Partitions, Topics, ContentFilteredTopics and code generated by the Vortex OpenSplice IDL Pre-Processor) exist in a single Java class file. This class file has the same name as the Application that it represents, and it contains static wrapper classes for all of the DDS entities contained by that Application in the model.

The class hierarchy within an Application class file closely follows the hierarchy which appears in the model.

The following conditions apply for all generated entities:

  • All underlying DDS Entities (DomainParticipants, Publishers, Subscribers, DataReaders, DataWriters, Partitions, Topics) in an application can be obtained by using accessor methods on the relevant generated wrapper.
  • When the code for an Application component is generated, all DDS entities that are associated to or contained within it are created and configured, including DomainParticipants, Publishers, Subscribers, DataReaders, DataWriters and associated Topics.
  • Each generated entity is set to the QoS policy values of its associated QoSSet (from the model).
  • Default QoSSet policy values are also set on the relevant Entities.
  • A specific entity’s QoS policy values are set when the entity is started (when the start() method is invoked on the Application class).

6.3.1. Applications

An Application component contains the configured DDS entities that you wish to use in your own application code.

Code can only be generated for modeled DDS entities such as DomainParticipants, Publishers, Subscribers, Listeners, DataReaders, DataWriters, Partitions, Waitsets and Conditions if they are contained or connected to entities within the Application component.

Each Application is generated into its own Eclipse Java project, with both project name and Java class name reflecting the fully scoped name of the Application in the model.

Example 1

For example, an Application called MyApplication located in the com/prismtech module would result in a Java project called MyApplication. Within that project, located in the generated folder, there would be a source file called MyApplication.java under the com.prismtech package.

There are a number of generated artefacts in the Application class, itself:

  • static classes for all Listeners, Waitsets and Conditions associated with the Application and its contained Entities

  • static classes for all DomainParticipants contained by that Application (these classes, in turn, contain static classes for the entities that they contain - this is explained in subsequent sections)

  • a static WrapperException Wrapper class for error handling at runtime

  • a start() method for creating and initializing all Entities contained by the Application

    info Although Topics and ContentFilteredTopics are not directly contained within an Application, any DataReaders or DataWriters that use them will create them.

  • a stop() method for deleting all Entities contained by the Application

    • Listeners are explained under Listeners.
    • Waitsets and Conditions are explained under WaitSets.
    • The nested classes generated for DomainParticipants and their contained entities are explained under DomainParticipants.
    • The WrapperException class is described under Error Handling.

The start() and stop() methods are used to control Application lifecycle. The start() method will configure and start all contained Entities, whilst the stop() method will attempt to cleanly shutdown the Application and delete all Entities.

Example 2

The following code would be used to start an Application called com.prismtech.MyApplication:

com.prismtech.MyApplication.start ();

Alternatively, the MyApplication class can be imported using a Java import statement, simplifying the code:

MyApplication.start();

All DDS entities contained by the Application should be configured and ready to use after invoking the start() method. The QoS Policy values for these entities will be set, according to values of their QoS Sets, and any default QoS policy values will be set on the appropriate Entities.

6.3.2. DomainParticipants

DomainParticipants are generated as nested static classes contained directly by the generated Application class.

A DomainParticipant wrapper class contains:

  • a getDomainParticipant() method for access to the DDS Entity
  • static wrapper classes for all contained Publishers and Subscribers
  • typed attach() and detach() methods for any associated Listeners

The getDomainParticipant() method will return the underlying DDS DomainParticipant Entity. This method is statically invoked.

Example

Continuing with the com.prismtech.MyApplication Application class example from above, if this class contains a DomainParticipant called MyAppDP, then the code to access the DomainParticipant would be:

DDS.DomainParticipant participant =
   com.prismtech.MyApplication.MyAppDP.getDomainParticipant ();

caution The containing Application must have been started via its start() method, otherwise a null object reference will be returned.

The typed attach() and detach() listener methods are described under Listeners.

6.3.3. Publishers

Publishers are generated as nested static classes contained directly by a generated DomainParticipant class.

A Publisher wrapper class contains :

  • a getPublisher() method for gaining access to the DDS Entity
  • static wrapper classes for all contained DataWriters
  • typed attach() and detach() methods for any associated Listeners

The getPublisher() method will return the underlying DDS Publisher Entity. This method is statically invoked.

Example

Continuing with the com.prismtech.MyApplication Application class from above, if this class contains a DomainParticipant called MyAppDP, and a Publisher called MyPublisher, then the code to access the Publisher would be:

DDS.Publisher publisher =
  com.prismtech.MyApplication.MyAppDP.MyPublisher.getPublisher ();

caution The containing Application must have been started via its start() method, otherwise a null object reference will be returned.

6.3.4. Subscribers

Subscribers are generated as nested static classes contained directly by a generated DomainParticipant class.

A Subscriber wrapper class contains:

  • a getSubscriber() method for access to the DDS Entity
  • static wrapper classes for all contained DataReaders
  • typed attach() and detach() methods for any associated Listeners

The getSubscriber() method will return the underlying DDS Subscriber Entity. This method is statically invoked.

Example

Continuing with the com.prismtech.MyApplication Application class from above, if this class contained a DomainParticipant called MyAppDP, and a Subscriber called MySubscriber, then the code to access the Subscriber would be:

DDS.Subscriber subscriber =
   com.prismtech.MyApplication.MyAppDP.MySubscriber.
      getSubscriber ();

caution The containing Application must have been started via its start() method, otherwise a null object reference will be returned.

6.3.5. Data Readers

DataReaders are generated as nested static classes contained directly by a generated Subscriber class.

A DataReader wrapper class contains:

  • a getDataReader() method for access to the DDS Entity
  • typed attach() and detach() methods for any associated Listeners

The getDataReader() method will return the typed underlying DDS DataReader Entity. This method is statically invoked.

Example

Continuing with the com.prismtech.MyApplication Application class from above, if this class contained a DomainParticipant called MyAppDP, a Subscriber called MySubscriber, and a DataReader called MyReader, then the code to access the DataReader would be:

<typed DataReader class> reader =
   com.prismtech.MyApplication.MyAppDP.MySubscriber.
      MyReader.getDataReader ();

caution The containing Application must have been started via its start() method, otherwise a null object reference will be returned.

6.3.6. Data Writers

DataWriters are generated as nested static classes contained directly by a generated Publisher class.

A DataWriter wrapper class contains:

  • a getDataWriter() method for access to the DDS Entity
  • typed attach() and detach() methods for any associated Listeners

The getDataWriter() method will return the typed underlying DDS DataWriter Entity. This method is statically invoked.

Example

Continuing with the com.prismtech.MyApplication Application class from above, if this class contained a DomainParticipant called MyAppDP, a Subscriber called MySubscriber, and a DataWriter called MyWriter, then the code to access the DataWriter would be:

<typed DataWriter class> writer =
   com.prismtech.MyApplication.MyAppDP.MySubscriber.
      MyWriter.getDataWriter ();

caution The containing Application must have been started via its start() method, otherwise a null object reference will be returned.

6.3.7. Listeners

Listeners are generated as abstract nested static classes contained directly by the generated Application class. This class acts as a base class for the user’s Listener implementation.

The user must:

  • extend the generated Listener class and implement all abstract methods.
  • attach an instance of the class to the appropriate Entity via the typed ‘attach’ method on the wrapper class for that Entity.
  • detach the Listener if notifications are no longer required, via the typed ‘detach’ method on the wrapper class for that Entity.

Each Listener class contains:

  • abstract methods for each status condition in which an interest was expressed. Other communication status callback methods do nothing and are defined as ‘final’ so that they cannot be overridden.
  • a status mask indicating which statuses the Listener is interested in.

info For each generated Application that contained Entities with associated listeners, typed methods for attaching and detaching listeners will be generated on that Entity’s nested wrapper class.

The user must extend the generated Listener class, then instantiate the class within their own application code, and finally install the listener on the relevant entity via the appropriate typed attach() method.

Example

For a listener called Listener1, with an interest in the communication status on_data_available, the following base class would be generated:

public abstract class Listener1 implements DDS.DomainParticipantListener {
   public final int STATUS_MASK =
      DDS.DATA_AVAILABLE_STATUS.value;

   public final void on_data_on_readers(DDS.Subscriber subscriber) {
   }

   public final void on_offered_incompatible_qos(
      DDS.DataWriter dataWriter,
         DDS.OfferedIncompatibleQosStatus status) {
   }

   public abstract void on_data_available(DDS.DataReader dataReader);

   public final void on_requested_incompatible_qos(
      DDS.DataReader dataReader,
         DDS.RequestedIncompatibleQosStatus status) {
   }

   public final void on_subscription_match(
      DDS.DataReader dataReader,
         DDS.SubscriptionMatchStatus status) {
   }

   public final void on_requested_deadline_missed(
      DDS.DataReader dataReader,
         DDS.RequestedDeadlineMissedStatus status) {
   }

   public final void on_offered_deadline_missed(
      DDS.DataWriter dataWriter,
         DDS.OfferedDeadlineMissedStatus status) {
   }

   public final void on_sample_rejected(
      DDS.DataReader dataReader,
         DDS.SampleRejectedStatus status) {
   }

   public final void on_liveliness_lost(
      DDS.DataWriter dataWriter,
         DDS.LivelinessLostStatus status) {
   }

   public final void on_inconsistent_topic(
      DDS.Topic topic,
         DDS.InconsistentTopicStatus status) {
   }

   public final void on_publication_match(
      DDS.DataWriter dataWriter,
         DDS.PublicationMatchStatus status) {
   }

   public final void on_sample_lost(
      DDS.DataReader dataReader,
         DDS.SampleLostStatus status) {
   }

   public final void on_liveliness_changed(
      DDS.DataReader dataReader,
         DDS.LivelinessChangedStatus status) {
   }
}

The user should then extend this class and implement the on_data_available() method.

If the Listener is attached to the DomainParticipant MyParticipant in the model, then within the class, for the application containing MyParticipant, we would find a static wrapper class representing MyParticipant containing the methods :

public static int attach (Listener1 listener);

public static int detach (Listener1 listener);

The user would instantiate the class that they implemented before passing the object reference to the attach() method to connect the listener. The user would call the detach() method to disconnect the listener.

6.3.8. WaitSets

WaitSets are generated as nested static classes contained directly in the generated Application class.

A WaitSet wrapper class has:

  • a getWaitSet() method for access to the DDS Entity
  • a start() method which creates the WaitSet and attaches the appropriate Conditions
  • a stop() method which detaches the WaitSet’s Conditions and deletes the WaitSet itself

Example

Continuing with the com.prismtech.MyApplication Application class example from above, if this class contains a WaitSet called MyWaitSet, then the code to access the WaitSet would be:

DDS.WaitSet waitset =
   com.prismtech.MyApplication.MyWaitSet.getWaitSet();

caution The Application must be running before the WaitSet is started. Also, the WaitSet must be started using the start() method or a null object reference will be returned by the getWaitSet() method.

6.3.9. Conditions

All Conditions are generated as nested static classes contained directly in the generated Application class.

6.3.9.1. StatusCondition

A StatusCondition wrapper class has:

  • a start() method for accessing the DDS StatusCondition
  • a getStatusCondition() method for accessing the wrapped StatusCondition
  • a setDefaultStatusMask() method returns the value of the Status Mask to its original (modelled) state
  • a stop() method to set the StatusCondition back to null, allowing for a future garbage collection

Example

In DDS, each Entity owns exactly one StatusCondition. Therefore, a StatusCondition does not need to be created, but only retrieved through the Entity which it is associated within the model. (Note that the start() method does not start the statusCondition; it just gets a handle on the DDS entity.)

Continuing with the com.prismtech.MyApplication Application class example from above, if this class contains a StatusCondition called MySC, a DomainParticipant called MyAppDP and a Subscriber called MySubscriber which is associated with the MySC, then the code for accessing the StatusCondition would be:

DDS.StatusCondition statusCondition =
   com.prismtech.MyApplication.MySC.
      getStatusCondition();

6.3.9.2. ReadCondition

A ReadCondition wrapper class has:

  • a start() method for creating the DDS ReadCondition
  • a getReadCondition() method for accessing the wrapped ReadCondition
  • a stop() method for deleting the ReadCondition from its associated DataReader and setting the ReadCondition to null

Example

Continuing with the com.prismtech.MyApplication Application class example, if this class contained a DomainParticipant called MyAddDP, a Subscriber called MySubscriber, a WaitSet called MyWaitSet, and a ReadCondition called MyRC, then the code to access the ReadCondition would be:

DDS.ReadCondition readCondition =
   com.prismtech.MyApplication.MyRC.getReadCondition();

All ReadConditions are created lazily when the getReadCondition() method is called.

6.3.9.3. QueryCondition

A QueryCondition wrapper class has:

  • a start() method for creating the DDS QueryCondition
  • a getQueryCondition() method for accessing the wrapped QueryCondition
  • a stop() method for deleting the QueryCondition from its associated DataReader and setting the QueryCondition to null
  • a setQueryParameter() method for setting the parameters for the QueryExpression associated with the QueryCondition

Example

Continuing with the com.prismtech.MyApplication Application class example, if this class contained a DomainParticipant called MyAddDP, a Subscriber called MySubscriber, a WaitSet called MyWaitSet, and a QueryCondition called MyQC, then the code to access the QueryCondition would be:

DDS.QueryCondition queryCondition =
   com.prismtech.MyApplication.MyQC.getQueryCondition();

QueryConditions are created lazily when the getQueryCondition() method is called, like the ReadCondition.

caution The setQueryParameters() method must be called with the appropriate argument before the getQueryCondition() method is called, otherwise an exception is raised.

6.3.9.4. GuardCondition

A GuardCondition wrapper class contains:

  • a start() method for creating the DDS GuardCondition
  • a getGuardCondition() method that returns the wrapped GuardCondition
  • a stop() method that sets the value of the GuardCondition to null allowing a future garbage collection

Example

Continuing with the com.prismtech.MyApplication Application class example, if this class contained a WaitSet called MyWaitSet, and a GuardCondition called MyGC, then the code to access the GuardCondition would be:

DDS.GuardCondition guardCondition =
   com.prismtech.MyApplication.MyGC.getGuardCondition();

The GuardConditions are created lazily by the getGuardCondition() method.

6.3.10. Partitions

The Java code for the Modeler Partition component (in the model) is generated as an abstract class; this class can be used to get and set a name in the Partition QoS of connected Publishers and Subscribers.

The generated Partition class is assigned the name of the Partition used in the name model.

A class containing static methods to get and set the name of that Partition is generated for each Partition connected to a Publisher or Subscriber, as defined in the model. The methods listed below are defined in this class:

public static void setName (String partitionName) -
This method sets the Partition’s QoS for all registered DDS Publishers and Subscribers when it is invoked.
public static String getName () -
Return the current DDS name for this partition.

The Partition wrapper class also contains the following methods:

  • an addPublisher()/Subscriber() method that adds a publisher/subscriber to the list of publishers/subscribers connected to the partition.
  • a removePublisher()/Subscriber() method that removes a publisher/subscriber from the list of publishers/subscribers connected to the partition.

6.3.11. Error Handling

Exceptions are used to handle errors in the Wrappers. Most Entity Wrappers’ methods can throw a WrapperException.

A WrapperException is thrown when an error is encountered while performing a DDS API call or, less frequently, when an internal error in the Wrapper occurs.

An example of the first case is when a Wrapper must create a DomainParticipant but a call to create_participant fails.

An example of the second case is when the user starts a QueryCondition Wrapper but the QueryParameters have not been defined.

In all cases, WrapperException provides enough information to know where the errors occurred; for example, what was the error code returned by the DDS call.

The WrapperException class is generated as a direct nested class in generated Application and Topic wrapper classes.

6.4. C++ Code Generation

cpp

The C++ generated files are placed in a project’s generated folder. All modules, entities and other (scoped) items placed in this folder will correspond to a folder in the Project Manager tree.

info All entity names are postfixed by the word Wrapper in order to avoid conflicts between C++ name spaces and class names.

Three files are generated for each entity. Their filenames use a convention whereby they take the entity’s name and add it to a suffix associated with the file type. The generated files and their filename conventions are:

  • An abstract base class called Wrapper.h.

    An entity called Publisher1, for example, would produce Publisher1Wrapper.h. Publisher1Wrapper.h is the interface that the application developer should use.

  • A class header file called WrapperImplementation.h.

    Publisher1WrapperImplementation.h would be produced for a Publisher1 entity. This class implements the abstract base class and should not be used by application developers.

  • An implementation file called WrapperImplementation.cpp.

    Publisher1WrapperImplementation.cpp would be generated for a Publisher1 entity. This file contains the class method’s implementations.

The following conditions apply for all generated entities:

  • All underlying DDS Entities (DomainParticipants, Publishers, Subscribers, DataReaders, DataWriters, Partitions, Topics) in an application can be obtained by using accessor member functions on the relevant generated wrapper.
  • When the code for an Application component is generated, all DDS Entities that are associated to or contained within it are created and configured, including DomainParticipants, Publishers, Subscribers, DataReaders, DataWriters and associated Topics.
  • Each generated entity is set to the QoS policy values of its associated QoSSet (from the model). Default QoSSet policy values are also set on the relevant Entities.
  • A specific entity’s QoS policy values are set when the entity is started (in other words, when the start() member function is invoked on the Application class).
  • The default behaviour for error handling is to call the stop() member function and throw a WrapperException. The WrapperException is always generated within the application’s name space.

6.4.1. Applications

An Application component contains the configured DDS Entities that you wish to use in your application code.

Each application is generated into its own Eclipse C++, Visual Studio 2005, or Visual Studio 2008 project.

For example, an application called MyApplication located in the com/prismtech module would result in a source file called MyApplicationWrapper.h in the com::prismtech namespace.

The Application class contains several generated methods:

  • a get<entity_name>Wrapper() member function for all entities that are the application’s children, including partitions and topics
  • a start() member function which creates and initializes all Entities contained by the Application
  • a stop() member function which deletes all Entities contained by the Application

The start() and stop() methods are used to control the Application’s lifecycle. The start() member function configures and starts all contained Entities, whilst the stop() member function attempts to cleanly shut down the Application and delete all Entities.

Example

The following code starts an Application called com::prismtech::MyApplication:

com::prismtech::MyApplicationWrapper* myApp =
new com::prismtech::MyApplicationWrapperImplementation;
myApp->start();

info It is important to note that for all entities in the model, only the generated abstract base classes (*Wrapper.h) should be included in the business logic. The only exception is when the application wrapper has to be instantiated, then the application wrapper implementation header must be included. For example:

#include "com/prismtech/MyApplicationWrapperImplementation.h"
#include "com/prismtech/MyApplicationWrapper.h"

All DDS entities contained by the Application should be configured and ready to use after the start() member function is invoked. The QoS Policy values for these entities are set according to values of their QoS Sets. Any default QoS policy values will be set on the appropriate Entities.

6.4.2. DomainParticipants

DomainParticipants are generated in the <domainparticipant_name>Wrapper.h, <domainparticipant_name>WrapperImplementation.h and <domainparticipant_name>WrapperImplementation.cpp class files.

A DomainParticipant wrapper class contains:

  • a getDomainParticipant() member function for accessing the DDS Entity
  • a get<entity_name>Wrapper() member function for retrieving the DomainParticipant’s Publishers and Subscribers and their associated Topics
  • typed attach() and detach() member functions for attaching a Listener to and detaching it from the DDS Entity.

The getDomainParticipant() member function returns the underlying DDS DomainParticipant Entity.

The get<entity_name>Wrapper() member function returns the modeled entity’s wrappers, which are then used, in turn, to retrieve the underlying DDS Entity.

The attach() member function can either be used on the corresponding wrapper class or on the desired DDS entity directly.

Listeners are described in Listeners.

Example

Continuing with the com::prismtech::MyApplication Application class example from above, if the MyApplication model contains a DomainParticipant called MyDP, then the code to access the DomainParticipant would be:

DDS::DomainParticipant* domainparticipant =
   myApp->getMyDPWrapper()->getDomainParticipant();

caution The containing Application must have been started with its start() member function or a null pointer will be returned.

6.4.3. Publishers

Publishers are generated in the <publisher_name>Wrapper.h, <publisher_name>WrapperImplementation.h and <publisher_name>WrapperImplementation.cpp class files.

A Publisher wrapper class contains:

  • a getPublisher() member function for gaining access to the DDS Entity
  • a get<datawriter_name>Wrapper() member function for retrieving the data writer
  • typed attach() and detach() member functions for attaching a Listener to and detaching it from the DDS Entity.

The getPublisher() member function returns the underlying DDS Publisher Entity.

The get<entity_name>Wrapper() member function returns the modeled entity’s wrapper, which is used in turn to retrieve the underlying DDS Entity.

The attach() member function can either be used on the corresponding wrapper class or called on the desired DDS entity directly.

Listeners are described in Listeners.

Example

Continuing with the com::prismtech::MyApplication Application class example from above, if this class contains a DomainParticipant called MyDP and a Publisher called MyPublisher, then the code to access the Publisher is:

DDS::Publisher* publisher =
   myApp->getMyDPWrapper()->getMyPublisherWrapper()->
      getPublisher();

caution The containing Application must have been started with its start() member function or a null pointer will be returned.

6.4.4. Subscribers

Subscribers are generated in the <subscriber_name>Wrapper.h, <subscriber_name>WrapperImplementation.h and <subscriber_name>WrapperImplementation.cpp class files.

A Subscriber wrapper class contains:

  • a getSubscriber() member function for access to the DDS Entity
  • a get<reader_name>Wrapper() member function for retrieving the data reader
  • typed attach() and detach() member functions for attaching a Listener to and detaching it from the DDS Entity.

The getSubscriber() member function returns the underlying DDS Subscriber Entity.

get<entity_name>Wrapper() returns the modeled entity’s wrapper with which the underlying DDS Entity can be retrieved.

The attach() member function can either be used on the corresponding wrapper class, or called on the desired DDS entity directly.

Listeners are described in Listeners.

Example

Continuing with the com::prismtech::MyApplication Application class from above, if this class contains a DomainParticipant called MyDP, and a Subscriber called MySubscriber, then the code to access the Subscriber would be:

DDS::Subscriber* subscriber =
   myApp->getMyDPWrapper()->getMySubscriberWrapper()->
      getSubscriber();

caution The containing Application must have been started with its start() member function or a null pointer will be returned.

6.4.5. Data Readers

DataReaders are generated in the <reader_name>Wrapper.h, <reader_name>WrapperImplementation.h and <reader_name>WrapperImplementation.cpp class files.

A DataReader wrapper class contains:

  • a getDataReader() member function for access to the DDS Entity
  • typed attach() and detach() member functions for attaching a Listener to and detaching it from the DDS Entity.

The getDataReader() member function returns the typed underlying DDS DataReader Entity.

The attach() member function can either be used on the corresponding wrapper class or called on the desired DDS entity directly.

Listeners are described in Listeners.

Example

Continuing with the com::prismtech::MyApplication Application class from above, if this class contains a DomainParticipant called MyDP, a Subscriber called MySubscriber, and a DataReader called MyReader, then the code to access the DataReader would be:

DDS::DataReader* reader =
   myApp->getMyDPWrapper()->getMySubscriberWrapper()->
      getMyReaderWrapper()->getDataReader();

caution The containing Application must have been started with its start() member function or a null pointer will be returned.

6.4.6. Data Writers

DataWriters are generated in the <writer_name>Wrapper.h, <writer_name>WrapperImplementation.h and <writer_name>WrapperImplementation.cpp class files.

A DataWriterswrapper class contains:

  • a getDataWriter() member function for access to the DDS Entity
  • typed attach() and detach() member functions for attaching a Listener to and detaching it from the DDS Entity.

The getDataWriter() member function returns the typed underlying DDS DataWriters Entity.

The attach() member function can either be used on the corresponding wrapper class or called on the desired DDS entity directly.

Listeners are described in Listeners.

Example

Continuing with the com::prismtech::MyApplication Application class from above, if this class contains a DomainParticipant called MyDP, a Publisher called MyPublisher and a DataWriter called MyWriter, then the code to access the DataWriter would be:

DDS::DataWriter* writer =
   myApp->getMyDPWrapper()->getMyPublisherWrapper()->
      getMyWriterWrapper()->getDataWriter();

caution The containing Application must have been started with its start() member function or a null pointer will be returned.

6.4.7. Listeners

Each listener that is defined in the model has a file, <listener name>.h [2] , generated for it which acts as a base class for the user’s listener implementation. This class must be subclassed.

The generated class subclasses the corresponding entity listener from the OMG DDS DCPS API for the DDS entity that the listener is connected to in the model.

Function declarations are inserted as comments for all the enabled listener functions. These serve as an easy reference for what users must provide in their implementation.

The generated listener class also contains the status mask (as defined in the model). The value is accessible through the getStatusMask() member function.

A dummy implementation is inserted for all disabled listener member functions so these functions do not need to be present in the user’s listener implementations.

These listeners can be used by either invoking the attach() member function on the corresponding wrapper class or directly on the desired DDS entity.

When the listener must be attached to the DDS entity at its creation time, then the wrapper’s attach() member function should be used. In this case, it must be called before invoking start(), so as to be aware of all triggered events.

info Please note that when calling attach() on the wrapper class, the listener will be duplicated and held in a _var auto pointer. Once the user’s code is not interested any more in receiving notifications through a listener, detach() should be called.

Example

For a listener called Listener1, with an interest in the communication status on_data_available, the following base class will be generated:

#ifndef _MODULE1_APPLICATION1_LISTENER1_H_
#define _MODULE1_APPLICATION1_LISTENER1_H_

#include <ccpp_dds_dcps.h>

namespace Module1
{
namespace Application1
{


class Listener1  : virtual public DDS::DataReaderListener
{
public:
    Listener1() :
        m_statusMask(0 | DDS::DATA_AVAILABLE_STATUS)
    {
    }

    int getStatusMask() const
    {
        return m_statusMask;
    }

    DDS::Boolean _local_is_a (const char * repositryID)
    {
        return false  || DDS::DataReaderListener::_local_is_a (repositryID);
    }

    // DO NOT OVERRIDE THIS METHOD
   // It is disabled in the status mask
    void on_sample_rejected (DDS::DataReader_ptr dataReader,
         const DDS::SampleRejectedStatus& status)
    {
    }

    // Implement this method, it's enabled in the status mask
    // void on_data_available (DDS::DataReader_ptr dataReader)

    // DO NOT OVERRIDE THIS METHOD
   // It is disabled in the status mask
    void on_subscription_matched (DDS::DataReader_ptr dataReader,
          const DDS::SubscriptionMatchedStatus& status)
    {
    }

    // DO NOT OVERRIDE THIS METHOD
   // It is disabled in the status mask
    void on_requested_incompatible_qos (
         DDS::DataReader_ptr dataReader,
         const DDS::RequestedIncompatibleQosStatus& status)
    {
    }

    // DO NOT OVERRIDE THIS METHOD
   // It is disabled in the status mask
    void on_sample_lost (DDS::DataReader_ptr dataReader,
         const DDS::SampleLostStatus& status)
    {
    }

    // DO NOT OVERRIDE THIS METHOD
   // It is disabled in the status mask
    void on_liveliness_changed (DDS::DataReader_ptr dataReader,
         const DDS::LivelinessChangedStatus& status)
    {
    }

    // DO NOT OVERRIDE THIS METHOD
   // It is disabled in the status mask
    void on_requested_deadline_missed(DDS::DataReader_ptr dataReader,
         const DDS::RequestedDeadlineMissedStatus& status)
    {
    }

private:
    const DDS::StatusMask m_statusMask;
};

};
};

#endif
// _MODULE1_APPLICATION1_LISTENER1_H_

The user should now inherit from this class and implement the on_data_available() method.

If the Listener is attached to the DomainParticipant Participant1 in the model, then within the generated wrapper implementation class, for Participant1, we would find a method:

virtual void attach(Module1::Application1::Listener1* listener) = 0;

The user would call the detach() member function to disconnect the listener.

6.4.8. WaitSets

Waitsets are generated in the <waitset_name>Wrapper.h, <waitset_name>WrapperImplementation.h and <waitset_name>WrapperImplementation.cpp class files.

A WaitSet wrapper class has:

  • a getWaitSet() member function for accessing the DDS Entity
  • a start() member function which creates the WaitSet and attaches the appropriate Conditions
  • a stop() member function which detaches the WaitSet’s Conditions and deletes the WaitSet itself

Example

Continuing the com::prismtech::MyApplication Application class example from above, if this class contains a WaitSet called MyWaitSet, then the code to access the WaitSet would be:

DDS::WaitSet* waitset =
   myApp->getMyWaitSetWrapper()->getWaitSet();

6.4.9. Conditions

All Conditions are generated in the <condition_name>Wrapper.h, <condition_name>WrapperImplementation.h and <condition_name>WrapperImplementation.cpp class files.

caution It is important to note that before accessing the DDS Condition with the getCondition() member function, the condition wrapper must have been started with start(). If the condition is attached to a WaitSets, it will be started upon the start of the WaitSet.

6.4.9.1. StatusCondition

A StatusCondition wrapper class has:

  • a getCondition() member function for accessing the DDS StatusCondition
  • a getStatusMask() member function which returns the value of the Status Mask
  • a start() member function which creates the Condition
  • a stop() member function which detaches the Condition

Example

Each Entity owns exactly one StatusCondition in DDS. Therefore, a StatusCondition does not need to be created, but only retrieved through the Entity which it is associated with, within the model.

Continuing the com::prismtech::MyApplication Application class example from above, if this class contains a StatusCondition called MySC then the code for accessing the StatusCondtion would be:

DDS::StatusCondition* statusCondition =
   myApp->getMySCWrapper()->getCondition();

6.4.9.2. ReadCondition

A ReadCondition wrapper class has:

  • a getCondition() member function for accessing the DDS ReadCondition
  • a getInstanceStateMask() member function for accessing the instance state mask
  • a getSampleStateMask() member function for accessing the sample state mask
  • a getViewStateMask() member function for accessing the view state mask
  • a start() member function for attaching the ReadCondition to its associated DataReader
  • a stop() member function for deleting the ReadCondition from its associated DataReader

Example

Continuing the com::prismtech::MyApplication Application class example from above, if the MyApplication model has a ReadCondition called MyRC, then the code to access the ReadCondition would be:

DDS::ReadCondition* readCondition =
   myApp->getMyRCWrapper()->getCondition();

6.4.9.3. QueryCondition

A QueryCondition wrapper class has:

  • a getCondition() member function for accessing the DDS ReadCondition
  • a getInstanceStateMask() member function for accessing the instance state mask
  • a getSampleStateMask() member function for accessing the sample state mask
  • a getViewStateMaks() member function for accessing the view state mask
  • a start() member function for attaching the ReadCondition to its associated DataReader
  • a stop() member function for deleting the ReadCondition from its associated DataReader
  • a setQueryParameters() member function for setting the parameters for the QueryExpression associated with the QueryCondition

Example

Continuing the com::prismtech::MyApplication Application class example from above, if the MyApplication model contains a QueryCondition called MyQC, then the code to access the QueryCondition would be:

DDS::QueryCondition* queryCondition =
   myApp->getMyQCWrapper()->getCondition();

caution The setQueryParameters() member function must be called with the appropriate argument before the getCondition() member function is called or an exception will be raised.

6.4.9.4. GuardCondition

A GuardCondition wrapper class contains:

  • a getCondition() member function that returns the DDS GuardCondition
  • a start() member function for creating the GuardCondition
  • a stop() member function that sets the value of the GuardCondition to 0

Example

Continuing the com::prismtech::MyApplication Application class example, if the MyApplication model contains a GuardCondition called MyGC, then the code to access the GuardCondition would be:

DDS::GuardCondition* guardCondition =
   myApp->getMyGCWrapper()->getCondition();

6.4.10. Partitions

The C++ code for the Modeler Partition component (in the model) is generated in the Wrapper.h, WrapperImplementation.h and WrapperImplementation.cpp class files.

The generated code can be used to get and set the names of connected Publishers and Subscribers in the Partition QoS.

The generated Partition class is assigned the same name as the name of the Partition in the model.

This class defines the following methods:

  • a getName() member function which retrieves the partition name
  • a setName() member function which sets the partition name
  • an addPublisher()/Subscriber() member function that adds a publisher/subscriber to the list of publishers/subscribers connected to the partition
  • a removePublisher()/Subscriber() member function that removes a publisher/subscriber from the list of publishers/subscribers connected to the partition

Footnotes

[1]Refer to the Modeler Release Notes for the Visual Studio supported versions.
[2]Where <listener name> is the name of the listener.