43 #include "TObjArray.h" 44 #include "TObjString.h" 45 #include "TSystemFile.h" 47 #include <libxml/xmlreader.h> 48 #include <libxml/parser.h> 49 #include <libxml/xmlschemas.h> 52 #include "git-revision.h" 93 virtual void DumpFolder(TFolder *folder, UInt_t offset);
94 virtual void DumpObjArray(TObjArray *obj, UInt_t offset);
95 virtual void DumpEntry(TObject *obj, UInt_t offset);
96 virtual void CheckClass(TObject *obj, TString str, UInt_t offset);
97 virtual void GetType(TString entry, TString &type);
98 virtual void GetLabel(TString entry, TString &label);
120 std::cerr << std::endl <<
"**ERROR** couldn't open file " <<
fFileName << std::endl;
124 fXmlData.push_back(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
125 fXmlData.push_back(
"<MusrRoot xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"file:MusrRoot.xsd\">");
127 TIter next = f.GetListOfKeys();
134 while ((key = dynamic_cast<TKey*>(next())) !=
nullptr) {
135 if (!
fQuiet) std::cout << std::endl <<
"name: " << key->GetName() <<
", class name: " << key->GetClassName();
136 str = key->GetClassName();
137 if (str ==
"TFolder") {
138 folder =
dynamic_cast<TFolder*
>(key->ReadObj());
142 if (!
fQuiet) std::cout << std::endl;
158 for (UInt_t i=0; i<
fXmlData.size(); i++)
188 std::vector<std::string> temp_xml_data;
191 for (
unsigned int i=0; i<
fXmlData.size(); i++)
192 temp_xml_data.push_back(
fXmlData[i]);
195 unsigned int start = 0, end = 0;
196 for (
unsigned int i=0; i<temp_xml_data.size(); i++) {
197 if (temp_xml_data[i].find(
"<SCAnaModule>") != std::string::npos)
199 if (temp_xml_data[i].find(
"</SCAnaModule>") != std::string::npos)
202 if ((start > 0) && (end > 0))
203 temp_xml_data.erase(temp_xml_data.begin()+start, temp_xml_data.begin()+end);
209 unsigned int pos = 0;
210 for (
unsigned int i=0; i<temp_xml_data.size(); i++) {
211 if (temp_xml_data[i].find(
"</DecayAnaModule>") != std::string::npos) {
218 temp_xml_data.insert(temp_xml_data.begin()+pos,
fXmlData.begin()+start,
fXmlData.begin()+end);
222 for (
unsigned int i=0; i<temp_xml_data.size(); i++)
223 fXmlData.push_back(temp_xml_data[i]);
226 temp_xml_data.clear();
238 TString offsetStr=
"";
239 for (UInt_t i=0; i<offset; i++)
242 TIter next = folder->GetListOfFolders();
245 while ((obj = dynamic_cast<TObject*>(next())) !=
nullptr) {
246 if (!
fQuiet) std::cout << std::endl << offsetStr <<
"name: " << obj->GetName() <<
", class name: " << obj->ClassName();
247 str = obj->ClassName();
261 TString offsetStr=
"";
262 for (UInt_t i=0; i<offset; i++)
266 TString str, xmlStr, type, label, xmlLabel;
269 xmlLabel = TString(obj->GetName());
270 if (xmlLabel.BeginsWith(
"Detector")) {
271 xmlLabel.Remove(0, 8);
272 if (xmlLabel.IsDigit())
273 xmlLabel =
"Detector";
275 xmlLabel = TString(obj->GetName());
278 if (!
fQuiet) std::cout << std::endl << offsetStr << obj->GetName() <<
" (# " << obj->GetEntries() <<
")";
279 if (!strcmp(obj->GetName(),
"DetectorInfo"))
282 xmlStr = offsetStr +
"<" + xmlLabel +
">";
285 for (UInt_t i=0; i<static_cast<UInt_t>(obj->GetEntries()); i++) {
287 type = obj->At(i)->ClassName();
288 if (type ==
"TObjArray") {
289 DumpObjArray(dynamic_cast<TObjArray*>(obj->At(i)), offset+2);
291 tstr =
static_cast<TObjString*
>(obj->At(i));
292 str = tstr->GetString();
293 str.Remove(TString::kTrailing,
'\n');
298 if (!
fQuiet) std::cout << std::endl << offsetStr << i <<
": " << str;
301 if (str.Contains(
"- No of Histos: ")) {
302 TString histoStr = str;
303 Ssiz_t pos = histoStr.Last(
':');
304 histoStr.Remove(0, pos+1);
305 pos = histoStr.Last(
'-');
306 histoStr.Remove(pos);
311 if (str.Contains(
"- RedGreen Offsets: ")) {
312 TString redGreenStr = str;
313 Ssiz_t pos = redGreenStr.Last(
':');
314 redGreenStr.Remove(0, pos+1);
315 pos = redGreenStr.Last(
'-');
316 redGreenStr.Remove(pos);
317 TObjArray *tokens = redGreenStr.Tokenize(
";");
320 if (tokens)
delete tokens;
323 xmlStr = offsetStr +
" " +
"<" + label +
">" + type +
"</" + label +
">" ;
328 xmlStr = offsetStr +
"</" + xmlLabel +
">";
341 TString offsetStr=
"";
342 for (UInt_t i=0; i<offset; i++)
345 TString nameTag(
""), typeTag(
"");
348 nameTag =
"HistoName";
349 typeTag =
"HistoType";
352 nameTag =
"SlowControlName";
353 typeTag =
"SlowControlType";
367 str = offsetStr +
"<" + nameTag +
">";
368 str += obj->GetName();
369 str +=
"</" + nameTag +
">";
372 str = offsetStr +
"<" + typeTag +
">";
373 str += obj->ClassName();
374 str +=
"</" + typeTag +
">";
388 TString offsetStr=
"";
389 for (UInt_t i=0; i<offset; i++)
392 if (str ==
"TFolder") {
393 TString xmlTagName(TString(obj->GetName()));
396 if (!xmlTagName.CompareTo(
"DecayAnaModule"))
398 else if (!xmlTagName.CompareTo(
"SCAnaModule"))
400 else if (!xmlTagName.CompareTo(
"SCAnaModule"))
406 str = offsetStr +
"<" + xmlTagName +
">";
409 DumpFolder(dynamic_cast<TFolder*>(obj), offset);
411 str = offsetStr +
"</" + xmlTagName +
">";
413 }
else if (str ==
"TObjArray") {
418 TString entryTag(
"");
421 entryTag = TString(
"DecayHistoEntry");
424 entryTag = TString(
"SlowControlHistoEntry");
428 entryTag = TString(
"Entry");
433 str = offsetStr +
"<" + entryTag +
">";
435 DumpEntry(dynamic_cast<TObject*>(obj), offset);
436 str = offsetStr +
"</" + entryTag +
">";
450 if (entry.Contains(
"-@0")) {
452 }
else if (entry.Contains(
"-@1")) {
454 }
else if (entry.Contains(
"-@2")) {
456 }
else if (entry.Contains(
"-@3")) {
457 type =
"TMusrRunPhysicalQuantity";
458 }
else if (entry.Contains(
"-@4")) {
459 type =
"TStringVector";
460 }
else if (entry.Contains(
"-@5")) {
462 }
else if (entry.Contains(
"-@6")) {
463 type =
"TDoubleVector";
480 Ssiz_t start = entry.First(
'-');
481 Ssiz_t end = entry.First(
':');
483 if ((start == -1) || (end == -1))
490 Ssiz_t pos = entry.First(
'@');
493 if (entry(pos-1) !=
'-')
498 label.Remove(0, start+2);
499 label.Remove(end-start-2, label.Length());
501 label.ReplaceAll(
' ',
'_');
502 label.ReplaceAll(
'(',
'_');
503 label.ReplaceAll(
')',
'_');
504 label.ReplaceAll(
'[',
'_');
505 label.ReplaceAll(
']',
'_');
506 label.ReplaceAll(
'{',
'_');
507 label.ReplaceAll(
'}',
'_');
516 std::cout << std::endl <<
"usage: musrRootValidation <musrRootFile> <musrRootSchema> [--quiet] [--keep] | --help | --version";
517 std::cout << std::endl <<
" --quiet: do not dump the MusrRoot file info while validating";
518 std::cout << std::endl <<
" --keep: do NOT delete the intermediate XML-file";
519 std::cout << std::endl <<
" --help: shows this help";
520 std::cout << std::endl <<
" --version: shows the current version";
521 std::cout << std::endl << std::endl;
531 int is_valid(
const xmlDocPtr doc,
const char *schema_filename)
533 xmlDocPtr schema_doc = xmlReadFile(schema_filename,
nullptr, XML_PARSE_NONET);
534 if (schema_doc ==
nullptr) {
535 std::cerr << std::endl <<
"**ERROR** the schema (" << schema_filename <<
") cannot be loaded or is not well-formed" << std::endl << std::endl;
538 xmlSchemaParserCtxtPtr parser_ctxt = xmlSchemaNewDocParserCtxt(schema_doc);
539 if (parser_ctxt ==
nullptr) {
540 std::cerr << std::endl <<
"**ERROR** unable to create a parser context for the schema." << std::endl << std::endl;
541 xmlFreeDoc(schema_doc);
544 xmlSchemaPtr schema = xmlSchemaParse(parser_ctxt);
545 if (schema ==
nullptr) {
546 std::cerr << std::endl <<
"**ERROR** the schema itself is not valid." << std::endl << std::endl;
547 xmlSchemaFreeParserCtxt(parser_ctxt);
548 xmlFreeDoc(schema_doc);
551 xmlSchemaValidCtxtPtr valid_ctxt = xmlSchemaNewValidCtxt(schema);
552 if (valid_ctxt ==
nullptr) {
553 std::cerr << std::endl <<
"**ERROR** unable to create a validation context for the schema." << std::endl << std::endl;
554 xmlSchemaFree(schema);
555 xmlSchemaFreeParserCtxt(parser_ctxt);
556 xmlFreeDoc(schema_doc);
559 int is_valid = (xmlSchemaValidateDoc(valid_ctxt, doc) == 0);
560 xmlSchemaFreeValidCtxt(valid_ctxt);
561 xmlSchemaFree(schema);
562 xmlSchemaFreeParserCtxt(parser_ctxt);
563 xmlFreeDoc(schema_doc);
572 int main(
int argc,
char *argv[])
577 }
else if (argc==2) {
578 if (!strcmp(argv[1],
"--version")) {
580 #ifdef HAVE_GIT_REV_H 581 std::cout << std::endl <<
"musrRootValidation version: " << PACKAGE_VERSION <<
", git-branch: " << GIT_BRANCH <<
", git-rev: " << GIT_CURRENT_SHA1 <<
" (" << BUILD_TYPE <<
"), ROOT version: " << ROOT_VERSION_USED << std::endl << std::endl;
583 std::cout << std::endl <<
"musrRootValidation version: " << PACKAGE_VERSION <<
" (" << BUILD_TYPE <<
"), ROOT version: " << ROOT_VERSION_USED << std::endl << std::endl;
586 #ifdef HAVE_GIT_REV_H 587 std::cout << std::endl <<
"musrRootValidation git-branch: " << GIT_BRANCH <<
", git-rev: " << GIT_CURRENT_SHA1 << std::endl << std::endl;
589 std::cout << std::endl <<
"musrRootValidation version: unknown." << std::endl << std::endl;
600 bool quiet=
false, keep=
false;
601 for (
int i=1; i<argc; i++) {
602 if (!strcmp(argv[i],
"--quiet"))
604 if (!strcmp(argv[i],
"--keep"))
610 std::cerr << std::endl <<
"**ERROR** " << argv[1] <<
" is not a valid MusrRoot file." << std::endl << std::endl;
615 if (doc ==
nullptr) {
616 std::cerr << std::endl <<
"**ERROR** couldn't get xmlDocPtr for xml-file " << argv[1] <<
"." << std::endl << std::endl;
621 std::cout << std::endl <<
"xml-file " << argv[1] <<
" validates against xml-schema " << argv[2] << std::endl << std::endl;
623 std::cerr << std::endl <<
"**ERROR** xml-file " << argv[1] <<
" fails to validate against xml-schema " << argv[2] << std::endl << std::endl;
628 std::cerr << std::endl <<
"**ERROR** number of histogram found in the DecayAnaModule is inconsistent";
629 std::cerr << std::endl <<
" with the header; found " << dump.
GetNoOfDecayHistos() <<
" histograms in the DecayAnaModule,";
631 std::cerr << std::endl << std::endl;
635 std::cerr << std::endl <<
"**ERROR** number of histogram found in the DecayAnaModule is inconsistent";
636 std::cerr << std::endl <<
" with number of Detector entries in the RunHeader.";
637 std::cerr << std::endl <<
" Found " << dump.
GetNoOfDecayHistos() <<
" histograms in the DecayAnaModule,";
638 std::cerr << std::endl <<
" but " << dump.
GetNoOfDetectors() <<
" number of Detector entries.";
639 std::cerr << std::endl << std::endl;
Bool_t fKeep
true = keep the XML dump file
virtual void DumpObjArray(TObjArray *obj, UInt_t offset)
virtual UInt_t GetNoOfExpectedHistos()
UInt_t fNoOfDetectors
number of detector entries in the header
virtual void DumpFolder(TFolder *folder, UInt_t offset)
virtual void DumpEntry(TObject *obj, UInt_t offset)
Bool_t fValid
true if the conversion was fine
int is_valid(const xmlDocPtr doc, const char *schema_filename)
virtual void GetType(TString entry, TString &type)
PMusrRoot2Xml(const char *fileName, bool quiet, bool keep)
Bool_t fQuiet
true = suppress output while converting
virtual UInt_t GetNoOfRedGreenOffsets()
virtual void CheckClass(TObject *obj, TString str, UInt_t offset)
std::vector< std::string > fXmlData
keeps the XML structure dump of the ROOT file
UInt_t fNoOfHistos
number of histos from run header
EFolderTag fFolderTag
switch indicating which kind of TFolder object is found
UInt_t fNoOfRedGreenOffsets
number of RedGreen offsets
virtual TString GetXmlDumpFileName()
virtual void GetLabel(TString entry, TString &label)
virtual void SortHistoFolders()
UInt_t fNoOfDecayHistos
number of decay histos in the DecayAnaModule
virtual UInt_t GetNoOfDecayHistos()
TString fFileName
file name of the ROOT file
virtual UInt_t GetNoOfHistos()
int main(int argc, char *argv[])
virtual UInt_t GetNoOfDetectors()
TString fXmlDumpFileName
file name of the XML dump file