3. Proto message for a DDS system — OpenSplice GPB Tutorial

### Navigation

- index
- next |
- previous |
- OpenSplice GPB Tutorial »

# 3. Proto message for a DDS system

Individual declarations in a `.proto` file can be annotated with a number of options. Options do not change the overall meaning of a declaration, but may affect the way it is handled in a particular context.

Options can be defined at different levels:

> - File-level options: meaning they should be written at the top-level scope, not inside any message, enum, or service definition.
> - Message-level options: meaning they should be written inside message definitions.
> - Field-level options: meaning they should be written inside field definitions. Enum types, enum values, service types, and service methods.

## 3.1. Use case: Person

In this use case example, a system capable of describing the personal data of persons must be built using the GPB data-model

The layout can be:

    string name
    integer age
    sequence phone-number + type
    sequence friends

## 3.2. Proto file for the Person example

This use case is described in this `.proto` file:

    import "omg/dds/descriptor.proto";
    package address;

    message Person {
       required string name = 1;
       required int32 age = 2;
       optional string email = 3;

       enum PhoneType {
          UNDEFINED = 0;
          MOBILE    = 1;
          HOME      = 2;
          WORK      = 3;
       }

       message PhoneNumber {
          required string number = 1;
          optional PhoneType type  = 2 [default = HOME];
       }

    repeated PhoneNumber phone = 4;
    repeated Person friend = 5;
    }

GPB labels every field as either a required or an optional field. Required fields are always used/filled; optional fields may or may not be.

Different data models are compatible if all required fields are the same. Data models can be extended with extra fields; if those new fields are all optional, then the new model will still be compatible with older applications using the old data model.

In our example the name and age are always required. The email string is optional, as extra information for this person. The sequences with phone numbers and friends are allowed to be empty.

Detailed explanation for the layout of a `.proto` file can be found in the Google Protocol buffer documentation on https://developers.google.com/protocol-buffers/docs/proto

## 3.3. Annotating a proto message for use as a type in DDS

For the GPB message to be able to be handled correctly in a DDS system, some options are needed in the `.proto` file which define how the GPB message shall behave in the DDS system.

At the message level there is an extra option `.omg.dds.type`. This tells the protocol buffer compiler that this message is also a dds type message. This type option has a optional extra parameter for giving this type a dds type name. By default it has the same name in the DDS domain as it has in GPB.

The Person example with this option:

    import "omg/dds/descriptor.proto";

    package address;

    message Person {
     option (.omg.dds.type) = {};
     required string name = 1;
     required int32 age = 2;

    enum PhoneType {
      UNDEFINED = 0;
      MOBILE    = 1;
      HOME      = 2;
      WORK      = 3;
    }

    message PhoneNumber {
       required string number = 1;
      optional PhoneType type  = 2 [default = HOME];
     }
     repeated PhoneNumber phone = 4;
     repeated Person friend = 5;
    }

### 3.3.1. Proto file with omg.dds.member.key option

For support of a key value in the datamodel, the option `key` can be given as a field-member option. One or more fields containing this option will indicate that these members make a unique key identifier in the data model. A field indicated as a key field must always be a required field for GPB. Also a key field is automatically a filterable field, as described below.

The Person example with name as a unique key (this means that each unique value of the name will lead to a separate instance in DDS with its own history):

    import "omg/dds/descriptor.proto";

    package address;

    message Person {
       option (.omg.dds.type) = {};
       required string name = 1 [(.omg.dds.member).key = true];
       required int32 age = 2;
       optional string email = 3;
    }
    enum PhoneType {
       UNDEFINED = 0;
       MOBILE = 1;
       HOME = 2;
       WORK = 3;
    }
    message PhoneNumber {
       required string number = 1;
       optional PhoneType type = 2 [default = HOME];
    }

    repeated PhoneNumber phone = 4;
    repeated Person friend = 5;

### 3.3.2. Proto file with omg.dds.member.filterable option

For support of filterable fields in the datamodel, the option `filterable` can be given as a field-member option.

One or more fields with this option indicates that these members are available for dynamic querying and filtering by means of a `QueryCondition` or `ContentFilteredTopic` in DDS.

A field marked as a filterable field must always be a required field in GPB. A key field is always filterable, by definition.

The Person example with age as a filterable attribute:

    import "omg/dds/descriptor.proto";

    package address;

    message Person {
     option (.omg.dds.type) = {};
     required string name = 1 [(.omg.dds.member).key = true];
     required int32 age = 2 [(.omg.dds.member).filterable = true];
     optional string email = 3;

    enum PhoneType {
      UNDEFINED = 0;
      MOBILE    = 1;
      HOME      = 2;
      WORK      = 3;
    }

    message PhoneNumber {
       required string number = 1;
      optional PhoneType type  = 2 [default = HOME];
     }
     repeated PhoneNumber phone = 4;
     repeated Person friend = 5;
    }

### 3.3.3. Proto file with omg.dds.member.name option

The previous examples will result in a DDS type with the directly-mapped fields in IDL with the same name as in proto. (Key fields and filterable fields are directly mapped.)

If a different name is needed in the DDS domain for a fieldname in the generated IDL and dds type, a name can be given as an `omg.dds.member` option.

Example where the age field will be named `AgeInYears` in the DDS domain:

    import "omg/dds/descriptor.proto";

    package address;

    message Person {
     option (.omg.dds.type) = {};
     required string name = 1 [(.omg.dds.member).key = true];
     required int32 age = 2   [(.omg.dds.member) = { name: "AgeInYears" filterable: true }];
     optional string email = 3 ;

    enum PhoneType {
      UNDEFINED = 0;
      MOBILE    = 1;
      HOME      = 2;
      WORK      = 3;
    }

    message PhoneNumber {
       required string number = 1;
      optional PhoneType type  = 2 [default = HOME];
     }
     repeated PhoneNumber phone = 4;
     repeated Person friend = 5;
    }

### Navigation

- index
- next |
- previous |
- OpenSplice GPB Tutorial »