TXMLFile.cxx

Go to the documentation of this file.
00001 // @(#)root/xml:$Id: TXMLFile.cxx 35596 2010-09-22 14:33:08Z rdm $
00002 // Author: Sergey Linev, Rene Brun  10.05.2004
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //________________________________________________________________________
00013 //
00014 // The main motivation for the XML  format is to facilitate the
00015 // communication with other non ROOT applications. Currently
00016 // writing and reading XML files is limited to ROOT applications.
00017 // It is our intention to develop a simple reader independent
00018 // of the ROOT libraries that could be used as an example for
00019 // real applications. One of possible approach with code generation
00020 // is implemented in TXMLPlayer class.
00021 //
00022 // The XML format should be used only for small data volumes,
00023 // typically histogram files, pictures, geometries, calibrations.
00024 // The XML file is built in memory before being dumped to disk.
00025 //
00026 // Like for normal ROOT files, XML files use the same I/O mechanism
00027 // exploiting the ROOT/CINT dictionary. Any class having a dictionary
00028 // can be saved in XML format.
00029 //
00030 // This first implementation does not support subdirectories
00031 // or Trees.
00032 //
00033 // The shared library libRXML.so may be loaded dynamically
00034 // via gSystem->Load("libRXML"). This library is automatically
00035 // loaded by the plugin manager as soon as a XML file is created
00036 // via, eg
00037 //   TFile::Open("file.xml","recreate");
00038 // TFile::Open returns a TXMLFile object. When a XML file is open in write mode,
00039 // one can use the normal TObject::Write to write an object in the file.
00040 // Alternatively one can use the new functions TDirectoryFile::WriteObject and
00041 // TDirectoryFile::WriteObjectAny to write a TObject* or any class not deriving
00042 // from TObject.
00043 //
00044 // example of a session saving a histogram to a XML file
00045 // =====================================================
00046 //   TFile *f = TFile::Open("Example.xml","recreate");
00047 //   TH1F *h = new TH1F("h","test",1000,-2,2);
00048 //   h->FillRandom("gaus");
00049 //   h->Write();
00050 //   delete f;
00051 //
00052 // example of a session reading the histogram from the file
00053 // ========================================================
00054 //   TFile *f = TFile::Open("Example.xml");
00055 //   TH1F *h = (TH1F*)f->Get("h");
00056 //   h->Draw();
00057 //
00058 // A new option in the canvas "File" menu is available to save
00059 // a TCanvas as a XML file. One can also do
00060 //   canvas->Print("Example.xml");
00061 //
00062 // Configuring ROOT with the option "xml"
00063 // ======================================
00064 // The XML package is enabled by default
00065 //
00066 // documentation
00067 // =============
00068 // See also classes TBufferXML, TKeyXML, TXMLEngine, TXMLSetup and TXMLPlayer.
00069 // An example of XML file corresponding to the small example below
00070 // can be found at http://root.cern.ch/root/Example.xml
00071 //
00072 //______________________________________________________________________________
00073 
00074 #include "TXMLFile.h"
00075 
00076 #include "TROOT.h"
00077 #include "TSystem.h"
00078 #include "TList.h"
00079 #include "TBrowser.h"
00080 #include "TObjArray.h"
00081 #include "TBufferXML.h"
00082 #include "TKeyXML.h"
00083 #include "TObjArray.h"
00084 #include "TArrayC.h"
00085 #include "TStreamerInfo.h"
00086 #include "TStreamerElement.h"
00087 #include "TProcessID.h"
00088 #include "TError.h"
00089 #include "TClass.h"
00090 
00091 ClassImp(TXMLFile);
00092 
00093 //______________________________________________________________________________
00094 TXMLFile::TXMLFile() :
00095    TFile(),
00096    TXMLSetup(),
00097    fDoc(0),
00098    fStreamerInfoNode(0),
00099    fXML(0),
00100    fKeyCounter(0)
00101 {
00102    // default TXMLFile constructor
00103 
00104    SetBit(kBinaryFile, kFALSE);
00105    fIOVersion  = TXMLFile::Class_Version();
00106 }
00107 
00108 
00109 //______________________________________________________________________________
00110 TXMLFile::TXMLFile(const char* filename, Option_t* option, const char* title, Int_t compression) :
00111    TFile(),
00112    TXMLSetup(),
00113    fDoc(0),
00114    fStreamerInfoNode(0),
00115    fXML(0),
00116    fKeyCounter(0)
00117 {
00118    // Open or creates local XML file with name filename.
00119    // It is recommended to specify filename as "<file>.xml". The suffix ".xml"
00120    // will be used by object browsers to automatically identify the file as
00121    // a XML file. If the constructor fails in any way IsZombie() will
00122    // return true. Use IsOpen() to check if the file is (still) open.
00123    //
00124    // If option = NEW or CREATE   create a new file and open it for writing,
00125    //                             if the file already exists the file is
00126    //                             not opened.
00127    //           = RECREATE        create a new file, if the file already
00128    //                             exists it will be overwritten.
00129    //           = 2xoo            create a new file with specified xml settings
00130    //                             for more details see TXMLSetup class
00131    //           = UPDATE          open an existing file for writing.
00132    //                             if no file exists, it is created.
00133    //           = READ            open an existing file for reading.
00134    //
00135    // For more details see comments for TFile::TFile() constructor
00136    //
00137    // For a moment TXMLFile does not support TTree objects and subdirectories
00138 
00139    fXML = new TXMLEngine();
00140 
00141    if (!gROOT)
00142       ::Fatal("TFile::TFile", "ROOT system not initialized");
00143 
00144    if (filename && !strncmp(filename, "xml:", 4))
00145       filename += 4;
00146 
00147    gDirectory = 0;
00148    SetName(filename);
00149    SetTitle(title);
00150    TDirectoryFile::Build(this, 0);
00151 
00152    fD          = -1;
00153    fFile       = this;
00154    fFree       = 0;
00155    fVersion    = gROOT->GetVersionInt();  //ROOT version in integer format
00156    fUnits      = 4;
00157    fOption     = option;
00158    SetCompressionLevel(compression);
00159    fWritten    = 0;
00160    fSumBuffer  = 0;
00161    fSum2Buffer = 0;
00162    fBytesRead  = 0;
00163    fBytesWrite = 0;
00164    fClassIndex = 0;
00165    fSeekInfo   = 0;
00166    fNbytesInfo = 0;
00167    fProcessIDs = 0;
00168    fNProcessIDs= 0;
00169    fIOVersion  = TXMLFile::Class_Version();
00170    SetBit(kBinaryFile, kFALSE);
00171 
00172    fOption = option;
00173    fOption.ToUpper();
00174 
00175    if (fOption == "NEW") fOption = "CREATE";
00176 
00177    Bool_t create   = (fOption == "CREATE") ? kTRUE : kFALSE;
00178    Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
00179    Bool_t update   = (fOption == "UPDATE") ? kTRUE : kFALSE;
00180    Bool_t read     = (fOption == "READ") ? kTRUE : kFALSE;
00181    Bool_t xmlsetup = IsValidXmlSetup(option);
00182    if (xmlsetup) recreate = kTRUE;
00183 
00184    if (!create && !recreate && !update && !read) {
00185       read    = kTRUE;
00186       fOption = "READ";
00187    }
00188 
00189    Bool_t devnull = kFALSE;
00190    const char *fname = 0;
00191 
00192    if (!filename || !strlen(filename)) {
00193       Error("TXMLFile", "file name is not specified");
00194       goto zombie;
00195    }
00196 
00197    // support dumping to /dev/null on UNIX
00198    if (!strcmp(filename, "/dev/null") &&
00199        !gSystem->AccessPathName(filename, kWritePermission)) {
00200       devnull  = kTRUE;
00201       create   = kTRUE;
00202       recreate = kFALSE;
00203       update   = kFALSE;
00204       read     = kFALSE;
00205       fOption  = "CREATE";
00206       SetBit(TFile::kDevNull);
00207    }
00208 
00209    gROOT->cd();
00210 
00211    fname = gSystem->ExpandPathName(filename);
00212    if (fname) {
00213       SetName(fname);
00214       delete [] (char*)fname;
00215       fname = GetName();
00216    } else {
00217       Error("TXMLFile", "error expanding path %s", filename);
00218       goto zombie;
00219    }
00220 
00221    if (recreate) {
00222       if (!gSystem->AccessPathName(fname, kFileExists))
00223          gSystem->Unlink(fname);
00224       recreate = kFALSE;
00225       create   = kTRUE;
00226       fOption  = "CREATE";
00227    }
00228 
00229    if (create && !devnull && !gSystem->AccessPathName(fname, kFileExists)) {
00230       Error("TXMLFile", "file %s already exists", fname);
00231       goto zombie;
00232    }
00233 
00234    if (update) {
00235       if (gSystem->AccessPathName(fname, kFileExists)) {
00236          update = kFALSE;
00237          create = kTRUE;
00238       }
00239       if (update && gSystem->AccessPathName(fname, kWritePermission)) {
00240          Error("TXMLFile", "no write permission, could not open file %s", fname);
00241          goto zombie;
00242       }
00243    }
00244 
00245    if (read) {
00246       if (gSystem->AccessPathName(fname, kFileExists)) {
00247          Error("TXMLFile", "file %s does not exist", fname);
00248          goto zombie;
00249       }
00250       if (gSystem->AccessPathName(fname, kReadPermission)) {
00251          Error("TXMLFile", "no read permission, could not open file %s", fname);
00252          goto zombie;
00253       }
00254    }
00255 
00256    fRealName = fname;
00257 
00258    if (create || update)
00259       SetWritable(kTRUE);
00260    else
00261       SetWritable(kFALSE);
00262 
00263    if (create) {
00264       if (xmlsetup)
00265          ReadSetupFromStr(option);
00266       else
00267          ReadSetupFromStr(TXMLSetup::DefaultXmlSetup());
00268    }
00269 
00270    InitXmlFile(create);
00271 
00272    return;
00273 
00274 zombie:
00275    MakeZombie();
00276    gDirectory = gROOT;
00277 }
00278 
00279 //______________________________________________________________________________
00280 void TXMLFile::InitXmlFile(Bool_t create)
00281 {
00282    // initialize xml file and correspondent structures
00283    // identical to TFile::Init() function
00284 
00285    Int_t len = gROOT->GetListOfStreamerInfo()->GetSize()+1;
00286    if (len<5000) len = 5000;
00287    fClassIndex = new TArrayC(len);
00288    fClassIndex->Reset(0);
00289 
00290    if (create) {
00291       fDoc = fXML->NewDoc();
00292       XMLNodePointer_t fRootNode = fXML->NewChild(0, 0, xmlio::Root, 0);
00293       fXML->DocSetRootElement(fDoc, fRootNode);
00294    } else {
00295       ReadFromFile();
00296    }
00297 
00298    gROOT->GetListOfFiles()->Add(this);
00299    cd();
00300 
00301    fNProcessIDs = 0;
00302    TKey* key = 0;
00303    TIter iter(fKeys);
00304    while ((key = (TKey*)iter())!=0) {
00305       if (!strcmp(key->GetClassName(),"TProcessID")) fNProcessIDs++;
00306    }
00307 
00308    fProcessIDs = new TObjArray(fNProcessIDs+1);
00309 }
00310 
00311 //______________________________________________________________________________
00312 void TXMLFile::Close(Option_t *option)
00313 {
00314    // Close a XML file
00315    // For more comments see TFile::Close() function
00316 
00317    if (!IsOpen()) return;
00318 
00319    TString opt = option;
00320    if (opt.Length()>0)
00321       opt.ToLower();
00322 
00323    if (IsWritable()) SaveToFile();
00324 
00325    fWritable = kFALSE;
00326 
00327    if (fDoc) {
00328       fXML->FreeDoc(fDoc);
00329       fDoc = 0;
00330    }
00331 
00332    if (fClassIndex) {
00333       delete fClassIndex;
00334       fClassIndex = 0;
00335    }
00336 
00337    if (fStreamerInfoNode) {
00338       fXML->FreeNode(fStreamerInfoNode);
00339       fStreamerInfoNode = 0;
00340    }
00341 
00342    TDirectory *cursav = gDirectory;
00343    cd();
00344 
00345    if (cursav == this || cursav->GetFile() == this) {
00346       cursav = 0;
00347    }
00348 
00349    // Delete all supported directories structures from memory
00350    TDirectoryFile::Close();
00351    cd();      // Close() sets gFile = 0
00352 
00353    if (cursav)
00354       cursav->cd();
00355    else {
00356       gFile      = 0;
00357       gDirectory = gROOT;
00358    }
00359 
00360    //delete the TProcessIDs
00361    TList pidDeleted;
00362    TIter next(fProcessIDs);
00363    TProcessID *pid;
00364    while ((pid = (TProcessID*)next())) {
00365       if (!pid->DecrementCount()) {
00366          if (pid != TProcessID::GetSessionProcessID()) pidDeleted.Add(pid);
00367       } else if(opt.Contains("r")) {
00368          pid->Clear();
00369       }
00370    }
00371    pidDeleted.Delete();
00372 
00373    gROOT->GetListOfFiles()->Remove(this);
00374 }
00375 
00376 //______________________________________________________________________________
00377 TXMLFile::~TXMLFile()
00378 {
00379    // destructor of TXMLFile object
00380 
00381    Close();
00382 
00383    if (fXML!=0) {
00384       delete fXML;
00385       fXML = 0;
00386    }
00387 }
00388 
00389 //______________________________________________________________________________
00390 void TXMLFile::operator=(const TXMLFile &)
00391 {
00392    // make private to exclude copy operator
00393 }
00394 
00395 //______________________________________________________________________________
00396 Bool_t TXMLFile::IsOpen() const
00397 {
00398    // return kTRUE if file is opened and can be accessed
00399 
00400    return fDoc != 0;
00401 }
00402 
00403 //______________________________________________________________________________
00404 Int_t TXMLFile::ReOpen(Option_t* mode)
00405 {
00406    // Reopen a file with a different access mode, like from READ to
00407    // See TFile::Open() for details
00408 
00409    cd();
00410 
00411    TString opt = mode;
00412    opt.ToUpper();
00413 
00414    if (opt != "READ" && opt != "UPDATE") {
00415       Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
00416       return 1;
00417    }
00418 
00419    if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
00420       return 1;
00421 
00422    if (opt == "READ") {
00423       // switch to READ mode
00424 
00425       if (IsOpen() && IsWritable())
00426          SaveToFile();
00427       fOption = opt;
00428 
00429       SetWritable(kFALSE);
00430 
00431    } else {
00432       fOption = opt;
00433 
00434       SetWritable(kTRUE);
00435    }
00436 
00437    return 0;
00438 }
00439 
00440 //______________________________________________________________________________
00441 TKey* TXMLFile::CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t)
00442 {
00443    // create XML key, which will store object in xml structures
00444 
00445    return new TKeyXML(mother, ++fKeyCounter, obj, name);
00446 }
00447 
00448 //______________________________________________________________________________
00449 TKey* TXMLFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t)
00450 {
00451    // create XML key, which will store object in xml structures
00452 
00453    return new TKeyXML(mother, ++fKeyCounter, obj, cl, name);
00454 }
00455 
00456 //______________________________________________________________________________
00457 void TXMLFile::ProduceFileNames(const char* filename, TString& fname, TString& dtdname)
00458 {
00459    // function produces pair of xml and dtd file names
00460 
00461    fname = filename;
00462    dtdname = filename;
00463 
00464    Bool_t hasxmlext = kFALSE;
00465 
00466    if (fname.Length()>4) {
00467       TString last = fname(fname.Length()-4,4);
00468       last.ToLower();
00469       hasxmlext = (last==".xml");
00470    }
00471 
00472    if (hasxmlext) {
00473       dtdname.Replace(dtdname.Length()-4,4,".dtd");
00474    } else {
00475       fname+=".xml";
00476       dtdname+=".dtd";
00477    }
00478 }
00479 
00480 //______________________________________________________________________________
00481 void TXMLFile::SaveToFile()
00482 {
00483    // Saves xml structures to file
00484    // xml elements are kept in list of TKeyXML objects
00485    // When saving, all this elements are linked to root xml node
00486    // In the end StreamerInfo structures are added
00487    // After xml document is saved, all nodes will be unlinked from root node
00488    // and kept in memory.
00489    // Only Close() or destructor relase memory, used by xml structures
00490 
00491    if (fDoc==0) return;
00492 
00493    if (gDebug>1)
00494       Info("SaveToFile","File: %s",fRealName.Data());
00495 
00496    XMLNodePointer_t fRootNode = fXML->DocGetRootElement(fDoc);
00497 
00498    fXML->FreeAttr(fRootNode, xmlio::Setup);
00499    fXML->NewAttr(fRootNode, 0, xmlio::Setup, GetSetupAsString());
00500 
00501    fXML->FreeAttr(fRootNode, xmlio::Ref);
00502    fXML->NewAttr(fRootNode, 0, xmlio::Ref, xmlio::Null);
00503 
00504    if (GetIOVersion()>1) {
00505 
00506       fXML->FreeAttr(fRootNode, xmlio::CreateTm);
00507       fXML->NewAttr(fRootNode, 0, xmlio::CreateTm, fDatimeC.AsSQLString());
00508 
00509       fXML->FreeAttr(fRootNode, xmlio::ModifyTm);
00510       fXML->NewAttr(fRootNode, 0, xmlio::ModifyTm, fDatimeM.AsSQLString());
00511 
00512       fXML->FreeAttr(fRootNode, xmlio::ObjectUUID);
00513       fXML->NewAttr(fRootNode, 0, xmlio::ObjectUUID, fUUID.AsString());
00514 
00515       fXML->FreeAttr(fRootNode, xmlio::Title);
00516       if (strlen(GetTitle())>0)
00517          fXML->NewAttr(fRootNode, 0, xmlio::Title, GetTitle());
00518 
00519       fXML->FreeAttr(fRootNode, xmlio::IOVersion);
00520       fXML->NewIntAttr(fRootNode, xmlio::IOVersion, GetIOVersion());
00521    }
00522 
00523    TString fname, dtdname;
00524    ProduceFileNames(fRealName, fname, dtdname);
00525 
00526 /*
00527    TIter iter(GetListOfKeys());
00528    TKeyXML* key = 0;
00529    while ((key=(TKeyXML*)iter()) !=0)
00530       fXML->AddChild(fRootNode, key->KeyNode());
00531 */
00532 
00533    CombineNodesTree(this, fRootNode, kTRUE);
00534 
00535    WriteStreamerInfo();
00536 
00537    if (fStreamerInfoNode)
00538       fXML->AddChild(fRootNode, fStreamerInfoNode);
00539 
00540    Int_t layout = GetCompressionLevel()>5 ? 0 : 1;
00541 
00542    fXML->SaveDoc(fDoc, fname, layout);
00543 
00544 /*   iter.Reset();
00545    while ((key=(TKeyXML*)iter()) !=0)
00546       fXML->UnlinkNode(key->KeyNode());
00547 */
00548    CombineNodesTree(this, fRootNode, kFALSE);
00549 
00550    if (fStreamerInfoNode)
00551       fXML->UnlinkNode(fStreamerInfoNode);
00552 }
00553 
00554 //______________________________________________________________________________
00555 void TXMLFile::CombineNodesTree(TDirectory* dir, XMLNodePointer_t topnode, Bool_t dolink)
00556 {
00557    // Connect/disconnect all file nodes to single tree before/after saving
00558 
00559    if (dir==0) return;
00560 
00561    TIter iter(dir->GetListOfKeys());
00562    TKeyXML* key = 0;
00563 
00564    while ((key=(TKeyXML*)iter()) !=0) {
00565       if (dolink)
00566          fXML->AddChild(topnode, key->KeyNode());
00567       else
00568          fXML->UnlinkNode(key->KeyNode());
00569       if (key->IsSubdir())
00570          CombineNodesTree(FindKeyDir(dir, key->GetKeyId()), key->KeyNode(), dolink);
00571    }
00572 }
00573 
00574 
00575 //______________________________________________________________________________
00576 Bool_t TXMLFile::ReadFromFile()
00577 {
00578    // read document from file
00579    // Now full content of docuument reads into the memory
00580    // Then document decomposed to separate keys and streamer info structures
00581    // All inrelevant data will be cleaned
00582 
00583    fDoc = fXML->ParseFile(fRealName);
00584    if (fDoc==0) return kFALSE;
00585 
00586    XMLNodePointer_t fRootNode = fXML->DocGetRootElement(fDoc);
00587 
00588    if ((fRootNode==0) || !fXML->ValidateVersion(fDoc)) {
00589       fXML->FreeDoc(fDoc);
00590       fDoc=0;
00591       return kFALSE;
00592    }
00593 
00594    ReadSetupFromStr(fXML->GetAttr(fRootNode, xmlio::Setup));
00595 
00596    if (fXML->HasAttr(fRootNode, xmlio::CreateTm)) {
00597       TDatime tm(fXML->GetAttr(fRootNode, xmlio::CreateTm));
00598       fDatimeC = tm;
00599    }
00600 
00601    if (fXML->HasAttr(fRootNode, xmlio::ModifyTm)) {
00602       TDatime tm(fXML->GetAttr(fRootNode, xmlio::ModifyTm));
00603       fDatimeM = tm;
00604    }
00605 
00606    if (fXML->HasAttr(fRootNode, xmlio::ObjectUUID)) {
00607       TUUID id(fXML->GetAttr(fRootNode, xmlio::ObjectUUID));
00608       fUUID = id;
00609    }
00610 
00611    if (fXML->HasAttr(fRootNode, xmlio::Title))
00612       SetTitle(fXML->GetAttr(fRootNode, xmlio::Title));
00613 
00614    if (fXML->HasAttr(fRootNode, xmlio::IOVersion))
00615       fIOVersion = fXML->GetIntAttr(fRootNode, xmlio::IOVersion);
00616    else
00617       fIOVersion = 1;
00618 
00619    fStreamerInfoNode = fXML->GetChild(fRootNode);
00620    fXML->SkipEmpty(fStreamerInfoNode);
00621    while (fStreamerInfoNode!=0) {
00622       if (strcmp(xmlio::SInfos, fXML->GetNodeName(fStreamerInfoNode))==0) break;
00623       fXML->ShiftToNext(fStreamerInfoNode);
00624    }
00625    fXML->UnlinkNode(fStreamerInfoNode);
00626 
00627    if (fStreamerInfoNode!=0)
00628       ReadStreamerInfo();
00629 
00630    if (IsUseDtd())
00631       if (!fXML->ValidateDocument(fDoc, gDebug>0)) {
00632          fXML->FreeDoc(fDoc);
00633          fDoc=0;
00634          return kFALSE;
00635       }
00636 
00637    ReadKeysList(this, fRootNode);
00638 
00639    fXML->CleanNode(fRootNode);
00640 
00641    return kTRUE;
00642 }
00643 
00644 //______________________________________________________________________________
00645 Int_t TXMLFile::ReadKeysList(TDirectory* dir, XMLNodePointer_t topnode)
00646 {
00647    // Read list of keys for directory
00648 
00649    if ((dir==0) || (topnode==0)) return 0;
00650 
00651    Int_t nkeys = 0;
00652 
00653    XMLNodePointer_t keynode = fXML->GetChild(topnode);
00654    fXML->SkipEmpty(keynode);
00655    while (keynode!=0) {
00656       XMLNodePointer_t next = fXML->GetNext(keynode);
00657 
00658       if (strcmp(xmlio::Xmlkey, fXML->GetNodeName(keynode))==0) {
00659          fXML->UnlinkNode(keynode);
00660 
00661          TKeyXML* key = new TKeyXML(dir, ++fKeyCounter, keynode);
00662          dir->AppendKey(key);
00663 
00664          if (gDebug>2)
00665             Info("ReadKeysList","Add key %s from node %s",key->GetName(), fXML->GetNodeName(keynode));
00666 
00667          nkeys++;
00668       }
00669 
00670       keynode = next;
00671       fXML->SkipEmpty(keynode);
00672    }
00673 
00674    return nkeys;
00675 }
00676 
00677 //______________________________________________________________________________
00678 void TXMLFile::WriteStreamerInfo()
00679 {
00680    // convert all TStreamerInfo, used in file, to xml format
00681 
00682    if (fStreamerInfoNode) {
00683       fXML->FreeNode(fStreamerInfoNode);
00684       fStreamerInfoNode = 0;
00685    }
00686 
00687    if (!IsStoreStreamerInfos()) return;
00688 
00689    TObjArray list;
00690 
00691    TIter iter(gROOT->GetListOfStreamerInfo());
00692 
00693    TStreamerInfo* info = 0;
00694 
00695    while ((info = (TStreamerInfo*) iter()) !=0 ) {
00696       Int_t uid = info->GetNumber();
00697       if (fClassIndex->fArray[uid])
00698          list.Add(info);
00699    }
00700 
00701    if (list.GetSize()==0) return;
00702 
00703    fStreamerInfoNode = fXML->NewChild(0, 0, xmlio::SInfos);
00704    for (int n=0;n<=list.GetLast();n++) {
00705       info  = (TStreamerInfo*) list.At(n);
00706 
00707       XMLNodePointer_t infonode = fXML->NewChild(fStreamerInfoNode, 0, "TStreamerInfo");
00708 
00709       fXML->NewAttr(infonode, 0, "name", info->GetName());
00710       fXML->NewAttr(infonode, 0, "title", info->GetTitle());
00711 
00712       fXML->NewIntAttr(infonode, "v", info->IsA()->GetClassVersion());
00713       fXML->NewIntAttr(infonode, "classversion", info->GetClassVersion());
00714       fXML->NewAttr(infonode, 0, "canoptimize", (info->TestBit(TStreamerInfo::kCannotOptimize) ? xmlio::False : xmlio::True));
00715       fXML->NewIntAttr(infonode, "checksum", info->GetCheckSum());
00716 
00717       TIter iter2(info->GetElements());
00718       TStreamerElement* elem=0;
00719       while ((elem= (TStreamerElement*) iter2()) != 0) {
00720          StoreStreamerElement(infonode, elem);
00721       }
00722    }
00723 }
00724 
00725 //______________________________________________________________________________
00726 TList* TXMLFile::GetStreamerInfoList()
00727 {
00728    // Read streamerinfo structures from xml format and provide them in the list
00729    // It is user responsibility to destroy this list
00730 
00731    if (fStreamerInfoNode==0) return 0;
00732 
00733    TList* list = new TList();
00734 
00735    XMLNodePointer_t sinfonode = fXML->GetChild(fStreamerInfoNode);
00736    fXML->SkipEmpty(sinfonode);
00737 
00738    while (sinfonode!=0) {
00739       if (strcmp("TStreamerInfo",fXML->GetNodeName(sinfonode))==0) {
00740          TString fname = fXML->GetAttr(sinfonode,"name");
00741          TString ftitle = fXML->GetAttr(sinfonode,"title");
00742 
00743          TStreamerInfo* info = new TStreamerInfo(TClass::GetClass(fname));
00744          info->SetTitle(ftitle);
00745 
00746          list->Add(info);
00747 
00748          Int_t clversion = AtoI(fXML->GetAttr(sinfonode,"classversion"));
00749          info->SetClassVersion(clversion);
00750          Int_t checksum = AtoI(fXML->GetAttr(sinfonode,"checksum"));
00751          info->SetCheckSum(checksum);
00752 
00753          const char* canoptimize = fXML->GetAttr(sinfonode,"canoptimize");
00754          if ((canoptimize==0) || (strcmp(canoptimize,xmlio::False)==0))
00755             info->SetBit(TStreamerInfo::kCannotOptimize);
00756          else
00757             info->ResetBit(TStreamerInfo::kCannotOptimize);
00758 
00759          XMLNodePointer_t node = fXML->GetChild(sinfonode);
00760          fXML->SkipEmpty(node);
00761          while (node!=0) {
00762             ReadStreamerElement(node, info);
00763             fXML->ShiftToNext(node);
00764          }
00765       }
00766       fXML->ShiftToNext(sinfonode);
00767    }
00768 
00769    list->SetOwner();
00770 
00771    return list;
00772 }
00773 
00774 //______________________________________________________________________________
00775 void TXMLFile::StoreStreamerElement(XMLNodePointer_t infonode, TStreamerElement* elem)
00776 {
00777    // store data of single TStreamerElement in streamer node
00778 
00779    TClass* cl = elem->IsA();
00780 
00781    XMLNodePointer_t node = fXML->NewChild(infonode, 0, cl->GetName());
00782 
00783    char sbuf[100], namebuf[100];
00784 
00785    fXML->NewAttr(node,0,"name",elem->GetName());
00786    if (strlen(elem->GetTitle())>0)
00787       fXML->NewAttr(node,0,"title",elem->GetTitle());
00788 
00789    fXML->NewIntAttr(node, "v", cl->GetClassVersion());
00790 
00791    fXML->NewIntAttr(node, "type", elem->GetType());
00792 
00793    if (strlen(elem->GetTypeName())>0)
00794       fXML->NewAttr(node,0,"typename", elem->GetTypeName());
00795 
00796    fXML->NewIntAttr(node, "size", elem->GetSize());
00797 
00798    if (elem->GetArrayDim()>0) {
00799       fXML->NewIntAttr(node, "numdim", elem->GetArrayDim());
00800 
00801       for (int ndim=0;ndim<elem->GetArrayDim();ndim++) {
00802          sprintf(namebuf, "dim%d", ndim);
00803          fXML->NewIntAttr(node, namebuf, elem->GetMaxIndex(ndim));
00804       }
00805    }
00806 
00807    if (cl == TStreamerBase::Class()) {
00808       TStreamerBase* base = (TStreamerBase*) elem;
00809       sprintf(sbuf, "%d", base->GetBaseVersion());
00810       fXML->NewAttr(node,0, "baseversion", sbuf);
00811    } else
00812    if (cl == TStreamerBasicPointer::Class()) {
00813       TStreamerBasicPointer* bptr = (TStreamerBasicPointer*) elem;
00814       fXML->NewIntAttr(node, "countversion", bptr->GetCountVersion());
00815       fXML->NewAttr(node, 0, "countname", bptr->GetCountName());
00816       fXML->NewAttr(node, 0, "countclass", bptr->GetCountClass());
00817    } else
00818    if (cl == TStreamerLoop::Class()) {
00819       TStreamerLoop* loop = (TStreamerLoop*) elem;
00820       fXML->NewIntAttr(node, "countversion", loop->GetCountVersion());
00821       fXML->NewAttr(node, 0, "countname", loop->GetCountName());
00822       fXML->NewAttr(node, 0, "countclass", loop->GetCountClass());
00823    } else
00824    if ((cl == TStreamerSTL::Class()) || (cl == TStreamerSTLstring::Class())) {
00825       TStreamerSTL* stl = (TStreamerSTL*) elem;
00826       fXML->NewIntAttr(node, "STLtype", stl->GetSTLtype());
00827       fXML->NewIntAttr(node, "Ctype", stl->GetCtype());
00828    }
00829 }
00830 
00831 //______________________________________________________________________________
00832 void TXMLFile::ReadStreamerElement(XMLNodePointer_t node, TStreamerInfo* info)
00833 {
00834   // read and reconstruct single TStreamerElement from xml node
00835 
00836    TClass* cl = TClass::GetClass(fXML->GetNodeName(node));
00837    if ((cl==0) || !cl->InheritsFrom(TStreamerElement::Class())) return;
00838 
00839    TStreamerElement* elem = (TStreamerElement*) cl->New();
00840 
00841    int elem_type = fXML->GetIntAttr(node,"type");
00842 
00843    elem->SetName(fXML->GetAttr(node,"name"));
00844    elem->SetTitle(fXML->GetAttr(node,"title"));
00845    elem->SetType(elem_type);
00846    elem->SetTypeName(fXML->GetAttr(node,"typename"));
00847    elem->SetSize(fXML->GetIntAttr(node,"size"));
00848 
00849 
00850    if (cl == TStreamerBase::Class()) {
00851       int basever = fXML->GetIntAttr(node,"baseversion");
00852       ((TStreamerBase*) elem)->SetBaseVersion(basever);
00853    } else
00854    if (cl == TStreamerBasicPointer::Class()) {
00855       TString countname = fXML->GetAttr(node,"countname");
00856       TString countclass = fXML->GetAttr(node,"countclass");
00857       Int_t countversion = fXML->GetIntAttr(node, "countversion");
00858 
00859       ((TStreamerBasicPointer*)elem)->SetCountVersion(countversion);
00860       ((TStreamerBasicPointer*)elem)->SetCountName(countname);
00861       ((TStreamerBasicPointer*)elem)->SetCountClass(countclass);
00862    } else
00863    if (cl == TStreamerLoop::Class()) {
00864       TString countname = fXML->GetAttr(node,"countname");
00865       TString countclass = fXML->GetAttr(node,"countclass");
00866       Int_t countversion = fXML->GetIntAttr(node,"countversion");
00867       ((TStreamerLoop*)elem)->SetCountVersion(countversion);
00868       ((TStreamerLoop*)elem)->SetCountName(countname);
00869       ((TStreamerLoop*)elem)->SetCountClass(countclass);
00870    } else
00871    if ((cl == TStreamerSTL::Class()) || (cl == TStreamerSTLstring::Class()))  {
00872       int fSTLtype = fXML->GetIntAttr(node,"STLtype");
00873       int fCtype = fXML->GetIntAttr(node,"Ctype");
00874       ((TStreamerSTL*)elem)->SetSTLtype(fSTLtype);
00875       ((TStreamerSTL*)elem)->SetCtype(fCtype);
00876    }
00877 
00878    char namebuf[100];
00879 
00880    if (fXML->HasAttr(node, "numdim")) {
00881       int numdim = fXML->GetIntAttr(node,"numdim");
00882       elem->SetArrayDim(numdim);
00883       for (int ndim=0;ndim<numdim;ndim++) {
00884          sprintf(namebuf, "dim%d", ndim);
00885          int maxi = fXML->GetIntAttr(node, namebuf);
00886          elem->SetMaxIndex(ndim, maxi);
00887       }
00888    }
00889 
00890    elem->SetType(elem_type);
00891    elem->SetNewType(elem_type);
00892 
00893    info->GetElements()->Add(elem);
00894 }
00895 
00896 //______________________________________________________________________________
00897 void TXMLFile::SetXmlLayout(EXMLLayout layout)
00898 {
00899    // Change layout of objects in xml file
00900    // Can be changed only for newly created file.
00901    //
00902    // Currently there are two supported layouts:
00903    //
00904    // TXMLSetup::kSpecialized = 2
00905    //    This is default layout of the file, when xml nodes names class names and data member
00906    //    names are used. For instance:
00907    //          <TAttLine version="1">
00908    //            <fLineColor v="1"/>
00909    //            <fLineStyle v="1"/>
00910    //            <fLineWidth v="1"/>
00911    //          </TAttLine>
00912    //
00913    // TXMLSetup::kGeneralized = 3
00914    //    For this layout all nodes name does not depend from class definitions.
00915    //    The same class looks like
00916    //          <Class name="TAttLine" version="1">
00917    //            <Member name="fLineColor" v="1"/>
00918    //            <Member name="fLineStyle" v="1"/>
00919    //            <Member name="fLineWidth" v="1"/>
00920    //          </Member>
00921    //
00922 
00923    if (IsWritable() && (GetListOfKeys()->GetSize()==0))
00924       TXMLSetup::SetXmlLayout(layout);
00925 }
00926 
00927 //______________________________________________________________________________
00928 void TXMLFile::SetStoreStreamerInfos(Bool_t iConvert)
00929 {
00930    // If true, all correspondent to file TStreamerInfo objects will be stored in file
00931    // this allows to apply schema avolution later for this file
00932    // may be usefull, when file used outside ROOT and TStreamerInfo objects does not required
00933    // Can be changed only for newly created file.
00934 
00935    if (IsWritable() &&  (GetListOfKeys()->GetSize()==0))
00936       TXMLSetup::SetStoreStreamerInfos(iConvert);
00937 }
00938 
00939 //______________________________________________________________________________
00940 void TXMLFile::SetUsedDtd(Bool_t use)
00941 {
00942    // Specify usage of DTD for this file.
00943    // Currently this option not avaliable (always false).
00944    // Can be changed only for newly created file.
00945 
00946    if (IsWritable() &&  (GetListOfKeys()->GetSize()==0))
00947       TXMLSetup::SetUsedDtd(use);
00948 }
00949 
00950 //______________________________________________________________________________
00951 void TXMLFile::SetUseNamespaces(Bool_t iUseNamespaces)
00952 {
00953    // Specifiy usage of namespaces in xml file
00954    // In current implementation every instrumented class in file gets its unique namespace,
00955    // which is equal to name of class and refer to root documentation page like
00956    // <TAttPad xmlns:TAttPad="http://root.cern.ch/root/htmldoc/TAttPad.html" version="3">
00957    // And xml node for class member gets its name as combination of class name and member name
00958    //            <TAttPad:fLeftMargin v="0.100000"/>
00959    //            <TAttPad:fRightMargin v="0.100000"/>
00960    //            <TAttPad:fBottomMargin v="0.100000"/>
00961    //            and so on
00962    // Usage of namespace increase size of xml file, but makes file more readable
00963    // and allows to produce DTD in the case, when in several classes data member has same name
00964    // Can be changed only for newly created file.
00965 
00966    if (IsWritable() && (GetListOfKeys()->GetSize()==0))
00967       TXMLSetup::SetUseNamespaces(iUseNamespaces);
00968 }
00969 
00970 //______________________________________________________________________________
00971 Bool_t TXMLFile::AddXmlComment(const char* comment)
00972 {
00973    // Add comment line on the top of the xml document
00974    // This line can only be seen in xml editor and cannot be accessed later
00975    // with TXMLFile methods
00976 
00977    if (!IsWritable() || (fXML==0)) return kFALSE;
00978 
00979    return fXML->AddDocComment(fDoc, comment);
00980 }
00981 
00982 
00983 //______________________________________________________________________________
00984 Bool_t TXMLFile::AddXmlStyleSheet(const char* href,
00985                                   const char* type,
00986                                   const char* title,
00987                                   int alternate,
00988                                   const char* media,
00989                                   const char* charset)
00990 {
00991    // Adds style sheet definition on the top of xml document
00992    // Creates <?xml-stylesheet alternate="yes" title="compact" href="small-base.css" type="text/css"?>
00993    // Attributes href and type must be supplied,
00994    //  other attributes: title, alternate, media, charset are optional
00995    // if alternate==0, attribyte alternate="no" will be created,
00996    // if alternate>0, attribute alternate="yes"
00997    // if alternate<0, attribute will not be created
00998    // This style sheet definition cannot be later access with TXMLFile methods.
00999 
01000    if (!IsWritable() || (fXML==0)) return kFALSE;
01001 
01002    return fXML->AddDocStyleSheet(fDoc, href,type,title,alternate,media,charset);
01003 }
01004 
01005 //______________________________________________________________________________
01006 Bool_t TXMLFile::AddXmlLine(const char* line)
01007 {
01008    // Add just one line on the top of xml document
01009    // For instance, line can contain special xml processing instructions
01010    // Line should has correct xml syntax that later it can be decoded by xml parser
01011    // To be parsed later by TXMLFile again, this line should contain either
01012    // xml comments or xml processing instruction
01013 
01014    if (!IsWritable() || (fXML==0)) return kFALSE;
01015 
01016    return fXML->AddDocRawLine(fDoc, line);
01017 }
01018 
01019 //______________________________________________________________________________
01020 Long64_t TXMLFile::DirCreateEntry(TDirectory* dir)
01021 {
01022    // Create key for directory entry in the key
01023 
01024    TDirectory* mother = dir->GetMotherDir();
01025    if (mother==0) mother = this;
01026 
01027    TKeyXML* key = new TKeyXML(mother, ++fKeyCounter, dir, dir->GetName(), dir->GetTitle());
01028 
01029    key->SetSubir();
01030 
01031    return key->GetKeyId();
01032 }
01033 
01034 //______________________________________________________________________________
01035 TKeyXML* TXMLFile::FindDirKey(TDirectory* dir)
01036 {
01037    // Serach for key which correspond to direcory dir
01038 
01039    TDirectory* motherdir = dir->GetMotherDir();
01040    if (motherdir==0) motherdir = this;
01041 
01042    TIter next(motherdir->GetListOfKeys());
01043    TObject* obj = 0;
01044 
01045    while ((obj = next())!=0) {
01046       TKeyXML* key = dynamic_cast<TKeyXML*> (obj);
01047 
01048       if (key!=0)
01049          if (key->GetKeyId()==dir->GetSeekDir()) return key;
01050    }
01051 
01052    return 0;
01053 }
01054 
01055 
01056 //______________________________________________________________________________
01057 TDirectory* TXMLFile::FindKeyDir(TDirectory* motherdir, Long64_t keyid)
01058 {
01059    //Find a directory in motherdir with a seek equal to keyid
01060    if (motherdir==0) motherdir = this;
01061 
01062    TIter next(motherdir->GetList());
01063    TObject* obj = 0;
01064 
01065    while ((obj = next())!=0) {
01066       TDirectory* dir = dynamic_cast<TDirectory*> (obj);
01067       if (dir!=0)
01068          if (dir->GetSeekDir()==keyid) return dir;
01069    }
01070 
01071    return 0;
01072 
01073 }
01074 
01075 //______________________________________________________________________________
01076 Int_t TXMLFile::DirReadKeys(TDirectory* dir)
01077 {
01078    // Read keys for directory
01079    // Make sence only once, while next time no new subnodes will be created
01080 
01081    TKeyXML* key = FindDirKey(dir);
01082    if (key==0) return 0;
01083 
01084    return ReadKeysList(dir, key->KeyNode());
01085 }
01086 
01087 //______________________________________________________________________________
01088 void TXMLFile::DirWriteKeys(TDirectory*)
01089 {
01090    // Update key attributes
01091 
01092    TIter next(GetListOfKeys());
01093    TObject* obj = 0;
01094 
01095    while ((obj = next())!=0) {
01096       TKeyXML* key = dynamic_cast<TKeyXML*> (obj);
01097       if (key!=0) key->UpdateAttributes();
01098    }
01099 }
01100 
01101 //______________________________________________________________________________
01102 void TXMLFile::DirWriteHeader(TDirectory* dir)
01103 {
01104    //Write the directory header
01105    TKeyXML* key = FindDirKey(dir);
01106    if (key!=0)
01107       key->UpdateObject(dir);
01108 }

Generated on Tue Jul 5 14:30:39 2011 for ROOT_528-00b_version by  doxygen 1.5.1