AliPhysics  5be3bab (5be3bab)
 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 // operator<< has to be forward declared carefully to stay in the global namespace so that it works with CINT.
94 // For generally how to keep the operator in the global namespace, See: https://stackoverflow.com/a/38801633
95 namespace PWG { namespace Tools { class AliYAMLConfiguration; } }
96 std::ostream & operator<< (std::ostream &in, const PWG::Tools::AliYAMLConfiguration &myTask);
97 
98 namespace PWG {
99 namespace Tools {
100 
102  public:
103  AliYAMLConfiguration(const std::string prefixString = "AliEmcalCorrection", const std::string delimiterCharacter = ":");
105 
109  bool Initialize();
110  bool Reinitialize();
116  int AddEmptyConfiguration(const std::string & configurationName);
118  int AddConfiguration(std::string configurationFilename, std::string configurationName = "");
119  #if !(defined(__CINT__) || defined(__MAKECINT__))
120  int AddConfiguration(const YAML::Node node, std::string configurationName = "");
126  bool DoesConfigurationExist(const int i) const { return i >= 0 && static_cast<const unsigned int>(i) < fConfigurations.size(); }
127  bool DoesConfigurationExist(const std::string & name) const { return DoesConfigurationExist(GetConfigurationIndexFromName(name, fConfigurations)); }
128  const std::pair<std::string, YAML::Node> & GetConfiguration(const int i) const { return fConfigurations.at(i); }
129  const std::pair<std::string, YAML::Node> & GetConfiguration(const std::string & name) const { return GetConfiguration(GetConfigurationIndexFromName(name, fConfigurations)); }
130  std::pair<std::string, YAML::Node> & GetConfiguration(const int i) { return fConfigurations.at(i); }
131  std::pair<std::string, YAML::Node> & GetConfiguration(const std::string & name) { return GetConfiguration(GetConfigurationIndexFromName(name, fConfigurations)); }
137  std::string GetConfigurationNameFromIndex(const unsigned int i) const { return fConfigurations.at(i).first; }
138  int GetConfigurationIndexFromName(const std::string & name) const { return GetConfigurationIndexFromName(name, fConfigurations); }
144  bool RemoveConfiguration(const unsigned int i);
151  // Helper functions to retrieve property values
152  template<typename T>
153  bool GetProperty(std::vector<std::string> propertyPath, const std::string & propertyName, T & property, const bool requiredProperty) const;
154  template<typename T>
155  bool GetProperty(const std::vector<std::string> propertyPath, T & property, const bool requiredProperty) const;
156  // Retrieve property driver function.
157  template<typename T>
158  bool GetProperty(std::string propertyName, T & property, const bool requiredProperty = true) const;
164  // Write property driver function.
165  template<typename T>
166  bool WriteProperty(std::string propertyName, T & property, std::string configurationName = "");
168  #endif
169 
173  bool WriteConfiguration(const std::string & filename, const unsigned int i) const;
174  bool WriteConfiguration(const std::string & filename, const std::string & configurationName) const;
180  bool CompareConfigurations(const int config1, const int config2) const;
181  bool CompareConfigurations(const int config1, const std::string & config2) const { return CompareConfigurations(config1, GetConfigurationIndexFromName(config2, fConfigurations)); }
182  bool CompareConfigurations(const std::string & config1, const std::string & config2) const { return CompareConfigurations(GetConfigurationIndexFromName(config1, fConfigurations), GetConfigurationIndexFromName(config2, fConfigurations)); }
183 
189  std::string toString(const int index = -1) const;
190  std::ostream & Print(std::ostream &in, const int index = -1) const;
191  std::ostream & Print(std::ostream &in, const std::string & configurationName) const;
192  friend std::ostream & ::operator<< (std::ostream &in, const AliYAMLConfiguration &myTask);
193  void Print(Option_t* /* opt */ = "") const;
196  protected:
197 
198  // Utility functions
199  // File utilities
200  inline bool DoesFileExist(const std::string & filename) const;
201  void SetupReadingConfigurationFilePath(std::string & filename, const std::string & fileIdentifier) const;
202  void WriteConfigurationToFilePath(const std::string & localFilename, std::string filename) const;
203  #if !(defined(__CINT__) || defined(__MAKECINT__))
204  // Printing
205  void PrintConfiguration(std::ostream & stream, const std::pair<std::string, YAML::Node> & configPair) const;
206  #endif
207  // Configuration utilities
208  template<typename T>
209  unsigned int GetConfigurationIndexFromName(const std::string & name, const std::vector<std::pair<std::string, T>> & configurations) const;
210 
211  bool IsSharedValue(std::string & value) const;
212  #if !(defined(__CINT__) || defined(__MAKECINT__))
213  template<typename T>
214  auto PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, int) const -> decltype(tempMessage << property, void());
215  template<typename T>
216  auto PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const std::vector <T> & property, int) const -> decltype(property.begin(), property.end(), tempMessage << std::declval<T>(), void());
217  template<typename T>
218  void PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, long) const;
219  template<typename T>
220  void PrintRetrievedPropertyValue(std::stringstream & tempMessage, const T & property) const;
221 
222  template<typename T>
223  bool GetPropertyFromNode(const YAML::Node & node, std::string propertyName, T & property) const;
224  template<typename T>
225  bool GetProperty(YAML::Node & node, YAML::Node & sharedParametersNode, const std::string & configurationName, std::string propertyName, T & property) const;
226 
227  template<typename T>
228  void WriteValue(YAML::Node & node, std::string propertyName, T & proeprty);
229 
230  std::vector<std::pair<std::string, YAML::Node> > fConfigurations;
231  #endif
232  std::vector<std::pair<std::string, std::string> > fConfigurationsStrings;
233 
235  std::string fPrefixString;
236  std::string fDelimiter;
237 
239  ClassDef(AliYAMLConfiguration, 1); // YAML Configuration
241 };
242 
243 #if !(defined(__CINT__) || defined(__MAKECINT__))
244 
254 template<typename T>
255 auto AliYAMLConfiguration::PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, int) const -> decltype(tempMessage << property, void())
256 {
257  tempMessage << " with value \"" << property << "\"";
258 }
259 
268 template<typename T>
269 auto AliYAMLConfiguration::PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const std::vector <T> & property, int) const -> decltype(property.begin(), property.end(), tempMessage << std::declval<T>(), void())
270 {
271  tempMessage << " with value(s):";
272  for (auto it = property.begin(); it != property.end(); it++) {
273  tempMessage << "\n\t- " << *it;
274  }
275 }
276 
288 template<typename T>
289 void AliYAMLConfiguration::PrintRetrievedPropertyValueImpl(std::stringstream & tempMessage, const T & property, long) const
290 {
291  // Cannot easily print these types, so just note that is the case!
292  tempMessage << " with a value that cannot be trivially printed";
293 }
294 
306 template<typename T>
307 void AliYAMLConfiguration::PrintRetrievedPropertyValue(std::stringstream & tempMessage, const T & property) const
308 {
309  // By passing zero, it will first lookup the int, and then the long
311 }
312 
322 template<typename T>
323 bool AliYAMLConfiguration::GetPropertyFromNode(const YAML::Node & node, std::string propertyName, T & property) const
324 {
325  if (node[propertyName])
326  {
327  property = node[propertyName].as<T>();
328  return true;
329  }
330  return false;
331 }
332 
344 template<typename T>
345 bool AliYAMLConfiguration::GetProperty(std::vector <std::string> propertyPath, const std::string & propertyName, T & property, const bool requiredProperty) const
346 {
347  propertyPath.push_back(propertyName);
348  return GetProperty(propertyPath, property, requiredProperty);
349 }
350 
361 template<typename T>
362 bool AliYAMLConfiguration::GetProperty(const std::vector <std::string> propertyPath, T & property, const bool requiredProperty) const
363 {
364  // Combine the requested names together
365  std::string requestedName = "";
366  for (auto & str : propertyPath)
367  {
368  if (requestedName.length() > 0) {
369  requestedName += ":" + str;
370  }
371  else {
372  requestedName = str;
373  }
374  }
375 
376  // Pass on the properly requested call
377  return GetProperty(requestedName, property, requiredProperty);
378 }
379 
391 template<typename T>
392 bool AliYAMLConfiguration::GetProperty(std::string propertyName, T & property, const bool requiredProperty) const
393 {
394  // Remove the prefix string if in name
395  std::size_t prefixStringLocation = propertyName.find(fPrefixString);
396  if (prefixStringLocation != std::string::npos)
397  {
398  // Remove the prefix string
399  propertyName.erase(prefixStringLocation, prefixStringLocation + fPrefixString.length());
400  }
401 
402  bool setProperty = false;
403  for (auto configPair : fConfigurations)
404  {
405  if (setProperty == true) {
406  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Property \"" << propertyName << "\" found!\n";
407  break;
408  }
409 
410  // IsNull checks is a node is empty. A node is empty if it is created.
411  // IsDefined checks if the node that was requested was not actually created.
412  if (configPair.second.IsNull() != true)
413  {
414  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Looking for parameter \"" << propertyName << "\" in \"" << configPair.first << "\" configuration\n";
415  // NOTE: This may not exist, but that is entirely fine.
416  YAML::Node sharedParameters = configPair.second["sharedParameters"];
417  setProperty = GetProperty(configPair.second, sharedParameters, configPair.first, propertyName, property);
418  }
419  }
420 
421  if (setProperty != true && requiredProperty == true)
422  {
423  std::stringstream message;
424  message << "Failed to retrieve required property \""
425  << propertyName << "\" from available configurations!" << std::endl;
426  AliFatalGeneral("AliYAMLConfiguration", message.str().c_str());
427  }
428 
429  // Return whether the value was actually set
430  return setProperty;
431 }
432 
455 template<typename T>
456 bool AliYAMLConfiguration::GetProperty(YAML::Node & node, YAML::Node & sharedParametersNode, const std::string & configurationName, std::string propertyName, T & property) const
457 {
458  // Used as a buffer for printing complicated messages
459  std::stringstream tempMessage;
460 
461  bool returnValue = false;
462 
463  const std::string specializationDelimiter = "_";
464  size_t delimiterPosition = 0;
465  std::string tempPropertyName = propertyName;
466 
467  if ((delimiterPosition = tempPropertyName.find(fDelimiter)) != std::string::npos)
468  {
469  std::string nodeName = tempPropertyName.substr(0, delimiterPosition);
470  tempPropertyName.erase(0, delimiterPosition + fDelimiter.length());
471 
472  // Attempt to use the node name
473  if (node[nodeName].IsDefined() == true)
474  {
475  // Retrieve node and then recurse
476  YAML::Node tempNode = node[nodeName];
477  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Attempting to retrieving property \"" << tempPropertyName << "\" by going a node deeper with node \"" << nodeName << "\".\n";
478  returnValue = GetProperty(tempNode, sharedParametersNode, configurationName, tempPropertyName, property);
479  }
480 
481  // Check for the specialization if the nodeName is undefined.
482  // Alternatively, if the value was not returned successfully, we should also check for the specialization
483  // such as inheritnace for input objects.
484  if (node[nodeName].IsDefined() == false || returnValue == false)
485  {
486  // Check for specialization
487  if ((delimiterPosition = nodeName.find(specializationDelimiter)) != std::string::npos)
488  {
489  std::string specializationNodeName = nodeName.substr(0, delimiterPosition);
490  YAML::Node tempNode = node[specializationNodeName];
491  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Attempting to retrieving property \"" << tempPropertyName << "\" by going a node deeper through dropping the specializtion and using node \"" << specializationNodeName << "\".\n";
492  returnValue = GetProperty(tempNode, sharedParametersNode, configurationName, tempPropertyName, property);
493  }
494  else {
495  returnValue = false;
496  }
497  }
498  }
499  else
500  {
501  // Check if node exists!
502  if (node[propertyName])
503  {
504  // Handle shared parameters
505  bool isShared = false;
506  // Will contain the name of the property in the sharedParameters section that should be retrieved
507  // if it is requested through the user configuration.
508  std::string sharedValueName = "";
509  // Necessary because it fails on vectors and other complex objects that are YAML sequences.
510  if (std::is_arithmetic<T>::value || std::is_same<T, std::string>::value || std::is_same<T, bool>::value)
511  {
512  // Retrieve value as string to check for shared value
513  sharedValueName = node[propertyName].as<std::string>();
514  // Check for a shared value
515  isShared = IsSharedValue(sharedValueName);
516  }
517 
518  // Setup printable message
519  tempMessage.str("");
520  tempMessage << "property \""
521  << propertyName
522  << "\" using " << ( isShared ? "\"sharedParameters:" + sharedValueName + "\" in " : "" )
523  << "values from the " << configurationName << " configuration";
524 
525  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Retrieveing " << tempMessage.str() << "\n";
526 
527  // Retrieve result
528  bool retrievalResult = false;
529  if (isShared == true) {
530  // Retrieve from the shared parameter node directly.
531  retrievalResult = GetPropertyFromNode(sharedParametersNode, sharedValueName, property);
532  }
533  else {
534  retrievalResult = GetPropertyFromNode(node, propertyName, property);
535  }
536 
537  // Inform about the result
538  if (retrievalResult == true) {
539  // Add the retrieved value to the message (only if trivially printable)
541  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Succeeded in retrieveing " << tempMessage.str() << "\n";
542  returnValue = true;
543  }
544  else {
545  returnValue = false;
546  }
547  }
548  }
549 
550  return returnValue;
551 }
552 
563 template<typename T>
564 bool AliYAMLConfiguration::WriteProperty(std::string propertyName, T & property, std::string configurationName)
565 {
566  unsigned int configurationIndex = 0;
567  if (configurationName != "")
568  {
569  configurationIndex = GetConfigurationIndexFromName(configurationName, fConfigurations);
570  }
571 
572  if (fConfigurations.size() == 0) {
573  AliErrorStream() << "No configurations available! Property will not be written!\n";
574  return false;
575  }
576 
577  std::pair<std::string, YAML::Node> & configPair = fConfigurations.at(configurationIndex);
578 
579  WriteValue(configPair.second, propertyName, property);
580  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Final Node:\n" << configPair.second << "\n";
581 
582  return true;
583 }
584 
592 template<typename T>
593 void AliYAMLConfiguration::WriteValue(YAML::Node & node, std::string propertyName, T & property)
594 {
595  // Find the node name we are interested in
596  // Derived from: https://stackoverflow.com/a/14266139
597  const std::string delimiter = ":";
598  size_t delimiterPosition = 0;
599  std::string tempPropertyName = propertyName;
600 
601  if ((delimiterPosition = tempPropertyName.find(delimiter)) != std::string::npos)
602  {
603  std::string nodeName = tempPropertyName.substr(0, delimiterPosition);
604  tempPropertyName.erase(0, delimiterPosition + delimiter.length());
605  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "nodeName: " << nodeName << "\n";
606  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Node Before:\n" << node << "\n";
607  if (node[nodeName].IsDefined()) {
608  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Using existing node\n";
609  YAML::Node tempNode = node[nodeName];
610  WriteValue(tempNode, tempPropertyName, property);
611  }
612  else {
613  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Creating new node\n";
614  YAML::Node tempNode;
615  node[nodeName] = tempNode;
616  WriteValue(tempNode, tempPropertyName, property);
617  }
618  AliDebugGeneralStream("AliYAMLConfiguration", 2) << "Node After:\n" << node << "\n";
619  }
620  else {
621  // We have finished the recursion. Now we need to save the actual property.
622  node[propertyName] = property;
623  }
624 }
625 
626 #endif
627 
637 template<typename T>
638 unsigned int AliYAMLConfiguration::GetConfigurationIndexFromName(const std::string & name, const std::vector<std::pair<std::string, T>> & configurations) const
639 {
640  int index = -1;
641  for (const auto & configPair : configurations)
642  {
643  if (configPair.first == name) {
644  // Retrieve index
645  // See: https://stackoverflow.com/a/10962459
646  index = std::addressof(configPair) - std::addressof(configurations[0]);
647  break;
648  }
649  }
650 
651  return index;
652 }
653 
654 } // namespace Tools
655 } // namespace PWG
656 
657 #endif /* ALIYAMLCONFIGURATION_H */
bool RemoveConfiguration(const std::string &name)
const char * filename
Definition: TestFCM.C:1
bool CompareConfigurations(const int config1, const std::string &config2) const
bool CompareConfigurations(const int config1, const int config2) const
bool WriteConfiguration(const std::string &filename, const unsigned int i) const
const std::pair< std::string, YAML::Node > & GetConfiguration(const int i) const
void WriteConfigurationToFilePath(const std::string &localFilename, std::string filename) const
bool GetProperty(std::vector< std::string > propertyPath, const std::string &propertyName, T &property, const bool requiredProperty) const
bool fInitialized
True if the configurations have been initialized.
void SetupReadingConfigurationFilePath(std::string &filename, const std::string &fileIdentifier) const
bool DoesConfigurationExist(const int i) const
int GetConfigurationIndexFromName(const std::string &name) const
UShort_t T(UShort_t m, UShort_t t)
Definition: RingBits.C:60
const std::pair< std::string, YAML::Node > & GetConfiguration(const std::string &name) const
std::string fDelimiter
Delimiter character to separate each level of the request.
void PrintConfiguration(std::ostream &stream, const std::pair< std::string, YAML::Node > &configPair) const
bool DoesConfigurationExist(const std::string &name) const
std::ostream & operator<<(std::ostream &in, const PWG::Tools::AliYAMLConfiguration &myTask)
bool IsSharedValue(std::string &value) const
std::ostream & Print(std::ostream &in, const int index=-1) const
std::string fPrefixString
Contains the prefix of any names base node names which should be removed.
int AddEmptyConfiguration(const std::string &configurationName)
Add YAML configuration at configurationFilename to available configurations.
std::vector< std::pair< std::string, YAML::Node > > fConfigurations
! Contains all YAML configurations. The first element has the highest precedence. ...
bool CompareConfigurations(const std::string &config1, const std::string &config2) const
auto PrintRetrievedPropertyValueImpl(std::stringstream &tempMessage, const T &property, int) const -> decltype(tempMessage<< property, void())
std::pair< std::string, YAML::Node > & GetConfiguration(const int i)
AliYAMLConfiguration(const std::string prefixString="AliEmcalCorrection", const std::string delimiterCharacter=":")
std::vector< std::pair< std::string, std::string > > fConfigurationsStrings
Contains all YAML configurations as strings so that they can be streamed.
YAML configuration class for AliPhysics.
bool GetPropertyFromNode(const YAML::Node &node, std::string propertyName, T &property) const
bool WriteProperty(std::string propertyName, T &property, std::string configurationName="")
bool RemoveConfiguration(const unsigned int i)
void WriteValue(YAML::Node &node, std::string propertyName, T &proeprty)
int AddConfiguration(std::string configurationFilename, std::string configurationName="")
const char Option_t
Definition: External.C:48
bool DoesFileExist(const std::string &filename) const
std::string toString(const int index=-1) const
void PrintRetrievedPropertyValue(std::stringstream &tempMessage, const T &property) const
std::string GetConfigurationNameFromIndex(const unsigned int i) const
std::pair< std::string, YAML::Node > & GetConfiguration(const std::string &name)