TSchemaRuleSet.cxx

Go to the documentation of this file.
00001 // @(#)root/core:$Id: TSchemaRuleSet.cxx 37531 2010-12-10 20:38:06Z pcanal $
00002 // author: Lukasz Janyst <ljanyst@cern.ch>
00003 
00004 #include "TSchemaRuleSet.h"
00005 #include "TSchemaRule.h"
00006 #include "TObjArray.h"
00007 #include "TObjString.h"
00008 #include "TClass.h"
00009 #include "TROOT.h"
00010 #include "Riostream.h"
00011 
00012 ClassImp(TSchemaRule)
00013 
00014 using namespace ROOT;
00015 
00016 //------------------------------------------------------------------------------
00017 TSchemaRuleSet::TSchemaRuleSet(): fPersistentRules( 0 ), fRemainingRules( 0 ),
00018                                   fAllRules( 0 ), fVersion(-3), fCheckSum( 0 )
00019 {
00020    fPersistentRules = new TObjArray();
00021    fRemainingRules  = new TObjArray();
00022    fAllRules        = new TObjArray();
00023    fAllRules->SetOwner( kTRUE );
00024 }
00025 
00026 //------------------------------------------------------------------------------
00027 TSchemaRuleSet::~TSchemaRuleSet()
00028 {
00029    delete fPersistentRules;
00030    delete fRemainingRules;
00031    delete fAllRules;
00032 }
00033 
00034 //------------------------------------------------------------------------------
00035 void TSchemaRuleSet::ls(Option_t *) const
00036 {
00037    // The ls function lists the contents of a class on stdout. Ls output
00038    // is typically much less verbose then Dump().
00039    
00040    TROOT::IndentLevel();
00041    cout << "TSchemaRuleSet for " << fClassName << ":\n";
00042    TROOT::IncreaseDirLevel();
00043    TObject *object = 0;
00044    TIter next(fPersistentRules);
00045    while ((object = next())) {
00046       object->ls(fClassName);
00047    }
00048    TROOT::DecreaseDirLevel();   
00049 }
00050 
00051 //------------------------------------------------------------------------------
00052 Bool_t TSchemaRuleSet::AddRules( TSchemaRuleSet* /* rules */, EConsistencyCheck /* checkConsistency */ )
00053 {
00054    return kFALSE;
00055 }
00056 
00057 //------------------------------------------------------------------------------
00058 Bool_t TSchemaRuleSet::AddRule( TSchemaRule* rule, EConsistencyCheck checkConsistency )
00059 {
00060    // The consistency check always fails if the TClass object was not set!
00061    // if checkConsistency is:
00062    //   kNoCheck: no check is done, register the rule as is
00063    //   kCheckConflict: check only for conflicting rules
00064    //   kCheckAll: check for conflict and check for rule about members that are not in the current class layout.
00065    // return kTRUE if the layout is accepted, in which case we take ownership of
00066    // the rule object.
00067    // return kFALSE if the rule failed one of the test, the rule now needs to be deleted by the caller.
00068 
00069    //---------------------------------------------------------------------------
00070    // Cannot verify the consistency if the TClass object is not present
00071    //---------------------------------------------------------------------------
00072    if( (checkConsistency != kNoCheck) && !fClass )
00073       return kFALSE;
00074 
00075    if( !rule->IsValid() )
00076       return kFALSE;
00077 
00078    //---------------------------------------------------------------------------
00079    // If we don't check the consistency then we should just add the object
00080    //---------------------------------------------------------------------------
00081    if( checkConsistency == kNoCheck ) {
00082       if( rule->GetEmbed() )
00083          fPersistentRules->Add( rule );
00084       else
00085          fRemainingRules->Add( rule );
00086       fAllRules->Add( rule );
00087       return kTRUE;
00088    }
00089 
00090    //---------------------------------------------------------------------------
00091    // Check if all of the target data members specified in the rule are
00092    // present int the target class
00093    //---------------------------------------------------------------------------
00094    TObject* obj;
00095    // Check only if we have some information about the class, otherwise we have
00096    // nothing to check against
00097    if( rule->GetTarget()  && !(fClass->TestBit(TClass::kIsEmulation) && (fClass->GetStreamerInfos()==0 || fClass->GetStreamerInfos()->GetEntries()==0)) ) {
00098       TObjArrayIter titer( rule->GetTarget() );
00099       while( (obj = titer.Next()) ) {
00100          TObjString* str = (TObjString*)obj;
00101          if( !fClass->GetDataMember( str->GetString() ) && !fClass->GetBaseClass( str->GetString() ) ) {
00102             if (checkConsistency == kCheckAll) {
00103                return kFALSE;
00104             } else {
00105                // We ignore the rules that do not apply ...
00106                delete rule;
00107                return kTRUE;
00108             }
00109          }
00110       }
00111    }
00112 
00113    //---------------------------------------------------------------------------
00114    // Check if there is a rule conflicting with this one
00115    //---------------------------------------------------------------------------
00116    const TObjArray* rules = FindRules( rule->GetSourceClass() );
00117    TObjArrayIter it( rules );
00118    TSchemaRule *r;
00119 
00120    while( (obj = it.Next()) ) {
00121       r = (TSchemaRule *) obj;
00122       if( rule->Conflicts( r ) ) {
00123          delete rules;
00124          if ( *r == *rule) {
00125             // The rules are duplicate from each other,
00126             // just ignore the new ones.
00127             delete rule;
00128             return kTRUE;
00129          }
00130          return kFALSE;
00131       }
00132    }
00133    delete rules;
00134 
00135    //---------------------------------------------------------------------------
00136    // No conflicts - insert the rules
00137    //---------------------------------------------------------------------------
00138    if( rule->GetEmbed() )
00139       fPersistentRules->Add( rule );
00140    else
00141       fRemainingRules->Add( rule );
00142    fAllRules->Add( rule );
00143 
00144    return kTRUE;
00145 }
00146 
00147 //------------------------------------------------------------------------------
00148 void TSchemaRuleSet::AsString(TString &out) const
00149 {
00150    // Fill the string 'out' with the string representation of the rule.
00151    
00152    TObjArrayIter it( fAllRules );
00153    TSchemaRule *rule;
00154    while( (rule = (TSchemaRule*)it.Next()) ) {
00155       rule->AsString(out);
00156       out += "\n";
00157    }
00158 }
00159 
00160 //------------------------------------------------------------------------------
00161 Bool_t TSchemaRuleSet::HasRuleWithSourceClass( const TString &source ) const
00162 {
00163    // Return True if we have any rule whose source class is 'source'.
00164    
00165    TObjArrayIter it( fAllRules );
00166    TObject *obj;
00167    while( (obj = it.Next()) ) {
00168       TSchemaRule* rule = (TSchemaRule*)obj;
00169       if( rule->GetSourceClass() == source )
00170          return kTRUE;
00171    }
00172    return kFALSE;
00173 }
00174 
00175 //------------------------------------------------------------------------------
00176 const TObjArray* TSchemaRuleSet::FindRules( const TString &source ) const
00177 {
00178    // Return all the rules that are about the given 'source' class.
00179    // User has to delete the returned array
00180    TObject*      obj;
00181    TObjArrayIter it( fAllRules );
00182    TObjArray*    arr = new TObjArray();
00183    arr->SetOwner( kFALSE );
00184    
00185    while( (obj = it.Next()) ) {
00186       TSchemaRule* rule = (TSchemaRule*)obj;
00187       if( rule->GetSourceClass() == source )
00188          arr->Add( rule );
00189    }
00190    return arr;
00191 }
00192 
00193 //------------------------------------------------------------------------------
00194 const TSchemaMatch* TSchemaRuleSet::FindRules( const TString &source, Int_t version ) const
00195 {
00196    // Return all the rules that applies to the specified version of the given 'source' class.
00197    // User has to delete the returned array
00198 
00199    TObject*      obj;
00200    TObjArrayIter it( fAllRules );
00201    TSchemaMatch* arr = new TSchemaMatch();
00202    arr->SetOwner( kFALSE );
00203 
00204    while( (obj = it.Next()) ) {
00205       TSchemaRule* rule = (TSchemaRule*)obj;
00206       if( rule->GetSourceClass() == source && rule->TestVersion( version ) )
00207          arr->Add( rule );
00208    }
00209 
00210    if( arr->GetEntriesFast() )
00211       return arr;
00212    else {
00213       delete arr;
00214       return 0;
00215    }
00216 }
00217 
00218 //------------------------------------------------------------------------------
00219 const TSchemaMatch* TSchemaRuleSet::FindRules( const TString &source, UInt_t checksum ) const
00220 {
00221    // Return all the rules that applies to the specified checksum of the given 'source' class.
00222    // User has to delete the returned array
00223 
00224    TObject*      obj;
00225    TObjArrayIter it( fAllRules );
00226    TSchemaMatch* arr = new TSchemaMatch();
00227    arr->SetOwner( kFALSE );
00228 
00229    while( (obj = it.Next()) ) {
00230       TSchemaRule* rule = (TSchemaRule*)obj;
00231       if( rule->GetSourceClass() == source && rule->TestChecksum( checksum ) )
00232          arr->Add( rule );
00233    }
00234 
00235    if( arr->GetEntriesFast() )
00236       return arr;
00237    else {
00238       delete arr;
00239       return 0;
00240    }
00241 }
00242 
00243 //------------------------------------------------------------------------------
00244 const TSchemaMatch* TSchemaRuleSet::FindRules( const TString &source, Int_t version, UInt_t checksum ) const
00245 {
00246    // Return all the rules that applies to the specified version OR checksum of the given 'source' class.
00247    // User has to delete the returned array
00248 
00249    TObject*      obj;
00250    TObjArrayIter it( fAllRules );
00251    TSchemaMatch* arr = new TSchemaMatch();
00252    arr->SetOwner( kFALSE );
00253 
00254    while( (obj = it.Next()) ) {
00255       TSchemaRule* rule = (TSchemaRule*)obj;
00256       if( rule->GetSourceClass() == source && ( rule->TestVersion( version ) || rule->TestChecksum( checksum ) ) )
00257          arr->Add( rule );
00258    }
00259 
00260    if( arr->GetEntriesFast() )
00261       return arr;
00262    else {
00263       delete arr;
00264       return 0;
00265    }
00266 }
00267 
00268 //------------------------------------------------------------------------------
00269 TClass* TSchemaRuleSet::GetClass()
00270 {
00271    return fClass;
00272 }
00273 
00274 //------------------------------------------------------------------------------
00275 UInt_t TSchemaRuleSet::GetClassCheckSum() const
00276 {
00277    if (fCheckSum == 0 && fClass) {
00278       const_cast<TSchemaRuleSet*>(this)->fCheckSum = fClass->GetCheckSum();
00279    }
00280    return fCheckSum;
00281 }
00282 
00283 //------------------------------------------------------------------------------
00284 TString TSchemaRuleSet::GetClassName() const
00285 {
00286    return fClassName;
00287 }
00288 
00289 //------------------------------------------------------------------------------
00290 Int_t TSchemaRuleSet::GetClassVersion() const
00291 {
00292    return fVersion;
00293 }
00294 
00295 //------------------------------------------------------------------------------
00296 const TObjArray* TSchemaRuleSet::GetRules() const
00297 {
00298    return fAllRules;
00299 }
00300 
00301 //------------------------------------------------------------------------------
00302 const TObjArray* TSchemaRuleSet::GetPersistentRules() const
00303 {
00304    return fPersistentRules;
00305 }
00306 
00307 //------------------------------------------------------------------------------
00308 void TSchemaRuleSet::RemoveRule( TSchemaRule* rule )
00309 {
00310    // Remove given rule from the set - the rule is not being deleted!
00311    fPersistentRules->Remove( rule );
00312    fRemainingRules->Remove( rule );
00313    fAllRules->Remove( rule );
00314 }
00315 
00316 //------------------------------------------------------------------------------
00317 void TSchemaRuleSet::RemoveRules( TObjArray* rules )
00318 {
00319    // remove given array of rules from the set - the rules are not being deleted!
00320    TObject*      obj;
00321    TObjArrayIter it( rules );
00322 
00323    while( (obj = it.Next()) ) {
00324       fPersistentRules->Remove( obj );
00325       fRemainingRules->Remove( obj );
00326       fAllRules->Remove( obj );
00327    }
00328 }
00329 
00330 //------------------------------------------------------------------------------
00331 void TSchemaRuleSet::SetClass( TClass* cls )
00332 {
00333    fClass     = cls;
00334    fClassName = cls->GetName();
00335    fVersion   = cls->GetClassVersion();
00336 }
00337 
00338 
00339 //------------------------------------------------------------------------------
00340 const TSchemaRule* TSchemaMatch::GetRuleWithSource( const TString& name ) const
00341 {
00342    for( Int_t i = 0; i < GetEntries(); ++i ) {
00343       TSchemaRule* rule = (ROOT::TSchemaRule*)At(i);
00344       if( rule->HasSource( name ) ) return rule;
00345    }
00346    return 0;
00347 }
00348 
00349 //------------------------------------------------------------------------------
00350 const TSchemaRule* TSchemaMatch::GetRuleWithTarget( const TString& name ) const
00351 {
00352    for( Int_t i=0; i<GetEntries(); ++i) {
00353       ROOT::TSchemaRule *rule = (ROOT::TSchemaRule*)At(i);
00354       if( rule->HasTarget( name ) ) return rule;
00355    }
00356    return 0;
00357 }
00358 
00359 //------------------------------------------------------------------------------
00360 Bool_t TSchemaMatch::HasRuleWithSource( const TString& name, Bool_t needingAlloc ) const
00361 {
00362    // Return true if the set of rules has at least one rule that has the data
00363    // member named 'name' as a source.
00364    // If needingAlloc is true, only the rule that requires the data member to 
00365    // be cached will be taken in consideration.
00366    
00367    for( Int_t i = 0; i < GetEntries(); ++i ) {
00368       TSchemaRule* rule = (ROOT::TSchemaRule*)At(i);
00369       if( rule->HasSource( name ) ) {
00370          if (needingAlloc) {
00371             const TObjArray *targets = rule->GetTarget();
00372             if (targets && (targets->GetEntries() > 1 || targets->GetEntries()==0) ) {
00373                return kTRUE;
00374             }
00375             if (targets && name != targets->UncheckedAt(0)->GetName() ) {
00376                return kTRUE;
00377             }
00378             // If the rule has the same source and target and does not
00379             // have any actions, then it does not need allocation.
00380             if (rule->GetReadFunctionPointer() || rule->GetReadRawFunctionPointer()) {
00381                return kTRUE;
00382             }
00383          } else {
00384             return kTRUE;
00385          }
00386       }
00387    }
00388    return kFALSE;
00389 }
00390 
00391 //------------------------------------------------------------------------------
00392 Bool_t TSchemaMatch::HasRuleWithTarget( const TString& name, Bool_t willset ) const
00393 {
00394    // Return true if the set of rules has at least one rule that has the data
00395    // member named 'name' as a target.
00396    // If willset is true, only the rule that will set the value of the data member.
00397    
00398    for( Int_t i=0; i<GetEntries(); ++i) {
00399       ROOT::TSchemaRule *rule = (ROOT::TSchemaRule*)At(i);
00400       if( rule->HasTarget( name ) ) {
00401          if (willset) {
00402             const TObjArray *targets = rule->GetTarget();
00403             if (targets && (targets->GetEntries() > 1 || targets->GetEntries()==0) ) {
00404                return kTRUE;
00405             }
00406             const TObjArray *sources = rule->GetSource();
00407             if (sources && (sources->GetEntries() > 1 || sources->GetEntries()==0) ) {
00408                return kTRUE;
00409             }
00410             if (sources && name != sources->UncheckedAt(0)->GetName() ) {
00411                return kTRUE;
00412             }            
00413             // If the rule has the same source and target and does not
00414             // have any actions, then it will not directly set the value.
00415             if (rule->GetReadFunctionPointer() || rule->GetReadRawFunctionPointer()) {
00416                return kTRUE;
00417             }
00418          } else {
00419             return kTRUE;
00420          }
00421       }
00422    }
00423    return kFALSE;
00424 }
00425 
00426 //______________________________________________________________________________
00427 void TSchemaRuleSet::Streamer(TBuffer &R__b)
00428 {
00429    // Stream an object of class ROOT::TSchemaRuleSet.
00430    
00431    if (R__b.IsReading()) {
00432       R__b.ReadClassBuffer(ROOT::TSchemaRuleSet::Class(),this);
00433       fAllRules->Clear(); 
00434       fAllRules->AddAll(fPersistentRules);
00435    } else {
00436       GetClassCheckSum();
00437       R__b.WriteClassBuffer(ROOT::TSchemaRuleSet::Class(),this);
00438    }
00439 }
00440 

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