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/*
473namespace REST_VersionGlob {
474 inline TString GetRESTVersion() const { return REST_RELEASE; }
475 inline int GetRESTVersionCode() const { return ConvertVersionCode(REST_RELEASE); }
476}
477*/
478using namespace std;
479using namespace REST_Units;
480using 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
487map<string, string> TRestMetadata_UpdatedConfigFile;
488
489ClassImp(TRestMetadata);
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
515TRestMetadata::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
540TRestMetadata::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
574Int_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
660Int_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
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
788TRestMetadata* 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) {
835 e = e->NextSiblingElement();
836 }
837 }
838
839 // then from local section
840 TiXmlElement* e = fElement->FirstChildElement();
841 while (e != nullptr) {
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
870TiXmlElement* 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
910void 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
946void TRestMetadata::ReadElement(TiXmlElement* e, bool recursive) {
947 RESTDebug << ClassName() << "::ReadElement(<" << e->Value() << ")" << RESTendl;
948 if (e == nullptr) return;
949
952
953 if ((string)e->Value() == "for") {
954 ExpandForLoops(e, {});
955 } else if (e->Attribute("file") != nullptr) {
957 } else if ((string)e->Value() == "if") {
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
1003void 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
1090void 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
1121void 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
1188void 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
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
1242 RESTDebug << "----end of for loop----" << RESTendl;
1243 }
1244 // variable defined in for loop should be temporal
1245 fVariables.erase(_name);
1246}
1247
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
1472string 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
1511string 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
1535Double_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
1551TVector2 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
1569TVector3 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
1595std::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
1641Double_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
1654TVector2 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
1669TVector3 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
1700TiXmlElement* 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
1761TiXmlElement* TRestMetadata::GetElement(std::string eleDeclare, TiXmlElement* e) {
1762 if (e == nullptr) e = fElement;
1763 return e->FirstChildElement(eleDeclare.c_str());
1764}
1765
1769TiXmlElement* TRestMetadata::GetNextElement(TiXmlElement* e) {
1770 if (e == nullptr) return nullptr;
1771 return e->NextSiblingElement(e->Value());
1772}
1773
1778TiXmlElement* TRestMetadata::GetElementWithName(std::string eleDeclare, std::string eleName) {
1779 return GetElementWithName(eleDeclare, eleName, fElement);
1780}
1781
1786TiXmlElement* 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
1829string 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
1858pair<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
1893TiXmlElement* 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
1905string 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
1951string 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}
1957string TRestMetadata::GetKEYStructure(std::string keyName, size_t& Position) {
1958 string result = GetKEYStructure(keyName, Position, fElement);
1959 if (result == "") result = "NotFound";
1960 return result;
1961}
1962string 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}
1968string 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}
1974string 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
2003string TRestMetadata::GetKEYDefinition(string keyName) {
2004 string buffer = ElementToString(fElement);
2005 size_t Position = 0;
2006 return GetKEYDefinition(keyName, Position, buffer);
2007}
2008string TRestMetadata::GetKEYDefinition(string keyName, size_t& fromPosition) {
2009 string buffer = ElementToString(fElement);
2010 return GetKEYDefinition(keyName, fromPosition, buffer);
2011}
2012string TRestMetadata::GetKEYDefinition(string keyName, string buffer) {
2013 size_t Position = 0;
2014 return GetKEYDefinition(keyName, Position, buffer);
2015}
2016string 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
2053string 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
2075std::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
2089string 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
2108string 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
2152string 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
2183string 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
2196void 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
2285TString TRestMetadata::GetCommit() { return fCommit; }
2286
2290TString 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
2322void TRestMetadata::SetLibraryVersion(TString version) { fLibraryVersion = version; }
2323
2324Int_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
2344string TRestMetadata::GetDataMemberValue(string memberName) {
2345 return RESTValue(this, this->ClassName()).GetDataMemberValueString(memberName);
2346}
2347
2362std::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
2437Int_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
2482void TRestMetadata::ReadParametersList(std::map<string, string>& list) {
2483 for (auto i : list) {
2484 ReadOneParameter(i.first, i.second);
2485 }
2486}
2487
2491std::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
2542void 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
2629TRestStringOutput& 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
2652void 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
2659void 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
2670void 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
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
2706UInt_t TRestMetadata::GetVersionMajor() const {
2707 TString major = fVersion(0, fVersion.First('.'));
2708 return major.Atoi();
2709}
2710
2711UInt_t TRestMetadata::GetVersionMinor() const {
2712 TString minor = fVersion(fVersion.First('.') + 1, fVersion.Last('.'));
2713 return minor.Atoi();
2714}
2715
2716UInt_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:70
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:85
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.