ROOT logo
// @(#)root/xml:$Id: TKeyXML.cxx 24037 2008-05-28 06:32:07Z brun $
// Author: Sergey Linev, Rene Brun  10.05.2004

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//________________________________________________________________________
//
// TKeyXML is represents one block of data in TXMLFile
// Normally this block corresponds to data of single object like histogram,
// TObjArray and so on.
//________________________________________________________________________


#include "TKeyXML.h"

#include "TBufferXML.h"
#include "TXMLFile.h"
#include "TClass.h"
#include "TROOT.h"
#include "TBrowser.h"

ClassImp(TKeyXML);

//______________________________________________________________________________
TKeyXML::TKeyXML() :
   TKey(),
   fKeyNode(0),
   fKeyId(0),
   fSubdir(kFALSE)
{
   // default constructor
}

//______________________________________________________________________________
TKeyXML::TKeyXML(TDirectory* mother, Long64_t keyid, const TObject* obj, const char* name, const char* title) :
    TKey(mother),
    fKeyNode(0),
    fKeyId(keyid),
    fSubdir(kFALSE)
{
   // Creates TKeyXML and convert obj data to xml structures

   if (name)
      SetName(name);
   else
      if (obj!=0) {
         SetName(obj->GetName());
         fClassName=obj->ClassName();
      } else
         SetName("Noname");

   if (title) SetTitle(title);

   fCycle  = GetMotherDir()->AppendKey(this);

   TXMLEngine* xml = XMLEngine();
   if (xml!=0)
      fKeyNode = xml->NewChild(0, 0, xmlio::Xmlkey, 0);

   fDatime.Set();

   StoreObject((void*)obj, obj ? obj->IsA() : 0);
}

//______________________________________________________________________________
TKeyXML::TKeyXML(TDirectory* mother, Long64_t keyid, const void* obj, const TClass* cl, const char* name, const char* title) :
   TKey(mother),
   fKeyNode(0),
   fKeyId(keyid),
   fSubdir(kFALSE)
{
   // Creates TKeyXML and convert obj data to xml structures

   if (name && *name) SetName(name);
   else SetName(cl ? cl->GetName() : "Noname");

   if (title) SetTitle(title);

   fCycle  = GetMotherDir()->AppendKey(this);

   TXMLEngine* xml = XMLEngine();
   if (xml!=0)
      fKeyNode = xml->NewChild(0, 0, xmlio::Xmlkey, 0);

   fDatime.Set();

   StoreObject(obj, cl);
}

//______________________________________________________________________________
TKeyXML::TKeyXML(TDirectory* mother, Long64_t keyid, XMLNodePointer_t keynode) :
   TKey(mother),
   fKeyNode(keynode),
   fKeyId(keyid),
   fSubdir(kFALSE)
{
   // Creates TKeyXML and takes ownership over xml node, from which object can be restored

   TXMLEngine* xml = XMLEngine();

   SetName(xml->GetAttr(keynode, xmlio::Name));
   
   if (xml->HasAttr(keynode, xmlio::Title))
      SetTitle(xml->GetAttr(keynode, xmlio::Title));

   fCycle = xml->GetIntAttr(keynode, xmlio::Cycle);
      
   if (xml->HasAttr(keynode, xmlio::CreateTm)) {
      TDatime tm(xml->GetAttr(keynode, xmlio::CreateTm)); 
      fDatime = tm;
   }

   XMLNodePointer_t objnode = xml->GetChild(keynode);
   xml->SkipEmpty(objnode);

   fClassName = xml->GetAttr(objnode, xmlio::ObjClass);
}

//______________________________________________________________________________
TKeyXML::~TKeyXML()
{
   // TKeyXML destructor
   TXMLEngine* xml = XMLEngine();
   if (fKeyNode && xml)
      xml->FreeNode(fKeyNode);
}

//______________________________________________________________________________
void TKeyXML::Delete(Option_t * /*option*/)
{
   // Delete key from current directory
   // Note: TKeyXML object is not deleted. You still have to call "delete key"

   TXMLEngine* xml = XMLEngine();
   if (fKeyNode && xml) {
      xml->FreeNode(fKeyNode);
      fKeyNode = 0;
   }

   fMotherDir->GetListOfKeys()->Remove(this);
}

//______________________________________________________________________________
void TKeyXML::StoreKeyAttributes()
{
   // Stores keys attributes in key node
   
   TXMLEngine* xml = XMLEngine();
   TXMLFile* f = (TXMLFile*) GetFile();
   if ((f==0) || (xml==0) || (fKeyNode==0)) return;

   xml->NewAttr(fKeyNode, 0, xmlio::Name, GetName());
   
   xml->NewIntAttr(fKeyNode, xmlio::Cycle, fCycle);
   
   if (f->GetIOVersion()>1) {
      if (strlen(GetTitle())>0)
         xml->NewAttr(fKeyNode, 0, xmlio::Title, GetTitle());
      xml->NewAttr(fKeyNode, 0, xmlio::CreateTm, fDatime.AsSQLString());
   }
}

//______________________________________________________________________________
void TKeyXML::StoreObject(const void* obj, const TClass* cl)
{
   //  convert object to xml structure and keep this structure in key
   
   TXMLFile* f = (TXMLFile*) GetFile();
   TXMLEngine* xml = XMLEngine();
   if ((f==0) || (xml==0) || (fKeyNode==0)) return;

   StoreKeyAttributes();

   TBufferXML buffer(TBuffer::kWrite, f);
   if (f->GetIOVersion()==1)
      buffer.SetBit(TBuffer::kCannotHandleMemberWiseStreaming, kFALSE);
   
   XMLNodePointer_t node = buffer.XmlWriteAny(obj, cl);

   if (node!=0)
      xml->AddChildFirst(fKeyNode, node);
      
   buffer.XmlWriteBlock(fKeyNode);

   if (cl) fClassName = cl->GetName();
}

//______________________________________________________________________________
void TKeyXML::UpdateAttributes()
{
   // update key attributes in key node
   
   TXMLEngine* xml = XMLEngine();
   if ((xml==0) || (fKeyNode==0)) return;

   xml->FreeAllAttr(fKeyNode);
   
   StoreKeyAttributes();
}

//______________________________________________________________________________
void TKeyXML::UpdateObject(TObject* obj)
{
   // updates object, stored in the node
   // Used for TDirectory data update

   TXMLFile* f = (TXMLFile*) GetFile();
   TXMLEngine* xml = XMLEngine();
   if ((f==0) || (xml==0) || (obj==0) || (fKeyNode==0)) return;
   
   XMLNodePointer_t objnode = xml->GetChild(fKeyNode);
   xml->SkipEmpty(objnode);

   if (objnode==0) return;

   xml->UnlinkNode(objnode);
   xml->FreeNode(objnode);
   
   xml->FreeAllAttr(fKeyNode);
   
   StoreObject(obj, obj->IsA());
}

//______________________________________________________________________________
Int_t TKeyXML::Read(TObject* tobj)
{
   // To read an object from the file.
   // The object associated to this key is read from the file into memory.
   // Before invoking this function, obj has been created via the
   // default constructor.

   if (tobj==0) return 0; 
    
   void* res = XmlReadAny(tobj, 0);
   
   return res==0 ? 0 : 1;
}

//______________________________________________________________________________
TObject* TKeyXML::ReadObj()
{
   // read object derived from TObject class, from key
   // if it is not TObject or in case of error, return 0

   TObject* tobj = (TObject*) XmlReadAny(0, TObject::Class());
   
   if (tobj!=0) {
      if (gROOT->GetForceStyle()) tobj->UseCurrentStyle(); 
      if (tobj->IsA() == TDirectoryFile::Class()) {
         TDirectoryFile *dir = (TDirectoryFile*) tobj;
         dir->SetName(GetName());
         dir->SetTitle(GetTitle());
         dir->SetSeekDir(GetKeyId());
         // set mother before reading keys
         dir->SetMother(fMotherDir);
         dir->ReadKeys();
         fMotherDir->Append(dir);
         fSubdir = kTRUE;
      }
   }
       
   return tobj;
}

//______________________________________________________________________________
TObject* TKeyXML::ReadObjWithBuffer(char * /*bufferRead*/)
{
   // read object derived from TObject class, from key
   // if it is not TObject or in case of error, return 0

   TObject* tobj = (TObject*) XmlReadAny(0, TObject::Class());
   
   if (tobj!=0) {
      if (gROOT->GetForceStyle()) tobj->UseCurrentStyle(); 
      if (tobj->IsA() == TDirectoryFile::Class()) {
         TDirectoryFile *dir = (TDirectoryFile*) tobj;
         dir->SetName(GetName());
         dir->SetTitle(GetTitle());
         dir->SetSeekDir(GetKeyId());
         // set mother before reading keys
         dir->SetMother(fMotherDir);
         dir->ReadKeys();
         fMotherDir->Append(dir);
         fSubdir = kTRUE;
      }
   }
       
   return tobj;
}

//______________________________________________________________________________
void* TKeyXML::ReadObjectAny(const TClass *expectedClass)
{
   // read object of any type
   
   return XmlReadAny(0, expectedClass);
}

//______________________________________________________________________________
void* TKeyXML::XmlReadAny(void* obj, const TClass* expectedClass)
{
   // read object from key and cast to expected class

   if (fKeyNode==0) return obj;
   
   TXMLFile* f = (TXMLFile*) GetFile();
   TXMLEngine* xml = XMLEngine();
   if ((f==0) || (xml==0)) return obj;
   
   TBufferXML buffer(TBuffer::kRead, f);
   if (f->GetIOVersion()==1)
      buffer.SetBit(TBuffer::kCannotHandleMemberWiseStreaming, kFALSE);

   XMLNodePointer_t blocknode = xml->GetChild(fKeyNode);
   xml->SkipEmpty(blocknode);
   while (blocknode!=0) {
      if (strcmp(xml->GetNodeName(blocknode), xmlio::XmlBlock)==0) break;
      xml->ShiftToNext(blocknode);
   }
   buffer.XmlReadBlock(blocknode);

   XMLNodePointer_t objnode = xml->GetChild(fKeyNode);
   xml->SkipEmpty(objnode);

   TClass* cl = 0;
   void* res = buffer.XmlReadAny(objnode, obj, &cl);
   
   if ((cl==0) || (res==0)) return obj;
   
   Int_t delta = 0;
   
   if (expectedClass!=0) {
      delta = cl->GetBaseClassOffset(expectedClass);
      if (delta<0) {
         if (obj==0) cl->Destructor(res);
         return 0;
      }
      if (cl->GetClassInfo() && !expectedClass->GetClassInfo()) {
         //we cannot mix a compiled class with an emulated class in the inheritance
         Warning("XmlReadAny",
                 "Trying to read an emulated class (%s) to store in a compiled pointer (%s)",
                 cl->GetName(),expectedClass->GetName());
      }
   }
   
   return ((char*)res) + delta;
}

//______________________________________________________________________________
TXMLEngine* TKeyXML::XMLEngine()
{
   // return pointer on TXMLEngine object, used for xml conversion 
    
   TXMLFile* f = (TXMLFile*) GetFile();
   return f==0 ? 0 : f->XML();
}
 TKeyXML.cxx:1
 TKeyXML.cxx:2
 TKeyXML.cxx:3
 TKeyXML.cxx:4
 TKeyXML.cxx:5
 TKeyXML.cxx:6
 TKeyXML.cxx:7
 TKeyXML.cxx:8
 TKeyXML.cxx:9
 TKeyXML.cxx:10
 TKeyXML.cxx:11
 TKeyXML.cxx:12
 TKeyXML.cxx:13
 TKeyXML.cxx:14
 TKeyXML.cxx:15
 TKeyXML.cxx:16
 TKeyXML.cxx:17
 TKeyXML.cxx:18
 TKeyXML.cxx:19
 TKeyXML.cxx:20
 TKeyXML.cxx:21
 TKeyXML.cxx:22
 TKeyXML.cxx:23
 TKeyXML.cxx:24
 TKeyXML.cxx:25
 TKeyXML.cxx:26
 TKeyXML.cxx:27
 TKeyXML.cxx:28
 TKeyXML.cxx:29
 TKeyXML.cxx:30
 TKeyXML.cxx:31
 TKeyXML.cxx:32
 TKeyXML.cxx:33
 TKeyXML.cxx:34
 TKeyXML.cxx:35
 TKeyXML.cxx:36
 TKeyXML.cxx:37
 TKeyXML.cxx:38
 TKeyXML.cxx:39
 TKeyXML.cxx:40
 TKeyXML.cxx:41
 TKeyXML.cxx:42
 TKeyXML.cxx:43
 TKeyXML.cxx:44
 TKeyXML.cxx:45
 TKeyXML.cxx:46
 TKeyXML.cxx:47
 TKeyXML.cxx:48
 TKeyXML.cxx:49
 TKeyXML.cxx:50
 TKeyXML.cxx:51
 TKeyXML.cxx:52
 TKeyXML.cxx:53
 TKeyXML.cxx:54
 TKeyXML.cxx:55
 TKeyXML.cxx:56
 TKeyXML.cxx:57
 TKeyXML.cxx:58
 TKeyXML.cxx:59
 TKeyXML.cxx:60
 TKeyXML.cxx:61
 TKeyXML.cxx:62
 TKeyXML.cxx:63
 TKeyXML.cxx:64
 TKeyXML.cxx:65
 TKeyXML.cxx:66
 TKeyXML.cxx:67
 TKeyXML.cxx:68
 TKeyXML.cxx:69
 TKeyXML.cxx:70
 TKeyXML.cxx:71
 TKeyXML.cxx:72
 TKeyXML.cxx:73
 TKeyXML.cxx:74
 TKeyXML.cxx:75
 TKeyXML.cxx:76
 TKeyXML.cxx:77
 TKeyXML.cxx:78
 TKeyXML.cxx:79
 TKeyXML.cxx:80
 TKeyXML.cxx:81
 TKeyXML.cxx:82
 TKeyXML.cxx:83
 TKeyXML.cxx:84
 TKeyXML.cxx:85
 TKeyXML.cxx:86
 TKeyXML.cxx:87
 TKeyXML.cxx:88
 TKeyXML.cxx:89
 TKeyXML.cxx:90
 TKeyXML.cxx:91
 TKeyXML.cxx:92
 TKeyXML.cxx:93
 TKeyXML.cxx:94
 TKeyXML.cxx:95
 TKeyXML.cxx:96
 TKeyXML.cxx:97
 TKeyXML.cxx:98
 TKeyXML.cxx:99
 TKeyXML.cxx:100
 TKeyXML.cxx:101
 TKeyXML.cxx:102
 TKeyXML.cxx:103
 TKeyXML.cxx:104
 TKeyXML.cxx:105
 TKeyXML.cxx:106
 TKeyXML.cxx:107
 TKeyXML.cxx:108
 TKeyXML.cxx:109
 TKeyXML.cxx:110
 TKeyXML.cxx:111
 TKeyXML.cxx:112
 TKeyXML.cxx:113
 TKeyXML.cxx:114
 TKeyXML.cxx:115
 TKeyXML.cxx:116
 TKeyXML.cxx:117
 TKeyXML.cxx:118
 TKeyXML.cxx:119
 TKeyXML.cxx:120
 TKeyXML.cxx:121
 TKeyXML.cxx:122
 TKeyXML.cxx:123
 TKeyXML.cxx:124
 TKeyXML.cxx:125
 TKeyXML.cxx:126
 TKeyXML.cxx:127
 TKeyXML.cxx:128
 TKeyXML.cxx:129
 TKeyXML.cxx:130
 TKeyXML.cxx:131
 TKeyXML.cxx:132
 TKeyXML.cxx:133
 TKeyXML.cxx:134
 TKeyXML.cxx:135
 TKeyXML.cxx:136
 TKeyXML.cxx:137
 TKeyXML.cxx:138
 TKeyXML.cxx:139
 TKeyXML.cxx:140
 TKeyXML.cxx:141
 TKeyXML.cxx:142
 TKeyXML.cxx:143
 TKeyXML.cxx:144
 TKeyXML.cxx:145
 TKeyXML.cxx:146
 TKeyXML.cxx:147
 TKeyXML.cxx:148
 TKeyXML.cxx:149
 TKeyXML.cxx:150
 TKeyXML.cxx:151
 TKeyXML.cxx:152
 TKeyXML.cxx:153
 TKeyXML.cxx:154
 TKeyXML.cxx:155
 TKeyXML.cxx:156
 TKeyXML.cxx:157
 TKeyXML.cxx:158
 TKeyXML.cxx:159
 TKeyXML.cxx:160
 TKeyXML.cxx:161
 TKeyXML.cxx:162
 TKeyXML.cxx:163
 TKeyXML.cxx:164
 TKeyXML.cxx:165
 TKeyXML.cxx:166
 TKeyXML.cxx:167
 TKeyXML.cxx:168
 TKeyXML.cxx:169
 TKeyXML.cxx:170
 TKeyXML.cxx:171
 TKeyXML.cxx:172
 TKeyXML.cxx:173
 TKeyXML.cxx:174
 TKeyXML.cxx:175
 TKeyXML.cxx:176
 TKeyXML.cxx:177
 TKeyXML.cxx:178
 TKeyXML.cxx:179
 TKeyXML.cxx:180
 TKeyXML.cxx:181
 TKeyXML.cxx:182
 TKeyXML.cxx:183
 TKeyXML.cxx:184
 TKeyXML.cxx:185
 TKeyXML.cxx:186
 TKeyXML.cxx:187
 TKeyXML.cxx:188
 TKeyXML.cxx:189
 TKeyXML.cxx:190
 TKeyXML.cxx:191
 TKeyXML.cxx:192
 TKeyXML.cxx:193
 TKeyXML.cxx:194
 TKeyXML.cxx:195
 TKeyXML.cxx:196
 TKeyXML.cxx:197
 TKeyXML.cxx:198
 TKeyXML.cxx:199
 TKeyXML.cxx:200
 TKeyXML.cxx:201
 TKeyXML.cxx:202
 TKeyXML.cxx:203
 TKeyXML.cxx:204
 TKeyXML.cxx:205
 TKeyXML.cxx:206
 TKeyXML.cxx:207
 TKeyXML.cxx:208
 TKeyXML.cxx:209
 TKeyXML.cxx:210
 TKeyXML.cxx:211
 TKeyXML.cxx:212
 TKeyXML.cxx:213
 TKeyXML.cxx:214
 TKeyXML.cxx:215
 TKeyXML.cxx:216
 TKeyXML.cxx:217
 TKeyXML.cxx:218
 TKeyXML.cxx:219
 TKeyXML.cxx:220
 TKeyXML.cxx:221
 TKeyXML.cxx:222
 TKeyXML.cxx:223
 TKeyXML.cxx:224
 TKeyXML.cxx:225
 TKeyXML.cxx:226
 TKeyXML.cxx:227
 TKeyXML.cxx:228
 TKeyXML.cxx:229
 TKeyXML.cxx:230
 TKeyXML.cxx:231
 TKeyXML.cxx:232
 TKeyXML.cxx:233
 TKeyXML.cxx:234
 TKeyXML.cxx:235
 TKeyXML.cxx:236
 TKeyXML.cxx:237
 TKeyXML.cxx:238
 TKeyXML.cxx:239
 TKeyXML.cxx:240
 TKeyXML.cxx:241
 TKeyXML.cxx:242
 TKeyXML.cxx:243
 TKeyXML.cxx:244
 TKeyXML.cxx:245
 TKeyXML.cxx:246
 TKeyXML.cxx:247
 TKeyXML.cxx:248
 TKeyXML.cxx:249
 TKeyXML.cxx:250
 TKeyXML.cxx:251
 TKeyXML.cxx:252
 TKeyXML.cxx:253
 TKeyXML.cxx:254
 TKeyXML.cxx:255
 TKeyXML.cxx:256
 TKeyXML.cxx:257
 TKeyXML.cxx:258
 TKeyXML.cxx:259
 TKeyXML.cxx:260
 TKeyXML.cxx:261
 TKeyXML.cxx:262
 TKeyXML.cxx:263
 TKeyXML.cxx:264
 TKeyXML.cxx:265
 TKeyXML.cxx:266
 TKeyXML.cxx:267
 TKeyXML.cxx:268
 TKeyXML.cxx:269
 TKeyXML.cxx:270
 TKeyXML.cxx:271
 TKeyXML.cxx:272
 TKeyXML.cxx:273
 TKeyXML.cxx:274
 TKeyXML.cxx:275
 TKeyXML.cxx:276
 TKeyXML.cxx:277
 TKeyXML.cxx:278
 TKeyXML.cxx:279
 TKeyXML.cxx:280
 TKeyXML.cxx:281
 TKeyXML.cxx:282
 TKeyXML.cxx:283
 TKeyXML.cxx:284
 TKeyXML.cxx:285
 TKeyXML.cxx:286
 TKeyXML.cxx:287
 TKeyXML.cxx:288
 TKeyXML.cxx:289
 TKeyXML.cxx:290
 TKeyXML.cxx:291
 TKeyXML.cxx:292
 TKeyXML.cxx:293
 TKeyXML.cxx:294
 TKeyXML.cxx:295
 TKeyXML.cxx:296
 TKeyXML.cxx:297
 TKeyXML.cxx:298
 TKeyXML.cxx:299
 TKeyXML.cxx:300
 TKeyXML.cxx:301
 TKeyXML.cxx:302
 TKeyXML.cxx:303
 TKeyXML.cxx:304
 TKeyXML.cxx:305
 TKeyXML.cxx:306
 TKeyXML.cxx:307
 TKeyXML.cxx:308
 TKeyXML.cxx:309
 TKeyXML.cxx:310
 TKeyXML.cxx:311
 TKeyXML.cxx:312
 TKeyXML.cxx:313
 TKeyXML.cxx:314
 TKeyXML.cxx:315
 TKeyXML.cxx:316
 TKeyXML.cxx:317
 TKeyXML.cxx:318
 TKeyXML.cxx:319
 TKeyXML.cxx:320
 TKeyXML.cxx:321
 TKeyXML.cxx:322
 TKeyXML.cxx:323
 TKeyXML.cxx:324
 TKeyXML.cxx:325
 TKeyXML.cxx:326
 TKeyXML.cxx:327
 TKeyXML.cxx:328
 TKeyXML.cxx:329
 TKeyXML.cxx:330
 TKeyXML.cxx:331
 TKeyXML.cxx:332
 TKeyXML.cxx:333
 TKeyXML.cxx:334
 TKeyXML.cxx:335
 TKeyXML.cxx:336
 TKeyXML.cxx:337
 TKeyXML.cxx:338
 TKeyXML.cxx:339
 TKeyXML.cxx:340
 TKeyXML.cxx:341
 TKeyXML.cxx:342
 TKeyXML.cxx:343
 TKeyXML.cxx:344
 TKeyXML.cxx:345
 TKeyXML.cxx:346
 TKeyXML.cxx:347
 TKeyXML.cxx:348
 TKeyXML.cxx:349
 TKeyXML.cxx:350
 TKeyXML.cxx:351
 TKeyXML.cxx:352
 TKeyXML.cxx:353
 TKeyXML.cxx:354
 TKeyXML.cxx:355
 TKeyXML.cxx:356
 TKeyXML.cxx:357
 TKeyXML.cxx:358
 TKeyXML.cxx:359
 TKeyXML.cxx:360
 TKeyXML.cxx:361
 TKeyXML.cxx:362