/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Thomas Bretz, 11/2003 ! ! Copyright: MAGIC Software Development, 2000-2003 ! ! \* ======================================================================== */ ////////////////////////////////////////////////////////////////////////////// // // MReportFileRead // // Task to read the central control report file. For more information see // the base class of all reports MReport. // // To add a report which should be read use AddToList. // // eg. AddToList("Drive") will assume the existance of a class called // MReportDrive. It will create such an object automatically. It will // send all lines starting with 'MReportDrive::fIndetifier-REPORT' // to this class. // ////////////////////////////////////////////////////////////////////////////// #include "MReportFileRead.h" #include #include #include #include #include "MLog.h" #include "MLogManip.h" #include "MReport.h" #include "MParList.h" ClassImp(MReportFileRead); using namespace std; const TString MReportFileRead::gsReportHeader ="[CC Report File]"; const TString MReportFileRead::gsVersionPrefix="Arehucas Version Number"; class MReportHelp : public TObject { private: MReport *fReport; ULong_t fNumReports; public: MReportHelp(const char *name, MLog *fLog) : fReport(NULL), fNumReports(0) { TClass *cls = gROOT->GetClass(name); Int_t rc = 0; if (!cls) rc =1; else { if (!cls->Property()) rc = 5; if (!cls->Size()) rc = 4; if (!cls->IsLoaded()) rc = 3; if (!cls->HasDefaultConstructor()) rc = 2; } if (rc) { *fLog << err << dbginf << "Cannot create new instance of class '" << name << "': "; switch (rc) { case 1: *fLog << "gROOT->GetClass() returned NULL." << endl; return; case 2: *fLog << "no default constructor." << endl; return; case 3: *fLog << "not loaded." << endl; return; case 4: *fLog << "zero size." << endl; return; case 5: *fLog << "no property." << endl; return; } } // // create the parameter container of the the given class type // fReport = (MReport*)cls->New(); } ~MReportHelp() { if (fReport) delete fReport; } const char *GetName() const { return fReport->GetIdentifier(); } ULong_t GetNumReports() const { return fNumReports; } ULong_t Hash() const { return fReport->GetIdentifier().Hash(); } MReport *GetReport() { return fReport; } //void SetTime(MTime *t) { fReport->SetTime(t); } Int_t Interprete(TString &str, const MTime &start, const MTime &stop) { const Int_t rc = fReport->Interprete(str, start, stop); if (rc==kFALSE) return kFALSE; fNumReports++; return rc; } Bool_t SetupReading(MParList &plist) { return fReport->SetupReading(plist); } void AddToList(MParList &plist) { plist.AddToList(fReport); } }; // -------------------------------------------------------------------------- // // Default constructor. It tries to open the given file and creates a // THashTable which allows faster access to the MReport* objects. // MReportFileRead::MReportFileRead(const char *fname, const char *name, const char *title) : fFileName(fname), fIn(NULL) { fName = name ? name : "MReportFileRead"; fTitle = title ? title : "Read task to read Central Control report files"; fIn = new ifstream; fList = new THashTable(1,1); fList->SetOwner(); } // -------------------------------------------------------------------------- // // Destructor. Delete input stream and hash table. // MReportFileRead::~MReportFileRead() { delete fIn; delete fList; } MReportHelp *MReportFileRead::GetReportHelp(const TString &str) const { return (MReportHelp*)fList->FindObject(str); } MReport *MReportFileRead::GetReport(MReportHelp *help) const { return help ? help->GetReport() : 0; } MReport *MReportFileRead::GetReport(const TString &str) const { return GetReport(GetReportHelp(str)); } // -------------------------------------------------------------------------- // // Add a new MReport* to the list (eg 'Drive' will add MReportDrive) // For convinience the object is created as a MReportHelp object. // Bool_t MReportFileRead::AddToList(const char *name) const { MReportHelp *help = new MReportHelp(name, fLog); MReport *rep = NULL; if (!(rep=help->GetReport())) return kFALSE; if (GetReport(rep->GetIdentifier())) { *fLog << warn << "WARNING - Report with Identifier '"; *fLog << rep->GetIdentifier() << "' already added to the list... "; *fLog << "ignored." << endl; delete help; return kFALSE; } fList->Add(help); return kTRUE; } // -------------------------------------------------------------------------- // // Check whether the file header corresponds to a central control file // header and check for the existance of a correct version number. // The version number may later be used to be able to read different // file versions // Int_t MReportFileRead::CheckFileHeader() const { Int_t line = 0; TString str; str.ReadLine(*fIn); // Read to EOF or newline if (str != gsReportHeader) { *fLog << err << "ERROR - First line doesn't match '" << gsReportHeader <<"' "; *fLog << "in file '" << fFileName << "'"<" << endl; return line; } // -------------------------------------------------------------------------- // // Call SetupReading for all MReportHelp objects scheduled. // Try to open the file and check the file header. // Int_t MReportFileRead::PreProcess(MParList *pList) { //MTime *time = (MTime*)pList->FindCreateObj("MTime"); //if (!time) // return kFALSE; fNumLine = 0; TIter Next(fList); MReportHelp *help=0; while ((help=(MReportHelp*)Next())) if (!help->SetupReading(*pList)) return kFALSE; fList->ForEach(MReportHelp, AddToList)(*pList); // // open the input stream // first of all check if opening the file in the constructor was // successfull // fIn->open(fFileName); if (!(*fIn)) { *fLog << err << "Error: Cannot open file '" << fFileName << "'" << endl; return kFALSE; } if (TestBit(kHasNoHeader)) return kTRUE; const Int_t n = CheckFileHeader(); fNumLine += n; return n==2; } // -------------------------------------------------------------------------- // // Read the file line by line as long as a matching MReport* class is found. // In this case call its interpreter (Interprete()) and remove the identifier // first (XYZ-REPORT) // Int_t MReportFileRead::Process() { TString str; MReportHelp *rep=NULL; while (!GetReport(rep)) { str.ReadLine(*fIn); if (!*fIn) { *fLog << dbg << "EOF detected." << endl; return kFALSE; } fNumLine++; const Int_t pos = str.First(' '); if (pos<=0) continue; rep = GetReportHelp(str(0,pos)); if (GetReport(rep)) str.Remove(0, pos); } const Int_t rc = rep->Interprete(str, fStart, fStop); if (rc==kFALSE) { *fLog << err << "ERROR - Interpretation of '" << rep->GetName() << "' failed (Line #" << fNumLine << ")" << endl; return kFALSE; } return rc; } // -------------------------------------------------------------------------- // // Close the file and print some execution statistics // Int_t MReportFileRead::PostProcess() { fIn->close(); if (!GetNumExecutions()) return kTRUE; *fLog << inf << endl; *fLog << GetDescriptor() << " statistics:" << endl; *fLog << dec << setfill(' '); TIter Next(fList); MReportHelp *rep=0; while ((rep=(MReportHelp*)Next())) { *fLog << " " << setw(7) << rep->GetNumReports() << " ("; *fLog << setw(3) << (int)(100.*rep->GetNumReports()/GetNumExecutions()); *fLog << "%): " << rep->GetName() << endl; } return kTRUE; }