00001
00002
00003 #include "BaBar/BaBar.hh"
00004
00005
00006
00007
00008
00009
00010 #include "BaBar/BaBar.hh"
00011
00012 #include "CdbBdb/CdbBdbSchemaUtils.hh"
00013
00014 #include <ooas.h>
00015
00016 #include <assert.h>
00017
00018 #include <iostream>
00019 #include <iomanip>
00020 using std::cerr;
00021 using std::cout;
00022 using std::endl;
00023 using std::setfill;
00024 using std::setw;
00025
00026 namespace {
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 bool buildPartialDependencyTreeForClass( const ooas::d_Class& theClassDsc,
00041 std::map<ooTypeNumber, std::vector<ooTypeNumber> >& theDependencyTree )
00042 {
00043 if( !theClassDsc ) return false;
00044
00045 ooTypeNumber classTypeNumber = theClassDsc.id( );
00046
00047
00048
00049 if( theDependencyTree.end( ) != theDependencyTree.find( classTypeNumber )) return true;
00050
00051
00052
00053 theDependencyTree[classTypeNumber] = std::vector<ooTypeNumber>( );
00054
00055
00056
00057 ooas::attribute_iterator attributeItr = theClassDsc.defines_attribute_begin( );
00058 while( attributeItr != theClassDsc.defines_attribute_end( )) {
00059
00060 const ooas::d_Attribute& attrDsc = *attributeItr;
00061 if( attrDsc.is_base_class( )) {
00062
00063 const ooas::d_Class& baseClassDsc = attrDsc.class_type_of( );
00064
00065
00066
00067 ooTypeNumber baseClassTypeNumber = baseClassDsc.id( );
00068
00069 theDependencyTree[classTypeNumber].push_back( baseClassTypeNumber );
00070
00071
00072
00073 if( !buildPartialDependencyTreeForClass( baseClassDsc,
00074 theDependencyTree )) return false;
00075 }
00076 ++attributeItr;
00077 }
00078 return true;
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 void fillDependencyMatrixForClass( ooTypeNumber theDerivedClassTypeNumber,
00088 ooTypeNumber theBaseClassTypeNumber,
00089 std::map<ooTypeNumber, CdbBdbSchemaUtils::LocalTypeID>& theTypeNumberToLocalTypeId,
00090 std::map<ooTypeNumber, std::vector<ooTypeNumber> >& theDependencyTree,
00091 bool** derivedVsBase )
00092 {
00093 const std::vector<ooTypeNumber>* baseClasses = &(theDependencyTree[theBaseClassTypeNumber]);
00094
00095 size_t num = (*baseClasses).size( );
00096 for( size_t i = 0; i < num; ++i )
00097 fillDependencyMatrixForClass( theDerivedClassTypeNumber,
00098 (*baseClasses)[i],
00099 theTypeNumberToLocalTypeId,
00100 theDependencyTree,
00101 derivedVsBase );
00102
00103
00104
00105
00106 if( theDerivedClassTypeNumber != theBaseClassTypeNumber ) {;
00107
00108 CdbBdbSchemaUtils::LocalTypeID derived = theTypeNumberToLocalTypeId[theDerivedClassTypeNumber];
00109 CdbBdbSchemaUtils::LocalTypeID base = theTypeNumberToLocalTypeId[theBaseClassTypeNumber];
00110
00111 derivedVsBase[derived][base] = true;
00112 }
00113 }
00114 };
00115
00116
00117
00118
00119
00120 CdbBdbSchemaUtils::Node::Node( const ooTypeNumber theTypeNumber ) :
00121 typeNumber(theTypeNumber)
00122 { }
00123
00124 CdbBdbSchemaUtils::Tree::Tree( ) :
00125 _isLoaded(false)
00126 { }
00127
00128 CdbBdbSchemaUtils::Tree::~Tree( )
00129 {
00130 reset( );
00131 }
00132
00133 const CdbBdbSchemaUtils::Node*
00134 CdbBdbSchemaUtils::Tree::type_to_node( const ooTypeNumber theTypeNumber ) const
00135 {
00136 if( !_isLoaded ) {
00137 cerr << "CdbBdbSchemaUtils::Tree::type_to_node() - ERROR." << endl
00138 << " Inproper use of a non-loaded dependency tree object. Check if the caller" << endl
00139 << " application has explicitly requested to load the tree." << endl;
00140 return 0;
00141 }
00142 std::map<ooTypeNumber, Node*>::const_iterator itr = all.find( theTypeNumber );
00143 return ( all.end( ) == itr ? 0 : itr->second );
00144 }
00145
00146 void
00147 CdbBdbSchemaUtils::Tree::reset( )
00148 {
00149 _isLoaded = false;
00150
00151 std::map<ooTypeNumber, Node*>::iterator itr = all.begin( );
00152 while( all.begin( ) != itr ) {
00153 delete itr->second;
00154 ++itr;
00155 }
00156 all.clear( );
00157 root.clear( );
00158 }
00159
00160 bool
00161 CdbBdbSchemaUtils::Tree::load( const std::map<ooTypeNumber, std::vector<ooTypeNumber> >& thePartialTree,
00162 bool debugModeFlag )
00163 {
00164 reset( );
00165
00166
00167
00168 std::map<ooTypeNumber, std::vector<ooTypeNumber> >::const_iterator itr = thePartialTree.begin( );
00169 while( thePartialTree.end( ) != itr ) {
00170
00171
00172 type_to_node( thePartialTree,
00173 itr->first,
00174 debugModeFlag );
00175 ++itr;
00176 }
00177
00178 _isLoaded = true;
00179
00180 return true;
00181 }
00182
00183 CdbBdbSchemaUtils::Node*
00184 CdbBdbSchemaUtils::Tree::type_to_node( const std::map<ooTypeNumber, std::vector<ooTypeNumber> >& thePartialTree,
00185 const ooTypeNumber theTypeNumber,
00186 bool debugModeFlag )
00187 {
00188 assert( !_isLoaded );
00189
00190 Node* thisNode = 0;
00191 do {
00192
00193
00194
00195 std::map<ooTypeNumber, std::vector<ooTypeNumber> >::const_iterator partialItr = thePartialTree.find( theTypeNumber );
00196 if( thePartialTree.end( ) == partialItr ) {
00197
00198 cerr << "CdbBdbSchemaUtils::Tree::type_to_node() - FATAL INTERNAL ERROR" << endl
00199 << " Inconsistent schema information got from the federation. Something" << endl
00200 << " may be broken in the current code's implementation." << endl
00201 << " The input type number is: " << theTypeNumber << endl;
00202
00203 ::abort( );
00204 }
00205
00206
00207
00208 std::map<ooTypeNumber, Node*>::iterator itr = all.find( theTypeNumber );
00209 if( all.end( ) != itr ) {
00210
00211 thisNode = itr->second;
00212
00213
00214 if( debugModeFlag ) {
00215 cout << "Tree::type_to_node() ALREADY PROCESSED TYPE " << theTypeNumber << endl;
00216 }
00217
00218
00219 break;
00220 }
00221
00222
00223
00224 thisNode = new Node( theTypeNumber );
00225 all[theTypeNumber] = thisNode;
00226
00227
00228
00229
00230 int numBase = partialItr->second.size( );
00231 if( 0 == numBase ) {
00232
00233 root[theTypeNumber] = thisNode;
00234
00235
00236 if( debugModeFlag ) {
00237 cout << "Tree::type_to_node() VERY BASE TYPE " << theTypeNumber << endl;
00238 }
00239
00240 break;
00241 }
00242
00243
00244
00245
00246 if( debugModeFlag ) {
00247 cout << "Tree::type_to_node() SUBCLASS TYPE " << theTypeNumber << endl;
00248 }
00249
00250
00251 for( int i = 0; i < numBase; ++i ) {
00252
00253 ooTypeNumber baseTypeNumber = partialItr->second[i];
00254 Node* baseNode = type_to_node( thePartialTree,
00255 baseTypeNumber,
00256 debugModeFlag );
00257
00258 baseNode->subclasses [ theTypeNumber] = thisNode;
00259 thisNode->superclasses[baseTypeNumber] = baseNode;
00260
00261
00262 if( debugModeFlag ) {
00263 cout << "Tree::type_to_node() ADDED BASE TYPE " << baseTypeNumber << endl;
00264 }
00265
00266 }
00267
00268 } while( false );
00269
00270 return thisNode;
00271 }
00272
00273
00274
00275
00276
00277 bool
00278 CdbBdbSchemaUtils::debugMode = false;
00279
00280 CdbBdbSchemaUtils&
00281 CdbBdbSchemaUtils::instance( )
00282 {
00283 static CdbBdbSchemaUtils myInstance;
00284 return myInstance;
00285 }
00286
00287 CdbBdbSchemaUtils::CdbBdbSchemaUtils( ) :
00288 _derivedVsBase (0),
00289 _derivedVsBaseSize(0)
00290 {
00291 if( !update( )) {
00292 cerr << "CdbBdbSchemaUtils::CdbBdbSchemaUtils( ) - FATAL INTERNAL ERROR IN THE CONSTRUCTOR." << endl
00293 << " Unable to load/update schema information from the current federation." << endl;
00294 ::abort( );
00295 }
00296 }
00297
00298 CdbBdbSchemaUtils::~CdbBdbSchemaUtils( )
00299 {
00300 clearCache( );
00301 }
00302
00303 bool
00304 CdbBdbSchemaUtils::isA( const ooTypeNumber theDerivedTypeNumber,
00305 const ooTypeNumber theBaseTypeNumber ) const
00306 {
00307
00308
00309
00310 std::map<ooTypeNumber, LocalTypeID>::const_iterator derivedItr = _typeNumberToLocalTypeId.find( theDerivedTypeNumber );
00311 std::map<ooTypeNumber, LocalTypeID>::const_iterator baseItr = _typeNumberToLocalTypeId.find( theBaseTypeNumber );
00312
00313 if( _typeNumberToLocalTypeId.end( ) == derivedItr ) return false;
00314 if( _typeNumberToLocalTypeId.end( ) == baseItr ) return false;
00315
00316 LocalTypeID derived = derivedItr->second;
00317 LocalTypeID base = baseItr->second;
00318
00319
00320
00321 return ( derived == base ) || _derivedVsBase[derived][base];
00322 }
00323
00324 bool
00325 CdbBdbSchemaUtils::typeNumberToClassName( const ooTypeNumber theTypeNumber,
00326 std::string& theClassName ) const
00327 {
00328 std::map<ooTypeNumber, std::string>::const_iterator classNameItr = _typeNumberToName.find( theTypeNumber );
00329 if( _typeNumberToName.end( ) != classNameItr ) {
00330 theClassName = classNameItr->second;
00331 return true;
00332 }
00333 return false;
00334 }
00335
00336 bool
00337 CdbBdbSchemaUtils::classNameToTypeNumber( const char* theClassName,
00338 ooTypeNumber& theTypeNumber ) const
00339 {
00340 if( 0 == theClassName ) return false;
00341
00342 std::map<std::string, ooTypeNumber>::const_iterator typeNumberItr = _nameToTypeNumber.find( std::string( theClassName ));
00343 if( _nameToTypeNumber.end( ) != typeNumberItr ) {
00344 theTypeNumber = typeNumberItr->second;
00345 return true;
00346 }
00347 return false;
00348 }
00349
00350 bool
00351 CdbBdbSchemaUtils::loadDependencyTree( Tree& theTree ) const
00352 {
00353 return theTree.load( _dependencyTree,
00354 debugMode );
00355 }
00356
00357 bool
00358 CdbBdbSchemaUtils::update( )
00359 {
00360 clearCache( );
00361
00362
00363
00364 const ooas::d_Module& topModule = ooas::d_Module::top_level( );
00365
00366
00367 if( debugMode ) {
00368 cout << "MODULE: NAME=\"" << topModule.name( ) << "\", ID=" << topModule.id( ) << endl;
00369 }
00370
00371
00372 ooas::meta_object_iterator metaObjectItr = topModule.defines_begin( );
00373 while( metaObjectItr != topModule.defines_end( )) {
00374
00375 const ooas::d_Meta_Object& metaObject = *metaObjectItr;
00376 if( metaObject.is_module( )) {
00377
00378 const ooas::d_Module& module = (const ooas::d_Module&)metaObject;
00379
00380
00381 if( debugMode ) {
00382 cout << "MODULE: NAME=\"" << module.name( ) << "\", ID=" << module.id( ) << endl;
00383 }
00384
00385
00386 ooas::type_iterator typeItr = module.defines_types_begin( );
00387 while( typeItr != module.defines_types_end( )) {
00388
00389 const ooas::d_Type& type = *typeItr;
00390 if( type.is_class( )) {
00391
00392 const ooas::d_Class& classType = (const ooas::d_Class&)type;
00393
00394 registerClass( _derivedVsBaseSize++,
00395 classType.name( ),
00396 classType.type_number( ));
00397 }
00398 ++typeItr;
00399 }
00400
00401 } else if( metaObject.is_class( )) {
00402
00403
00404
00405
00406 const ooas::d_Class& classType = (const ooas::d_Class&)metaObject;
00407
00408 registerClass( _derivedVsBaseSize++,
00409 classType.name( ),
00410 classType.type_number( ));
00411 }
00412 ++metaObjectItr;
00413 }
00414
00415
00416 if( debugMode ) {
00417 cout << "TOTAL OF " << _derivedVsBaseSize << " classes were found." << endl;
00418 }
00419
00420
00421
00422
00423
00424 _derivedVsBase = new bool*[_derivedVsBaseSize];
00425 for( LocalTypeID derived = 0; derived < _derivedVsBaseSize; ++derived ) {
00426
00427 _derivedVsBase[derived] = new bool[_derivedVsBaseSize];
00428 for( LocalTypeID base = 0; base < _derivedVsBaseSize; ++base ) {
00429
00430 _derivedVsBase[derived][base] = false;
00431 }
00432 }
00433
00434
00435
00436
00437 {
00438 std::map<ooTypeNumber, std::string>::iterator classTypeNumberItr = _typeNumberToName.begin( );
00439 while( classTypeNumberItr != _typeNumberToName.end( )) {
00440
00441 ooTypeNumber classTypeNumber = classTypeNumberItr->first;
00442 if( !::buildPartialDependencyTreeForClass( topModule.resolve_class( classTypeNumber ),
00443 _dependencyTree )) {
00444
00445 cerr << "CdbBdbSchemaUtils::update( ) - ERROR." << endl
00446 << " Unable to obtain schema information for the class with type number: " << classTypeNumber << endl;
00447 return false;
00448 }
00449 ++classTypeNumberItr;
00450 }
00451 }
00452
00453
00454
00455
00456 {
00457 std::map<ooTypeNumber, std::vector<ooTypeNumber> >::iterator classTypeNumberItr = _dependencyTree.begin( );
00458 while( classTypeNumberItr != _dependencyTree.end( )) {
00459
00460 ooTypeNumber classTypeNumber = classTypeNumberItr->first;
00461
00462 fillDependencyMatrixForClass( classTypeNumber,
00463 classTypeNumber,
00464 _typeNumberToLocalTypeId,
00465 _dependencyTree,
00466 _derivedVsBase );
00467 ++classTypeNumberItr;
00468 }
00469 }
00470
00471 return true;
00472 }
00473
00474 void
00475 CdbBdbSchemaUtils::clearCache( )
00476 {
00477 _nameToTypeNumber.clear( );
00478 _typeNumberToName.clear( );
00479
00480 _localTypeIdToTypeNumber.clear( );
00481 _typeNumberToLocalTypeId.clear( );
00482
00483 _dependencyTree.clear( );
00484
00485 for( LocalTypeID i = 0; i < _derivedVsBaseSize; ++i ) delete [] _derivedVsBase[i];
00486 delete [] _derivedVsBase;
00487
00488 _derivedVsBase = 0;
00489 _derivedVsBaseSize = 0;
00490 }
00491
00492 void
00493 CdbBdbSchemaUtils::registerClass( const LocalTypeID theLocalTypeId,
00494 const char* theClassName,
00495 const ooTypeNumber theTypeNumber )
00496 {
00497 std::string className = theClassName;
00498
00499 _nameToTypeNumber[className] = theTypeNumber;
00500 _typeNumberToName[theTypeNumber] = className;
00501
00502 _localTypeIdToTypeNumber[theLocalTypeId] = theTypeNumber;
00503 _typeNumberToLocalTypeId[theTypeNumber] = theLocalTypeId;
00504
00505
00506 if( debugMode ) {
00507 cout << " "
00508 << setw(10) << setfill( ' ' ) << theLocalTypeId
00509 << " : "
00510 << setw(10) << setfill( ' ' ) << theTypeNumber
00511 << " : "
00512 << "\"" << theClassName << "\"" << endl;
00513 }
00514
00515 }
00516
00517
00518
00519