#include "TFileMerger.h"
#include "TUrl.h"
#include "TFile.h"
#include "TUUID.h"
#include "TSystem.h"
#include "TH1.h"
#include "TChain.h"
#include "TKey.h"
#include "THashList.h"
#include "TObjString.h"
#include "TClass.h"
#include "TMethodCall.h"
#include "Riostream.h"
ClassImp(TFileMerger)
TFileMerger::TFileMerger() : fOutputFile(0),fFastMethod(kTRUE), fNoTrees(kFALSE)
{
   
   fFileList = new TList;
   fFileList->SetOwner(kTRUE);
}
TFileMerger::~TFileMerger()
{
   
   if (fFileList)
      delete fFileList;
   if (fOutputFile)
      delete fOutputFile;
}
void TFileMerger::Reset()
{
   
   fFileList->Clear();
}
Bool_t TFileMerger::AddFile(const char *url)
{
   
   TUUID uuid;
   TString localcopy = "file:/tmp/";
   localcopy += "ROOTMERGE-";
   localcopy += uuid.AsString();
   localcopy += ".root";
   if (!TFile::Cp(url, localcopy)) {
      Error("AddFile", "cannot get a local copy of file %s", url);
      return kFALSE;
   }
   TFile *newfile = TFile::Open(localcopy, "READ");
   if (!newfile) {
      Error("AddFile", "cannot open local copy %s of URL %s",
            localcopy.Data(), url);
      return kFALSE;
   } else {
      fFileList->Add(newfile);
      return  kTRUE;
   }
}
Bool_t TFileMerger::OutputFile(const char *outputfile)
{
   
   if (fOutputFile)
      delete fOutputFile;
   fOutputFilename = outputfile;
   TUUID uuid;
   TString localcopy = "file:/tmp/";
   localcopy += "ROOTMERGED-";
   localcopy += uuid.AsString();
   localcopy += ".root";
   fOutputFile = TFile::Open(localcopy, "RECREATE");
   fOutputFilename1 = localcopy;
   if (!fOutputFile) {
      Error("OutputFile", "cannot open the MERGER output file %s", localcopy.Data());
      return kFALSE;
   }
   return kTRUE;
}
void TFileMerger::PrintFiles(Option_t *options)
{
   
   fFileList->Print(options);
}
Bool_t TFileMerger::Merge()
{
   
   
   
   if (!fOutputFile) {
      Info("Merge", "will merge the results to the file "
           "FileMerger.root\nin your working directory, "
           "since you didn't specify a merge filename");
      if (!OutputFile("FileMerger.root")) {
         return kFALSE;
      }
   }
   Bool_t result = MergeRecursive(fOutputFile, fFileList,0);
   if (!result) {
      Error("Merge", "error during merge of your ROOT files");
   } else {
      fOutputFile->Write();
      
      TFile::Cp(fOutputFilename1, fOutputFilename);
   }
   
   TString path(fOutputFile->GetPath());
   path = path(0, path.Index(':',0));
   gSystem->Unlink(path);
   fOutputFile = 0;
   TIter next(fFileList);
   TFile *file;
   while ((file = (TFile*) next())) {
      
      file->Close();
      
      TString path(file->GetPath());
      path = path(0, path.Index(':',0));
      gSystem->Unlink(path);
   }
   return result;
}
Bool_t TFileMerger::MergeRecursive(TDirectory *target, TList *sourcelist, Int_t isdir)
{
   
   
   
   TString path( (char*)strstr( target->GetPath(), ":" ) );
   path.Remove( 0, 2 );
   TDirectory *first_source = (TDirectory*)sourcelist->First();
   THashList allNames;
   while(first_source) {
      TDirectory *current_sourcedir = first_source->GetDirectory(path);
      if (!current_sourcedir) {
         first_source = (TDirectory*)sourcelist->After(first_source);
         continue;
      }
      
      TChain *globChain = 0;
      TIter nextkey( current_sourcedir->GetListOfKeys() );
      TKey *key, *oldkey=0;
      
      TH1::AddDirectory(kFALSE);
      while ( (key = (TKey*)nextkey())) {
         if (current_sourcedir == target) break;
         
         if (oldkey && !strcmp(oldkey->GetName(),key->GetName())) continue;
         if (allNames.FindObject(key->GetName())) continue;
         allNames.Add(new TObjString(key->GetName()));
         
         current_sourcedir->cd();
         TObject *obj = key->ReadObj();
         if ( obj->IsA()->InheritsFrom( TH1::Class() ) ) {
            
            TH1 *h1 = (TH1*)obj;
            TList listH;
            
            
            TFile *nextsource = (TFile*)sourcelist->After( first_source );
            while ( nextsource ) {
               
               TDirectory *ndir = nextsource->GetDirectory(path);
               if (ndir) {
                  ndir->cd();
                  TKey *key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(h1->GetName());
                  if (key2) {
                     TObject *hobj = key2->ReadObj();
                     hobj->ResetBit(kMustCleanup);
                     listH.Add(hobj);
                     h1->Merge(&listH);
                     listH.Delete();
                  }
               }
               nextsource = (TFile*)sourcelist->After( nextsource );
            }
         } else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {
            
            if (!fNoTrees) {
               TString obj_name;
               if (path.Length()) {
                  obj_name = path + "/" + obj->GetName();
               } else {
                  obj_name = obj->GetName();
               }
               globChain = new TChain(obj_name);
               globChain->Add(first_source->GetName());
               TFile *nextsource = (TFile*)sourcelist->After( first_source );
               while ( nextsource ) {
                  
                  TFile *curf = TFile::Open(nextsource->GetName());
                  if (curf) {
                     Bool_t mustAdd = kFALSE;
                     if (curf->FindKey(obj_name)) {
                        mustAdd = kTRUE;
                     } else {
                        
                        
                        TObject *aobj = curf->Get(obj_name);
                        if (aobj) { mustAdd = kTRUE; delete aobj;}
                     }
                     if (mustAdd) {
                        globChain->Add(nextsource->GetName());
                     }
                  }
                  delete curf;
                  nextsource = (TFile*)sourcelist->After( nextsource );
               }
            }
         } else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
            
            
            
            target->cd();
            TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
            
            
            
            MergeRecursive( newdir, sourcelist,1);
         } else {
            TMethodCall callEnv;
            if (obj->IsA())
               callEnv.InitWithPrototype(obj->IsA(), "Merge", "TCollection*");
            if (callEnv.IsValid()) {
               TList* tomerge = new TList;
               TFile *nextsource = (TFile*)sourcelist->After(first_source);
               while (nextsource) {
                  nextsource->cd(path);
                  TObject *newobj = gDirectory->Get(obj->GetName());
                  if (newobj) {
                     tomerge->Add(newobj);
                  }
                  nextsource = (TFile*)sourcelist->After(nextsource);
               }
               callEnv.SetParam((Long_t) tomerge);
               callEnv.Execute(obj);
               delete tomerge;
            } else {
               target->cd();
               obj->Write();
               TFile *nextsource = (TFile*)sourcelist->After(first_source);
               while (nextsource) {
                  nextsource->cd(path);
                  TObject *newobj = gDirectory->Get(obj->GetName());
                  if (newobj) {
                     target->cd();
                     newobj->Write();
                  }
                  nextsource = (TFile*)sourcelist->After(nextsource);
               }
               Warning("MergeRecursive", "object type without Merge function will be added unmerged, name: %s title: %s",
                       obj->GetName(), obj->GetTitle());
               return kTRUE;
            }
         }
         
         
         
         
         if ( obj ) {
            target->cd();
            
            if(obj->IsA()->InheritsFrom( "TDirectory" )) {
               
            } else if(obj->IsA()->InheritsFrom( "TTree" )) {
               if (!fNoTrees) {
                  globChain->ls();
                  if (fFastMethod) globChain->Merge(target->GetFile(),0,"keep fast");
                  else             globChain->Merge(target->GetFile(),0,"keep");
                  delete globChain;
               }
            } else {
               obj->Write( key->GetName() );
            }
         }
         oldkey = key;
      } 
      first_source = (TDirectory*)sourcelist->After(first_source);
   }
   
   target->SaveSelf(kTRUE);
   if (!isdir) sourcelist->Remove(sourcelist->First());
   return kTRUE;
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.