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 * @file ConfigurationExample1.cpp
  3 * @brief Source file for class ConfigurationExample1
  4 * @date 14/03/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class ConfigurationExample1 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ClassRegistryDatabase.h"
 35#include "ConfigurationDatabase.h"
 36#include "ErrorLoggerExample.h"
 37#include "Matrix.h"
 38#include "Object.h"
 39#include "Reference.h"
 40#include "ReferenceT.h"
 41#include "StreamString.h"
 42#include "Vector.h"
 43
 44/*---------------------------------------------------------------------------*/
 45/*                           Static definitions                              */
 46/*---------------------------------------------------------------------------*/
 47
 48/*---------------------------------------------------------------------------*/
 49/*                           Method definitions                              */
 50/*---------------------------------------------------------------------------*/
 51namespace MARTe2Tutorial {
 52/**
 53 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
 54 */
 55class ControllerEx1: public MARTe::Object {
 56public:
 57    CLASS_REGISTER_DECLARATION()
 58
 59    /**
 60     * @brief NOOP.
 61     */
 62    ControllerEx1 () {
 63        gain1 = 0u;
 64        gain2 = 0.f;
 65        mode = "";
 66        referencesArray = NULL;
 67        modesArray = NULL;
 68    }
 69
 70    virtual ~ControllerEx1 () {
 71        using namespace MARTe;
 72        if (referencesArray != NULL) {
 73            delete [] referencesArray;
 74        }
 75        if (modesArray != NULL) {
 76            delete [] modesArray;
 77        }
 78        if (GetName() != NULL) {
 79            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references pointing at %s [%s]. "
 80                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
 81        }
 82    }
 83
 84    /**
 85     * Read all the properties
 86     */
 87    virtual bool Initialise(MARTe::StructuredDataI &data) {
 88        using namespace MARTe;
 89        bool ok = Object::Initialise(data);
 90        if (ok) {
 91            ok = data.Read("Gain1", gain1);
 92            if (ok) {
 93                REPORT_ERROR(ErrorManagement::Information, "gain1 set to %d", gain1);
 94            }
 95            else {
 96                REPORT_ERROR(ErrorManagement::ParametersError, "The Gain1 property shall be set");
 97            }
 98        }
 99        if (ok) {
100            ok = data.Read("Gain2", gain2);
101            if (ok) {
102                REPORT_ERROR(ErrorManagement::Information, "gain2 set to %f", gain2);
103            }
104            else {
105                REPORT_ERROR(ErrorManagement::ParametersError, "The Gain2 property shall be set");
106            }
107        }
108
109        if (ok) {
110            mode = "";
111            ok = data.Read("Mode", mode);
112            if (ok) {
113                REPORT_ERROR(ErrorManagement::Information, "mode set to %s", mode.Buffer());
114            }
115            else {
116                REPORT_ERROR(ErrorManagement::ParametersError, "The Mode property shall be set");
117            }
118        }
119
120        if (ok) {
121            AnyType arrayDescription = data.GetType("References");
122            ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
123            uint32 numberOfElements = 0u;
124            if (ok) {
125                numberOfElements = arrayDescription.GetNumberOfElements(0u);
126                ok = (numberOfElements > 0u);
127                if (!ok) {
128                    REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array");
129                }
130            }
131            if (ok) {
132                //Reconfiguration...
133                if (referencesArray != NULL) {
134                    delete [] referencesArray;
135                }
136                referencesArray = new int32[numberOfElements];
137                Vector<int32> readVector(referencesArray, numberOfElements);
138                ok = data.Read("References", readVector);
139                if (ok) {
140                    REPORT_ERROR(ErrorManagement::Information, "referencesArray set to %d", readVector);
141                }
142                else {
143                    REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the References");
144                }
145            }
146        }
147
148        if (ok) {
149            AnyType arrayDescription = data.GetType("Modes");
150            ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
151            uint32 numberOfElements = 0u;
152            if (ok) {
153                numberOfElements = arrayDescription.GetNumberOfElements(0u);
154                ok = (numberOfElements > 0u);
155                if (!ok) {
156                    REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array");
157                }
158            }
159            if (ok) {
160                //Reconfiguration...
161                if (modesArray != NULL) {
162                    delete [] modesArray;
163                }
164                modesArray = new StreamString[numberOfElements];
165                Vector<StreamString> readVector(modesArray, numberOfElements);
166                ok = data.Read("Modes", readVector);
167                if (ok) {
168                    uint32 i;
169                    for (i=0u; i<numberOfElements; i++) {
170                        REPORT_ERROR(ErrorManagement::Information, "modesArray[%d] set to %s", i,readVector[i].Buffer());
171                    }
172                }
173                else {
174                    REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Modes");
175                }
176            }
177        }
178
179        if (ok) {
180            AnyType arrayDescription = data.GetType("Model");
181            ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
182            uint32 numberOfDimensions = 0u;
183            if (ok) {
184                numberOfDimensions = arrayDescription.GetNumberOfDimensions();
185                ok = (numberOfDimensions == 2u);
186                if (!ok) {
187                    REPORT_ERROR(ErrorManagement::ParametersError, "Model is not a Matrix");
188                }
189            }
190            uint32 numberOfRows = 0u;
191            uint32 numberOfCols = 0u;
192            if (ok) {
193                numberOfRows = arrayDescription.GetNumberOfElements(1u);
194                numberOfCols = arrayDescription.GetNumberOfElements(0u);
195                ok = (numberOfRows > 0u);
196                if (!ok) {
197                    REPORT_ERROR(ErrorManagement::ParametersError, "No rows defined in the matrix");
198                }
199            }
200            if (ok) {
201                ok = (numberOfCols > 0u);
202                if (!ok) {
203                    REPORT_ERROR(ErrorManagement::ParametersError, "No columns defined in the matrix");
204                }
205            }
206            if (ok) {
207                Matrix<float32> modelMatrix(numberOfRows, numberOfCols);
208                ok = data.Read("Model", modelMatrix);
209                if (ok) {
210                    REPORT_ERROR(ErrorManagement::Information, "modelMatrix set to %f", modelMatrix);
211                }
212                else {
213                    REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the References");
214                }
215            }
216        }
217
218        return ok;
219    }
220
221    /**
222     * A list of properties.
223     */
224    MARTe::uint32 gain1;
225    MARTe::float32 gain2;
226    MARTe::StreamString mode;
227    MARTe::int32 *referencesArray;
228    MARTe::StreamString *modesArray;
229};
230
231CLASS_REGISTER(ControllerEx1, "")
232
233}
234
235int main(int argc, char **argv) {
236    using namespace MARTe;
237    using namespace MARTe2Tutorial;
238    SetErrorProcessFunction(&ErrorProcessExampleFunction);
239
240    CCString className1 = "ControllerEx1";
241
242    int32 int32Arr[] = { -1, 2, -3, 4, -5 };
243    const char8 *stringArr[] = { "A", "BB", "CCC", "DDDD", "EEEEE" };
244    float32 float32Mat[3][2] = { { -1.0, 2.3 }, { 4.7, -3.2 }, { -7.1, 5.6 } };
245
246    ReferenceT<ControllerEx1> ref1(className1,
247            GlobalObjectsDatabase::Instance()->GetStandardHeap());
248    //Automatically generate a new object instance based on the class name and on the correct Heap
249    //and with the template reference.
250    if (ref1.IsValid()) {
251        ref1->SetName("ControllerInstance1");
252        REPORT_ERROR_STATIC(ErrorManagement::Information,
253                "Successfully created an instance of %s", className1.GetList());
254        //Write a valid configuration.
255        {
256            ConfigurationDatabase cdb;
257            cdb.Write("Gain1", 2);
258            cdb.Write("Gain2", 1.5);
259            cdb.Write("Mode", "ASTRING");
260            cdb.Write("Modes", stringArr);
261            cdb.Write("References", int32Arr);
262            cdb.Write("Model", float32Mat);
263
264            if (ref1->Initialise(cdb)) {
265                REPORT_ERROR_STATIC(ErrorManagement::Information,
266                        "Successfully configured instance of %s",
267                        ref1->GetName());
268            } else {
269                REPORT_ERROR_STATIC(ErrorManagement::FatalError,
270                        "Failed to configure instance of %s", ref1->GetName());
271            }
272        }
273        //Write an invalid configuration
274        {
275            ConfigurationDatabase cdb;
276            cdb.Write("Gain1", 2);
277            cdb.Write("Gain2", 1.5);
278            cdb.Write("Mode", "ASTRING");
279            cdb.Write("Modes", stringArr);
280            cdb.Write("References", int32Arr);
281            cdb.Write("Model", int32Arr);
282            if (!ref1->Initialise(cdb)) {
283                REPORT_ERROR_STATIC(ErrorManagement::Information,
284                        "As expected failed to reconfigure instance of %s",
285                        ref1->GetName());
286            }
287        }
288    }
289
290    return 0;
291}

This is a similar example, highlighting structured configurations.

Object configuration example (ConfigurationExample2)
  1/**
  2 * @file ConfigurationExample2.cpp
  3 * @brief Source file for class ConfigurationExample2
  4 * @date 14/03/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class ConfigurationExample2 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ClassRegistryDatabase.h"
 35#include "ConfigurationDatabase.h"
 36#include "ErrorLoggerExample.h"
 37#include "Object.h"
 38#include "Reference.h"
 39#include "ReferenceT.h"
 40#include "StreamString.h"
 41#include "Vector.h"
 42
 43/*---------------------------------------------------------------------------*/
 44/*                           Static definitions                              */
 45/*---------------------------------------------------------------------------*/
 46
 47/*---------------------------------------------------------------------------*/
 48/*                           Method definitions                              */
 49/*---------------------------------------------------------------------------*/
 50namespace MARTe2Tutorial {
 51
 52/**
 53 * Configuration structures
 54 */
 55struct Gains {
 56    MARTe::float32 gain1;
 57    MARTe::float32 gain2;
 58};
 59
 60struct Waveforms {
 61    MARTe::float32 *times;
 62    MARTe::float32 *values;
 63};
 64
 65/**
 66 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
 67 */
 68class ControllerEx1: public MARTe::Object {
 69public:
 70    CLASS_REGISTER_DECLARATION()
 71
 72    /**
 73     * @brief NOOP.
 74     */
 75ControllerEx1   () {
 76        slowWaveform.times = NULL;
 77        slowWaveform.values = NULL;
 78        fastWaveform.times = NULL;
 79        fastWaveform.values = NULL;
 80
 81    }
 82
 83    virtual ~ControllerEx1 () {
 84        if (slowWaveform.times != NULL) {
 85            delete [] slowWaveform.times;
 86        }
 87        if (slowWaveform.values != NULL) {
 88            delete [] slowWaveform.values;
 89        }
 90        if (fastWaveform.times != NULL) {
 91            delete [] fastWaveform.times;
 92        }
 93        if (fastWaveform.values != NULL) {
 94            delete [] fastWaveform.values;
 95        }
 96        if (GetName() != NULL) {
 97            REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at "
 98                    "%s [%s]. The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
 99        }
100    }
101
102    /**
103     * Read all the properties which are organised inside a tree
104     * Gains = {
105     *     Low = {
106     *         Gain1 = -1.0;
107     *         Gain2 = -3.0;
108     *     }
109     *     High = {
110     *         Gain1 = 7.0;
111     *         Gain2 = 9.0;
112     *     }
113     * }
114     * References = {
115     *     Slow = {
116     *         Waveform = {
117     *             Times  = {0 0.1 0.2 1}
118     *             Values = {1 2   3   4}
119     *         }
120     *     }
121     *     Fast = {
122     *         Waveform = {
123     *             Times  = {0 0.1 0.2 1}
124     *             Values = {1 2   3   4}
125     *         }
126     *     }
127     * }
128     */
129    virtual bool Initialise(MARTe::StructuredDataI &data) {
130        using namespace MARTe;
131        bool ok = Object::Initialise(data);
132        if (ok) {
133            //Move in the tree
134            ok = data.MoveRelative("Gains");
135            if (!ok) {
136                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains section");
137            }
138        }
139        if (ok) {
140            ok = data.MoveRelative("Low");
141            if (!ok) {
142                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains.Low section");
143            }
144        }
145        if (ok) {
146            ok = data.Read("Gain1", lowGains.gain1);
147            if (ok) {
148                REPORT_ERROR(ErrorManagement::Information, "Gains.Low.Gain1 = %f", lowGains.gain1);
149            }
150            else {
151                REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain1");
152            }
153        }
154        if (ok) {
155            ok = data.Read("Gain2", lowGains.gain2);
156            if (ok) {
157                REPORT_ERROR(ErrorManagement::Information, "Gains.Low.Gain1 = %f", lowGains.gain2);
158            }
159            else {
160            }
161        }
162        if (ok) {
163            ok = data.MoveToAncestor(1u);
164            if (!ok) {
165                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move back to the Gains section");
166            }
167        }
168        if (ok) {
169            ok = data.MoveRelative("High");
170            if (!ok) {
171                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains.High section");
172            }
173        }
174        if (ok) {
175            ok = data.Read("Gain1", highGains.gain1);
176            if (ok) {
177                REPORT_ERROR(ErrorManagement::Information, "Gains.High.Gain1 = %f", highGains.gain1);
178            }
179            else {
180                REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain1");
181            }
182        }
183        if (ok) {
184            ok = data.Read("Gain2", highGains.gain2);
185            if (ok) {
186                REPORT_ERROR(ErrorManagement::Information, "Gains.High.Gain1 = %f", highGains.gain2);
187            }
188            else {
189                REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain2");
190            }
191        }
192        if (ok) {
193            //Move to the ancestor
194            ok = data.MoveToAncestor(2u);
195            if (!ok) {
196                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move back to the References section");
197            }
198        }
199        if (ok) {
200            ok = data.MoveRelative("References.Slow.Waveform");
201            if (!ok) {
202                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the References.Slow.Waveform section");
203            }
204        }
205        if (ok) {
206            ok = ReadArray(data, "Times", slowWaveform.times);
207        }
208        if (ok) {
209            ok = ReadArray(data, "Values", slowWaveform.values);
210        }
211        //Move back to the parent
212        if (ok) {
213            ok = data.MoveToAncestor(2u);
214        }
215        if (ok) {
216            ok = data.MoveRelative("Fast.Waveform");
217            if (!ok) {
218                REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the References.fast.Waveform section");
219            }
220        }
221        if (ok) {
222            ok = ReadArray(data, "Times", fastWaveform.times);
223        }
224        if (ok) {
225            ok = ReadArray(data, "Values", fastWaveform.values);
226        }
227
228        return ok;
229    }
230
231private:
232    bool ReadArray(MARTe::StructuredDataI &data, const MARTe::char8 * const arrayName, MARTe::float32 *&dest) {
233        using namespace MARTe;
234        if (dest != NULL) {
235            delete [] dest;
236        }
237
238        AnyType arrayDescription = data.GetType(arrayName);
239        bool ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
240        uint32 numberOfElements = 0u;
241        if (ok) {
242            numberOfElements = arrayDescription.GetNumberOfElements(0u);
243            ok = (numberOfElements > 0u);
244            if (!ok) {
245                REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array with name %s", arrayName);
246            }
247        }
248        if (ok) {
249            dest = new float32[numberOfElements];
250            Vector<float32> readVector(dest, numberOfElements);
251            ok = data.Read(arrayName, readVector);
252            if (ok) {
253                REPORT_ERROR(ErrorManagement::Information, "Array set to %f", readVector);
254            }
255            else {
256                REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the array with name %s", arrayName);
257            }
258        }
259        return ok;
260    }
261
262    /**
263     * A list of properties.
264     */
265    Gains lowGains;
266    Gains highGains;
267    Waveforms slowWaveform;
268    Waveforms fastWaveform;
269};
270
271CLASS_REGISTER(ControllerEx1, "")
272
273}
274
275int main(int argc, char **argv) {
276    using namespace MARTe;
277    using namespace MARTe2Tutorial;
278    SetErrorProcessFunction(&ErrorProcessExampleFunction);
279
280    CCString className1 = "ControllerEx1";
281
282    float32 times1[] = { 0.0, 0.2, 1 };
283    float32 values1[] = { 1.0, -1.0, 1.0 };
284    float32 times2[] = { 0.0, 0.5, 1 };
285    float32 values2[] = { 0.0, 1.0, 0.0 };
286
287    ReferenceT<ControllerEx1> ref1(className1,
288            GlobalObjectsDatabase::Instance()->GetStandardHeap());
289    //Automatically generate a new object instance based on the class name and on the correct Heap and with the template reference.
290    if (ref1.IsValid()) {
291        ref1->SetName("ControllerInstance1");
292        REPORT_ERROR_STATIC(ErrorManagement::Information,
293                "Successfully created an instance of %s", className1.GetList());
294        //Write a valid configuration.
295        {
296            ConfigurationDatabase cdb;
297            //Create the structure nodes
298            cdb.CreateAbsolute("Gains.Low");
299            cdb.Write("Gain1", 1.0);
300            cdb.Write("Gain2", -1.0);
301            cdb.CreateAbsolute("Gains.High");
302            cdb.Write("Gain1", 5.0);
303            cdb.Write("Gain2", -5.0);
304            cdb.CreateAbsolute("References.Slow.Waveform");
305            cdb.Write("Times", times1);
306            cdb.Write("Values", values1);
307            cdb.CreateAbsolute("References.Fast.Waveform");
308            cdb.Write("Times", times2);
309            cdb.Write("Values", values2);
310            //Move back again to the root of the tree
311            cdb.MoveToRoot();
312
313            //Print the configuration
314            REPORT_ERROR_STATIC(ErrorManagement::Information,
315                    "Going to load the following configuration\n%s", cdb);
316            //Need to move back after the printf
317            cdb.MoveToRoot();
318            if (ref1->Initialise(cdb)) {
319                REPORT_ERROR_STATIC(ErrorManagement::Information,
320                        "Successfully configured instance of %s",
321                        ref1->GetName());
322            } else {
323                REPORT_ERROR_STATIC(ErrorManagement::FatalError,
324                        "Failed to configure instance of %s", ref1->GetName());
325            }
326        }
327        //Write an invalid configuration
328        {
329            ConfigurationDatabase cdb;
330            //Create the structure nodes with a typo: Gain (not Gains)
331            cdb.CreateAbsolute("Gain.Low");
332            cdb.Write("Gain1", 1.0);
333            cdb.Write("Gain2", -1.0);
334            cdb.CreateAbsolute("Gain.High");
335            cdb.Write("Gain1", 5.0);
336            cdb.Write("Gain2", -5.0);
337            cdb.CreateAbsolute("References.Slow.Waveform");
338            cdb.Write("Times", times1);
339            cdb.Write("Values", values1);
340            cdb.CreateAbsolute("References.Fast.Waveform");
341            cdb.Write("Times", times2);
342            cdb.Write("Values", values2);
343            //Move back again to the root of the tree
344            cdb.MoveToRoot();
345
346            //Print the configuration
347            REPORT_ERROR_STATIC(ErrorManagement::Information,
348                    "Going to load the following configuration\n%s", cdb);
349
350            if (!ref1->Initialise(cdb)) {
351                REPORT_ERROR_STATIC(ErrorManagement::Information,
352                        "As expected failed to configure instance of %s",
353                        ref1->GetName());
354            }
355        }
356    }
357
358    return 0;
359}

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

Object configuration example using the StructuredDataIHelper (ConfigurationExample8)
  1/**
  2 * @file ConfigurationExample8.cpp
  3 * @brief Source file for class ConfigurationExample8
  4 * @date 27/06/2022
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class ConfigurationExample8 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ClassRegistryDatabase.h"
 35#include "ConfigurationDatabase.h"
 36#include "ErrorLoggerExample.h"
 37#include "Matrix.h"
 38#include "Object.h"
 39#include "Reference.h"
 40#include "ReferenceT.h"
 41#include "StreamString.h"
 42#include "StructuredDataIHelper.h"
 43#include "Vector.h"
 44
 45/*---------------------------------------------------------------------------*/
 46/*                           Static definitions                              */
 47/*---------------------------------------------------------------------------*/
 48
 49/*---------------------------------------------------------------------------*/
 50/*                           Method definitions                              */
 51/*---------------------------------------------------------------------------*/
 52namespace MARTe2Tutorial {
 53/**
 54 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
 55 */
 56class ControllerEx1: public MARTe::Object {
 57public:
 58    CLASS_REGISTER_DECLARATION()
 59
 60    /**
 61     * @brief NOOP.
 62     */
 63    ControllerEx1 () {
 64        gain1 = 0u;
 65        gain2 = 0.f;
 66        gain3 = -1.0f;
 67        controllerType = 0u;
 68        mode = "";
 69        referencesArray = NULL;
 70        modesArray = NULL;
 71        model = NULL;
 72        modelRows = 0u;
 73    }
 74
 75    virtual ~ControllerEx1 () {
 76        using namespace MARTe;
 77        if (referencesArray != NULL) {
 78            delete [] referencesArray;
 79        }
 80        if (modesArray != NULL) {
 81            delete [] modesArray;
 82        }
 83        if (model != NULL) {
 84            for (uint32 i=0; i<modelRows; i++) {
 85                delete [] model[i];
 86            }
 87            delete [] model;
 88        }
 89
 90        if (GetName() != NULL) {
 91            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references pointing at %s [%s]. "
 92                    "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
 93        }
 94    }
 95
 96    /**
 97     * Read all the properties
 98     */
 99    virtual bool Initialise(MARTe::StructuredDataI &data) {
100        using namespace MARTe;
101        bool ok = Object::Initialise(data);
102        StructuredDataIHelper helper(data, this);
103        if (ok) {
104            ok = helper.Read("Gain1", gain1);
105        }
106        if (ok) {
107            //Read with default
108            ok = helper.Read("Gain2", gain2, 1.7);
109        }
110        if (ok) {
111            ok = helper.Read("Mode", mode);
112        }
113        if (ok) {
114            const char8 * controllerTypesStr[] = {"C1", "C2", "C3"};
115            uint32 controllerTypes[] = {1, 2, 3};
116            ok = helper.ReadEnum("ControllerType", controllerType, controllerTypesStr, controllerTypes);
117        }
118
119        if (ok) {
120            uint32 nOfReferences = 0u;
121            //Reconfiguration...
122            if (referencesArray != NULL) {
123                delete [] referencesArray;
124                referencesArray = NULL;
125            }
126            ok = helper.ReadArray("References", referencesArray, nOfReferences);
127        }
128
129        if (ok) {
130            uint32 nOfModes = 0u;
131            //Reconfiguration...
132            if (modesArray != NULL) {
133                delete [] modesArray;
134                modesArray = NULL;
135            }
136            ok = helper.ReadArray("Modes", modesArray, nOfModes);
137        }
138
139        if (ok) {
140            //Reconfiguration...
141            if (model != NULL) {
142                for (uint32 i=0; i<modelRows; i++) {
143                    delete [] model[i];
144                }
145                delete [] model;
146                model = NULL;
147            }
148
149            uint32 modelCols = 0u;
150            ok = helper.ReadMatrix("Model", model, modelRows, modelCols);
151        }
152
153        if (ok) {
154            ok = helper.ReadValidated("Gain3", gain3, "(Gain3 > (float32)(-3.0)) && (Gain3 <= (float32)(0.0))");
155        }
156
157        return ok;
158    }
159
160    /**
161     * A list of properties.
162     */
163    MARTe::uint32 gain1;
164    MARTe::uint32 modelRows;
165    MARTe::uint32 controllerType;
166    MARTe::float32 gain2;
167    MARTe::float32 gain3;
168    MARTe::StreamString mode;
169    MARTe::int32 *referencesArray;
170    MARTe::StreamString *modesArray;
171    MARTe::float32 **model;
172};
173
174CLASS_REGISTER(ControllerEx1, "")
175
176}
177
178int main(int argc, char **argv) {
179    using namespace MARTe;
180    using namespace MARTe2Tutorial;
181    SetErrorProcessFunction(&ErrorProcessExampleFunction);
182
183    CCString className1 = "ControllerEx1";
184
185    int32 int32Arr[] = { -1, 2, -3, 4, -5 };
186    const char8 *stringArr[] = { "A", "BB", "CCC", "DDDD", "EEEEE" };
187    float32 float32Mat[3][2] = { { -1.0, 2.3 }, { 4.7, -3.2 }, { -7.1, 5.6 } };
188
189    ReferenceT<ControllerEx1> ref1(className1,
190            GlobalObjectsDatabase::Instance()->GetStandardHeap());
191    //Automatically generate a new object instance based on the class name and on the correct Heap
192    //and with the template reference.
193    if (ref1.IsValid()) {
194        ref1->SetName("ControllerInstance1");
195        REPORT_ERROR_STATIC(ErrorManagement::Information,
196                "Successfully created an instance of %s", className1.GetList());
197        //Write a valid configuration.
198        {
199            ConfigurationDatabase cdb;
200            cdb.Write("Gain1", 2);
201            cdb.Write("Gain3", -2.0);
202            cdb.Write("Mode", "ASTRING");
203            cdb.Write("ControllerType", "C3");
204            cdb.Write("Modes", stringArr);
205            cdb.Write("References", int32Arr);
206            cdb.Write("Model", float32Mat);
207
208            if (ref1->Initialise(cdb)) {
209                REPORT_ERROR_STATIC(ErrorManagement::Information,
210                        "Successfully configured instance of %s",
211                        ref1->GetName());
212            } else {
213                REPORT_ERROR_STATIC(ErrorManagement::FatalError,
214                        "Failed to configure instance of %s", ref1->GetName());
215            }
216        }
217        //Write an invalid configuration - missing compulsory parameter
218        {
219            ConfigurationDatabase cdb;
220            cdb.Write("Gain1", 2);
221            cdb.Write("Gain2", 1.5);
222            cdb.Write("Gain3", -2.0);
223            cdb.Write("ControllerType", "C3");
224            cdb.Write("Modes", stringArr);
225            cdb.Write("References", int32Arr);
226            cdb.Write("Model", float32Mat);
227            if (!ref1->Initialise(cdb)) {
228                REPORT_ERROR_STATIC(ErrorManagement::Information,
229                        "As expected failed to reconfigure instance of %s",
230                        ref1->GetName());
231            }
232        }
233        //Write a configuration without a parameter that is out of range
234        {
235            ConfigurationDatabase cdb;
236            cdb.Write("Gain1", 2);
237            cdb.Write("Gain2", 1.5);
238            cdb.Write("Gain3", 2.0);
239            cdb.Write("ControllerType", "C3");
240            cdb.Write("Mode", "ASTRING");
241            cdb.Write("Modes", stringArr);
242            cdb.Write("References", int32Arr);
243            cdb.Write("Model", float32Mat);
244            if (!ref1->Initialise(cdb)) {
245                REPORT_ERROR_STATIC(ErrorManagement::Information,
246                        "As expected failed to reconfigure instance of %s",
247                        ref1->GetName());
248            }
249        }
250
251    }
252
253    return 0;
254}

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