The mechanism used for user-defined modification of attributes values has been changed.
Before a user-defined function was used, which was invoked when an attribute of certain type was read from database. This was not flexible enough, since parameters of the function were not defined by the user.
The substitution function was replaced by the substitution object. The user defines a class as he likes and can define any parameters he needs. The only rules he has to follow are:
To register a converter object the user needs to create an object of his class dynamically and pass pointer to the ::Configuration::register_converter() method. The configuration destructor will destroy all registered converter objects itself, so user must not do it himself and be careful with registering of the same object more than once.
Below there is example, which demonstrates how to write a simple class, which will add user-defined prefix to values of attributes of string type.
class AddPrefix : public ::Configuration::AttributeConverter<std::string> { private: std::string my_prefix; // keep parameters, provided by user (a single string in our case, but can be everything also) public: AddPrefix (const std::string& s) : my_prefix(s) {;} // constructor to initialize user parameters virtual void convert(std::string& value, const ::Configuration&, const ::ConfigObject&, const std::string&) { if(...) value = my_prefix + value; // the code, which in some cases does the conversion } };...::Configuration db(...); db.register_converter(new AddPrefix("test-")); // registration of the conversion object
If there is a composite relationship between two classes (e.g. from class A to B), then there is a fast way to get value of reverse relationship. E.g. if class A has composite relationship X to class B, then from given object of class B one can get information about objects of class A pointing to this object via relationship X. In particular this can be useful to answer a question "Whom this object belongs?", e.g. if a crate contains list of modules, then the operation to get crate of this module is straightforward.
The list of objects referencing given one can be obtained using two methods:
The first method should be used for objects of classes generated by the genconfig. Below there is example to get crates referencing given module via relationship "Modules":
::Configuration db(...); ::daq::core::Module m = db.get<daq::core::Module>("my module"); // get a module by any mean, e.g. by ID std::vector<const daq::core::Crate *> crates; // the output vector db.referenced_by(m, "Modules", crates); // get crates referencing given module std::cout << "Module " << m << " is referenced by " << crates.size() << " crates\n"; if(crates.size() > 0) { std::cout << "first crate is = " << crates[0] << std::endl; }
The second method should be used by developers, which use config abstract database API directly.