ROOT logo
// $Id: ZComet.cxx 2088 2008-11-23 20:26:46Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.


//
// ZComet
//
// ZComet is a container class for streaming collections of glasses.
// It can be created from a ZCometBag, ZQueen or ZKing by calling the
// appropriate MakeComet() method.
// Service is rather elementary ... external references are only
// meaningfull if Saturn layout used for writing/reading is identical.
// A special class will be provided to make proper references into
// static objects.
// Comets of type CT_Queen & CT_King are used internally for exportation
// to connecting Moons.
//
// !!!!!! Need structure { ZGlass* g; bool links_done, lists_done; }
// as value type of idHash. Loops of infiniteness are awaiting you otherwise.
// Then, also, need no special treatment of ZNode::Parent. Or just maybe.

#include "ZComet.h"
#include <Gled/GledNS.h>
#include <Glasses/ZList.h>
#include <Glasses/ZKing.h>
#include <Glasses/ZQueen.h>
#include <Ephra/Saturn.h>
#include <Gled/Gled.h>

#include <TBuffer.h>
#include <TDirectory.h>
#include <TFile.h>

ClassImp(ZComet);

/**************************************************************************/

void ZComet::_init()
{
  mType = CT_CometBag;
  mExtDemangler = 0;

  bWarnOn = false; bVerbose = false;
  mQueen = 0; mKing = 0;
}

/**************************************************************************/

Int_t ZComet::AddTopLevel(ZGlass* g, Bool_t do_links, Bool_t do_lists, Int_t depth)
{
  // !! should check if already in? not my problem ...
  mTopLevels.push_back(g);
  return AddGlass(g, do_links, do_lists, depth);
}

Int_t ZComet::AddGlass(ZGlass* g, Bool_t do_links, Bool_t do_lists, Int_t depth)
{
  // Adds a glass (et al) into local structure
  // depth controls traversal length
  // depth of 0 means add ONLY g, not even its links or lists.
  // depth of -1 means don't stop

  Int_t num_new = 0;
  ID_t id = g->GetSaturnID();
  if(mIDMap.find(id) == mIDMap.end()) {
    ++num_new;
    mIDMap[id] = g;
    mLibSets.insert(g->VFID().fLid);
    ISdebug(D_STREAM, GForm("ZComet::AddGlass added lens %s, id=%u",
			    g->GetName(), id));
  }

  if(depth==0) return num_new;

  if(do_links) {
    ZGlass::lLinkRep_t lreps; g->CopyLinkReps(lreps);
    for(ZGlass::lLinkRep_i i = lreps.begin(); i != lreps.end(); ++i) {
      ZGlass* l = i->fLinkRef;
      if(l != 0 && mIgnoredLinks.find(i->fLinkInfo->FullName())==mIgnoredLinks.end()) {
	num_new += AddGlass(l, do_links, do_lists, depth-1);
      }
    }
  }

  ZList* l = dynamic_cast<ZList*>(g);
  if(l && do_lists) {
    lpZGlass_t members; l->CopyList(members);
    for(lpZGlass_i i=members.begin(); i!=members.end(); ++i) {
      num_new += AddGlass(*i, do_links, do_lists, depth-1);
    }
  }
  return num_new;
}

/**************************************************************************/

ZGlass* ZComet::DemangleID(ID_t id)
{
  static const Exc_t _eh("ZComet::DemangleID ");

  if(id == 0) return 0;
  mID2pZGlass_i i;
  if((i = mIDMap.find(id)) != mIDMap.end())
    return i->second;

  if(mExtDemangler != 0) {
    ZGlass* l = mExtDemangler->DemangleID(id);
    if(l == 0 && bVerbose)
      ISmess(_eh + GForm("id %u not found (comet, ext-demangler).", id));
    return l;
  } else {
    if(bVerbose)
      ISmess(_eh + GForm("id %u not found (comet).", id));
    return 0;
  }
}

/**************************************************************************/

void ZComet::AssignQueen(ZQueen* queen)
{
  // Sets the ZGlass::mQueen pointer to queen for all elements of the comet.
  // This should be called prior to RebuildGraph if it is desired that
  // reference counts are properly increased.

  for(mID2pZGlass_i i=mIDMap.begin(); i!=mIDMap.end(); i++) {
    i->second->mQueen = queen;
  }
}

Int_t ZComet::RebuildGraph()
{
  static const Exc_t _eh("ZComet::RebuildGraph ");

  if(bGraphRebuilt) return 0;
  Int_t ret = 0;

  // First pass: rebuild and count missed links & list members
  for(mID2pZGlass_i i=mIDMap.begin(); i!=mIDMap.end(); i++) {
    ZGlass* g = i->second;
    if(Int_t m = g->RebuildLinkRefs(this)) {
      ret += m;
      if(bWarnOn)
	ISwarn(_eh + GForm("(links) %d missed lens(es) in '%s'.",
			   m, g->GetName()));
    }
    ZList* l = dynamic_cast<ZList*>(g);
    if(l) {
      Int_t m = l->RebuildListRefs(this);
      if(m>0) {
	ret += m;
	if(bWarnOn)
	  ISwarn(_eh + GForm("(list) %d missed lens(es) in '%s'.",
			     m, g->GetName()));
      }
    }
  }

  // Second pass: grep NotRefed Glasses that are NOT toplevel
  // !!!! hmmph ... should copy map, and remove connected ones.
  for(mID2pZGlass_i i=mIDMap.begin(); i!=mIDMap.end(); ++i) {
    ZGlass* g = i->second;
    if(g->GetRefCount()==0) {
      if(find(mTopLevels.begin(), mTopLevels.end(), g) == mTopLevels.end()) {
	ISdebug(D_STREAM, _eh + GForm("'%s' is an orphan.", g->GetName()));
	mOrphans.push_back(g);
      }
    }
  }
  bGraphRebuilt = true;
  return ret;
}

/**************************************************************************/
/**************************************************************************/
// Streamer functions
/**************************************************************************/
/**************************************************************************/

void ZComet::Streamer(TBuffer& b)
{
  static const Exc_t _eh("ZComet::Streamer ");

  StreamHeader(b);
  StreamContents(b);

  if(b.IsReading()) {
    // Rebuild kings/queens
    if(mType == CT_Queen) {
      ID_t qid = GledNS::CastLens2ID(mQueen);
      mQueen = dynamic_cast<ZQueen*>(DemangleID(qid));
      if(mQueen==0) {
	ISerr(_eh + GForm("(Queen) couldn't demangle QueenID %u.", qid));
      }
    }
    if(mType == CT_King) {
      ID_t kid = GledNS::CastLens2ID(mKing);
      mKing = dynamic_cast<ZKing*>(DemangleID(kid));
      if(mKing==0) {
	ISerr(_eh + GForm("(King) couldn't demangle KingID %u.", kid));
      }
    }
    // Reconstruct TopLevels
    for(lpZGlass_i i=mTopLevels.begin(); i!=mTopLevels.end(); ++i) {
      ID_t id = GledNS::CastLens2ID(*i);
      mID2pZGlass_i j = mIDMap.find(id);
      if(j != mIDMap.end()) {
	*i = j->second;
      } else {
	if(bWarnOn)
	  ISwarn(_eh + GForm("(top_levels) missing ID %u.", id));
      }
    }
  }
}

void ZComet::StreamHeader(TBuffer& b)
{
  // Streams Type, Size, Libsets, TopLevels|Queen|King

  static const Exc_t _eh("ZComet::StreamHeader ");

  if(b.IsReading()) {
    /*** Reading ***/
    bGraphRebuilt = false;
    mLibSets.clear(); mTopLevels.clear(); mOrphans.clear();

    UInt_t t; b >> t; mType = CometType_e(t);

    UInt_t cnt; b >> cnt;
    bFail = false;
    for(UInt_t i=0; i<cnt; i++) {
      LID_t lid; b >> lid;
      mLibSets.insert(lid);
      if(!GledNS::IsLoaded(lid)) {
	ISmess(_eh + GForm("attempting to load LibSet w/ id=%u.", lid));
	int ret = Gled::theOne->LoadLibSet(lid);
	if(ret != 0) {
	  ISerr(_eh + GForm("failed to load LibSet w/ id=%u.", lid));
	  bFail = true;
	}
      }
    }
    if(bFail) throw _eh + "LibSets missing.";

    switch(mType) {
    case CT_CometBag:
      b >> cnt;
      for(UInt_t i=0; i<cnt; i++) {
	mTopLevels.push_back(GledNS::ReadLensIDAsPtr(b));
      }
      break;
    case CT_Queen: {
      mQueen = (ZQueen*) GledNS::ReadLensIDAsPtr(b);
      break;
    }
    case CT_King: {
      mKing  = (ZKing*)  GledNS::ReadLensIDAsPtr(b);
      break;
    }
    }

  } else {
    /*** Writing ***/
    b << (UInt_t) mType;
    b << (UInt_t) mLibSets.size();
    for(set<LID_t>::iterator i=mLibSets.begin(); i!=mLibSets.end(); ++i)
      b << *i;
    switch(mType) {
    case CT_CometBag:
      b << (UInt_t) mTopLevels.size();
      for(lpZGlass_i i=mTopLevels.begin(); i!=mTopLevels.end(); ++i)
	GledNS::WriteLensID(b, *i);
      break;
    case CT_Queen: GledNS::WriteLensID(b, mQueen); break;
    case CT_King:  GledNS::WriteLensID(b, mKing);  break;
    }
  }
}

void ZComet::StreamContents(TBuffer& b)
{
  static const Exc_t _eh("ZComet::StreamContents ");

  if(b.IsReading()) {
    UInt_t size;
    b >> size;
    ISdebug(D_STREAM, _eh + GForm("reading %u glasses.", size));
    for(UInt_t i=0; i<size; ++i) {
      ZGlass *g = GledNS::StreamLens(b);
      if(g) {
	ID_t id = g->GetSaturnID();
	mIDMap[id] = g;
	ISdebug(D_STREAM+1, _eh + GForm("read lens %s[%s] addr=%p.",
				  g->GetName(), g->ClassName(), (void*)g));
      } else {
	ISdebug(D_STREAM, _eh + "lens creation failed.");
      }
    }
  } else {
    UInt_t size = (UInt_t)(mIDMap.size());
    b << size;
    ISdebug(D_STREAM, _eh + GForm("writing %u glasses.", size));
    if(size > 0) {
      for(mID2pZGlass_i i=mIDMap.begin(); i!=mIDMap.end(); i++) {
	ISdebug(D_STREAM+1, _eh + GForm("writing %s", (i->second)->GetName()));
	GledNS::StreamLens(b, i->second);
      }
    }
  }
}

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