rad  5.1.0
config.hpp
Go to the documentation of this file.
1 
9 #ifndef RAD_CONFIG_HPP
10 #define RAD_CONFIG_HPP
11 
12 #include <rad/logger.hpp>
13 #include <rad/assert.hpp>
14 #include <rad/exceptions.hpp>
15 
16 #include <config-ng/ciiConfigApi.hpp>
17 
18 #include <boost/program_options.hpp>
19 #include <boost/algorithm/string.hpp>
20 
21 #include <string>
22 #include <memory>
23 
24 namespace bpo = boost::program_options;
25 
26 namespace rad {
27 
28 const char CONFIG_KEY_SEPARATOR_OLDB = '/';
29 //const char CONFIG_KEY_SEPARATOR_CFG = '.';
30 //const std::string CONFIG_DEFAULT_ROOT_NODE = "cfg";
31 
35 const std::string KEY_CONFIG = "cfg/";
36 const std::string KEY_CONFIG_VERSION = KEY_CONFIG + "version";
37 const std::string KEY_CONFIG_MODNAME = KEY_CONFIG + "modname";
38 const std::string KEY_CONFIG_PROCNAME = KEY_CONFIG + "procname";
39 const std::string KEY_CONFIG_FILENAME = KEY_CONFIG + "filename";
40 const std::string KEY_CONFIG_LOG_LEVEL = KEY_CONFIG + "log_level";
41 const std::string KEY_CONFIG_LOG_PROPERTIES = KEY_CONFIG + "log_properties";
42 const std::string KEY_CONFIG_SM_SCXML = KEY_CONFIG + "sm_scxml";
43 const std::string KEY_CONFIG_SM_APPEND = KEY_CONFIG + "sm_scxml_append";
44 const std::string KEY_CONFIG_REQ_ENDPOINT = KEY_CONFIG + "req_endpoint";
45 const std::string KEY_CONFIG_OLDB_URI_PREFIX = KEY_CONFIG + "oldb_uri_prefix";
46 const std::string KEY_CONFIG_OLDB_CONN_TIMEOUT = KEY_CONFIG + "oldb_conn_timeout";
47 const std::string KEY_CONFIG_TRS_HEALTH_ENABLED = KEY_CONFIG + "trs_health_enabled";
48 
49 const std::vector<std::string> KEYS_CONFIG = {
60 };
61 
62 
67 class Config {
68  public:
79  explicit Config(const std::string& name = LOGGER_NAME,
80  const std::string& log_level = "ERROR");
81 
85  virtual ~Config();
86 
91  inline const elt::configng::CiiConfigDocument& GetConfigDoc() { return *m_config_doc; }
92 
96  inline bpo::options_description& GetOptionsDesc() { return m_options_desc; }
97 
101  inline bpo::variables_map& GetOptionsMap() { return m_options_map; }
102 
111  virtual bool ParseOptions(int argc, char* argv[]);
112 
121  virtual void LoadConfig(const std::string& filename = "");
122 
132  virtual void ConfigureLogging(const std::string& filename = "");
133 
138  virtual void ApplyCmdLineOptions();
139 
147  //void MergeConfig(const elt::configng::CiiConfigInstanceNamespace& instance);
148  void MergeConfig(const elt::configng::CiiConfigDocument& cfg_doc);
149 
156  void CreateDefaultConfig(const std::string& default_cfg);
157 
165  template<typename T>
166  void AddParam(const std::string& key, const T& value);
167 
174  bool HasParam(const std::string& key) const;
175 
182  template<typename T>
183  T GetParam(const std::string& key) const;
184 
191  template<typename T>
192  void SetParam(const std::string& key, const T& value);
193 
199  const std::string GetConfigAsString() const;
200 
212  std::vector<std::string> SetConfigAsString(const std::string& config);
213 
218  std::string PrintNode(const elt::configng::CiiConfigInstanceNode& node,
219  const std::string& indentation);
220 
228  std::string Print(const elt::configng::CiiConfigInstanceNamespace& instances);
229 
235  std::string Print();
236 
237 
238  Config(const Config&) = delete;
239  Config& operator=(const Config&) = delete;
240 
241  private:
251  bool SplitKeyValue(const std::string& keyval, std::string& key, std::string& value);
252 
262  void SplitVectorStr(const std::string& vector_str, std::string& vector_name,
263  int& vector_index) const;
264 
265  bpo::options_description m_options_desc;
266  bpo::variables_map m_options_map;
267  std::string m_name;
268 
269  /*
270  * We need to declare CiiConfigDocument as pointer since it logs info
271  * in the constructor and therefore uses [CII] logging before it has
272  * been properly configured.
273  */
274  std::unique_ptr<elt::configng::CiiConfigDocument> m_config_doc;
275 };
276 
277 
278 template<typename T>
279 void Config::AddParam(const std::string& key, const T& value) {
280  RAD_TRACE(GetLogger());
281 
282  std::vector<std::string> nodes;
283  std::string delim(1, CONFIG_KEY_SEPARATOR_OLDB);
284  boost::split(nodes, key, boost::is_any_of(delim));
285  if (nodes.size() < 2) {
286  RAD_LOG_THROW(rad::Exception, GetLogger(), "Key " + key +
287  " has no root/leaf node(s).");
288  }
289 
290  /*
291  builder["three"] = elt::configng::CiiConfigInstanceNode::From(3);
292  builder["vector"] = elt::configng::CiiConfigInstanceNode::From(std::vector<int>{1,2,3,4,5,6},
293  "!cfg.type:vector_int32");
294  builder["map"]["d"] = elt::configng::CiiConfigInstanceNode::From(4);
295  builder["map"]["e"] = elt::configng::CiiConfigInstanceNode::From("text");
296  builder["map"]["f"] = elt::configng::CiiConfigInstanceNode::From(false, "!cfg.type:boolean");
297  */
298  elt::configng::CiiConfigMapBuilder builder;
299 
300  auto curr_node = builder[nodes[0]];
301  size_t index = 1;
302  while (index < nodes.size()) {
303  //std::string child_node_name = nodes[index];
304  curr_node = curr_node[nodes[index]];
305  if (index + 1 == nodes.size()) {
306  //child_node.As<T>();
307  curr_node = elt::configng::CiiConfigInstanceNode::From(value);
308  }
309  index++;
310  }
311 
312  if (m_config_doc == nullptr) {
313  m_config_doc = std::make_unique<elt::configng::CiiConfigDocument>();
314  m_config_doc->SetInstancesFromMap(builder);
315  } else {
316  auto document = elt::configng::CiiConfigDocument();
317  document.SetInstancesFromMap(builder);
318  MergeConfig(document);
319  }
320 
321  auto issues = m_config_doc->Check();
322  if (issues.HasErrors() || issues.HasWarnings()) {
323  for (auto& issue : issues) {
324  LOG4CPLUS_ERROR(GetLogger(), "Config. issue: " << issue.GetMessage());
325  //std::cout << issue << std::endl;
326  }
327  RAD_LOG_THROW(rad::Exception, GetLogger(), "Error/warning while adding key " + key);
328  }
329 }
330 
331 template<typename T>
332 T Config::GetParam(const std::string& key) const {
333  RAD_TRACE(GetLogger());
334 
335  if (m_config_doc == nullptr) {
336  RAD_LOG_THROW(rad::Exception, GetLogger(), "No configuration available.");
337  }
338 
339  try {
340  std::vector<std::string> nodes;
341  std::string delim(1, CONFIG_KEY_SEPARATOR_OLDB);
342  boost::split(nodes, key, boost::is_any_of(delim));
343  if (nodes.size() < 2) {
344  RAD_LOG_THROW(rad::Exception, GetLogger(), "Key " + key +
345  " has no root/leaf node(s).");
346  }
347 
348  auto instance = m_config_doc->Instances();
349  auto parent_node = instance[nodes[0]];
350  auto child_node = parent_node;
351  size_t index = 1;
352  while (index < nodes.size()) {
353  std::string child_node_name = nodes[index];
354 
355  // check for arrays
356  int vector_index = -1;
357  SplitVectorStr(nodes[index], child_node_name, vector_index);
358  //std::cout << "Child node name: " << child_node_name << std::endl;
359 
360  // check for sub-node or leaf-node.
361  if (parent_node.Has(child_node_name)) {
362  if (vector_index == -1) {
363  child_node = parent_node[child_node_name];
364  } else {
365  child_node = parent_node[child_node_name][vector_index];
366  }
367  if (index + 1 == nodes.size()) {
368  T val = child_node.As<T>();
369  return val;
370  }
371  parent_node = child_node;
372  } else {
373  RAD_LOG_THROW(rad::Exception, GetLogger(), "Configuration parameter " +
374  key + " does not exists.");
375  }
376  index++;
377  }
378  RAD_LOG_THROW(rad::Exception, GetLogger(), "Configuration parameter " +
379  key + " does not exists.");
380  } catch (std::exception& e) {
381  RAD_LOG_THROW(rad::Exception, GetLogger(), "Reading configuration parameter <" +
382  key + ">: " + std::string(e.what()));
383  }
384 }
385 
386 template<typename T>
387 void Config::SetParam(const std::string& key, const T& value) {
388  RAD_TRACE(GetLogger());
389 
390  if (m_config_doc == nullptr) {
391  RAD_LOG_THROW(rad::Exception, GetLogger(), "No configuration available.");
392  }
393 
394  try {
395  std::vector<std::string> nodes;
396  std::string delim(1, CONFIG_KEY_SEPARATOR_OLDB);
397  boost::split(nodes, key, boost::is_any_of(delim));
398  if (nodes.size() < 2) {
399  RAD_LOG_THROW(rad::Exception, GetLogger(), "Key " + key +
400  " has no root/leaf node(s).");
401  }
402 
403  auto instance = m_config_doc->Instances();
404  auto parent_node = instance[nodes[0]];
405  auto child_node = parent_node;
406  size_t index = 1;
407  while (index < nodes.size()) {
408  std::string child_node_name = nodes[index];
409 
410  // check for arrays
411  int vector_index = -1;
412  SplitVectorStr(nodes[index], child_node_name, vector_index);
413 
414  // check for sub-node or leaf-node.
415  if (parent_node.Has(child_node_name)) {
416  if (vector_index == -1) {
417  child_node = parent_node[child_node_name];
418  } else {
419  child_node = parent_node[child_node_name][vector_index];
420  }
421  if (index + 1 == nodes.size()) {
422  child_node = value;
423  return;
424  }
425  parent_node = child_node;
426  } else {
427  RAD_LOG_THROW(rad::Exception, GetLogger(), "Configuration parameter " +
428  key + " does not exists.");
429  }
430  index++;
431  }
432  RAD_LOG_THROW(rad::Exception, GetLogger(), "Configuration parameter " +
433  key + " does not exists.");
434  } catch (std::exception& e) {
435  LOG4CPLUS_ERROR(GetLogger(), "Writing configuration parameter <"
436  << key << ">: " << e.what());
437  }
438 }
439 
446 void GetListOfKeysFromConfig(const elt::configng::CiiConfigInstanceNode& node,
447  std::vector<std::string>& keys);
448 
455 std::vector<std::string> GetListOfKeysFromConfig(const elt::configng::CiiConfigDocument& cfg_doc);
456 
457 } // namespace rad
458 
459 #endif // RAD_CONFIG_HPP
Assert header file.
Definition: config.hpp:67
void AddParam(const std::string &key, const T &value)
Definition: config.hpp:279
void SetParam(const std::string &key, const T &value)
Definition: config.hpp:387
std::string PrintNode(const elt::configng::CiiConfigInstanceNode &node, const std::string &indentation)
Definition: config.cpp:418
Config(const Config &)=delete
Config(const std::string &name=LOGGER_NAME, const std::string &log_level="ERROR")
Definition: config.cpp:22
bpo::variables_map & GetOptionsMap()
Definition: config.hpp:101
std::vector< std::string > SetConfigAsString(const std::string &config)
Definition: config.cpp:350
const std::string GetConfigAsString() const
Definition: config.cpp:329
void CreateDefaultConfig(const std::string &default_cfg)
Definition: config.cpp:270
bpo::options_description & GetOptionsDesc()
Definition: config.hpp:96
T GetParam(const std::string &key) const
Definition: config.hpp:332
const elt::configng::CiiConfigDocument & GetConfigDoc()
Definition: config.hpp:91
virtual void ConfigureLogging(const std::string &filename="")
Definition: config.cpp:190
virtual ~Config()
Definition: config.cpp:69
virtual void LoadConfig(const std::string &filename="")
Definition: config.cpp:154
Config & operator=(const Config &)=delete
Disable copy constructor.
virtual bool ParseOptions(int argc, char *argv[])
Definition: config.cpp:73
void MergeConfig(const elt::configng::CiiConfigDocument &cfg_doc)
Definition: config.cpp:254
virtual void ApplyCmdLineOptions()
Definition: config.cpp:222
std::string Print()
Definition: config.cpp:466
bool HasParam(const std::string &key) const
Definition: config.cpp:278
Base class for the exceptions thrown by RAD and its users.
Definition: exceptions.hpp:53
Logger class.
#define RAD_TRACE(logger)
Definition: logger.hpp:24
Exception classes header file.
#define RAD_LOG_THROW(exceptionType_t, logger, msg)
Throw exception with information about the throw location.
Definition: exceptions.hpp:356
Definition: actionsApp.cpp:20
const std::string KEY_CONFIG_PROCNAME
Definition: config.hpp:38
const std::string KEY_CONFIG_VERSION
Definition: config.hpp:36
const std::string LOGGER_NAME
Definition: logger.hpp:79
void GetListOfKeysFromConfig(const elt::configng::CiiConfigInstanceNode &node, const std::string &prefix, std::vector< std::string > &keys)
Definition: config.cpp:511
const std::string KEY_CONFIG_SM_APPEND
Definition: config.hpp:43
const std::string KEY_CONFIG_FILENAME
Definition: config.hpp:39
log4cplus::Logger & GetLogger()
Definition: logger.cpp:70
const char CONFIG_KEY_SEPARATOR_OLDB
Definition: config.hpp:28
const std::string KEY_CONFIG_SM_SCXML
Definition: config.hpp:42
const std::string KEY_CONFIG_TRS_HEALTH_ENABLED
Definition: config.hpp:47
const std::string KEY_CONFIG_LOG_LEVEL
Definition: config.hpp:40
const std::vector< std::string > KEYS_CONFIG
Definition: config.hpp:49
const std::string KEY_CONFIG_OLDB_CONN_TIMEOUT
Definition: config.hpp:46
const std::string KEY_CONFIG
Definition: config.hpp:35
const std::string KEY_CONFIG_MODNAME
Definition: config.hpp:37
const std::string KEY_CONFIG_LOG_PROPERTIES
Definition: config.hpp:41
const std::string KEY_CONFIG_OLDB_URI_PREFIX
Definition: config.hpp:45
const std::string KEY_CONFIG_REQ_ENDPOINT
Definition: config.hpp:44
name
Definition: wscript:8