REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestMetadata.cxx
1 /*************************************************************************
2  * This file is part of the REST software framework. *
3  * *
4  * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5  * For more information see http://gifna.unizar.es/trex *
6  * *
7  * REST is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * REST is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have a copy of the GNU General Public License along with *
18  * REST in $REST_PATH/LICENSE. *
19  * If not, see http://www.gnu.org/licenses/. *
20  * For the list of contributors see $REST_PATH/CREDITS. *
21  *************************************************************************/
22 
460 
461 #include "TRestMetadata.h"
462 
463 #include <TFormula.h>
464 #include <TMath.h>
465 #include <TStreamerInfo.h>
466 
467 #include <iomanip>
468 
469 #include "TRestDataBase.h"
470 
471 // implementation of version methods in namespace rest_version
472 /*
473 namespace REST_VersionGlob {
474  inline TString GetRESTVersion() const { return REST_RELEASE; }
475  inline int GetRESTVersionCode() const { return ConvertVersionCode(REST_RELEASE); }
476 }
477 */
478 using namespace std;
479 using namespace REST_Units;
480 using namespace REST_Physics;
481 
482 // We introduce the gases file here.
483 // But, should we have a corner somewhere to define hard-coded globals?
484 // nkx, 20200228: We now define the global data servers in database file
485 // const char* gasesFile = "https://sultan.unizar.es/gasFiles/gases.rml";
486 
487 map<string, string> TRestMetadata_UpdatedConfigFile;
488 
489 ClassImp(TRestMetadata);
493 TRestMetadata::TRestMetadata() : RESTendl(this) {
494  fStore = true;
495  fElementGlobal = nullptr;
496  fElement = nullptr;
497  fVerboseLevel = gVerbose;
498  fVariables.clear();
499  fConstants.clear();
500  fHostmgr = nullptr;
501 
502  fConfigFileName = "null";
503  configBuffer = "";
504  RESTMetadata.setlength(100);
505 
506 #ifdef WIN32
507  fOfficialRelease = true;
508  fCleanState = true;
509 #else
510  if (TRestTools::Execute("rest-config --release") == "Yes") fOfficialRelease = true;
511  if (TRestTools::Execute("rest-config --clean") == "Yes") fCleanState = true;
512 #endif
513 }
514 
515 TRestMetadata::TRestMetadata(const TRestMetadata&) : RESTendl(this) {
516  fStore = true;
517  fElementGlobal = nullptr;
518  fElement = nullptr;
519  fVerboseLevel = gVerbose;
520  fVariables.clear();
521  fConstants.clear();
522  fHostmgr = nullptr;
523 
524  fConfigFileName = "null";
525  configBuffer = "";
526  RESTMetadata.setlength(100);
527 
528 #ifdef WIN32
529  fOfficialRelease = true;
530  fCleanState = true;
531 #else
532  if (TRestTools::Execute("rest-config --release") == "Yes") fOfficialRelease = true;
533  if (TRestTools::Execute("rest-config --clean") == "Yes") fCleanState = true;
534 #endif
535 }
536 
540 TRestMetadata::TRestMetadata(const char* configFilename) : RESTendl(this) {
541  fStore = true;
542  fElementGlobal = nullptr;
543  fElement = nullptr;
544  fVerboseLevel = gVerbose;
545  fVariables.clear();
546  fConstants.clear();
547  fHostmgr = nullptr;
548 
549  fConfigFileName = configFilename;
550  configBuffer = "";
551  RESTMetadata.setlength(100);
552 
553 #ifdef WIN32
554  fOfficialRelease = true;
555  fCleanState = true;
556 #else
557  if (TRestTools::Execute("rest-config --release") == "Yes") fOfficialRelease = true;
558  if (TRestTools::Execute("rest-config --clean") == "Yes") fCleanState = true;
559 #endif
560 }
561 
566  delete fElementGlobal;
567  delete fElement;
568 }
569 
574 Int_t TRestMetadata::LoadConfigFromFile(const string& configFilename, const string& sectionName) {
575  fConfigFileName = configFilename;
576 
577  const string thisSectionName = sectionName.empty() ? this->ClassName() : sectionName;
578 
580 
582  // find the xml section corresponding to the sectionName
583  TiXmlElement* Sectional = GetElementFromFile(fConfigFileName, thisSectionName);
584  if (Sectional == nullptr) {
585  RESTError << "cannot find xml section \"" << ClassName() << "\" with name \"" << sectionName
586  << "\"" << RESTendl;
587  RESTError << "in config file: " << fConfigFileName << RESTendl;
588  exit(1);
589  }
590 
591  // find the "globals" section. Multiple sections are supported.
592  TiXmlElement* rootEle = GetElementFromFile(fConfigFileName);
593  TiXmlElement* Global = GetElement("globals", rootEle);
594  if (Global != nullptr) ReadElement(Global);
595  if (Global != nullptr && Global->NextSiblingElement("globals") != nullptr) {
596  TiXmlElement* ele = Global->NextSiblingElement("globals");
597  if (ele != nullptr) ReadElement(ele);
598  while (ele != nullptr) {
599  TiXmlElement* e = ele->FirstChildElement();
600  while (e != nullptr) {
601  Global->InsertEndChild(*e);
602  e = e->NextSiblingElement();
603  }
604  ele = ele->NextSiblingElement("globals");
605  }
606  }
607 
608  // call the real loading method
609  int result = LoadConfigFromElement(Sectional, Global, {});
610  delete Sectional;
611  delete rootEle;
612  return result;
613  } else {
614  RESTError << "Filename: " << fConfigFileName << RESTendl;
615  RESTError << "Config File does not exist. Right path/filename?" << RESTendl;
616  GetChar();
617  return -1;
618  }
619 
620  // find the xml section corresponding to the sectionName
621  TiXmlElement* sectional = GetElementFromFile(fConfigFileName, thisSectionName);
622  if (sectional == nullptr) {
623  RESTError << "cannot find xml section \"" << ClassName() << "\" with name \"" << thisSectionName
624  << "\"" << RESTendl;
625  RESTError << "in config file: " << fConfigFileName << RESTendl;
626  exit(1);
627  }
628 
629  // find the "globals" section. Multiple sections are supported.
630  TiXmlElement* rootEle = GetElementFromFile(fConfigFileName);
631  TiXmlElement* global = GetElement("globals", rootEle);
632  if (global != nullptr) ReadElement(global);
633  if (global != nullptr && global->NextSiblingElement("globals") != nullptr) {
634  TiXmlElement* ele = global->NextSiblingElement("globals");
635  if (ele != nullptr) ReadElement(ele);
636  while (ele != nullptr) {
637  TiXmlElement* e = ele->FirstChildElement();
638  while (e != nullptr) {
639  global->InsertEndChild(*e);
640  e = e->NextSiblingElement();
641  }
642  ele = ele->NextSiblingElement("globals");
643  }
644  }
645 
646  // call the real loading method
647  int result = LoadConfigFromElement(sectional, global, {});
648  delete sectional;
649  delete rootEle;
650  return result;
651 }
652 
660 Int_t TRestMetadata::LoadConfigFromElement(TiXmlElement* eSectional, TiXmlElement* eGlobal,
661  map<string, string> envs) {
662  Initialize();
663  TiXmlElement* theElement;
664  if (eSectional != nullptr && eGlobal != nullptr) {
665  // Sectional and global elements are first combined.
666  theElement = (TiXmlElement*)eSectional->Clone();
667  TiXmlElement* echild = eGlobal->FirstChildElement();
668  while (echild != nullptr) {
669  theElement->LinkEndChild(echild->Clone());
670  echild = echild->NextSiblingElement();
671  }
672  // for (int i = 0; i < eEnv.size(); i++) {
673  // theElement->LinkEndChild(eEnv[i]->Clone());
674  //}
675  } else if (eSectional != nullptr) {
676  theElement = (TiXmlElement*)eSectional->Clone();
677  } else if (eGlobal != nullptr) {
678  theElement = (TiXmlElement*)eGlobal->Clone();
679  } else {
680  return 0;
681  }
682  fElement = theElement;
683  fElementGlobal = eGlobal ? (TiXmlElement*)eGlobal->Clone() : nullptr;
684  fVariables = envs;
685 
686  int result = LoadSectionMetadata();
687  if (result == 0) InitFromConfigFile();
688  RESTDebug << ClassName() << " has finished preparing config data" << RESTendl;
689  return result;
690 }
691 
698  if (configBuffer != "") {
700  configBuffer = "";
702  return 0;
703  }
704  return -1;
705 }
706 
734 TRestMetadata* TRestMetadata::InstantiateChildMetadata(int index, std::string pattern) {
735  int count = 0;
736  auto paraele = fElement->FirstChildElement();
737  while (paraele != nullptr) {
738  std::string xmlChild = paraele->Value();
739  if (xmlChild.find("TRest") == 0) {
740  if (pattern == "" || xmlChild.find(pattern) != string::npos) {
741  if (count == index) {
742  TClass* c = TClass::GetClass(xmlChild.c_str());
743  if (c) // this means that the metadata class was found
744  {
745  TRestMetadata* md = (TRestMetadata*)c->New();
746  if (!md) return nullptr;
748  TiXmlElement* rootEle = GetElementFromFile(fConfigFileName);
749  TiXmlElement* Global = GetElement("globals", rootEle);
750  md->LoadConfigFromElement(paraele, Global, {});
751  md->Initialize();
752  return md;
753  }
754  }
755  count++;
756  }
757  }
758  paraele = paraele->NextSiblingElement();
759  }
760  return nullptr;
761 }
762 
788 TRestMetadata* TRestMetadata::InstantiateChildMetadata(std::string pattern, std::string name) {
789  auto paraele = fElement->FirstChildElement();
790  while (paraele != nullptr) {
791  std::string xmlChild = paraele->Value();
792  if (xmlChild.find("TRest") == 0) {
793  if (pattern.empty() || xmlChild.find(pattern) != string::npos) {
794  if (name.empty() || (!name.empty() && name == (string)paraele->Attribute("name"))) {
795  TClass* c = TClass::GetClass(xmlChild.c_str());
796  if (c) // this means we have the metadata class was found
797  {
798  TRestMetadata* md = (TRestMetadata*)c->New();
799  TiXmlElement* rootEle = GetElementFromFile(fConfigFileName);
800  TiXmlElement* Global = GetElement("globals", rootEle);
801  md->LoadConfigFromElement(paraele, Global, {});
802  md->Initialize();
803  return md;
804  }
805  }
806  }
807  }
808  paraele = paraele->NextSiblingElement();
809  }
810  return nullptr;
811 }
812 
823  // get debug level
824  string debugStr = GetParameter("verboseLevel", ToString(static_cast<int>(fVerboseLevel)));
825  fVerboseLevel = StringToVerboseLevel(debugStr);
826 
827  RESTDebug << "Loading Config for : " << this->ClassName() << RESTendl;
828 
829  // set env first from global section
830  if (fElementGlobal != nullptr) {
831  TiXmlElement* e = fElementGlobal->FirstChildElement();
832  while (e != nullptr) {
834  ReadEnvInElement(e);
835  e = e->NextSiblingElement();
836  }
837  }
838 
839  // then from local section
840  TiXmlElement* e = fElement->FirstChildElement();
841  while (e != nullptr) {
843  ReadEnvInElement(e);
844  e = e->NextSiblingElement();
845  }
846 
847  // look through the elements and expand for, include, etc. structures
849 
850  // get debug level again in case it is defined in the included file
851  debugStr = GetParameter("verboseLevel", ToString(static_cast<int>(fVerboseLevel)));
852  fVerboseLevel = StringToVerboseLevel(debugStr);
853 
854  // fill the general metadata info: name, title, fstore
855  this->SetName(GetParameter("name", "default" + string(this->ClassName())).c_str());
856  this->SetTitle(GetParameter("title", "Default " + string(this->ClassName())).c_str());
857  this->SetSectionName(this->ClassName());
858 
859  fStore = StringToBool(GetParameter("store", to_string(true)));
860 
861  return 0;
862 }
863 
870 TiXmlElement* TRestMetadata::ReplaceElementAttributes(TiXmlElement* e) {
871  if (e == nullptr) return nullptr;
872 
873  RESTDebug << "Entering ... TRestMetadata::ReplaceElementAttributes" << RESTendl;
874 
875  std::string parName = "";
876  TiXmlAttribute* attr = e->FirstAttribute();
877  while (attr != nullptr) {
878  const char* val = attr->Value();
879  const char* name = attr->Name();
880  RESTDebug << "Element name : " << name << " value : " << val << RESTendl;
881 
882  string newVal = val != nullptr ? val : "";
883  newVal = ReplaceVariables(newVal);
884 
885  // for name attribute, don't replace constants
886  if (strcmp(name, "name") != 0) newVal = ReplaceConstants(newVal);
887 
888  e->SetAttribute(name, ReplaceMathematicalExpressions(newVal));
889 
890  attr = attr->Next();
891  }
892 
893  return e;
894 }
895 
910 void TRestMetadata::ReadEnvInElement(TiXmlElement* e, bool overwrite) {
911  if (e == nullptr) return;
912 
913  const char* name = e->Attribute("name");
914  if (name == nullptr) return;
915  const char* value = e->Attribute("value");
916  if (value == nullptr) return;
917 
918  if ((string)e->Value() == "variable") {
919  // if overwrite is false, try to replace the value from system env.
920  const char* overwritesysenv = e->Attribute("overwrite");
921  if (overwritesysenv == nullptr) overwritesysenv = "false";
922  if (!StringToBool(overwritesysenv)) {
923  char* sysenv = getenv(name);
924  if (sysenv != nullptr) value = sysenv;
925  }
926  if (!overwrite && fVariables.count(name) > 0) return;
927  fVariables[name] = value;
928  } else if ((string)e->Value() == "constant") {
929  if (!overwrite && fVariables.count(name) > 0) return;
930  fConstants[name] = value;
931  } else if ((string)e->Value() == "myParameter") {
932  RESTWarning << "myParameter is obsolete now! use \"constant\" instead" << RESTendl;
933  if (!overwrite && fVariables.count(name) > 0) return;
934  fConstants[name] = value;
935  }
936 }
937 
946 void TRestMetadata::ReadElement(TiXmlElement* e, bool recursive) {
947  RESTDebug << ClassName() << "::ReadElement(<" << e->Value() << ")" << RESTendl;
948  if (e == nullptr) return;
949 
951  ReadEnvInElement(e);
952 
953  if ((string)e->Value() == "for") {
954  ExpandForLoops(e, {});
955  } else if (e->Attribute("file") != nullptr) {
957  } else if ((string)e->Value() == "if") {
958  ExpandIfSections(e);
959  } else if (e->FirstChildElement() != nullptr) {
960  TiXmlElement* contentelement = e->FirstChildElement();
961  // we won't expand child TRestXXX sections unless forced recursive. The expansion of
962  // these sections will be executed individually by the corresponding TRestXXX class
963  while (contentelement != nullptr) {
964  TiXmlElement* nxt = contentelement->NextSiblingElement();
965  if (recursive || ((string)contentelement->Value()).find("TRest") == string::npos) {
966  RESTDebug << "into child element \"" << contentelement->Value() << "\" of \"" << e->Value()
967  << "\"" << RESTendl;
968  ReadElement(contentelement, recursive);
969  } else {
970  RESTDebug << "skipping child element \"" << contentelement->Value() << "\" of \""
971  << e->Value() << "\"" << RESTendl;
972  }
973  contentelement = nxt;
974  }
975  }
976 }
977 
1003 void TRestMetadata::ExpandIfSections(TiXmlElement* e) {
1004  if (e == nullptr) return;
1005  if ((string)e->Value() != "if") return;
1006 
1007  const char* evaluate = e->Attribute("evaluate");
1008  const char* condition = e->Attribute("condition");
1009 
1010  if (condition == nullptr || string(condition).find_first_of("=!<>") == string::npos) {
1011  RESTWarning << "Invalid \"IF\" structure!" << RESTendl;
1012  return;
1013  }
1014 
1015  int p1 = string(condition).find_first_of("=!<>");
1016  int p2 = string(condition).find_first_not_of("=!<>", p1);
1017 
1018  string v1 = "";
1019  bool matches = false;
1020  if (evaluate != nullptr) {
1021  v1 = TRestTools::Execute(evaluate);
1022  } else if (p1 > 0) {
1023  v1 = string(condition).substr(0, p1);
1024  } else {
1025  RESTWarning << "Invalid \"IF\" structure!" << RESTendl;
1026  return;
1027  }
1028 
1029  string con = string(condition).substr(p1, p2 - p1);
1030  string v2 = string(condition).substr(p2, -1);
1031 
1032  if (con == "==") {
1033  if (isANumber(v1) && isANumber(v2)) {
1034  if (atof(v1.c_str()) == atof(v2.c_str())) matches = true;
1035  } else {
1036  if (v1 == v2) matches = true;
1037  }
1038  } else if (con == "!=") {
1039  if (isANumber(v1) && isANumber(v2)) {
1040  if (atof(v1.c_str()) != atof(v2.c_str())) matches = true;
1041  } else {
1042  if (v1 != v2) matches = true;
1043  }
1044  } else if (con == ">") {
1045  if (isANumber(v1) && isANumber(v2)) {
1046  if (atof(v1.c_str()) > atof(v2.c_str())) matches = true;
1047  } else {
1048  if (v1 > v2) matches = true;
1049  }
1050  } else if (con == "<") {
1051  if (isANumber(v1) && isANumber(v2)) {
1052  if (atof(v1.c_str()) < atof(v2.c_str())) matches = true;
1053  } else {
1054  if (v1 < v2) matches = true;
1055  }
1056  } else if (con == ">=") {
1057  if (isANumber(v1) && isANumber(v2)) {
1058  if (atof(v1.c_str()) >= atof(v2.c_str())) matches = true;
1059  } else {
1060  if (v1 >= v2) matches = true;
1061  }
1062  } else if (con == "<=") {
1063  if (isANumber(v1) && isANumber(v2)) {
1064  if (atof(v1.c_str()) <= atof(v2.c_str())) matches = true;
1065  } else {
1066  if (v1 <= v2) matches = true;
1067  }
1068  } else {
1069  RESTWarning << "Invalid \"IF\" structure!" << RESTendl;
1070  return;
1071  }
1072 
1073  if (matches) {
1074  TiXmlElement* parele = (TiXmlElement*)e->Parent();
1075  if (parele == nullptr) return;
1076  TiXmlElement* contentelement = e->FirstChildElement();
1077  while (contentelement != nullptr) {
1078  TiXmlElement* attachedelement = (TiXmlElement*)contentelement->Clone();
1079  ReadElement(attachedelement, true);
1080  // RESTDebug << *attachedelement << RESTendl;
1081  parele->InsertBeforeChild(e, *attachedelement);
1082  delete attachedelement;
1083  contentelement = contentelement->NextSiblingElement();
1084  }
1085  }
1086 }
1087 
1090 void TRestMetadata::ExpandForLoopOnce(TiXmlElement* e, const map<string, string>& forLoopVar) {
1091  if (e == nullptr) {
1092  return;
1093  }
1094 
1095  TiXmlElement* parele = (TiXmlElement*)e->Parent();
1096  TiXmlElement* contentelement = e->FirstChildElement();
1097  while (contentelement != nullptr) {
1098  if ((string)contentelement->Value() == "for") {
1099  TiXmlElement* newforloop = (TiXmlElement*)contentelement->Clone();
1100  // ReplaceElementAttributes(newforloop);
1101  TiXmlElement* tempnew = (TiXmlElement*)parele->InsertBeforeChild(e, *newforloop);
1102  delete newforloop;
1103  newforloop = tempnew;
1104  ExpandForLoops(newforloop, forLoopVar);
1105  contentelement = contentelement->NextSiblingElement();
1106  } else {
1107  TiXmlElement* attachedelement = (TiXmlElement*)contentelement->Clone();
1108  ReplaceForLoopVars(attachedelement, forLoopVar);
1109  ReadElement(attachedelement, true);
1110  // RESTDebug << *attachedelement << RESTendl;
1111  parele->InsertBeforeChild(e, *attachedelement);
1112  delete attachedelement;
1113  contentelement = contentelement->NextSiblingElement();
1114  }
1115  }
1116 }
1117 
1121 void TRestMetadata::ReplaceForLoopVars(TiXmlElement* e, map<string, string> forLoopVar) {
1122  if (e == nullptr) return;
1123 
1124  RESTDebug << "Entering ... TRestMetadata::ReplaceForLoopVars" << RESTendl;
1125  std::string parName;
1126  TiXmlAttribute* attr = e->FirstAttribute();
1127  while (attr != nullptr) {
1128  const char* val = attr->Value();
1129  const char* name = attr->Name();
1130  RESTDebug << "Attribute name : " << name << " value : " << val << RESTendl;
1131 
1132  if (strcmp(name, "name") == 0) parName = (string)val;
1133 
1134  // set attribute except name field
1135  if (strcmp(name, "name") != 0) {
1136  string outputBuffer = val;
1137 
1138  if (outputBuffer.find('[') != string::npos || outputBuffer.find(']') != string::npos) {
1139  RESTError << "TRestMetadata::ReplaceForLoopVars. Old for-loop construction identified"
1140  << RESTendl;
1141  RESTError << "Please, replace [] variable nomenclature by ${}." << RESTendl;
1142  exit(1);
1143  }
1144 
1145  // replace variables with mark ${}
1146  int startPosition = 0;
1147  int endPosition = 0;
1148  while ((startPosition = outputBuffer.find("{", endPosition)) != (int)string::npos) {
1149  endPosition = outputBuffer.find("}", startPosition + 1);
1150  if (endPosition == (int)string::npos) break;
1151  if (startPosition >= 1 && outputBuffer[startPosition - 1] == '$')
1152  break; // to prevent replacing ${} mark
1153 
1154  string expression = outputBuffer.substr(startPosition + 1, endPosition - startPosition - 1);
1155 
1156  int replacePos = startPosition;
1157  int replaceLen = endPosition - startPosition + 1;
1158 
1159  string proenv = forLoopVar.count(expression) > 0 ? forLoopVar[expression] : "";
1160 
1161  if (!proenv.empty()) {
1162  outputBuffer.replace(replacePos, replaceLen, proenv);
1163  endPosition = 0;
1164  } else {
1165  RESTError << this->ClassName() << ", replace for loop env : cannot find \"{" << expression
1166  << "}\"" << RESTendl;
1167  exit(1);
1168  }
1169  }
1170 
1171  e->SetAttribute(name, ReplaceMathematicalExpressions(
1172  outputBuffer, 0,
1173  "Please, check parameter name: " + parName + " (ReplaceForLoopVars)")
1174  .c_str());
1175  }
1176 
1177  attr = attr->Next();
1178  }
1179 }
1180 
1188 void TRestMetadata::ExpandForLoops(TiXmlElement* e, map<string, string> forloopvar) {
1189  if (e == nullptr) return;
1190  if ((string)e->Value() != "for") return;
1191  RESTDebug << "Entering ... ExpandForLoops" << RESTendl;
1193 
1194  TString varname = TString(e->Attribute("variable"));
1195  TString varfrom = TString(e->Attribute("from"));
1196  TString varto = TString(e->Attribute("to"));
1197  TString varstep = TString(e->Attribute("step"));
1198  TString varin = TString(e->Attribute("in"));
1199 
1200  RESTDebug << "variable: " << varname << " from: " << varfrom << " to: " << varto << " step: " << varstep
1201  << " in: " << varin << RESTendl;
1202 
1203  if ((varin == "") && (varname == "" || varfrom == "" || varto == "")) return;
1204  if (varstep == "") varstep = "1";
1205  TiXmlElement* parele = (TiXmlElement*)e->Parent();
1206  if (parele == nullptr) return;
1207 
1208  string _name = (string)varname;
1209  string _from = (string)varfrom;
1210  string _to = (string)varto;
1211  string _step = (string)varstep;
1212  string _in = (string)varin;
1213  RESTDebug << "_from: " << _from << " _to: " << _to << " _step: " << _step << RESTendl;
1214  if (isANumber(_from) && isANumber(_to) && isANumber(_step)) {
1215  double from = StringToDouble(_from);
1216  double to = StringToDouble(_to);
1217  double step = StringToDouble(_step);
1218 
1219  RESTDebug << "----expanding for loop----" << RESTendl;
1220  double i = 0;
1221  for (i = from; i <= to; i = i + step) {
1222  forloopvar[_name] = ToString(i);
1223  fVariables[_name] = ToString(i);
1224  ExpandForLoopOnce(e, forloopvar);
1225  }
1226  parele->RemoveChild(e);
1227 
1228  if (fVerboseLevel >= TRestStringOutput::REST_Verbose_Level::REST_Extreme) parele->Print(stdout, 0);
1229  RESTDebug << "----end of for loop----" << RESTendl;
1230  } else if (!_in.empty()) {
1231  vector<string> loopvars = Split(_in, ":");
1232 
1233  RESTDebug << "----expanding for loop----" << RESTendl;
1234  for (const string& loopvar : loopvars) {
1235  forloopvar[_name] = loopvar;
1236  fVariables[_name] = loopvar;
1237  ExpandForLoopOnce(e, forloopvar);
1238  }
1239  parele->RemoveChild(e);
1240 
1241  if (fVerboseLevel >= TRestStringOutput::REST_Verbose_Level::REST_Extreme) parele->Print(stdout, 0);
1242  RESTDebug << "----end of for loop----" << RESTendl;
1243  }
1244  // variable defined in for loop should be temporal
1245  fVariables.erase(_name);
1246 }
1247 
1268 void TRestMetadata::ExpandIncludeFile(TiXmlElement* e) {
1269  RESTDebug << "Entering ... " << __PRETTY_FUNCTION__ << RESTendl;
1270  if (e == nullptr) return;
1271 
1273  const char* _filename = e->Attribute("file");
1274  if (_filename == nullptr) return;
1275 
1276  string filename;
1277  if (string(_filename) == "server" || TRestTools::isURL(_filename)) {
1278  // Let TRestRun to retrieve data according to run number later-on
1279 
1280  // match the database, runNumber=0(default data), type="META_RML", tag=<section name>
1281  auto url = gDataBase->query_data(DBEntry(0, "META_RML", e->Value())).value;
1282  if (url.empty()) {
1283  // don't really understand this "database" code, this just works
1284  url = _filename;
1285  }
1286 
1287  filename = TRestTools::DownloadRemoteFile(url, true);
1288  } else {
1289  filename = SearchFile(_filename);
1290  }
1291 
1292  if (filename.empty()) {
1293  RESTError << "TRestMetadata::ExpandIncludeFile. Include file \"" << _filename << "\" does not exist!"
1294  << RESTendl;
1295  exit(1);
1296  return;
1297  }
1298  if (!TRestTools::isRootFile(filename)) // root file inclusion is implemented in TRestRun
1299  {
1300  RESTDebug << "----expanding include file----" << RESTendl;
1301  // we find the local element(the element to receive content)
1302  // and the remote element(the element to provide content)
1303  TiXmlElement* remoteele = nullptr;
1304  TiXmlElement* localele = nullptr;
1305  string type;
1306  string name;
1307 
1309  // condition 1(raw file include):
1310  // <TRestXXX name="" .....>
1311  // <include file="aaa.rml"/>
1312  // ....
1313  // </TRestXXX>
1314  //
1315  // We will insert all the xml elements in aaa.rml into this section
1316  if ((string)e->Value() == "include") {
1317  localele = (TiXmlElement*)e->Parent();
1318  if (localele == nullptr) return;
1319  if (localele->Attribute("expanded") == nullptr
1320  ? false
1321  : ((string)localele->Attribute("expanded") == "true")) {
1322  RESTDebug << "----already expanded----" << RESTendl;
1323  return;
1324  }
1325 
1326  remoteele = new TiXmlElement("Config");
1327 
1328  TiXmlElement* ele = GetElementFromFile(filename);
1329  if (ele == nullptr) {
1330  RESTError << "TRestMetadata::ExpandIncludeFile. No xml elements contained in the include "
1331  "file \""
1332  << filename << "\"" << RESTendl;
1333  exit(1);
1334  }
1335  while (ele != nullptr) {
1336  remoteele->InsertEndChild(*ele);
1337  ele = ele->NextSiblingElement();
1338  }
1339 
1340  }
1341 
1343  // condition 2(auto insert):
1344  // <TRestXXX file=""/>
1345  // or
1346  // <TRestXXX name="" ... file="aaa.rml" .../>
1347  // or
1348  // <addXXX name="" ... file="aaa.rml" .../>
1349  // or
1350  // <addXXX type="" name="" ... file="aaa.rml" .../>
1351  //
1352  // Here TRestXXX will be "type". we will find the corresponding section, and
1353  // insert all its attributes and child elements into this section. "name"
1354  // overwrites "type"
1355  else {
1356  localele = e;
1357  if (localele->Attribute("expanded") == nullptr
1358  ? false
1359  : ((string)localele->Attribute("expanded") == "true")) {
1360  RESTDebug << "----already expanded----" << RESTendl;
1361  return;
1362  }
1363 
1364  type = e->Attribute("type") != nullptr ? e->Attribute("type") : e->Value();
1365  name = localele->Attribute("name") == nullptr ? "" : localele->Attribute("name");
1366 
1367  // get the root element
1368  TiXmlElement* rootele = GetElementFromFile(filename);
1369  if (rootele == nullptr) {
1370  RESTError << "TRestMetaddata::ExpandIncludeFile. Include file " << filename
1371  << " is of wrong xml format!" << RESTendl;
1372  exit(1);
1373  return;
1374  }
1375  if ((string)rootele->Value() == type) {
1376  // if root element in the included file is of given type, directly use
1377  // it
1378  remoteele = rootele;
1379  } else {
1380  // import env first
1381  if (type != "globals" && GetElement("globals", rootele) != nullptr) {
1382  TiXmlElement* globaldef = GetElement("globals", rootele)->FirstChildElement();
1383  while (globaldef != nullptr) {
1384  ReadEnvInElement(globaldef, false);
1385  globaldef = globaldef->NextSiblingElement();
1386  }
1387  }
1388 
1389  // find its child section according to type and name
1390  if (name != "") {
1391  // we find only according to the name
1392  vector<TiXmlElement*> eles;
1393  TiXmlElement* ele = rootele->FirstChildElement();
1394  while (ele != nullptr) {
1395  if (ele->Attribute("name") != nullptr && (string)ele->Attribute("name") == name) {
1396  eles.push_back(ele);
1397  }
1398  ele = ele->NextSiblingElement();
1399  }
1400  // more than 1 element found
1401  if (eles.size() > 1) {
1402  RESTWarning << "(expand include file): find multiple xml sections with same name!"
1403  << RESTendl;
1404  RESTWarning << "Using the first one!" << RESTendl;
1405  }
1406 
1407  if (eles.size() > 0) remoteele = (TiXmlElement*)eles[0]->Clone();
1408  } else if (type != "") {
1409  remoteele = (TiXmlElement*)GetElement(type, rootele)->Clone();
1410  }
1411 
1412  if (remoteele == nullptr) {
1413  RESTWarning << "Cannot find the needed xml section in "
1414  "include file!"
1415  << RESTendl;
1416  RESTWarning << "type: \"" << type << "\" , name: \"" << name << "\" . Skipping"
1417  << RESTendl;
1418  RESTWarning << RESTendl;
1419  return;
1420  }
1421  delete rootele;
1422  }
1423  }
1424 
1425  RESTDebug << "Target xml element spotted" << RESTendl;
1426 
1428  // begin inserting remote element into local element
1429  ReadElement(remoteele, true);
1430  int nattr = 0;
1431  int nele = 0;
1432  TiXmlAttribute* attr = remoteele->FirstAttribute();
1433  while (attr != nullptr) {
1434  if (localele->Attribute(attr->Name()) == nullptr) {
1435  localele->SetAttribute(attr->Name(), attr->Value());
1436  nattr++;
1437  }
1438  attr = attr->Next();
1439  }
1440  TiXmlElement* ele = remoteele->FirstChildElement();
1441  while (ele != nullptr) {
1442  // ReadElement(ele);
1443  if ((string)ele->Value() != "for") {
1444  localele->InsertEndChild(*ele);
1445  nele++;
1446  }
1447  ele = ele->NextSiblingElement();
1448  }
1449 
1450  localele->SetAttribute("expanded", "true");
1452  localele->Print(stdout, 0);
1453  cout << endl;
1454  }
1455  delete remoteele;
1456  RESTDebug << nattr << " attributes and " << nele << " xml elements added by inclusion" << RESTendl;
1457  RESTDebug << "----end of expansion file----" << RESTendl;
1458  }
1459 }
1460 
1472 string TRestMetadata::GetParameter(std::string parName, TString defaultValue) {
1473  // first search the parameter in REST args
1474  if (REST_ARGS.count(parName) != 0) {
1475  return REST_ARGS[parName];
1476  }
1477 
1478  // then look within local xml element
1479  string result = GetParameter(parName, fElement);
1480  if (result != PARAMETER_NOT_FOUND_STR) {
1481  return result;
1482  }
1483 
1484  return (string)defaultValue;
1485 }
1486 
1511 string TRestMetadata::GetParameter(std::string parName, TiXmlElement* e, TString defaultValue) {
1512  if (e == nullptr) {
1513  RESTDebug << "Element is null" << RESTendl;
1514  return (string)defaultValue;
1515  }
1516  string result = (string)defaultValue;
1517  // first find in attribute
1518  if (e->Attribute(parName.c_str()) != nullptr) {
1519  result = e->Attribute(parName.c_str());
1520  }
1521  // then find in child sections/elements
1522  else {
1523  TiXmlElement* element = GetElementWithName("parameter", parName, e);
1524  if (element != nullptr && element->Attribute("value") != nullptr) {
1525  result = element->Attribute("value");
1526  } else {
1527  RESTDebug << ClassName() << ": Parameter : " << parName << " not found!" << RESTendl;
1528  }
1529  }
1530 
1532  "Please, check parameter name: " + parName);
1533 }
1534 
1535 Double_t TRestMetadata::GetDblParameterWithUnits(std::string parName, TiXmlElement* ele,
1536  Double_t defaultVal) {
1537  if (ele == nullptr) return defaultVal;
1538  pair<string, string> val_unit = GetParameterAndUnits(parName, ele);
1539  string val = val_unit.first;
1540  string unit = val_unit.second;
1541  if (val == PARAMETER_NOT_FOUND_STR) {
1542  return defaultVal;
1543  } else {
1544  Double_t value = StringToDouble(val);
1545  return REST_Units::ConvertValueToRESTUnits(value, unit);
1546  }
1547 
1548  return defaultVal;
1549 }
1550 
1551 TVector2 TRestMetadata::Get2DVectorParameterWithUnits(std::string parName, TiXmlElement* ele,
1552  TVector2 defaultVal) {
1553  if (ele == nullptr) return defaultVal;
1554  pair<string, string> val_unit = GetParameterAndUnits(parName, ele);
1555  string val = val_unit.first;
1556  string unit = val_unit.second;
1557  if (val == PARAMETER_NOT_FOUND_STR) {
1558  return defaultVal;
1559  } else {
1560  TVector2 value = StringTo2DVector(val);
1561  Double_t valueX = REST_Units::ConvertValueToRESTUnits(value.X(), unit);
1562  Double_t valueY = REST_Units::ConvertValueToRESTUnits(value.Y(), unit);
1563  return TVector2(valueX, valueY);
1564  }
1565 
1566  return defaultVal;
1567 }
1568 
1569 TVector3 TRestMetadata::Get3DVectorParameterWithUnits(std::string parName, TiXmlElement* ele,
1570  TVector3 defaultVal) {
1571  if (ele == nullptr) return defaultVal;
1572  pair<string, string> val_unit = GetParameterAndUnits(parName, ele);
1573  string val = val_unit.first;
1574  string unit = val_unit.second;
1575  if (val == PARAMETER_NOT_FOUND_STR) {
1576  return defaultVal;
1577  } else {
1578  TVector3 value = StringTo3DVector(val);
1579  Double_t valueX = REST_Units::ConvertValueToRESTUnits(value.X(), unit);
1580  Double_t valueY = REST_Units::ConvertValueToRESTUnits(value.Y(), unit);
1581  Double_t valueZ = REST_Units::ConvertValueToRESTUnits(value.Z(), unit);
1582  return TVector3(valueX, valueY, valueZ);
1583  }
1584 
1585  return defaultVal;
1586 }
1587 
1595 std::string TRestMetadata::GetFieldValue(std::string parName, TiXmlElement* e) {
1596  if (e == nullptr) {
1597  RESTDebug << "Element is null" << RESTendl;
1598  return "Not defined";
1599  }
1600  const char* val = e->Attribute(parName.c_str());
1601  if (val == nullptr) {
1602  return "Not defined";
1603  }
1604 
1605  string result = (string)val;
1606  result = Replace(result, " AND ", " && ");
1607  result = Replace(result, " OR ", " || ");
1608 
1609  return result;
1610 }
1611 
1641 Double_t TRestMetadata::GetDblParameterWithUnits(std::string parName, Double_t defaultVal) {
1642  pair<string, string> val_unit = GetParameterAndUnits(parName);
1643  string val = val_unit.first;
1644  string unit = val_unit.second;
1645  if (val == PARAMETER_NOT_FOUND_STR) {
1646  return defaultVal;
1647  } else {
1648  Double_t value = StringToDouble(val);
1649  return REST_Units::ConvertValueToRESTUnits(value, unit);
1650  }
1651  return defaultVal;
1652 }
1653 
1654 TVector2 TRestMetadata::Get2DVectorParameterWithUnits(std::string parName, TVector2 defaultVal) {
1655  pair<string, string> val_unit = GetParameterAndUnits(parName);
1656  string val = val_unit.first;
1657  string unit = val_unit.second;
1658  if (val == PARAMETER_NOT_FOUND_STR) {
1659  return defaultVal;
1660  } else {
1661  TVector2 value = StringTo2DVector(val);
1662  Double_t valueX = REST_Units::ConvertValueToRESTUnits(value.X(), unit);
1663  Double_t valueY = REST_Units::ConvertValueToRESTUnits(value.Y(), unit);
1664  return TVector2(valueX, valueY);
1665  }
1666  return defaultVal;
1667 }
1668 
1669 TVector3 TRestMetadata::Get3DVectorParameterWithUnits(std::string parName, TVector3 defaultVal) {
1670  pair<string, string> val_unit = GetParameterAndUnits(parName);
1671  string val = val_unit.first;
1672  string unit = val_unit.second;
1673  if (val == PARAMETER_NOT_FOUND_STR) {
1674  return defaultVal;
1675  } else {
1676  TVector3 value = StringTo3DVector(val);
1677  Double_t valueX = REST_Units::ConvertValueToRESTUnits(value.X(), unit);
1678  Double_t valueY = REST_Units::ConvertValueToRESTUnits(value.Y(), unit);
1679  Double_t valueZ = REST_Units::ConvertValueToRESTUnits(value.Z(), unit);
1680  return TVector3(valueX, valueY, valueZ);
1681  }
1682  return defaultVal;
1683 }
1684 
1700 TiXmlElement* TRestMetadata::GetElementFromFile(std::string configFilename, std::string NameOrDeclare) {
1701  TiXmlDocument doc;
1702  TiXmlElement* rootele;
1703 
1704  string filename = configFilename;
1705  if (TRestMetadata_UpdatedConfigFile.count(filename) > 0)
1706  filename = TRestMetadata_UpdatedConfigFile[filename];
1707 
1708  if (!TRestTools::fileExists(filename)) {
1709  RESTError << "Config file does not exist. The file is: " << filename << RESTendl;
1710  exit(1);
1711  }
1712 
1713  if (!doc.LoadFile(filename.c_str())) {
1714  RESTError << "Failed to load xml file, syntax maybe wrong. The file is: " << filename << RESTendl;
1715  exit(1);
1716  }
1717 
1718  rootele = doc.RootElement();
1719  if (rootele == nullptr) {
1720  RESTError << "The rml file \"" << configFilename << "\" does not contain any valid elements!"
1721  << RESTendl;
1722  exit(1);
1723  }
1724  if (NameOrDeclare == "") {
1725  return (TiXmlElement*)rootele->Clone();
1726  }
1727  // search with either name or declare in either root element or sub-root
1728  // element
1729  while (rootele != nullptr) {
1730  if (rootele->Value() != nullptr && (string)rootele->Value() == NameOrDeclare) {
1731  return (TiXmlElement*)rootele->Clone();
1732  }
1733 
1734  if (rootele->Attribute("name") != nullptr && (string)rootele->Attribute("name") == NameOrDeclare) {
1735  return (TiXmlElement*)rootele->Clone();
1736  }
1737 
1738  TiXmlElement* etemp = GetElement(NameOrDeclare, rootele);
1739  if (etemp != nullptr) {
1740  return (TiXmlElement*)etemp->Clone();
1741  }
1742 
1743  etemp = GetElementWithName("", NameOrDeclare, rootele);
1744 
1745  if (etemp != nullptr) {
1746  return (TiXmlElement*)etemp->Clone();
1747  }
1748 
1749  rootele = rootele->NextSiblingElement();
1750  }
1751 
1752  return nullptr;
1753  /*ferr << "Cannot find xml element with name \""<< NameOrDeclare <<"\" in rml
1754  file \"" << configFilename << endl; GetChar(); exit(1);*/
1755 }
1756 
1761 TiXmlElement* TRestMetadata::GetElement(std::string eleDeclare, TiXmlElement* e) {
1762  if (e == nullptr) e = fElement;
1763  return e->FirstChildElement(eleDeclare.c_str());
1764 }
1765 
1769 TiXmlElement* TRestMetadata::GetNextElement(TiXmlElement* e) {
1770  if (e == nullptr) return nullptr;
1771  return e->NextSiblingElement(e->Value());
1772 }
1773 
1778 TiXmlElement* TRestMetadata::GetElementWithName(std::string eleDeclare, std::string eleName) {
1779  return GetElementWithName(eleDeclare, eleName, fElement);
1780 }
1781 
1786 TiXmlElement* TRestMetadata::GetElementWithName(std::string eleDeclare, std::string eleName,
1787  TiXmlElement* e) {
1788  if (e == nullptr) return nullptr;
1789  if (eleDeclare == "") // find only with name
1790  {
1791  TiXmlElement* ele = e->FirstChildElement();
1792  while (ele != nullptr) {
1793  if (ele->Attribute("name") != nullptr) {
1794  std::string nameValue = (string)ele->Attribute("name");
1795  nameValue = ReplaceVariables(nameValue);
1796  if (nameValue == eleName) {
1797  return ele;
1798  }
1799  }
1800  ele = ele->NextSiblingElement();
1801  }
1802  return ele;
1803  } else // find with name and declare
1804  {
1805  TiXmlElement* ele = e->FirstChildElement(eleDeclare.c_str());
1806  while (ele != nullptr) {
1807  if (ele->Attribute("name") != nullptr) {
1808  std::string nameValue = (string)ele->Attribute("name");
1809  nameValue = ReplaceVariables(nameValue);
1810  if (nameValue == eleName) {
1811  return ele;
1812  }
1813  }
1814  ele = ele->NextSiblingElement(eleDeclare.c_str());
1815  }
1816  return ele;
1817  }
1818 
1819  return nullptr;
1820 }
1821 
1829 string TRestMetadata::GetUnits(TiXmlElement* e) {
1830  if (e == nullptr) {
1831  RESTWarning << "TRestMetadata::GetUnits(): NULL element given!" << RESTendl;
1832  return "";
1833  }
1834 
1835  string valstr = e->Attribute("value") == nullptr ? "" : e->Attribute("value");
1836  string unitattr = e->Attribute("units") == nullptr ? "" : e->Attribute("units");
1837 
1838  string unitembeded = REST_Units::FindRESTUnitsInString(valstr);
1839  if (IsUnit(unitembeded)) {
1840  return unitembeded;
1841  }
1842  if (IsUnit(unitattr)) {
1843  return unitattr;
1844  }
1845  return "";
1846 }
1847 
1858 pair<string, string> TRestMetadata::GetParameterAndUnits(string parName, TiXmlElement* e) {
1859  string parvalue;
1860  if (e == nullptr) {
1861  parvalue = GetParameter(parName);
1862  e = fElement;
1863  } else {
1864  parvalue = GetParameter(parName, e);
1865  }
1866 
1867  if (parvalue == PARAMETER_NOT_FOUND_STR) {
1868  return {parvalue, ""};
1869  } else {
1870  // first try to use unit embeded in parvalue
1871  string unit = REST_Units::FindRESTUnitsInString(parvalue);
1872  // then try to find unit in corresponding "parameter" section
1873  if (unit == "") {
1874  TiXmlElement* paraele = GetElementWithName("parameter", parName, e);
1875  if (paraele != nullptr) {
1876  unit = GetUnits(paraele);
1877  }
1878  }
1879  // finally try to find unit in local section attribute
1880  if (unit == "") {
1881  unit = GetUnits(e);
1882  }
1883  return {REST_Units::RemoveUnitsFromString(parvalue), unit};
1884  }
1885  return {parvalue, ""};
1886 }
1887 
1893 TiXmlElement* TRestMetadata::StringToElement(string definition) {
1894  TiXmlElement* ele = new TiXmlElement("temp");
1895  // TiXmlDocument*doc = new TiXmlDocument();
1896  ele->Parse(definition.c_str(), nullptr, TIXML_ENCODING_UTF8);
1897  return ele;
1898 }
1899 
1905 string TRestMetadata::ElementToString(TiXmlElement* ele) {
1906  if (ele != nullptr) {
1907  // remove comments
1908  TiXmlNode* n = ele->FirstChild();
1909  while (n != nullptr) {
1910  TiXmlComment* cmt = n->ToComment();
1911  if (cmt != nullptr) {
1912  TiXmlNode* nn = n;
1913  n = n->NextSibling();
1914  ele->RemoveChild(nn);
1915  continue;
1916  }
1917  n = n->NextSibling();
1918  }
1919 
1920  stringstream ss;
1921  ss << (*ele);
1922  string s = ss.str();
1923 
1924  // int pos = 0;
1925  // int pos2 = 0;
1926  // while ((pos = s.find("<!--", pos)) != -1 && (pos2 = s.find("-->", pos))
1927  // != -1)
1928  //{
1929  // s.replace(pos, pos2 - pos + 3, "");//3 is the length of "-->"
1930  // pos = pos + 1;
1931  //}
1932 
1933  return s;
1934  }
1935 
1936  return " ";
1937 }
1938 
1951 string TRestMetadata::GetKEYStructure(std::string keyName) {
1952  size_t Position = 0;
1953  string result = GetKEYStructure(keyName, Position, fElement);
1954  if (result == "") result = "NotFound";
1955  return result;
1956 }
1957 string TRestMetadata::GetKEYStructure(std::string keyName, size_t& Position) {
1958  string result = GetKEYStructure(keyName, Position, fElement);
1959  if (result == "") result = "NotFound";
1960  return result;
1961 }
1962 string TRestMetadata::GetKEYStructure(std::string keyName, string buffer) {
1963  size_t Position = 0;
1964  string result = GetKEYStructure(keyName, Position, buffer);
1965  if (result == "") result = "NotFound";
1966  return result;
1967 }
1968 string TRestMetadata::GetKEYStructure(std::string keyName, size_t& fromPosition, string buffer) {
1969  TiXmlElement* ele = StringToElement(buffer);
1970  string result = GetKEYStructure(keyName, fromPosition, ele);
1971  delete ele;
1972  return result;
1973 }
1974 string TRestMetadata::GetKEYStructure(std::string keyName, size_t& fromPosition, TiXmlElement* ele) {
1975  RESTDebug << "Finding " << fromPosition << "th appearance of KEY Structure \"" << keyName << "\"..."
1976  << RESTendl;
1977 
1978  TiXmlElement* childele = ele->FirstChildElement(keyName);
1979  for (unsigned int i = 0; childele != nullptr && i < fromPosition; i++) {
1980  childele = childele->NextSiblingElement(keyName);
1981  }
1982  if (childele != nullptr) {
1983  string result = ElementToString(childele);
1984  fromPosition = fromPosition + 1;
1985  RESTDebug << "Found Key : " << result << RESTendl;
1986  return result;
1987  }
1988 
1989  RESTDebug << "Finding hit the end, KEY Structure not found!!" << RESTendl;
1990  return "";
1991 }
1992 
2003 string TRestMetadata::GetKEYDefinition(string keyName) {
2004  string buffer = ElementToString(fElement);
2005  size_t Position = 0;
2006  return GetKEYDefinition(keyName, Position, buffer);
2007 }
2008 string TRestMetadata::GetKEYDefinition(string keyName, size_t& fromPosition) {
2009  string buffer = ElementToString(fElement);
2010  return GetKEYDefinition(keyName, fromPosition, buffer);
2011 }
2012 string TRestMetadata::GetKEYDefinition(string keyName, string buffer) {
2013  size_t Position = 0;
2014  return GetKEYDefinition(keyName, Position, buffer);
2015 }
2016 string TRestMetadata::GetKEYDefinition(string keyName, size_t& fromPosition, string buffer) {
2017  string key = "<" + keyName;
2018  size_t startPos = buffer.find(key, fromPosition);
2019  if (startPos == string::npos) return "";
2020  size_t endPos = buffer.find(">", startPos);
2021  if (endPos == string::npos) return "";
2022 
2023  fromPosition = endPos;
2024 
2025  Int_t notDefinitionEnd = 1;
2026 
2027  while (notDefinitionEnd) {
2028  // We might find a problem when we insert > symbol inside a field value.
2029  // As for example: condition=">100" This patch checks if the definition
2030  // finishes in "= If it is the case it searches the next > symbol ending
2031  // the definition.
2032 
2033  string def = RemoveWhiteSpaces(buffer.substr(startPos, endPos - startPos));
2034 
2035  if ((TString)def[def.length() - 1] == "\"" && (TString)def[def.length() - 2] == "=")
2036  endPos = buffer.find(">", endPos + 1);
2037  else
2038  notDefinitionEnd = 0;
2039  }
2040 
2041  string result = buffer.substr(startPos, endPos - startPos + 1);
2042  if (result[result.size() - 2] != '/') result.insert(result.size() - 1, 1, '/');
2043  // cout << result << endl << endl;
2044  // getchar();
2045  return result;
2046 }
2047 
2053 string TRestMetadata::FieldNamesToUpper(string definition) {
2054  string result = definition;
2055  TiXmlElement* e = StringToElement(definition);
2056  if (e == nullptr) return nullptr;
2057 
2058  TiXmlAttribute* attr = e->FirstAttribute();
2059  while (attr != nullptr) {
2060  string parName = std::string(attr->Name());
2061 
2062  size_t pos = 0;
2063  result = Replace(result, parName, ToUpper(parName), pos);
2064 
2065  attr = attr->Next();
2066  }
2067 
2068  return result;
2069 }
2070 
2075 std::string TRestMetadata::GetFieldValue(std::string fieldName, std::string definition, size_t fromPosition) {
2076  TiXmlElement* ele = StringToElement(FieldNamesToUpper(definition));
2077  string value = GetFieldValue(ToUpper(fieldName), ele);
2078  delete ele;
2079  return value;
2080 }
2081 
2089 string TRestMetadata::GetParameter(string parName, size_t& pos, string inputString) {
2090  pos = inputString.find(parName, pos);
2091 
2092  TiXmlElement* ele = StringToElement(inputString);
2093  string value = GetParameter(parName, ele);
2094 
2095  delete ele;
2096  return value;
2097 }
2098 
2108 string TRestMetadata::ReplaceVariables(const string buffer) {
2109  RESTDebug << "Entering ... TRestMetadata::ReplaceVariables (" << buffer << ")" << RESTendl;
2110  string outputBuffer = buffer;
2111 
2112  // replace variables with mark ${}
2113  int startPosition = 0;
2114  int endPosition = 0;
2115  while ((startPosition = outputBuffer.find("${", endPosition)) != (int)string::npos) {
2116  endPosition = outputBuffer.find("}", startPosition + 2);
2117  if (endPosition == (int)string::npos) break;
2118 
2119  string expression = outputBuffer.substr(startPosition + 2, endPosition - startPosition - 2);
2120 
2121  int replacePos = startPosition;
2122  int replaceLen = endPosition - startPosition + 1;
2123 
2124  string sysenv = getenv(expression.c_str()) != nullptr ? getenv(expression.c_str()) : "";
2125  string proenv = fVariables.count(expression) > 0 ? fVariables[expression] : "";
2126  string argenv = REST_ARGS.count(expression) > 0 ? REST_ARGS[expression] : "";
2127 
2128  if (sysenv != "") {
2129  outputBuffer.replace(replacePos, replaceLen, sysenv);
2130  endPosition = 0;
2131  } else if (argenv != "") {
2132  outputBuffer.replace(replacePos, replaceLen, argenv);
2133  endPosition = 0;
2134  } else if (proenv != "") {
2135  outputBuffer.replace(replacePos, replaceLen, proenv);
2136  endPosition = 0;
2137  } else {
2138  RESTError << this->ClassName() << ", replace env : cannot find \"${" << expression
2139  << "}\" in either system or program env, exiting..." << RESTendl;
2140  exit(1);
2141  }
2142  }
2143 
2144  if (buffer != outputBuffer) RESTDebug << "Replaced by : " << outputBuffer << RESTendl;
2145  return outputBuffer;
2146 }
2147 
2152 string TRestMetadata::ReplaceConstants(const string buffer) {
2153  RESTDebug << "Entering ... TRestMetadata::ReplaceConstants (" << buffer << ")" << RESTendl;
2154  string outputBuffer = buffer;
2155 
2156  // replace bare constant name. ignore sub strings.
2157  // e.g. variable "nCh" with value "3" cannot replace the string "nChannels+1"
2158  for (auto iter : fConstants) {
2159  int pos = outputBuffer.find(iter.first, 0);
2160  while (pos != -1) {
2161  char next =
2162  (pos + iter.first.size()) >= outputBuffer.size() ? 0 : outputBuffer[pos + iter.first.size()];
2163  char prev = pos == 0 ? 0 : outputBuffer[pos - 1];
2164  if (!isalpha(next) && !isalpha(prev)) {
2165  outputBuffer.replace(pos, iter.first.size(), iter.second);
2166  pos = outputBuffer.find(iter.first, pos + iter.second.size());
2167  } else {
2168  pos = outputBuffer.find(iter.first, pos + iter.first.size());
2169  }
2170  }
2171  }
2172 
2173  if (buffer != outputBuffer) RESTDebug << "Replaced by : " << outputBuffer << RESTendl;
2174  return outputBuffer;
2175 }
2176 
2183 string TRestMetadata::SearchFile(string filename) {
2184  if (TRestTools::fileExists(filename)) {
2185  return filename;
2186  } else {
2187  auto pathString = GetSearchPath();
2188  auto paths = Split((string)pathString, ":");
2189  return TRestTools::SearchFileInPath(paths, filename);
2190  }
2191 }
2192 
2196 void TRestMetadata::PrintTimeStamp(Double_t timeStamp) {
2197  cout.precision(10);
2198 
2199  time_t tt = (time_t)timeStamp;
2200  struct tm* tm = localtime(&tt);
2201 
2202  char date[20];
2203  strftime(date, sizeof(date), "%Y-%m-%d", tm);
2204  cout << "Date : " << date << endl;
2205 
2206  char time[20];
2207  strftime(time, sizeof(time), "%H:%M:%S", tm);
2208  cout << "Time : " << time << endl;
2209  cout << "++++++++++++++++++++++++" << endl;
2210 }
2211 
2216  if (fElement != nullptr) {
2217  fElement->Print(stdout, 0);
2218  cout << endl;
2219  } else {
2220  if (configBuffer != "") {
2221  auto ele = StringToElement(configBuffer);
2222  ele->Print(stdout, 0);
2223  cout << endl;
2224  delete ele;
2225  } else {
2226  cout << "N/A" << endl;
2227  }
2228  }
2229 }
2230 
2232  if (fElement != nullptr) {
2233  FILE* f = fopen(fname.c_str(), "at");
2234  fElement->Print(f, 0);
2235  fclose(f);
2236  return;
2237  } else if (configBuffer != "") {
2238  FILE* f = fopen(fname.c_str(), "at");
2239  auto ele = StringToElement(configBuffer);
2240  ele->Print(f, 0);
2241  fclose(f);
2242  delete ele;
2243  return;
2244  }
2245 
2246  RESTError << "Something missing here. Call the police" << RESTendl;
2247 }
2248 
2250 
2256  RESTMetadata << "+++++++++++++++++++++++++++++++++++++++++++++" << RESTendl;
2257  RESTMetadata << this->ClassName() << " content" << RESTendl;
2258  RESTMetadata << "Config file : " << fConfigFileName << RESTendl;
2259  RESTMetadata << "+++++++++++++++++++++++++++++++++++++++++++++" << RESTendl;
2260  RESTMetadata << "Name : " << GetName() << RESTendl;
2261  RESTMetadata << "Title : " << GetTitle() << RESTendl;
2262  RESTMetadata << "REST Version : " << GetVersion() << RESTendl;
2263  if (fOfficialRelease)
2264  RESTMetadata << "REST Official release: Yes" << RESTendl;
2265  else
2266  RESTMetadata << "REST Official release: No" << RESTendl;
2267  if (fCleanState)
2268  RESTMetadata << "Clean state: Yes" << RESTendl;
2269  else
2270  RESTMetadata << "Clean state: No" << RESTendl;
2271  RESTMetadata << "REST Commit : " << GetCommit() << RESTendl;
2272  if (GetLibraryVersion() != "0.0")
2273  RESTMetadata << "REST Library version : " << GetLibraryVersion() << RESTendl;
2274  RESTMetadata << "---------------------------------------" << RESTendl;
2275 }
2276 
2281 
2285 TString TRestMetadata::GetCommit() { return fCommit; }
2286 
2290 TString TRestMetadata::GetLibraryVersion() { return fLibraryVersion; }
2291 
2296  if (!this->InheritsFrom("TRestRun"))
2297  RESTError << "version is a static value, you cannot set version "
2298  "for a class!"
2299  << RESTendl;
2300  else {
2301  fVersion = REST_RELEASE;
2302  }
2303 }
2304 
2309  if (!this->InheritsFrom("TRestRun"))
2310  RESTError << "version is a static value, you cannot set version "
2311  "for a class!"
2312  << RESTendl;
2313  else {
2314  fVersion = -1;
2315  fCommit = -1;
2316  }
2317 }
2318 
2322 void TRestMetadata::SetLibraryVersion(TString version) { fLibraryVersion = version; }
2323 
2324 Int_t TRestMetadata::GetVersionCode() { return TRestTools::ConvertVersionCode((string)GetVersion()); }
2325 
2330  auto a = fSectionName.find('\n', 0);
2331  if (a != string::npos) return fSectionName.substr(0, a);
2332  return fSectionName;
2333 }
2334 
2338 
2344 string TRestMetadata::GetDataMemberValue(string memberName) {
2345  return RESTValue(this, this->ClassName()).GetDataMemberValueString(memberName);
2346 }
2347 
2362 std::vector<string> TRestMetadata::GetDataMemberValues(string memberName, Int_t precision) {
2363  string result = GetDataMemberValue(memberName);
2364 
2365  result = Replace(result, "{", "");
2366  result = Replace(result, "}", "");
2367  result = Replace(result, "(", "");
2368  result = Replace(result, ")", "");
2369 
2370  std::vector<std::string> results = REST_StringHelper::Split(result, ",");
2371 
2372  for (auto& x : results) x = REST_StringHelper::CropWithPrecision(x, precision);
2373 
2374  return results;
2375 }
2376 
2381  TString level = "unknown";
2386 
2387  return level;
2388 }
2389 
2413  string result = "";
2414 
2415  // If fElement=0 we haven't initialized the class from RML.
2416  // Then we skip adding user paths
2417  if (fElement) {
2418  TiXmlElement* ele = fElement->FirstChildElement("searchPath");
2419  while (ele != nullptr) {
2420  if (ele->Attribute("value") != nullptr) {
2421  result += (string)ele->Attribute("value") + ":";
2422  }
2423  ele = ele->NextSiblingElement("searchPath");
2424  }
2425  }
2426 
2427  if (getenv("configPath")) result += getenv("configPath") + (string) ":";
2428  result += REST_PATH + "/data/:";
2429  result += REST_PATH + "/examples/:";
2430  // We give priority to the official /data/ and /examples/ path.
2431  result += REST_USER_PATH + ":";
2432  if (result.back() == ':') result.erase(result.size() - 1);
2433 
2434  return ReplaceConstants(ReplaceVariables(result));
2435 }
2436 
2437 Int_t TRestMetadata::Write(const char* name, Int_t option, Int_t bufsize) {
2438  if (fStore) {
2440  return TNamed::Write(name, option, bufsize);
2441  }
2442  return -1;
2443 }
2444 
2471  // we shall first add all the parameters to a temporary map to avoid
2472  // first parameter being overriden by the repeated parameter section
2473  map<string, string> parameters = GetParametersList();
2474 
2475  ReadParametersList(parameters);
2476 }
2477 
2482 void TRestMetadata::ReadParametersList(std::map<string, string>& list) {
2483  for (auto i : list) {
2484  ReadOneParameter(i.first, i.second);
2485  }
2486 }
2487 
2491 std::map<string, string> TRestMetadata::GetParametersList() {
2492  // we shall first add all the parameters to a temporary map to avoid
2493  // first parameter being overriden by the repeated parameter section
2494  map<string, string> parameters;
2495 
2496  // Loop over REST_ARGS
2497  auto iter = REST_ARGS.begin();
2498  while (iter != REST_ARGS.end()) {
2499  // if (parameters.count(iter->first) == 0) {
2500  parameters[iter->first] = iter->second;
2501  //}
2502  iter++;
2503  }
2504 
2505  // Loop over attribute set
2506  auto paraattr = fElement->FirstAttribute();
2507  while (paraattr != nullptr) {
2508  string name = paraattr->Name();
2509  string value = paraattr->Value();
2510 
2511  if (parameters.count(name) == 0) {
2512  parameters[name] = value;
2513  }
2514  // ReadOneParameter((string)name, (string)value);
2515  paraattr = paraattr->Next();
2516  }
2517 
2518  // Loop over <parameter section
2519  auto paraele = fElement->FirstChildElement("parameter");
2520  while (paraele != nullptr) {
2521  string name = paraele->Attribute("name");
2522  string value = paraele->Attribute("value");
2523  // In case <parameter section contains units definitions in extra attribute field,
2524  // not together with "value" attribute field
2525  // We should concat the value and units together.
2526  TString units = paraele->Attribute("units");
2527 
2528  if (name == "") {
2529  RESTWarning << "bad <parameter section: " << *paraele << RESTendl;
2530  } else {
2531  if (parameters.count(name) == 0) {
2532  parameters[name] = value + units;
2533  }
2534  // ReadOneParameter((string)name, (string)value);
2535  }
2536  paraele = paraele->NextSiblingElement("parameter");
2537  }
2538 
2539  return parameters;
2540 }
2541 
2542 void TRestMetadata::ReadOneParameter(string name, string value) {
2543  if (name == "name" || name == "title" || name == "verboseLevel" || name == "type" || name == "value" ||
2544  name == "store") {
2545  // we omit these parameters since they are already loaded in LoadSectionMetadata()
2546  } else {
2547  RESTValue thisactual(this, this->ClassName());
2548  string datamembername = ParameterNameToDataMemberName(name);
2549  if (datamembername != "") {
2550  RESTValue datamember = thisactual.GetDataMember(datamembername);
2551  if (!datamember.IsZombie()) {
2552  RESTDebug << this->ClassName() << "::ReadAllParameters(): parsing value \"" << value
2553  << "\" to data member \"" << datamembername << "\"" << RESTendl;
2554 
2555  if (REST_Units::FindRESTUnitsInString(value) != "") {
2556  // there is units contained in this parameter.
2557  string val = REST_Units::RemoveUnitsFromString(value);
2558  string unit = REST_Units::FindRESTUnitsInString(value);
2559 
2560  if (datamember.type == "double") {
2561  Double_t value = StringToDouble(val);
2562  *(double*)datamember = REST_Units::ConvertValueToRESTUnits(value, unit);
2563  } else if (datamember.type == "TVector2") {
2564  TVector2 value = StringTo2DVector(val);
2565  Double_t valueX = REST_Units::ConvertValueToRESTUnits(value.X(), unit);
2566  Double_t valueY = REST_Units::ConvertValueToRESTUnits(value.Y(), unit);
2567  *(TVector2*)datamember = TVector2(valueX, valueY);
2568  } else if (datamember.type == "TVector3") {
2569  TVector3 value = StringTo3DVector(val);
2570  Double_t valueX = REST_Units::ConvertValueToRESTUnits(value.X(), unit);
2571  Double_t valueY = REST_Units::ConvertValueToRESTUnits(value.Y(), unit);
2572  Double_t valueZ = REST_Units::ConvertValueToRESTUnits(value.Z(), unit);
2573  *(TVector3*)datamember = TVector3(valueX, valueY, valueZ);
2574  } else if (datamember.type == "string") {
2575  // We just ignore this case
2576  } else {
2577  RESTWarning << this->ClassName() << " find unit definition in parameter: " << name
2578  << ", but the corresponding data member doesn't support it. Data "
2579  "member type: "
2580  << datamember.type << RESTendl;
2581  datamember.ParseString(value);
2582  }
2583  } else {
2584  datamember.ParseString(value);
2585  }
2586  } else if (datamember.name != "") {
2587  // this mean the datamember is found with type not recognized.
2588  // We won't try to find the misspelling
2589  } else {
2590  RESTDebug << this->ClassName() << "::ReadAllParameters(): parameter \"" << name
2591  << "\" not recognized for automatic load" << RESTendl;
2592  vector<string> availableparameters;
2593 
2594  vector<string> datamembers = thisactual.GetListOfDataMembers();
2595  for (unsigned int i = 0; i < datamembers.size(); i++) {
2596  string parameter = DataMemberNameToParameterName(datamembers[i]);
2597  if (parameter != "") {
2598  if (parameter == "name" || parameter == "title" || parameter == "verboseLevel" ||
2599  parameter == "type" || parameter == "value" || parameter == "store") {
2600  } else {
2601  availableparameters.push_back(parameter);
2602  }
2603  }
2604  }
2605 
2606  int mindiff = 100;
2607  string hintParameter = "";
2608  for (auto parameter : availableparameters) {
2609  int diff = DiffString(name, parameter);
2610  if (diff < mindiff) {
2611  mindiff = diff;
2612  hintParameter = parameter;
2613  }
2614  }
2615 
2616  // we regard the unset parameter with less than 2 characters different from
2617  // the data member as "misspelling" parameter. We prompt a warning for it.
2618  if (hintParameter != "" && mindiff <= 2) {
2619  RESTWarning << this->ClassName() << "::ReadAllParameters(): parameter \"" << name
2620  << "\" not recognized for automatic load, did you mean \"" << hintParameter
2621  << "\" ?" << RESTendl;
2622  GetChar();
2623  }
2624  }
2625  }
2626  }
2627 }
2628 
2629 TRestStringOutput& TRestStringOutput::operator<<(endl_t et) {
2630  if (et.TRestMetadataPtr->GetVerboseLevel() <= TRestStringOutput::REST_Verbose_Level::REST_Info) {
2631  et.TRestMetadataPtr->AddLog(this->buf.str());
2632  }
2633 
2634  if (this->iserror) {
2635  if (this->verbose == TRestStringOutput::REST_Verbose_Level::REST_Warning) {
2636  et.TRestMetadataPtr->SetWarning(this->buf.str(), false);
2637  }
2639  et.TRestMetadataPtr->SetError(this->buf.str(), false);
2640  }
2641  }
2642 
2643  if (et.TRestMetadataPtr->GetVerboseLevel() >= this->verbose) {
2644  this->flushstring();
2645  } else {
2646  this->resetstring();
2647  }
2648 
2649  return *this;
2650 }
2651 
2652 void TRestMetadata::AddLog(string log, bool print) {
2653  messageBuffer += log + "\n";
2654  if (messageBuffer.size() > 1000) {
2655  messageBuffer.erase(0, messageBuffer.size() - 1000);
2656  }
2657 }
2658 
2659 void TRestMetadata::SetError(string message, bool print, int maxPrint) {
2660  fError = true;
2661  fNErrors++;
2662  if (message != "") {
2663  fErrorMessage += message + "\n";
2664  if (print && fNErrors < maxPrint) {
2665  cout << message << endl;
2666  }
2667  }
2668 }
2669 
2670 void TRestMetadata::SetWarning(string message, bool print, int maxPrint) {
2671  fWarning = true;
2672  fNWarnings++;
2673  if (message != "") {
2674  fWarningMessage += message + "\n";
2675  if (print && fNWarnings < maxPrint) {
2676  RESTWarning << message << RESTendl;
2677  }
2678  }
2679 }
2680 
2682  if (GetError())
2683  return fErrorMessage;
2684  else
2685  return "No error!";
2686 }
2687 
2689  if (GetWarning())
2690  return fWarningMessage;
2691  else
2692  return "No warning!";
2693 }
2694 
2695 void TRestMetadata::Merge(const TRestMetadata& metadata) {
2696  if (!metadata.InheritsFrom(ClassName())) {
2697  RESTError << "TRestMetadata::Merge. Metadata is not of type " << ClassName() << RESTendl;
2698  exit(1);
2699  }
2700 
2701  if (fName.IsNull()) {
2702  fName = metadata.GetName();
2703  }
2704 }
2705 
2706 UInt_t TRestMetadata::GetVersionMajor() const {
2707  TString major = fVersion(0, fVersion.First('.'));
2708  return major.Atoi();
2709 }
2710 
2711 UInt_t TRestMetadata::GetVersionMinor() const {
2712  TString minor = fVersion(fVersion.First('.') + 1, fVersion.Last('.'));
2713  return minor.Atoi();
2714 }
2715 
2716 UInt_t TRestMetadata::GetVersionPatch() const {
2717  TString patch = fVersion(fVersion.Last('.') + 1, fVersion.Length());
2718  return patch.Atoi();
2719 }
std::string GetDataMemberValueString(const std::string &name)
Get the value of datamember as std::string.
std::string type
Type of the wrapped object.
bool IsZombie() const
If this object type wrapper is invalid.
std::string name
Name field.
TRestReflector GetDataMember(const std::string &name)
Find the class's datamember as TRestReflector object, including those from base class.
void ParseString(const std::string &str) const
Set the value of the wrapped object from std::string.
virtual DBEntry query_data(DBEntry info)
A base class for any REST metadata class.
Definition: TRestMetadata.h:74
void UnSetVersion()
Resets the version of TRestRun to -1, in case the file is old REST file. Only TRestRun is allowed to ...
std::map< std::string, std::string > fVariables
Saving a list of rml variables. name-value std::pair.
virtual void PrintMetadata()
Implemented it in the derived metadata class to print out specific metadata information.
endl_t RESTendl
Termination flag object for TRestStringOutput.
std::string ElementToString(TiXmlElement *ele)
Convert an TiXmlElement object to string.
TiXmlElement * GetElement(std::string eleDeclare, TiXmlElement *e=nullptr)
Get an xml element from a given parent element, according to its declaration.
virtual void Initialize()
Making default settings.
TString GetSearchPath()
Int_t LoadConfigFromFile(const std::string &configFilename, const std::string &sectionName="")
Give the file name, find out the corresponding section. Then call the main starter.
TiXmlElement * fElementGlobal
Saving the global element, to be passed to the resident class, if necessary.
void PrintMessageBuffer()
Print the buffered message.
std::map< std::string, std::string > GetParametersList()
It retrieves a map of all parameter:value found in the metadata class.
void PrintConfigBuffer()
Print the config xml section stored in the class.
std::string GetUnits(TiXmlElement *e)
Returns a string with the unit name given in the given xml element.
TiXmlElement * GetElementWithName(std::string eleDeclare, std::string eleName, TiXmlElement *e)
Get an xml element from a given parent element, according to its declaration and its field "name".
TRestStringOutput::REST_Verbose_Level fVerboseLevel
Verbose level used to print debug info.
TiXmlElement * StringToElement(std::string definition)
Parsing a string into TiXmlElement object.
TiXmlElement * GetElementFromFile(std::string configFilename, std::string NameOrDecalre="")
Open an xml encoded file and find its element.
TRestMetadata * InstantiateChildMetadata(int index, std::string pattern="")
This method will retrieve a new TRestMetadata instance of a child element of the present TRestMetadat...
Int_t fNErrors
It counts the number of errors notified.
TString GetCommit()
Returns the REST commit value stored in fCommit.
virtual void InitFromConfigFile()
To make settings from rml file. This method must be implemented in the derived class.
TString fErrorMessage
A std::string to store an optional error message through method SetError.
void SetLibraryVersion(TString version)
Set the library version of this metadata class.
TString GetVerboseLevelString()
returns the verbose level in type of TString
TRestStringOutput::REST_Verbose_Level GetVerboseLevel()
returns the verboselevel in type of REST_Verbose_Level enumerator
std::string ReplaceVariables(const std::string buffer)
Identifies environmental variable replacing marks in the input buffer, and replace them with correspo...
Int_t LoadConfigFromBuffer()
Initialize data from a string element buffer.
Int_t fNWarnings
It counts the number of warnings notified.
void ReplaceForLoopVars(TiXmlElement *e, std::map< std::string, std::string > forLoopVar)
Helper method for TRestMetadata::ExpandForLoops().
std::string GetFieldValue(std::string parName, TiXmlElement *e)
Returns the field value of an xml element which has the specified name.
std::string messageBuffer
The buffer to store the output message through TRestStringOutput in this class.
void SetWarning(std::string message="", bool print=true, int maxPrint=5)
A metadata class may use this method to signal that something went wrong.
virtual void InitFromRootFile()
Method called after the object is retrieved from root file.
Bool_t GetError() const
It returns true if an error was identified by a derived metadata class.
Int_t LoadConfigFromElement(TiXmlElement *eSectional, TiXmlElement *eGlobal, std::map< std::string, std::string > envs={})
Main starter method.
void ReSetVersion()
Resets the version of TRestRun to REST_RELEASE. Only TRestRun is allowed to update version.
TString fWarningMessage
It can be used as a way to identify that something went wrong using SetWarning method.
TiXmlElement * ReplaceElementAttributes(TiXmlElement *e)
replace the field value(attribute) of the given xml element
void SetConfigFile(std::string configFilename)
set config file path from external
std::string GetKEYStructure(std::string keyName)
Gets the first key structure for keyName found inside buffer after fromPosition.
TString GetErrorMessage()
Returns a std::string containing the error message.
void ReadAllParameters()
Reflection methods, Set value of a datamember in class according to TRestMetadata::fElement.
void SetSectionName(std::string sName)
set the section name, clear the section content
void ExpandIncludeFile(TiXmlElement *e)
Open the given rml file and find the corresponding section.
TString GetWarningMessage()
Returns a std::string containing the warning message.
TString GetVersion()
Returns the REST version stored in fVersion.
std::string SearchFile(std::string filename)
Search files in current directory and directories specified in "searchPath" section.
TString fVersion
REST version std::string, only used for archive and retrieve.
Definition: TRestMetadata.h:89
void ExpandForLoopOnce(TiXmlElement *e, const std::map< std::string, std::string > &forLoopVar)
Helper method for TRestMetadata::ExpandForLoops().
void ReadParametersList(std::map< std::string, std::string > &list)
It reads a parameter list and associates it to its corresponding metadata member. par0 --> fPar0.
void AddLog(std::string log="", bool print=true)
Add logs to messageBuffer.
std::string GetSectionName()
Returns the section name of this class, defined at the beginning of fSectionName.
Bool_t fError
It can be used as a way to identify that something went wrong using SetError method.
std::vector< std::string > GetDataMemberValues(std::string memberName, Int_t precision=0)
Get the value of datamember as a vector of strings.
std::string GetConfigBuffer()
Returns the config section of this class.
virtual void Merge(const TRestMetadata &)
Bool_t fStore
This variable is used to determine if the metadata structure should be stored in the ROOT file.
void ExpandForLoops(TiXmlElement *e, std::map< std::string, std::string > forLoopVar)
Expands the loop structures found in the given xml section.
TRestManager * fHostmgr
All metadata classes can be initialized and managed by TRestManager.
void WriteConfigBuffer(std::string fName)
Writes the config buffer to a file in append mode.
std::string GetDataMemberValue(std::string memberName)
Get the value of data member as string.
void ReadEnvInElement(TiXmlElement *e, bool overwrite=true)
Identify an environmental variable section and add it into env section list.
virtual Int_t LoadSectionMetadata()
This method does some preparation of xml section.
std::string fConfigFileName
Full name of the rml file.
std::string FieldNamesToUpper(std::string inputString)
This method updates all the field names inside the definition string provided by argument to make the...
TString GetLibraryVersion()
Returns the REST libraty version stored in fLibraryVersion.
std::string ReplaceConstants(const std::string buffer)
Identifies "constants" in the input buffer, and replace them with corresponding value.
std::map< std::string, std::string > fConstants
Saving a list of rml constants. name-value std::pair. Constants are temporary for this class only.
std::pair< std::string, std::string > GetParameterAndUnits(std::string parname, TiXmlElement *e=nullptr)
Returns the unit string of the given parameter of the given xml section.
Bool_t fWarning
It can be used as a way to identify that something went wrong using SetWarning method.
TRestMetadata()
TRestMetadata default constructor.
void PrintTimeStamp(Double_t timeStamp)
Print the current time on local machine.
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
overwriting the write() method with fStore considered
void ExpandIfSections(TiXmlElement *e)
Judge the if condition and expands the elements inside it.
void ReadElement(TiXmlElement *e, bool recursive=false)
Read the given xml section, applying rml syntax(if, for, include, etc.)
void SetError(std::string message="", bool print=true, int maxPrint=5)
A metadata class may use this method to signal that something went wrong.
Bool_t GetWarning() const
It returns true if an error was identified by a derived metadata class.
TiXmlElement * GetNextElement(TiXmlElement *e)
Get the next sibling xml element of this element, with same eleDeclare.
std::string GetParameter(std::string parName, TiXmlElement *e, TString defaultValue=PARAMETER_NOT_FOUND_STR)
Returns the value for the parameter named parName in the given section.
std::string GetKEYDefinition(std::string keyName)
Gets the first key definition for keyName found inside buffer starting at fromPosition.
std::string fSectionName
Section name given in the constructor of the derived metadata class.
std::string configBuffer
The buffer where the corresponding metadata section is stored. Filled only during Write()
TiXmlElement * fElement
Saving the sectional element together with global element.
~TRestMetadata()
TRestMetadata default destructor.
@ REST_Essential
+show some essential information, as well as warnings
@ REST_Info
+show most of the information for each steps
@ REST_Debug
+show the defined debug messages
@ REST_Silent
show minimum information of the software, as well as error messages
static std::string Execute(std::string cmd)
Executes a shell command and returns its output in a string.
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
Definition: TRestTools.cxx:728
static std::string DownloadRemoteFile(const std::string &remoteFile, bool pidPrefix=false)
download the remote file automatically, returns the downloaded file name.
static int ConvertVersionCode(std::string in)
Convert version to a unique string.
static bool isURL(const std::string &filename)
Returns true if filename is an http address.
Definition: TRestTools.cxx:770
static bool isRootFile(const std::string &filename)
Returns true if the filename has *.root* extension.
Definition: TRestTools.cxx:733
static std::string SearchFileInPath(std::vector< std::string > path, std::string filename)
Search file in the given vector of path strings, return a full name if found, return "" if not.
Definition: TRestTools.cxx:929
This namespace serves to define physics constants and other basic physical operations.
Definition: TRestPhysics.h:34
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
std::vector< std::string > Split(std::string in, std::string separator, bool allowBlankString=false, bool removeWhiteSpaces=false, int startPos=-1)
Split the input string according to the given separator. Returning a vector of fragments.
Double_t StringToDouble(std::string in)
Gets a double from a string.
std::string ToUpper(std::string in)
Convert string to its upper case. Alternative of TString::ToUpper.
TVector2 StringTo2DVector(std::string in)
Gets a 2D-vector from a string.
Int_t DiffString(const std::string &source, const std::string &target)
Returns the number of different characters between two strings.
std::string ParameterNameToDataMemberName(std::string name)
Convert parameter name to datamember name, following REST parameter naming convention.
std::string DataMemberNameToParameterName(std::string name)
Convert data member name to parameter name, following REST parameter naming convention.
Int_t isANumber(std::string in)
Returns 1 only if a valid number is found in the string in. If not it returns 0.
TVector3 StringTo3DVector(std::string in)
Gets a 3D-vector from a string. Format should be : (X,Y,Z).
std::string RemoveWhiteSpaces(std::string in)
Returns the input string removing all white spaces.
std::string CropWithPrecision(std::string in, Int_t precision)
It crops a floating number given inside the string in with the given precision. I....
std::string Replace(std::string in, std::string thisString, std::string byThisString, size_t fromPosition=0, Int_t N=0)
Replace any occurences of thisSring by byThisString inside string in.
std::string ReplaceMathematicalExpressions(std::string buffer, Int_t precision=0, std::string errorMessage="")
Evaluates and replaces valid mathematical expressions found in the input string buffer.
This namespace defines the unit conversion for different units which are understood by REST.
std::string FindRESTUnitsInString(std::string InString)
Find and return the units definition in a string.
bool IsUnit(std::string in)
Checks if the string is a REST supported unit.
Double_t ConvertValueToRESTUnits(Double_t value, std::string unitsStr)
Convert value into REST units.
std::string RemoveUnitsFromString(std::string s)
It should remove all units found inside the input string.