AliPhysics  bdbde52 (bdbde52)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AliYAMLConfiguration.h
Go to the documentation of this file.
1 #ifndef ALIYAMLCONFIGURATION_H
2 #define ALIYAMLCONFIGURATION_H
3 
4 // CINT can't handle the yaml header because it has c++11!
5 #if !(defined(__CINT__) || defined(__MAKECINT__))
6 #include <yaml-cpp/yaml.h>
7 #endif
8 
9 #include <string>
10 #include <vector>
11 #include <ostream>
12 
13 #include <TObject.h>
14 
15 #include <AliLog.h>
16 
93 class AliYAMLConfiguration : public TObject {
94  public:
95  AliYAMLConfiguration(const std::string prefixString = "AliEmcalCorrection", const std::string delimiterCharacter = ":");
96  virtual ~AliYAMLConfiguration() {}
97 
98  bool Initialize();
99  bool Reinitialize();
100 
102  bool AddEmptyConfiguration(const std::string & configurationName);
103  bool AddConfiguration(std::string configurationFilename, std::string configurationName = "");
104  #if !(defined(__CINT__) || defined(__MAKECINT__))
105  bool AddConfiguration(const YAML::Node node, std::string configurationName = "");
106 
107  const std::pair<std::string, YAML::Node> & GetConfiguration(const int i) const { return fConfigurations.at(i); }
108  const std::pair<std::string, YAML::Node> & GetConfiguration(const std::string & name) const { return fConfigurations.at(GetConfigurationIndexByName(name, fConfigurations)); }
109  std::pair<std::string, YAML::Node> & GetConfiguration(const int i) { return fConfigurations.at(i); }
110  std::pair<std::string, YAML::Node> & GetConfiguration(const std::string & name) { return fConfigurations.at(GetConfigurationIndexByName(name, fConfigurations)); }
111 
112  // Helper functions to retrieve property values
113  template<typename T>
114  bool GetProperty(std::vector<std::string> propertyPath, const std::string & propertyName, T & property, const bool requiredProperty) const;
115  template<typename T>
116  bool GetProperty(const std::vector<std::string> propertyPath, T & property, const bool requiredProperty) const;
117  // Retrieve property driver function.
118  template<typename T>
119  bool GetProperty(std::string propertyName, T & property, const bool requiredProperty = true) const;
120 
121  // Write property driver function.
122  template<typename T>
123  bool WriteProperty(std::string propertyName, T & property, std::string configurationName = "");
124  #endif
125 
126  bool WriteConfiguration(const std::string & filename, const unsigned int i) const;
127  bool WriteConfiguration(const std::string & filename, const std::string & configurationName) const;
128 
129  void PrintConfiguration(const unsigned int i = 0) const;
130  void PrintConfiguration(const std::string & name) const;
131  void PrintConfigurations() const;
132 
133  protected:
134 
135  // Utility functions
136  // File utilities
137  inline bool DoesFileExist(const std::string & filename) const;
138  void SetupReadingConfigurationFilePath(std::string & filename, const std::string & fileIdentifier) const;
139  void WriteConfigurationToFilePath(const std::string & localFilename, std::string filename) const;
140  // Configuration utilities
141  template<typename T>
142  unsigned int GetConfigurationIndexByName(const std::string & name, const std::vector<std::pair<std::string, T>> & configurations) const;
143 
144  bool IsSharedValue(std::string & value) const;
145  #if !(defined(__CINT__) || defined(__MAKECINT__))
146  template<typename T>
147  auto PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, int) const -> decltype(tempMessage << property, void());
148  template<typename T>
149  auto PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const std::vector <T> & property, int) const -> decltype(property.begin(), property.end(), tempMessage << std::declval<T>(), void());
150  template<typename T>
151  void PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, long) const;
152  template<typename T>
153  void PrintRetrievedPropertyValue(std::stringstream & tempMessage, const T & property) const;
154 
155  template<typename T>
156  bool GetPropertyFromNode(const YAML::Node & node, std::string propertyName, T & property) const;
157  template<typename T>
158  bool GetProperty(YAML::Node & node, YAML::Node & sharedParametersNode, const std::string & configurationName, std::string propertyName, T & property) const;
159 
160  template<typename T>
161  void WriteValue(YAML::Node & node, std::string propertyName, T & proeprty);
162 
163  std::vector<std::pair<std::string, YAML::Node> > fConfigurations;
164  #endif
165  std::vector<std::pair<std::string, std::string> > fConfigurationsStrings;
166 
168  std::string fPrefixString;
169  std::string fDelimiter;
170 
172  ClassDef(AliYAMLConfiguration, 1); // YAML Configuration
174 };
175 
176 #if !(defined(__CINT__) || defined(__MAKECINT__))
177 
187 template<typename T>
188 auto AliYAMLConfiguration::PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, int) const -> decltype(tempMessage << property, void())
189 {
190  tempMessage << " with value \"" << property << "\"";
191 }
192 
201 template<typename T>
202 auto AliYAMLConfiguration::PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const std::vector <T> & property, int) const -> decltype(property.begin(), property.end(), tempMessage << std::declval<T>(), void())
203 {
204  tempMessage << " with value(s):";
205  for (auto it = property.begin(); it != property.end(); it++) {
206  tempMessage << "\n\t- " << *it;
207  }
208 }
209 
221 template<typename T>
222 void AliYAMLConfiguration::PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, long) const
223 {
224  // Cannot easily print these types, so just note that is the case!
225  tempMessage << " with a value that cannot be trivially printed";
226 }
227 
239 template<typename T>
240 void AliYAMLConfiguration::PrintRetrievedPropertyValue(std::stringstream & tempMessage, const T & property) const
241 {
242  // By passing zero, it will first lookup the int, and then the long
244 }
245 
255 template<typename T>
256 bool AliYAMLConfiguration::GetPropertyFromNode(const YAML::Node & node, std::string propertyName, T & property) const
257 {
258  if (node[propertyName])
259  {
260  property = node[propertyName].as<T>();
261  return true;
262  }
263  return false;
264 }
265 
277 template<typename T>
278 bool AliYAMLConfiguration::GetProperty(std::vector <std::string> propertyPath, const std::string & propertyName, T & property, const bool requiredProperty) const
279 {
280  propertyPath.push_back(propertyName);
281  return GetProperty(propertyPath, property, requiredProperty);
282 }
283 
294 template<typename T>
295 bool AliYAMLConfiguration::GetProperty(const std::vector <std::string> propertyPath, T & property, const bool requiredProperty) const
296 {
297  // Combine the requested names together
298  std::string requestedName = "";
299  for (auto & str : propertyPath)
300  {
301  if (requestedName.length() > 0) {
302  requestedName += ":" + str;
303  }
304  else {
305  requestedName = str;
306  }
307  }
308 
309  // Pass on the properly requested call
310  return GetProperty(requestedName, property, requiredProperty);
311 }
312 
325 template<typename T>
326 bool AliYAMLConfiguration::GetProperty(std::string propertyName, T & property, const bool requiredProperty) const
327 {
328  // Remove AliEmcalCorrection if in name
329  std::size_t prefixStringLocation = propertyName.find(fPrefixString);
330  if (prefixStringLocation != std::string::npos)
331  {
332  // Remove the prefix string
333  propertyName.erase(prefixStringLocation, prefixStringLocation + fPrefixString.length());
334  }
335 
336  bool setProperty = false;
337  for (auto configPair : fConfigurations)
338  {
339  if (setProperty == true) {
340  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Property \"" << propertyName << "\" found!\n";
341  break;
342  }
343 
344  // IsNull checks is a node is empty. A node is empty if it is created.
345  // IsDefined checks if the node that was requested was not actually created.
346  if (configPair.second.IsNull() != true)
347  {
348  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Looking for parameter \"" << propertyName << "\" in \"" << configPair.first << "\" configuration\n";
349  // NOTE: This may not exist, but that is entirely fine.
350  YAML::Node sharedParameters = configPair.second["sharedParameters"];
351  setProperty = GetProperty(configPair.second, sharedParameters, configPair.first, propertyName, property);
352  }
353  }
354 
355  if (setProperty != true && requiredProperty == true)
356  {
357  std::stringstream message;
358  message << "Failed to retrieve required property \""
359  << propertyName << "\" from available configurations!" << std::endl;
360  AliFatalGeneral("AliYAMLConfiguration", message.str().c_str());
361  }
362 
363  // Return whether the value was actually set
364  return setProperty;
365 }
366 
389 template<typename T>
390 bool AliYAMLConfiguration::GetProperty(YAML::Node & node, YAML::Node & sharedParametersNode, const std::string & configurationName, std::string propertyName, T & property) const
391 {
392  // Used as a buffer for printing complicated messages
393  std::stringstream tempMessage;
394 
395  bool returnValue = false;
396 
397  const std::string specializationDelimiter = "_";
398  size_t delimiterPosition = 0;
399  std::string tempPropertyName = propertyName;
400 
401  if ((delimiterPosition = tempPropertyName.find(fDelimiter)) != std::string::npos)
402  {
403  std::string nodeName = tempPropertyName.substr(0, delimiterPosition);
404  tempPropertyName.erase(0, delimiterPosition + fDelimiter.length());
405 
406  // Attempt to use the node name
407  if (node[nodeName].IsDefined() == true)
408  {
409  // Retrieve node and then recurse
410  YAML::Node tempNode = node[nodeName];
411  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Attempting to retrieving property \"" << tempPropertyName << "\" by going a node deeper with node \"" << nodeName << "\".\n";
412  returnValue = GetProperty(tempNode, sharedParametersNode, configurationName, tempPropertyName, property);
413  }
414 
415  // Check for the specialization if the nodeName is undefined.
416  // Alternatively, if the value was not returned successfully, we should also check for the specialization
417  // such as inheritnace for input objects.
418  if (node[nodeName].IsDefined() == false || returnValue == false)
419  {
420  // Check for specialization
421  if ((delimiterPosition = nodeName.find(specializationDelimiter)) != std::string::npos)
422  {
423  std::string specializationNodeName = nodeName.substr(0, delimiterPosition);
424  YAML::Node tempNode = node[specializationNodeName];
425  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Attempting to retrieving property \"" << tempPropertyName << "\" by going a node deeper through dropping the specializtion and using node \"" << specializationNodeName << "\".\n";
426  returnValue = GetProperty(tempNode, sharedParametersNode, configurationName, tempPropertyName, property);
427  }
428  else {
429  returnValue = false;
430  }
431  }
432  }
433  else
434  {
435  // Check if node exists!
436  if (node[propertyName])
437  {
438  // Handle shared parameters
439  bool isShared = false;
440  // Will contain the name of the property in the sharedParameters section that should be retrieved
441  // if it is requested through the user configuration.
442  std::string sharedValueName = "";
443  // Necessary because it fails on vectors and other complex objects that are YAML sequences.
444  if (std::is_arithmetic<T>::value || std::is_same<T, std::string>::value || std::is_same<T, bool>::value)
445  {
446  // Retrieve value as string to check for shared value
447  sharedValueName = node[propertyName].as<std::string>();
448  // Check for a shared value
449  isShared = IsSharedValue(sharedValueName);
450  }
451 
452  // Setup printable message
453  tempMessage.str("");
454  tempMessage << "property \""
455  << propertyName
456  << "\" using " << ( isShared ? "\"sharedParameters:" + sharedValueName + "\" in " : "" )
457  << "values from the " << configurationName << " configuration";
458 
459  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Retrieveing " << tempMessage.str() << "\n";
460 
461  // Retrieve result
462  bool retrievalResult = false;
463  if (isShared == true) {
464  // Retrieve from the shared parameter node directly.
465  retrievalResult = GetPropertyFromNode(sharedParametersNode, sharedValueName, property);
466  }
467  else {
468  retrievalResult = GetPropertyFromNode(node, propertyName, property);
469  }
470 
471  // Inform about the result
472  if (retrievalResult == true) {
473  // Add the retrieved value to the message (only if trivially printable)
475  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Succeeded in retrieveing " << tempMessage.str() << "\n";
476  returnValue = true;
477  }
478  else {
479  returnValue = false;
480  }
481  }
482  }
483 
484  return returnValue;
485 }
486 
497 template<typename T>
498 bool AliYAMLConfiguration::WriteProperty(std::string propertyName, T & property, std::string configurationName)
499 {
500  unsigned int configurationIndex = 0;
501  if (configurationName != "")
502  {
503  configurationIndex = GetConfigurationIndexByName(configurationName, fConfigurations);
504  }
505 
506  if (fConfigurations.size() == 0) {
507  AliErrorStream() << "No configurations available! Property will not be written!\n";
508  return false;
509  }
510 
511  std::pair<std::string, YAML::Node> & configPair = fConfigurations.at(configurationIndex);
512 
513  WriteValue(configPair.second, propertyName, property);
514  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Final Node:\n" << configPair.second << "\n";
515 
516  return true;
517 }
518 
526 template<typename T>
527 void AliYAMLConfiguration::WriteValue(YAML::Node & node, std::string propertyName, T & property)
528 {
529  // Find the node name we are interested in
530  // Derived from: https://stackoverflow.com/a/14266139
531  const std::string delimiter = ":";
532  size_t delimiterPosition = 0;
533  std::string tempPropertyName = propertyName;
534 
535  if ((delimiterPosition = tempPropertyName.find(delimiter)) != std::string::npos)
536  {
537  std::string nodeName = tempPropertyName.substr(0, delimiterPosition);
538  tempPropertyName.erase(0, delimiterPosition + delimiter.length());
539  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "nodeName: " << nodeName << "\n";
540  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Node Before:\n" << node << "\n";
541  if (node[nodeName].IsDefined()) {
542  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Using existing node\n";
543  YAML::Node tempNode = node[nodeName];
544  WriteValue(tempNode, tempPropertyName, property);
545  }
546  else {
547  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Creating new node\n";
548  YAML::Node tempNode;
549  node[nodeName] = tempNode;
550  WriteValue(tempNode, tempPropertyName, property);
551  }
552  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Node After:\n" << node << "\n";
553  }
554  else {
555  // We have finished the recursion. Now we need to save the actual property.
556  node[propertyName] = property;
557  }
558 }
559 
560 #endif
561 
570 template<typename T>
571 unsigned int AliYAMLConfiguration::GetConfigurationIndexByName(const std::string & name, const std::vector<std::pair<std::string, T>> & configurations) const
572 {
573  int index = -1;
574  for (const auto & configPair : configurations)
575  {
576  if (configPair.first == name) {
577  // Retrieve index
578  // See: https://stackoverflow.com/a/10962459
579  index = std::addressof(configPair) - std::addressof(configurations[0]);
580  break;
581  }
582  }
583 
584  return index;
585 }
586 
587 #endif /* ALIYAMLCONFIGURATION_H */
const char * filename
Definition: TestFCM.C:1
AliYAMLConfiguration(const std::string prefixString="AliEmcalCorrection", const std::string delimiterCharacter=":")
void WriteConfigurationToFilePath(const std::string &localFilename, std::string filename) const
void PrintConfiguration(const unsigned int i=0) const
bool WriteConfiguration(const std::string &filename, const unsigned int i) const
bool GetPropertyFromNode(const YAML::Node &node, std::string propertyName, T &property) const
std::string fDelimiter
Delimiter character to separate each level of the request.
bool AddEmptyConfiguration(const std::string &configurationName)
Add YAML configuration at configurationFilename to available configurations.
bool WriteProperty(std::string propertyName, T &property, std::string configurationName="")
UShort_t T(UShort_t m, UShort_t t)
Definition: RingBits.C:60
void WriteValue(YAML::Node &node, std::string propertyName, T &proeprty)
auto PrintRetrievedPropertyValueImpl(std::stringstream &tempMessage, const T &property, int) const -> decltype(tempMessage<< property, void())
bool GetProperty(std::vector< std::string > propertyPath, const std::string &propertyName, T &property, const bool requiredProperty) const
std::vector< std::pair< std::string, std::string > > fConfigurationsStrings
Contains all YAML configurations as strings so that they can be streamed.
const std::pair< std::string, YAML::Node > & GetConfiguration(const std::string &name) const
void PrintRetrievedPropertyValue(std::stringstream &tempMessage, const T &property) const
unsigned int GetConfigurationIndexByName(const std::string &name, const std::vector< std::pair< std::string, T >> &configurations) const
bool AddConfiguration(std::string configurationFilename, std::string configurationName="")
const std::pair< std::string, YAML::Node > & GetConfiguration(const int i) const
bool fInitialized
True if the configurations have been initialized.
YAML configuration class for AliPhysics.
std::pair< std::string, YAML::Node > & GetConfiguration(const std::string &name)
std::string fPrefixString
Contains the prefix of any names base node names which should be removed.
std::pair< std::string, YAML::Node > & GetConfiguration(const int i)
std::vector< std::pair< std::string, YAML::Node > > fConfigurations
! Contains all YAML configurations. The first element has the highest precedence. ...
bool DoesFileExist(const std::string &filename) const
bool IsSharedValue(std::string &value) const
void SetupReadingConfigurationFilePath(std::string &filename, const std::string &fileIdentifier) const