Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

CdbBdbPrintObjectTreeImpl.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbPrintObjectTreeImpl.cc,v 1.5 2004/10/21 20:35:51 gapon Exp $
00003 #include "BaBar/BaBar.hh"
00004 
00005 /// The implementation of the CdbBdbPrintObjectTreeImpl.
00006 /**
00007   * @see CdbBdbPrintObjectTreeImpl
00008   */
00009 
00010 #include "BaBar/BaBar.hh"
00011 
00012 #include "CdbBdb/CdbBdbPrintObjectTreeImpl.hh"
00013 
00014 #include "CdbBdb/CdbBdbPrintObjectTreeUserAction.hh"
00015 #include "CdbBdb/CdbBdbSimpleCache.hh"
00016 
00017 #include <assert.h>
00018 
00019 #include <iostream>     // Use STD I/O streams to avoid conflicts with
00020                         // Objectivity/DB Active Schema API caused by a bug
00021                         // in its header file at version 7.
00022 
00023 #include <ooMap.h>      // Objectivity/DB core API for the Map Dictionary class
00024 using std::cerr;
00025 using std::cout;
00026 using std::endl;
00027 
00028 
00029 //////////////////////////////////////
00030 // CdbBdbPrintObjectTreeImpl::Prefix //
00031 //////////////////////////////////////
00032 
00033 CdbBdbPrintObjectTreeImpl::Prefix::Prefix(               int& theLevel,
00034                                            const std::string& theStep ) :
00035     _level(theLevel),
00036     _str  ("")
00037 {
00038     ++_level;
00039     for( int i = 0; i < _level; ++i ) _str += theStep;
00040 }
00041 
00042 CdbBdbPrintObjectTreeImpl::Prefix::~Prefix( )
00043 {
00044     --_level;
00045 }
00046         
00047 const char*
00048 CdbBdbPrintObjectTreeImpl::Prefix::c_str( ) const
00049 {
00050     return _str.c_str( );
00051 }
00052 
00053 ///////////////////////
00054 // CdbBdbPrintObjectTree //
00055 ///////////////////////
00056 
00057 CdbBdbPrintObjectTreeImpl::CdbBdbPrintObjectTreeImpl( CdbBdbPrintObjectTreeUserAction* theUserAction,
00058                                                                                   bool verboseMode,
00059                                                                                   bool debugMode ) :
00060     _verboseMode(verboseMode),
00061     _debugMode  (debugMode),
00062     _userAction (theUserAction),
00063     _dictionary (new CdbBdbSimpleCache( )),
00064     _level      (0)
00065 {
00066     if( 0 == theUserAction ) {
00067         cerr << "CdbBdbPrintObjectTreeImpl::CdbBdbPrintObjectTreeImpl() -- a null pointer instead of a valid user" << endl
00068              << "action object passed into the constructor." << endl;
00069         ::abort( );
00070     }
00071 
00072   // Force verbose mode if the debug mode is srequired
00073 
00074     if( _debugMode ) _verboseMode = true;
00075 }
00076 
00077 CdbBdbPrintObjectTreeImpl::~CdbBdbPrintObjectTreeImpl( )
00078 {
00079     if( 0 != _dictionary ) {
00080         delete _dictionary;
00081         _dictionary = 0;
00082     }
00083 }
00084 
00085 bool
00086 CdbBdbPrintObjectTreeImpl::print( const ooHandle(ooObj)& theInputH )
00087 {
00088   // Accept only valid objects to begin with
00089 
00090     if( !theInputH.isValid( )) {
00091         cerr << "CdbBdbPrintObjectTreeImpl::print() -- an invalid object passed to the procedure: " << theInputH.sprint( ) << endl;
00092         return false;
00093     }
00094 
00095   // Reset the operation's context
00096 
00097     _level = 0;
00098 
00099   // Proceed with the copy
00100 
00101     return printObject( theInputH );
00102 }
00103 
00104 CdbBdbPrintObjectTreeUserAction*
00105 CdbBdbPrintObjectTreeImpl::setUserAction( CdbBdbPrintObjectTreeUserAction* theUserAction )
00106 {
00107     if( 0 == theUserAction ) { 
00108         cerr << "CdbBdbPrintObjectTreeImpl::setUserAction() -- a null pointer instead of a valid user" << endl 
00109              << "action object passed into the method." << endl;
00110         ::abort( );
00111     }
00112 
00113     CdbBdbPrintObjectTreeUserAction* previousAction = _userAction;
00114     _userAction = theUserAction;
00115 
00116     return previousAction;
00117 }
00118 
00119 bool
00120 CdbBdbPrintObjectTreeImpl::printObject( const ooHandle(ooObj)& theInputH )
00121 {
00122     const char* context = "CdbBdbPrintObjectTreeImpl::printObject() : ";
00123 
00124     Prefix prefix( _level );
00125 
00126 ////////////////////////////////////////////////////////////////
00127 if( _verboseMode ) {
00128     std::string  inStr = theInputH.sprint( );
00129     cout << prefix.c_str( ) << inStr.c_str( ) << " >> " << endl;
00130 }
00131 ////////////////////////////////////////////////////////////////
00132 
00133   // Simply ignore the null objects. It's not a error conditions since its quite
00134   // normal for persistent objects to have null references.
00135 
00136     if( theInputH == 0 ) {
00137 
00138 /////////////////////////////////////////////////////////////////////////////////////////////////////
00139 //if( _verboseMode ) {
00140     std::string  inStr = theInputH.sprint( );
00141     cout << prefix.c_str( ) << inStr.c_str( ) << endl;
00142 //}
00143 /////////////////////////////////////////////////////////////////////////////////////////////////////
00144 
00145     } else {
00146 
00147       // Find an object in the transient cache first if the cache is present
00148       // in the current test's environment.
00149 
00150         if( 0 != _dictionary->findObject( theInputH )) {
00151 
00152 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00153 //if( _verboseMode ) {
00154     std::string  inStr = theInputH.sprint( );
00155     cout << prefix.c_str( ) << inStr.c_str( ) << endl;
00156 //}
00157 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00158 
00159         } else {
00160 
00161           // Engage a user action to see what has to be done next
00162 
00163             switch( _userAction->action( theInputH )) {
00164 
00165             default :
00166                 {
00167                     bool isKnownUserAction = false;
00168                     assert( isKnownUserAction );
00169                 }
00170 
00171             case CdbBdbPrintObjectTreeUserAction::ACTION_ERROR :
00172 
00173                 cerr << context << "user action failed for: " << theInputH.sprint( ) << endl;
00174                 return false;
00175 
00176             case CdbBdbPrintObjectTreeUserAction::ACTION_STOP :
00177 
00178                 _dictionary->addObject( theInputH, theInputH );
00179 
00180 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00181 if( _verboseMode ) {
00182     std::string  inStr = theInputH.sprint( );
00183     cout << prefix.c_str( ) << inStr.c_str( ) << " (STOP BY USER ACTION)" << endl;
00184 }
00185 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00186 
00187                 break;
00188 
00189             case CdbBdbPrintObjectTreeUserAction::ACTION_PROCEED :
00190 
00191                 {
00192                   // Now we're diving into another object which has been successfully
00193                   // validated by the user action.
00194 
00195 
00196                   // Check for special case of the ooMap class. Use regular (as opposed to the Active
00197                   // Schema API) to browse the map.
00198                   //
00199                   // IMPLEMENTATION NOTE: In theory this operation could also be resolved for
00200                   //                      user defined subclasses of the ooMap class. Besides we have
00201                   //                      a set of other internal classes defined by Objectivity itself
00202                   //                      (containers, sets, B-Trees, etc.) It's unclear whether they
00203                   //                      can also be browsed in this way.
00204 
00205                     ooTypeNumber typeN = theInputH.typeN( );
00206 
00207                     if( ooTypeN(ooMap) == typeN ) {
00208 
00209                         ooHandle(ooMap) inputMapH;      // non-const handle is needed to set up an iterator
00210                         inputMapH = (ooHandle(ooMap))theInputH;
00211 
00212                       // ATTENTION: update the cache _before_ copying the object to prevent
00213                       //            "visit self" loop. This may cause crashes in the algorithm.
00214 
00215                         _dictionary->addObject( theInputH, theInputH );
00216 
00217 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00218 //if( _verboseMode ) {
00219     std::string  inStr = theInputH.sprint( );
00220     cout << prefix.c_str( ) << inStr.c_str( ) << endl;
00221 //}
00222 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00223 
00224                         {
00225                             ooMapItr itr( inputMapH );
00226                             while( itr.next( )) {
00227 
00228                                 ooRef(ooObj) inputRef = itr->oid( );
00229 
00230                                 ooHandle(ooObj) inputH;
00231                                 inputH = inputRef;
00232 
00233                                 if( ! printObject( inputH )) return false;
00234                             }
00235                         }
00236 
00237                     } else {
00238 
00239                       // Visit the persisten object using recursive algorithm.
00240                       //
00241                       // NOTE: The cast is needed as a workaround of the buggy interface
00242                       //       of the "ooas::Class_Object" class. It does not really need
00243                       //       non-const handle.
00244 
00245                         ooas::Class_Object classObj((ooHandle(ooObj)&)theInputH );
00246                         if( !classObj ) {
00247                             cerr << context << "no ooas::Class_Object for the input object reference: " << theInputH.sprint( ) << endl;
00248                             ::exit( 1 );
00249                         }
00250 
00251                       // ATTENTION: update the cache _before_ prifiling the object to prevent
00252                       //            "copy self" loop. This may cause crashes in the code.
00253 
00254                         _dictionary->addObject( theInputH, theInputH );
00255 
00256 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00257 //if( _verboseMode ) {
00258     std::string  inStr = theInputH.sprint( );
00259     cout << prefix.c_str( ) << inStr.c_str( ) << endl;
00260 //}
00261 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00262 
00263                         if( !printObjectContents( classObj, prefix )) return false;
00264                     }
00265                 }
00266             }
00267         }
00268     }
00269 
00270 ////////////////////////////////////////////////////////////////
00271 if( _verboseMode ) {
00272     std::string  inStr = theInputH.sprint( );
00273     cout << prefix.c_str( ) << inStr.c_str( ) << " << " << endl;
00274 }
00275 ////////////////////////////////////////////////////////////////
00276 
00277     return true;
00278 }
00279 
00280 bool
00281 CdbBdbPrintObjectTreeImpl::printObjectContents( const ooas::Class_Object& theClassObject,
00282                                                              const Prefix& thePrefix )
00283 {
00284     if( !theClassObject ) {
00285         cerr << "CdbBdbPrintObjectTreeImpl::printObjectContents() -- an invalid class object passed into the method." << endl;
00286         ::abort( );
00287     }
00288 
00289   // Get the class object
00290 
00291     const ooas::d_Class& classDsc = theClassObject.type_of( );
00292 
00293   // We're only interested in a user defined (non-internal) classes.
00294 
00295     if( !classDsc.is_class   ( )) return true;
00296     if(  classDsc.is_internal( )) return true;
00297 
00298   // Browse all attributes
00299 
00300     {
00301         attribute_iterator itr = classDsc.defines_attribute_begin( );
00302         while( classDsc.defines_attribute_end( ) != itr ) {
00303 
00304             const ooas::d_Attribute& attrDsc = *itr;
00305 
00306             if( attrDsc.is_base_class( )) {
00307 
00308 ///////////////////////////////////////////////////////
00309 if( _debugMode ) {
00310     cout << thePrefix.c_str( ) << "BASE CLASS" << endl;
00311 }
00312 ///////////////////////////////////////////////////////
00313 
00314                 ooas::Class_Object inputClassObj = theClassObject.get_class_obj( attrDsc.position( ));
00315 
00316                 printObjectContents( inputClassObj, thePrefix );
00317 
00318             } else if( attrDsc.is_relationship( )) {
00319 
00320                 const d_Relationship&     relDsc          = (const d_Relationship&)attrDsc;
00321                 ooas::Relationship_Object relationshipObj =  theClassObject.get_relationship( attrDsc.position( ));
00322                 assert( relationshipObj );  // a consistency bug in the Objectivity/DB Active Schema API
00323 
00324                 if( relDsc.is_to_many( )) {
00325 
00326 ///////////////////////////////////////////////////////////
00327 if( _debugMode ) {
00328     cout << thePrefix.c_str( ) << "n-RELATIONSHIP" << endl;
00329 }
00330 ///////////////////////////////////////////////////////////
00331 
00332                     uint32 num = 0;     // The cardinality of the association
00333 
00334                     ooItr(ooObj) itr;
00335                     relationshipObj.get_iterator( itr );
00336 
00337                     while( itr.next( )) {
00338 
00339                         ooHandle(ooObj) inputH;
00340                         inputH = itr;
00341 
00342                         if( !printObject( inputH )) return false;
00343 
00344                         ++num;
00345                     }
00346 
00347                 } else {
00348 
00349 ///////////////////////////////////////////////////////////
00350 if( _debugMode ) {
00351     cout << thePrefix.c_str( ) << "1-RELATIONSHIP" << endl;
00352 }
00353 ///////////////////////////////////////////////////////////
00354 
00355                     ooHandle(ooObj) inputH;
00356                     inputH = relationshipObj.get_ooref( );
00357 
00358                     if( !printObject(inputH )) return false;
00359                 }
00360 
00361             } else {
00362 
00363                 const ooas::d_Type& typeDsc = attrDsc.type_of( );
00364 
00365                 size_t fixedArraySize = attrDsc.array_size( );
00366 
00367                 if( typeDsc.is_ref_type( )) {
00368 
00369 //////////////////////////////////////////////////////////////////
00370 if( _debugMode ) {
00371     cout << thePrefix.c_str( ) << "REFERENCE";
00372     if( fixedArraySize > 1 ) cout << "[" << fixedArraySize << "]";
00373     cout << endl;
00374 }
00375 //////////////////////////////////////////////////////////////////
00376 
00377                     for( size_t i = 0; i < fixedArraySize; ++i ) {
00378 
00379                         ooHandle(ooObj) inputH;
00380                         inputH = theClassObject.get_ooref( attrDsc.position( ), i );
00381 
00382                         if( !printObject( inputH )) return false;
00383                     }
00384 
00385                 } else if( typeDsc.is_basic_type( )) {
00386 
00387                     ;
00388 
00389                 } else if( typeDsc.is_string_type( )) {     // It may also be an embedded string class,
00390                                                             // so we make this scheck before the next one.
00391                     ;
00392 
00393                 } else if( typeDsc.is_class( ) && !typeDsc.is_string_type( )) {     // strings may also be represented
00394                                                                                     // by embedded classes.
00395 
00396 //////////////////////////////////////////////////////////////////
00397 if( _debugMode ) {
00398     cout << thePrefix.c_str( ) << "EMBEDDED OBJECT";
00399     if( fixedArraySize > 1 ) cout << "[" << fixedArraySize << "]";
00400     cout << endl;
00401 }
00402 //////////////////////////////////////////////////////////////////
00403 
00404                     for( size_t i = 0; i < fixedArraySize; ++i ) {
00405 
00406                         ooas::Class_Object inputClassObj = theClassObject.get_class_obj( attrDsc.position( ), i );
00407 
00408                         if( !printObjectContents( inputClassObj, thePrefix )) return false;
00409                     }
00410 
00411                 } else if( typeDsc.is_varray_type( )) {
00412 
00413                     ooas::VArray_Object inputVArrayObject = theClassObject.get_varray( attrDsc.position( ));
00414 
00415                     uint32 varraySize = inputVArrayObject.size( );
00416 
00417                     if( typeDsc.is_varray_basic_type( )) {
00418 
00419                         ;
00420 
00421                     } else if( typeDsc.is_varray_ref_type( )) {
00422 
00423 ////////////////////////////////////////////
00424 if( _debugMode ) {
00425     cout << thePrefix.c_str( )
00426          << "V-ARRAY OF REFERENCES" << endl;
00427 }
00428 ////////////////////////////////////////////
00429 
00430                         for( uint32 i = 0; i < varraySize; ++i ) {
00431 
00432                             ooHandle(ooObj) inputH;
00433                             inputH = inputVArrayObject.get_ooref( i );
00434 
00435                             if( !printObject( inputH )) return false;
00436                         }
00437 
00438                     } else if( typeDsc.is_string_type( )) {     // It may also be an embedded string class,
00439                                                                 // so we make this scheck before the next one.
00440                         ;
00441 
00442                     } else if(  typeDsc.is_varray_embedded_class_type( ) &&
00443                                !typeDsc.is_string_type( )) {
00444 
00445 //////////////////////////////////////////////////
00446 if( _debugMode ) {
00447     cout << thePrefix.c_str( )
00448          << "V-ARRAY OF EMBEDDED OBJECTS" << endl;
00449 }
00450 //////////////////////////////////////////////////
00451 
00452                       // NOTE: In theory embedded objects should have the same size, so we could
00453                       //       speed up the profiling. Unfortunatelly it's hard to get this size
00454                       //       of these objects are of a hierarhical class and/or if these objects
00455                       //       have external references.
00456                       //
00457                       //       Therefore we're using the bruit force method when profiling these
00458                       //       objects.
00459 
00460                         for( uint32 i = 0; i < varraySize; ++i )
00461                             if( !printObjectContents(  inputVArrayObject.get_class_obj( i ),
00462                                                          thePrefix )) return false;
00463 
00464                     } else {
00465 
00466                         bool isKnownTypeOfVarrayElements = false;
00467                         assert( isKnownTypeOfVarrayElements );
00468                     }
00469 
00470                 } else {
00471 
00472                     bool isKnownType = false;
00473                     assert( isKnownType );
00474                 }
00475             }
00476             ++itr;
00477         }
00478     }
00479     return true;
00480 }
00481 
00482 /////////////////
00483 // End Of File //
00484 /////////////////

Generated on Mon Dec 5 18:22:00 2005 for CDB by doxygen1.3-rc3