Object configuration

Objects are configured using inputs from a (tree) database. The access to this database is abstracted by the StructuredDataI interface.

The StructuredDataI offers methods to navigate the tree, create new nodes and read/write values from/to the tree leafs. Note that the StructuredDataI does not prescribe the configuration language of the database implementation (which can be e.g. XML, JSON, …).

Using the Object Initialise method the class implementation is expected to query the database, verify the values and assign them to its members.

...
virtual bool Initialise(MARTe::StructuredDataI &data) {
   bool ok = Object::Initialise(data);
   if (ok) {
       ok = data.Read("Gain1", gain1);
...

The ConfigurationDatabase offers a read/write implementation of the StructuredDataI and is used internally in the core of the framework.

...
ConfigurationDatabase cdb;
cdb.Write("Gain1", 2);
...

Reading values

The StructuredDataI::Read method accepts an AnyType and will automatically convert the value stored in the database into the target type (i.e. the type of the variable passed in the Read).

The return value should always be checked. It will fail if the type cannot be converted or if the variable does not exist in the database.

To read multi-dimensional values, the memory must be allocated beforehand. As a consequence, the type and dimension of the variable to be read must be known. This is achieved by querying the type StructuredDataI::GetType("NAME_OF_THE_LEAF_TO_QUERY");.

...
AnyType arrayDescription = data.GetType("Modes");
ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
//The leaf exists
if (ok) {
   numberOfElements = arrayDescription.GetNumberOfElements(0u);
   ...
if (ok) {
   ...
   modesArray = new StreamString[numberOfElements];
   Vector<StreamString> readVector(modesArray, numberOfElements);
   ok = data.Read("Modes", readVector);
   ...

Warning

The StructuredDataI::GetType method does not return any memory/value and shall only be used to query information about the type.

For matrices a similar strategy applies:

...
AnyType arrayDescription = data.GetType("Model");
ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
...
if (ok) {
   numberOfDimensions = arrayDescription.GetNumberOfDimensions();
   ok = (numberOfDimensions == 2u);
   ...
   numberOfRows = arrayDescription.GetNumberOfElements(1u);
   numberOfCols = arrayDescription.GetNumberOfElements(0u);
...
if (ok) {
   Matrix<float32> modelMatrix(numberOfRows, numberOfCols);
   ok = data.Read("Model", modelMatrix);
   ...

Reading values with the StructuredDataIHelper

As of v1.7.0 of MARTe2, the StructuredDataIHelper facilitates the reading and validation of configuration values. In particular, it allows to:

  • Read arrays and matrices without having to query for their size:

virtual bool Initialise(MARTe::StructuredDataI &data) {
    bool ok = Object::Initialise(data);
    StructuredDataIHelper helper(data, this);
    ...
    MARTe::int32 *referencesArray;
    if (ok) {
        uint32 nOfReferences = 0u;
        ok = helper.ReadArray("References", referencesArray, nOfReferences);
    }
    ...
    MARTe::float32 **model;
    if (ok) {
        uint32 modelCols = 0u;
        ok = helper.ReadMatrix("Model", model, modelRows, modelCols);
    }
    ...
  • Automatically assign default values for parameters that are not defined:

virtual bool Initialise(MARTe::StructuredDataI &data) {
    bool ok = Object::Initialise(data);
    StructuredDataIHelper helper(data, this);
    ...
    //Assign default of 1.7 to gain2
    ok = helper.Read("Gain2", gain2, 1.7);
    ...
  • Read “enum-like” types:

virtual bool Initialise(MARTe::StructuredDataI &data) {
    bool ok = Object::Initialise(data);
    StructuredDataIHelper helper(data, this);
    ...
    const char8 * controllerTypesStr[] = {"C1", "C2", "C3"};
    uint32 controllerTypes[] = {1, 2, 3};
    ok = helper.ReadEnum("ControllerType", controllerType, controllerTypesStr, controllerTypes);
    ...
  • Validate parameters against simple mathematical expressions:

virtual bool Initialise(MARTe::StructuredDataI &data) {
    bool ok = Object::Initialise(data);
    StructuredDataIHelper helper(data, this);
    ...

    if (ok) {
        ok = helper.ReadValidated("Gain3", gain3, "(Gain3 > (float32)(-3.0)) && (Gain3 <= (float32)(0.0))");
    }

Examples

The following example shows how to read parameters (including arrays and matrices).

Object configuration example (ConfigurationExample1)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/**
 * @file ConfigurationExample1.cpp
 * @brief Source file for class ConfigurationExample1
 * @date 14/03/2018
 * @author Andre' Neto
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing, 
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.

 * @details This source file contains the definition of all the methods for
 * the class ConfigurationExample1 (public, protected, and private). Be aware that some
 * methods, such as those inline could be defined on the header file, instead.
 */

#define DLL_API

/*---------------------------------------------------------------------------*/
/*                         Standard header includes                          */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                         Project header includes                           */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "ClassRegistryDatabase.h"
#include "ConfigurationDatabase.h"
#include "ErrorLoggerExample.h"
#include "Matrix.h"
#include "Object.h"
#include "Reference.h"
#include "ReferenceT.h"
#include "StreamString.h"
#include "Vector.h"

/*---------------------------------------------------------------------------*/
/*                           Static definitions                              */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                           Method definitions                              */
/*---------------------------------------------------------------------------*/
namespace MARTe2Tutorial {
/**
 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
 */
class ControllerEx1: public MARTe::Object {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief NOOP.
     */
    ControllerEx1 () {
        gain1 = 0u;
        gain2 = 0.f;
        mode = "";
        referencesArray = NULL;
        modesArray = NULL;
    }

    virtual ~ControllerEx1 () {
        using namespace MARTe;
        if (referencesArray != NULL) {
            delete [] referencesArray;
        }
        if (modesArray != NULL) {
            delete [] modesArray;
        }
        if (GetName() != NULL) {
            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references pointing at %s [%s]. "
                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
        }
    }

    /**
     * Read all the properties
     */
    virtual bool Initialise(MARTe::StructuredDataI &data) {
        using namespace MARTe;
        bool ok = Object::Initialise(data);
        if (ok) {
            ok = data.Read("Gain1", gain1);
            if (ok) {
                REPORT_ERROR(ErrorManagement::Information, "gain1 set to %d", gain1);
            }
            else {
                REPORT_ERROR(ErrorManagement::ParametersError, "The Gain1 property shall be set");
            }
        }
        if (ok) {
            ok = data.Read("Gain2", gain2);
            if (ok) {
                REPORT_ERROR(ErrorManagement::Information, "gain2 set to %f", gain2);
            }
            else {
                REPORT_ERROR(ErrorManagement::ParametersError, "The Gain2 property shall be set");
            }
        }

        if (ok) {
            mode = "";
            ok = data.Read("Mode", mode);
            if (ok) {
                REPORT_ERROR(ErrorManagement::Information, "mode set to %s", mode.Buffer());
            }
            else {
                REPORT_ERROR(ErrorManagement::ParametersError, "The Mode property shall be set");
            }
        }

        if (ok) {
            AnyType arrayDescription = data.GetType("References");
            ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
            uint32 numberOfElements = 0u;
            if (ok) {
                numberOfElements = arrayDescription.GetNumberOfElements(0u);
                ok = (numberOfElements > 0u);
                if (!ok) {
                    REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array");
                }
            }
            if (ok) {
                //Reconfiguration...
                if (referencesArray != NULL) {
                    delete [] referencesArray;
                }
                referencesArray = new int32[numberOfElements];
                Vector<int32> readVector(referencesArray, numberOfElements);
                ok = data.Read("References", readVector);
                if (ok) {
                    REPORT_ERROR(ErrorManagement::Information, "referencesArray set to %d", readVector);
                }
                else {
                    REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the References");
                }
            }
        }

        if (ok) {
            AnyType arrayDescription = data.GetType("Modes");
            ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
            uint32 numberOfElements = 0u;
            if (ok) {
                numberOfElements = arrayDescription.GetNumberOfElements(0u);
                ok = (numberOfElements > 0u);
                if (!ok) {
                    REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array");
                }
            }
            if (ok) {
                //Reconfiguration...
                if (modesArray != NULL) {
                    delete [] modesArray;
                }
                modesArray = new StreamString[numberOfElements];
                Vector<StreamString> readVector(modesArray, numberOfElements);
                ok = data.Read("Modes", readVector);
                if (ok) {
                    uint32 i;
                    for (i=0u; i<numberOfElements; i++) {
                        REPORT_ERROR(ErrorManagement::Information, "modesArray[%d] set to %s", i,readVector[i].Buffer());
                    }
                }
                else {
                    REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Modes");
                }
            }
        }

        if (ok) {
            AnyType arrayDescription = data.GetType("Model");
            ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
            uint32 numberOfDimensions = 0u;
            if (ok) {
                numberOfDimensions = arrayDescription.GetNumberOfDimensions();
                ok = (numberOfDimensions == 2u);
                if (!ok) {
                    REPORT_ERROR(ErrorManagement::ParametersError, "Model is not a Matrix");
                }
            }
            uint32 numberOfRows = 0u;
            uint32 numberOfCols = 0u;
            if (ok) {
                numberOfRows = arrayDescription.GetNumberOfElements(1u);
                numberOfCols = arrayDescription.GetNumberOfElements(0u);
                ok = (numberOfRows > 0u);
                if (!ok) {
                    REPORT_ERROR(ErrorManagement::ParametersError, "No rows defined in the matrix");
                }
            }
            if (ok) {
                ok = (numberOfCols > 0u);
                if (!ok) {
                    REPORT_ERROR(ErrorManagement::ParametersError, "No columns defined in the matrix");
                }
            }
            if (ok) {
                Matrix<float32> modelMatrix(numberOfRows, numberOfCols);
                ok = data.Read("Model", modelMatrix);
                if (ok) {
                    REPORT_ERROR(ErrorManagement::Information, "modelMatrix set to %f", modelMatrix);
                }
                else {
                    REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the References");
                }
            }
        }

        return ok;
    }

    /**
     * A list of properties.
     */
    MARTe::uint32 gain1;
    MARTe::float32 gain2;
    MARTe::StreamString mode;
    MARTe::int32 *referencesArray;
    MARTe::StreamString *modesArray;
};

CLASS_REGISTER(ControllerEx1, "")

}

int main(int argc, char **argv) {
    using namespace MARTe;
    using namespace MARTe2Tutorial;
    SetErrorProcessFunction(&ErrorProcessExampleFunction);

    CCString className1 = "ControllerEx1";

    int32 int32Arr[] = { -1, 2, -3, 4, -5 };
    const char8 *stringArr[] = { "A", "BB", "CCC", "DDDD", "EEEEE" };
    float32 float32Mat[3][2] = { { -1.0, 2.3 }, { 4.7, -3.2 }, { -7.1, 5.6 } };

    ReferenceT<ControllerEx1> ref1(className1,
            GlobalObjectsDatabase::Instance()->GetStandardHeap());
    //Automatically generate a new object instance based on the class name and on the correct Heap
    //and with the template reference.
    if (ref1.IsValid()) {
        ref1->SetName("ControllerInstance1");
        REPORT_ERROR_STATIC(ErrorManagement::Information,
                "Successfully created an instance of %s", className1.GetList());
        //Write a valid configuration.
        {
            ConfigurationDatabase cdb;
            cdb.Write("Gain1", 2);
            cdb.Write("Gain2", 1.5);
            cdb.Write("Mode", "ASTRING");
            cdb.Write("Modes", stringArr);
            cdb.Write("References", int32Arr);
            cdb.Write("Model", float32Mat);

            if (ref1->Initialise(cdb)) {
                REPORT_ERROR_STATIC(ErrorManagement::Information,
                        "Successfully configured instance of %s",
                        ref1->GetName());
            } else {
                REPORT_ERROR_STATIC(ErrorManagement::FatalError,
                        "Failed to configure instance of %s", ref1->GetName());
            }
        }
        //Write an invalid configuration
        {
            ConfigurationDatabase cdb;
            cdb.Write("Gain1", 2);
            cdb.Write("Gain2", 1.5);
            cdb.Write("Mode", "ASTRING");
            cdb.Write("Modes", stringArr);
            cdb.Write("References", int32Arr);
            cdb.Write("Model", int32Arr);
            if (!ref1->Initialise(cdb)) {
                REPORT_ERROR_STATIC(ErrorManagement::Information,
                        "As expected failed to reconfigure instance of %s",
                        ref1->GetName());
            }
        }
    }

    return 0;
}

This is a similar example, highlighting structured configurations.

Object configuration example (ConfigurationExample2)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
/**
 * @file ConfigurationExample2.cpp
 * @brief Source file for class ConfigurationExample2
 * @date 14/03/2018
 * @author Andre' Neto
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing, 
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.

 * @details This source file contains the definition of all the methods for
 * the class ConfigurationExample2 (public, protected, and private). Be aware that some
 * methods, such as those inline could be defined on the header file, instead.
 */

#define DLL_API

/*---------------------------------------------------------------------------*/
/*                         Standard header includes                          */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                         Project header includes                           */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "ClassRegistryDatabase.h"
#include "ConfigurationDatabase.h"
#include "ErrorLoggerExample.h"
#include "Object.h"
#include "Reference.h"
#include "ReferenceT.h"
#include "StreamString.h"
#include "Vector.h"

/*---------------------------------------------------------------------------*/
/*                           Static definitions                              */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                           Method definitions                              */
/*---------------------------------------------------------------------------*/
namespace MARTe2Tutorial {

/**
 * Configuration structures
 */
struct Gains {
    MARTe::float32 gain1;
    MARTe::float32 gain2;
};

struct Waveforms {
    MARTe::float32 *times;
    MARTe::float32 *values;
};

/**
 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
 */
class ControllerEx1: public MARTe::Object {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief NOOP.
     */
ControllerEx1   () {
        slowWaveform.times = NULL;
        slowWaveform.values = NULL;
        fastWaveform.times = NULL;
        fastWaveform.values = NULL;

    }

    virtual ~ControllerEx1 () {
        if (slowWaveform.times != NULL) {
            delete [] slowWaveform.times;
        }
        if (slowWaveform.values != NULL) {
            delete [] slowWaveform.values;
        }
        if (fastWaveform.times != NULL) {
            delete [] fastWaveform.times;
        }
        if (fastWaveform.values != NULL) {
            delete [] fastWaveform.values;
        }
        if (GetName() != NULL) {
            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at "
                    "%s [%s]. The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
        }
    }

    /**
     * Read all the properties which are organised inside a tree
     * Gains = {
     *     Low = {
     *         Gain1 = -1.0;
     *         Gain2 = -3.0;
     *     }
     *     High = {
     *         Gain1 = 7.0;
     *         Gain2 = 9.0;
     *     }
     * }
     * References = {
     *     Slow = {
     *         Waveform = {
     *             Times  = {0 0.1 0.2 1}
     *             Values = {1 2   3   4}
     *         }
     *     }
     *     Fast = {
     *         Waveform = {
     *             Times  = {0 0.1 0.2 1}
     *             Values = {1 2   3   4}
     *         }
     *     }
     * }
     */
    virtual bool Initialise(MARTe::StructuredDataI &data) {
        using namespace MARTe;
        bool ok = Object::Initialise(data);
        if (ok) {
            //Move in the tree
            ok = data.MoveRelative("Gains");
            if (!ok) {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains section");
            }
        }
        if (ok) {
            ok = data.MoveRelative("Low");
            if (!ok) {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains.Low section");
            }
        }
        if (ok) {
            ok = data.Read("Gain1", lowGains.gain1);
            if (ok) {
                REPORT_ERROR(ErrorManagement::Information, "Gains.Low.Gain1 = %f", lowGains.gain1);
            }
            else {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain1");
            }
        }
        if (ok) {
            ok = data.Read("Gain2", lowGains.gain2);
            if (ok) {
                REPORT_ERROR(ErrorManagement::Information, "Gains.Low.Gain1 = %f", lowGains.gain2);
            }
            else {
            }
        }
        if (ok) {
            ok = data.MoveToAncestor(1u);
            if (!ok) {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move back to the Gains section");
            }
        }
        if (ok) {
            ok = data.MoveRelative("High");
            if (!ok) {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains.High section");
            }
        }
        if (ok) {
            ok = data.Read("Gain1", highGains.gain1);
            if (ok) {
                REPORT_ERROR(ErrorManagement::Information, "Gains.High.Gain1 = %f", highGains.gain1);
            }
            else {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain1");
            }
        }
        if (ok) {
            ok = data.Read("Gain2", highGains.gain2);
            if (ok) {
                REPORT_ERROR(ErrorManagement::Information, "Gains.High.Gain1 = %f", highGains.gain2);
            }
            else {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain2");
            }
        }
        if (ok) {
            //Move to the ancestor
            ok = data.MoveToAncestor(2u);
            if (!ok) {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move back to the References section");
            }
        }
        if (ok) {
            ok = data.MoveRelative("References.Slow.Waveform");
            if (!ok) {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the References.Slow.Waveform section");
            }
        }
        if (ok) {
            ok = ReadArray(data, "Times", slowWaveform.times);
        }
        if (ok) {
            ok = ReadArray(data, "Values", slowWaveform.values);
        }
        //Move back to the parent
        if (ok) {
            ok = data.MoveToAncestor(2u);
        }
        if (ok) {
            ok = data.MoveRelative("Fast.Waveform");
            if (!ok) {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the References.fast.Waveform section");
            }
        }
        if (ok) {
            ok = ReadArray(data, "Times", fastWaveform.times);
        }
        if (ok) {
            ok = ReadArray(data, "Values", fastWaveform.values);
        }

        return ok;
    }

private:
    bool ReadArray(MARTe::StructuredDataI &data, const MARTe::char8 * const arrayName, MARTe::float32 *&dest) {
        using namespace MARTe;
        if (dest != NULL) {
            delete [] dest;
        }

        AnyType arrayDescription = data.GetType(arrayName);
        bool ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
        uint32 numberOfElements = 0u;
        if (ok) {
            numberOfElements = arrayDescription.GetNumberOfElements(0u);
            ok = (numberOfElements > 0u);
            if (!ok) {
                REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array with name %s", arrayName);
            }
        }
        if (ok) {
            dest = new float32[numberOfElements];
            Vector<float32> readVector(dest, numberOfElements);
            ok = data.Read(arrayName, readVector);
            if (ok) {
                REPORT_ERROR(ErrorManagement::Information, "Array set to %f", readVector);
            }
            else {
                REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the array with name %s", arrayName);
            }
        }
        return ok;
    }

    /**
     * A list of properties.
     */
    Gains lowGains;
    Gains highGains;
    Waveforms slowWaveform;
    Waveforms fastWaveform;
};

CLASS_REGISTER(ControllerEx1, "")

}

int main(int argc, char **argv) {
    using namespace MARTe;
    using namespace MARTe2Tutorial;
    SetErrorProcessFunction(&ErrorProcessExampleFunction);

    CCString className1 = "ControllerEx1";

    float32 times1[] = { 0.0, 0.2, 1 };
    float32 values1[] = { 1.0, -1.0, 1.0 };
    float32 times2[] = { 0.0, 0.5, 1 };
    float32 values2[] = { 0.0, 1.0, 0.0 };

    ReferenceT<ControllerEx1> ref1(className1,
            GlobalObjectsDatabase::Instance()->GetStandardHeap());
    //Automatically generate a new object instance based on the class name and on the correct Heap and with the template reference.
    if (ref1.IsValid()) {
        ref1->SetName("ControllerInstance1");
        REPORT_ERROR_STATIC(ErrorManagement::Information,
                "Successfully created an instance of %s", className1.GetList());
        //Write a valid configuration.
        {
            ConfigurationDatabase cdb;
            //Create the structure nodes
            cdb.CreateAbsolute("Gains.Low");
            cdb.Write("Gain1", 1.0);
            cdb.Write("Gain2", -1.0);
            cdb.CreateAbsolute("Gains.High");
            cdb.Write("Gain1", 5.0);
            cdb.Write("Gain2", -5.0);
            cdb.CreateAbsolute("References.Slow.Waveform");
            cdb.Write("Times", times1);
            cdb.Write("Values", values1);
            cdb.CreateAbsolute("References.Fast.Waveform");
            cdb.Write("Times", times2);
            cdb.Write("Values", values2);
            //Move back again to the root of the tree
            cdb.MoveToRoot();

            //Print the configuration
            REPORT_ERROR_STATIC(ErrorManagement::Information,
                    "Going to load the following configuration\n%s", cdb);
            //Need to move back after the printf
            cdb.MoveToRoot();
            if (ref1->Initialise(cdb)) {
                REPORT_ERROR_STATIC(ErrorManagement::Information,
                        "Successfully configured instance of %s",
                        ref1->GetName());
            } else {
                REPORT_ERROR_STATIC(ErrorManagement::FatalError,
                        "Failed to configure instance of %s", ref1->GetName());
            }
        }
        //Write an invalid configuration
        {
            ConfigurationDatabase cdb;
            //Create the structure nodes with a typo: Gain (not Gains)
            cdb.CreateAbsolute("Gain.Low");
            cdb.Write("Gain1", 1.0);
            cdb.Write("Gain2", -1.0);
            cdb.CreateAbsolute("Gain.High");
            cdb.Write("Gain1", 5.0);
            cdb.Write("Gain2", -5.0);
            cdb.CreateAbsolute("References.Slow.Waveform");
            cdb.Write("Times", times1);
            cdb.Write("Values", values1);
            cdb.CreateAbsolute("References.Fast.Waveform");
            cdb.Write("Times", times2);
            cdb.Write("Values", values2);
            //Move back again to the root of the tree
            cdb.MoveToRoot();

            //Print the configuration
            REPORT_ERROR_STATIC(ErrorManagement::Information,
                    "Going to load the following configuration\n%s", cdb);

            if (!ref1->Initialise(cdb)) {
                REPORT_ERROR_STATIC(ErrorManagement::Information,
                        "As expected failed to configure instance of %s",
                        ref1->GetName());
            }
        }
    }

    return 0;
}

The following example shows how the reading of parameters can be simplified with the StructuredDataIHelper.

Object configuration example using the StructuredDataIHelper (ConfigurationExample8)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/**
 * @file ConfigurationExample8.cpp
 * @brief Source file for class ConfigurationExample8
 * @date 27/06/2022
 * @author Andre' Neto
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing, 
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.

 * @details This source file contains the definition of all the methods for
 * the class ConfigurationExample8 (public, protected, and private). Be aware that some
 * methods, such as those inline could be defined on the header file, instead.
 */

#define DLL_API

/*---------------------------------------------------------------------------*/
/*                         Standard header includes                          */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                         Project header includes                           */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "ClassRegistryDatabase.h"
#include "ConfigurationDatabase.h"
#include "ErrorLoggerExample.h"
#include "Matrix.h"
#include "Object.h"
#include "Reference.h"
#include "ReferenceT.h"
#include "StreamString.h"
#include "StructuredDataIHelper.h"
#include "Vector.h"

/*---------------------------------------------------------------------------*/
/*                           Static definitions                              */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                           Method definitions                              */
/*---------------------------------------------------------------------------*/
namespace MARTe2Tutorial {
/**
 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
 */
class ControllerEx1: public MARTe::Object {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief NOOP.
     */
    ControllerEx1 () {
        gain1 = 0u;
        gain2 = 0.f;
        gain3 = -1.0f;
        controllerType = 0u;
        mode = "";
        referencesArray = NULL;
        modesArray = NULL;
        model = NULL;
        modelRows = 0u;
    }

    virtual ~ControllerEx1 () {
        using namespace MARTe;
        if (referencesArray != NULL) {
            delete [] referencesArray;
        }
        if (modesArray != NULL) {
            delete [] modesArray;
        }
        if (model != NULL) {
            for (uint32 i=0; i<modelRows; i++) {
                delete [] model[i];
            }
            delete [] model;
        }

        if (GetName() != NULL) {
            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references pointing at %s [%s]. "
                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
        }
    }

    /**
     * Read all the properties
     */
    virtual bool Initialise(MARTe::StructuredDataI &data) {
        using namespace MARTe;
        bool ok = Object::Initialise(data);
        StructuredDataIHelper helper(data, this);
        if (ok) {
            ok = helper.Read("Gain1", gain1);
        }
        if (ok) {
            //Read with default
            ok = helper.Read("Gain2", gain2, 1.7);
        }
        if (ok) {
            ok = helper.Read("Mode", mode);
        }
        if (ok) {
            const char8 * controllerTypesStr[] = {"C1", "C2", "C3"};
            uint32 controllerTypes[] = {1, 2, 3};
            ok = helper.ReadEnum("ControllerType", controllerType, controllerTypesStr, controllerTypes);
        }

        if (ok) {
            uint32 nOfReferences = 0u;
            //Reconfiguration...
            if (referencesArray != NULL) {
                delete [] referencesArray;
                referencesArray = NULL;
            }
            ok = helper.ReadArray("References", referencesArray, nOfReferences);
        }

        if (ok) {
            uint32 nOfModes = 0u;
            //Reconfiguration...
            if (modesArray != NULL) {
                delete [] modesArray;
                modesArray = NULL;
            }
            ok = helper.ReadArray("Modes", modesArray, nOfModes);
        }

        if (ok) {
            //Reconfiguration...
            if (model != NULL) {
                for (uint32 i=0; i<modelRows; i++) {
                    delete [] model[i];
                }
                delete [] model;
                model = NULL;
            }

            uint32 modelCols = 0u;
            ok = helper.ReadMatrix("Model", model, modelRows, modelCols);
        }

        if (ok) {
            ok = helper.ReadValidated("Gain3", gain3, "(Gain3 > (float32)(-3.0)) && (Gain3 <= (float32)(0.0))");
        }

        return ok;
    }

    /**
     * A list of properties.
     */
    MARTe::uint32 gain1;
    MARTe::uint32 modelRows;
    MARTe::uint32 controllerType;
    MARTe::float32 gain2;
    MARTe::float32 gain3;
    MARTe::StreamString mode;
    MARTe::int32 *referencesArray;
    MARTe::StreamString *modesArray;
    MARTe::float32 **model;
};

CLASS_REGISTER(ControllerEx1, "")

}

int main(int argc, char **argv) {
    using namespace MARTe;
    using namespace MARTe2Tutorial;
    SetErrorProcessFunction(&ErrorProcessExampleFunction);

    CCString className1 = "ControllerEx1";

    int32 int32Arr[] = { -1, 2, -3, 4, -5 };
    const char8 *stringArr[] = { "A", "BB", "CCC", "DDDD", "EEEEE" };
    float32 float32Mat[3][2] = { { -1.0, 2.3 }, { 4.7, -3.2 }, { -7.1, 5.6 } };

    ReferenceT<ControllerEx1> ref1(className1,
            GlobalObjectsDatabase::Instance()->GetStandardHeap());
    //Automatically generate a new object instance based on the class name and on the correct Heap
    //and with the template reference.
    if (ref1.IsValid()) {
        ref1->SetName("ControllerInstance1");
        REPORT_ERROR_STATIC(ErrorManagement::Information,
                "Successfully created an instance of %s", className1.GetList());
        //Write a valid configuration.
        {
            ConfigurationDatabase cdb;
            cdb.Write("Gain1", 2);
            cdb.Write("Gain3", -2.0);
            cdb.Write("Mode", "ASTRING");
            cdb.Write("ControllerType", "C3");
            cdb.Write("Modes", stringArr);
            cdb.Write("References", int32Arr);
            cdb.Write("Model", float32Mat);

            if (ref1->Initialise(cdb)) {
                REPORT_ERROR_STATIC(ErrorManagement::Information,
                        "Successfully configured instance of %s",
                        ref1->GetName());
            } else {
                REPORT_ERROR_STATIC(ErrorManagement::FatalError,
                        "Failed to configure instance of %s", ref1->GetName());
            }
        }
        //Write an invalid configuration - missing compulsory parameter
        {
            ConfigurationDatabase cdb;
            cdb.Write("Gain1", 2);
            cdb.Write("Gain2", 1.5);
            cdb.Write("Gain3", -2.0);
            cdb.Write("ControllerType", "C3");
            cdb.Write("Modes", stringArr);
            cdb.Write("References", int32Arr);
            cdb.Write("Model", float32Mat);
            if (!ref1->Initialise(cdb)) {
                REPORT_ERROR_STATIC(ErrorManagement::Information,
                        "As expected failed to reconfigure instance of %s",
                        ref1->GetName());
            }
        }
        //Write a configuration without a parameter that is out of range
        {
            ConfigurationDatabase cdb;
            cdb.Write("Gain1", 2);
            cdb.Write("Gain2", 1.5);
            cdb.Write("Gain3", 2.0);
            cdb.Write("ControllerType", "C3");
            cdb.Write("Mode", "ASTRING");
            cdb.Write("Modes", stringArr);
            cdb.Write("References", int32Arr);
            cdb.Write("Model", float32Mat);
            if (!ref1->Initialise(cdb)) {
                REPORT_ERROR_STATIC(ErrorManagement::Information,
                        "As expected failed to reconfigure instance of %s",
                        ref1->GetName());
            }
        }

    }

    return 0;
}

Instructions on how to compile and execute the example can be found here.