SFrame 3.6
core/src/SCycleBaseConfig.cxx
Go to the documentation of this file.
00001 // $Id: SCycleBaseConfig.cxx 331 2012-11-20 17:12:44Z krasznaa $
00002 /***************************************************************************
00003  * @Project: SFrame - ROOT-based analysis framework for ATLAS
00004  * @Package: Core
00005  *
00006  * @author Stefan Ask       <Stefan.Ask@cern.ch>           - Manchester
00007  * @author David Berge      <David.Berge@cern.ch>          - CERN
00008  * @author Johannes Haller  <Johannes.Haller@cern.ch>      - Hamburg
00009  * @author A. Krasznahorkay <Attila.Krasznahorkay@cern.ch> - CERN/Debrecen
00010  *
00011  ***************************************************************************/
00012 
00013 // System include(s):
00014 #include <cstdlib>
00015 #include <sstream>
00016 
00017 // ROOT include(s):
00018 #include <TString.h>
00019 #include <TXMLNode.h>
00020 #include <TList.h>
00021 #include <TXMLAttr.h>
00022 #include <TSystem.h>
00023 
00024 // Local include(s):
00025 #include "../include/SCycleBaseConfig.h"
00026 #include "../include/SGeneratorCut.h"
00027 #include "../include/STreeTypeDecoder.h"
00028 
00029 #ifndef DOXYGEN_IGNORE
00030 ClassImp( SCycleBaseConfig )
00031 #endif // DOXYGEN_IGNORE
00032 
00034 #define CHECK_FOR_DUPLICATES(NAME) {                                    \
00035       if( ( m_stringPrefs.find( NAME ) !=                               \
00036             m_stringPrefs.end() ) ||                                    \
00037           ( m_intPrefs.find( NAME ) !=                                  \
00038             m_intPrefs.end() ) ||                                       \
00039           ( m_doublePrefs.find( NAME ) !=                               \
00040             m_doublePrefs.end() ) ||                                    \
00041           ( m_boolPrefs.find( NAME ) !=                                 \
00042             m_boolPrefs.end() ) ||                                      \
00043           ( m_stringListPrefs.find( NAME ) !=                           \
00044             m_stringListPrefs.end() ) ||                                \
00045           ( m_intListPrefs.find( NAME ) !=                              \
00046             m_intListPrefs.end() ) ||                                   \
00047           ( m_doubleListPrefs.find( NAME ) !=                           \
00048             m_doubleListPrefs.end() ) ||                                \
00049           ( m_boolListPrefs.find( NAME ) !=                             \
00050             m_boolListPrefs.end() ) ) {                                 \
00051          REPORT_ERROR( "The property name \"" << NAME                   \
00052                        << "\" is used in multiple locations!" );        \
00053          REPORT_ERROR( "Some parts of the code will not be "            \
00054                        "configured correctly!" );                       \
00055       }                                                                 \
00056    } while( 0 )
00057 
00058 namespace {
00059 
00070    template< typename T >
00071    std::ostream& operator<<( std::ostream& out,
00072                              const std::vector< T >& vec ) {
00073 
00074       for( size_t i = 0; i < vec.size(); ++i ) {
00075          out << vec[ i ];
00076          if( i + 1 < vec.size() ) out << " ";
00077       }
00078 
00079       return out;
00080    }
00081 
00082 } // private namespace
00083 
00087 SCycleBaseConfig::SCycleBaseConfig()
00088    : m_input( 0 ) {
00089 
00090    REPORT_VERBOSE( "SCycleBaseConfig constructed" );
00091 }
00092 
00103 void SCycleBaseConfig::Initialize( TXMLNode* node ) throw( SError ) {
00104 
00105    m_logger << INFO << "Initializing from configuration" << SLogger::endmsg;
00106 
00107    // Clear the current cycle configuration:
00108    m_config.ClearConfig();
00109    REPORT_VERBOSE( "Cleared the current configuration" );
00110 
00111    // Set the name of the cycle in the configuration:
00112    m_config.SetCycleName( m_logger.GetSource() );
00113 
00114    //
00115    // Get the properties of the Cycle node:
00116    //
00117    TListIter attribIt = node->GetAttributes();
00118    TXMLAttr* curAttr = 0;
00119    while( ( curAttr = dynamic_cast< TXMLAttr* >( attribIt() ) ) != 0 ) {
00120       if( curAttr->GetName() == TString( "TargetLumi" ) ) {
00121          m_config.SetTargetLumi( atof( curAttr->GetValue() ) );
00122       } else if( curAttr->GetName() == TString( "RunMode" ) ) {
00123          SCycleConfig::RunMode mode = SCycleConfig::LOCAL;
00124          if( curAttr->GetValue() == TString( "LOCAL" ) )
00125             mode = SCycleConfig::LOCAL;
00126          else if( curAttr->GetValue() == TString( "PROOF" ) )
00127             mode = SCycleConfig::PROOF;
00128          else {
00129             m_logger << WARNING << "Running mode (\"" << curAttr->GetValue()
00130                      << "\") not recognised. Running locally!" << SLogger::endmsg;
00131          }
00132          m_config.SetRunMode( mode );
00133       } else if( curAttr->GetName() == TString( "ProofServer" ) ) {
00134          m_config.SetProofServer( curAttr->GetValue() );
00135       } else if( curAttr->GetName() == TString( "ProofWorkDir" ) ) {
00136          m_config.SetProofWorkDir( curAttr->GetValue() );
00137       } else if( curAttr->GetName() == TString( "ProofNodes" ) ) {
00138          m_config.SetProofNodes( atoi(curAttr->GetValue()) );
00139       } else if( curAttr->GetName() == TString( "OutputDirectory" ) ) {
00140          m_config.SetOutputDirectory( curAttr->GetValue() );
00141       } else if( curAttr->GetName() == TString( "PostFix" ) ) {
00142          m_config.SetPostFix( curAttr->GetValue() );
00143       } else if( curAttr->GetName() == TString( "UseTreeCache" ) ) {
00144          m_config.SetUseTreeCache( ToBool( curAttr->GetValue() ) );
00145       } else if( curAttr->GetName() == TString( "TreeCacheSize" ) ) {
00146          m_config.SetCacheSize( atoi( curAttr->GetValue() ) );
00147       } else if( curAttr->GetName() == TString( "TreeCacheLearnEntries" ) ) {
00148          m_config.SetCacheLearnEntries( atoi( curAttr->GetValue() ) );
00149       } else if( curAttr->GetName() == TString( "ProcessOnlyLocal" ) ) {
00150          m_config.SetProcessOnlyLocal( ToBool( curAttr->GetValue() ) );
00151       }
00152    }
00153 
00154    // ------------- parse xml element ------------------------------------
00155 
00156    TXMLNode* nodes = node->GetChildren();
00157    while( nodes != 0 ) {
00158       if( ! nodes->HasChildren() ) {
00159          nodes = nodes->GetNextNode();
00160          continue;
00161       }
00162 
00163       if( nodes->GetNodeName() == TString( "InputData" ) ) {
00164 
00165          m_config.AddInputData( this->InitializeInputData( nodes ) );
00166 
00167       } else if( nodes->GetNodeName() == TString( "UserConfig" ) ) {
00168 
00169          this->InitializeUserConfig( nodes );
00170 
00171       }
00172       nodes = nodes->GetNextNode();
00173    }
00174 
00175    // now check if input data type appears multiple times
00176    m_config.ArrangeInputData();
00177    REPORT_VERBOSE( "Arranged the input data" );
00178 
00179    // print configuration
00180    m_config.PrintConfig();
00181 
00182    // ------------- xml parsing terminated -------------------------------
00183 
00184    return;
00185 }
00186 
00187 const SCycleConfig& SCycleBaseConfig::GetConfig() const {
00188 
00189    return m_config;
00190 }
00191 
00192 SCycleConfig& SCycleBaseConfig::GetConfig() {
00193 
00194    return m_config;
00195 }
00196 
00197 void SCycleBaseConfig::SetConfig( const SCycleConfig& config ) {
00198 
00199    //
00200    // Save the new configuration:
00201    //
00202    m_config = config;
00203 
00204    // Clear the configuration name cache:
00205    m_configuredPrefs.clear();
00206 
00207    //
00208    // Set the user properties according to the new configuration:
00209    //
00210    for( SCycleConfig::property_type::const_iterator it =
00211            m_config.GetProperties().begin();
00212         it != m_config.GetProperties().end(); ++it ) {
00213       SetProperty( it->first, it->second );
00214    }
00215 
00216    return;
00217 }
00218 
00219 const TList& SCycleBaseConfig::GetConfigurationObjects() const {
00220 
00221    return m_configList;
00222 }
00223 
00224 void SCycleBaseConfig::SetConfInput( TList* input ) {
00225 
00226    m_input = input;
00227    return;
00228 }
00229 
00230 TList* SCycleBaseConfig::GetConfInput() const {
00231 
00232    return m_input;
00233 }
00234 
00236 //                                                                       //
00237 // Implementation of the functions declaring the properties of the       //
00238 // derived class                                                         //
00239 //                                                                       //
00241 
00250 void SCycleBaseConfig::DeclareProperty( const std::string& name,
00251                                         std::string& value ) {
00252 
00253    // Check if the property name is still available:
00254    CHECK_FOR_DUPLICATES( name );
00255 
00256    m_stringPrefs[ name ] = &value;
00257    return;
00258 
00259 }
00260 
00269 void SCycleBaseConfig::DeclareProperty( const std::string& name, int& value ) {
00270 
00271    // Check if the property name is still available:
00272    CHECK_FOR_DUPLICATES( name );
00273 
00274    m_intPrefs[ name ] = &value;
00275    return;
00276 
00277 }
00278 
00287 void SCycleBaseConfig::DeclareProperty( const std::string& name,
00288                                         double& value ) {
00289 
00290    // Check if the property name is still available:
00291    CHECK_FOR_DUPLICATES( name );
00292 
00293    m_doublePrefs[ name ] = &value;
00294    return;
00295 
00296 }
00297 
00310 void SCycleBaseConfig::DeclareProperty( const std::string& name, bool& value ) {
00311 
00312    // Check if the property name is still available:
00313    CHECK_FOR_DUPLICATES( name );
00314 
00315    m_boolPrefs[ name ] = &value;
00316    return;
00317 
00318 }
00319 
00329 void SCycleBaseConfig::DeclareProperty( const std::string& name,
00330                                         std::vector< std::string >& value ) {
00331 
00332    // Check if the property name is still available:
00333    CHECK_FOR_DUPLICATES( name );
00334 
00335    m_stringListPrefs[ name ] = &value;
00336    return;
00337 
00338 }
00339 
00349 void SCycleBaseConfig::DeclareProperty( const std::string& name,
00350                                         std::vector< int >& value ) {
00351 
00352    // Check if the property name is still available:
00353    CHECK_FOR_DUPLICATES( name );
00354 
00355    m_intListPrefs[ name ] = &value;
00356    return;
00357 
00358 }
00359 
00369 void SCycleBaseConfig::DeclareProperty( const std::string& name,
00370                                         std::vector< double >& value ) {
00371 
00372    // Check if the property name is still available:
00373    CHECK_FOR_DUPLICATES( name );
00374 
00375    m_doubleListPrefs[ name ] = &value;
00376    return;
00377 
00378 }
00379 
00393 void SCycleBaseConfig::DeclareProperty( const std::string& name,
00394                                         std::vector< bool >& value ) {
00395 
00396    // Check if the property name is still available:
00397    CHECK_FOR_DUPLICATES( name );
00398 
00399    m_boolListPrefs[ name ] = &value;
00400    return;
00401 
00402 }
00403 
00404 void SCycleBaseConfig::AddConfigObject( TObject* object ) {
00405 
00406    m_configList.Add( object );
00407    return;
00408 }
00409 
00410 TObject* SCycleBaseConfig::GetConfigObject( const char* name ) const {
00411 
00412    if( ! m_input ) return 0;
00413 
00414    return m_input->FindObject( name );
00415 }
00416 
00418 //                                                                       //
00419 // Implementation of the functions called by the public Initialize(...)  //
00420 // that handle the different aspects of the initialisation.              //
00421 //                                                                       //
00423 
00424 SInputData
00425 SCycleBaseConfig::InitializeInputData( TXMLNode* node ) throw( SError ) {
00426 
00427    // Create the SInputData object
00428    SInputData inputData;
00429 
00430    REPORT_VERBOSE( "Reading an input data definition" );
00431 
00432    TListIter attribIt( node->GetAttributes() );
00433    TXMLAttr* curAttr( 0 );
00434    while( ( curAttr = dynamic_cast< TXMLAttr* >( attribIt() ) ) != 0 ) {
00435 
00436       if( curAttr->GetName() == TString( "Type" ) ) {
00437          inputData.SetType( curAttr->GetValue() );
00438       } else if( curAttr->GetName() == TString( "Version" ) ) {
00439          inputData.SetVersion( curAttr->GetValue() );
00440       } else if( curAttr->GetName() == TString( "Lumi" ) ) {
00441          inputData.SetTotalLumi( atof( curAttr->GetValue() ) );
00442       } else if( curAttr->GetName() == TString( "NEventsMax" ) ) {
00443          inputData.SetNEventsMax( atoi( curAttr->GetValue() ) );
00444       } else if( curAttr->GetName() == TString( "NEventsSkip" ) ) {
00445          inputData.SetNEventsSkip( atoi( curAttr->GetValue() ) );
00446       } else if( curAttr->GetName() == TString( "Cacheable" ) ) {
00447          inputData.SetCacheable( ToBool( curAttr->GetValue() ) );
00448       } else if( curAttr->GetName() == TString( "SkipValid" ) ) {
00449          inputData.SetSkipValid( ToBool( curAttr->GetValue() ) );
00450       }
00451    }
00452 
00453    m_logger << INFO << "Reading SInputData: " << inputData.GetType()
00454             << " - " << inputData.GetVersion() << SLogger::endmsg;
00455 
00456    // Access the tree type decoder:
00457    const STreeTypeDecoder* decoder = STreeTypeDecoder::Instance();
00458 
00459    TXMLNode* child = node->GetChildren();
00460    while( child != 0 ) {
00461       if( ! child->HasAttributes() ) {
00462          child = child->GetNextNode();
00463          continue;
00464       }
00465 
00466       TListIter attributes( child->GetAttributes() );
00467       TXMLAttr* attribute = 0;
00468 
00469       // get the generator cuts
00470       if( child->GetNodeName() == TString( "GeneratorCut" ) ) {
00471 
00472          TString treeName = "";
00473          TString formula = "";
00474          attribute = 0;
00475          while( ( attribute =
00476                   dynamic_cast< TXMLAttr* >( attributes() ) ) != 0 ) {
00477             if( attribute->GetName() == TString( "Tree" ) ) {
00478                treeName = attribute->GetValue();
00479             }
00480             if( attribute->GetName() == TString( "Formula" ) ) {
00481                formula = attribute->GetValue();
00482             }
00483          }
00484 
00485          REPORT_VERBOSE( "Found a generator cut on tree \"" << treeName
00486                          << "\" with formula: " << formula );
00487          inputData.AddGenCut( SGeneratorCut( treeName, formula ) );
00488 
00489       }
00490       // get the input datasets
00491       else if( child->GetNodeName() == TString( "DataSet" ) ) {
00492 
00493          TString name = "";
00494          Double_t lumi = 0.;
00495          attribute = 0;
00496          while( ( attribute =
00497                   dynamic_cast< TXMLAttr* >( attributes() ) ) != 0 ) {
00498             if( attribute->GetName() == TString( "Name" ) )
00499                name = attribute->GetValue();
00500             if( attribute->GetName() == TString( "Lumi" ) )
00501                lumi = atof( attribute->GetValue() );
00502          }
00503 
00504          REPORT_VERBOSE( "Found a dataset with name \"" << name
00505                          << "\" and lumi: " << lumi );
00506          inputData.AddDataSet( SDataSet( name, lumi ) );
00507 
00508       }
00509       // get the input files
00510       else if( child->GetNodeName() == TString( "In" ) ) {
00511 
00512          TString fileName = "";
00513          Double_t lumi = 0.;
00514          attribute = 0;
00515          while( ( attribute =
00516                   dynamic_cast< TXMLAttr* >( attributes() ) ) != 0 ) {
00517             if( attribute->GetName() == TString( "FileName" ) )
00518                fileName = attribute->GetValue();
00519             if( attribute->GetName() == TString( "Lumi" ) )
00520                lumi = atof( attribute->GetValue() );
00521          }
00522 
00523          REPORT_VERBOSE( "Found an input file with name \"" << fileName
00524                          << "\" and lumi: " << lumi );
00525          inputData.AddSFileIn( SFile( fileName, lumi ) );
00526 
00527       }
00528       // get a "regular" input tree
00529       else if( child->GetNodeName() == TString( "InputTree" ) ) {
00530 
00531          TString treeName = "";
00532          attribute = 0;
00533          while( ( attribute =
00534                   dynamic_cast< TXMLAttr* >( attributes() ) ) != 0 ) {
00535             if( attribute->GetName() == TString( "Name" ) )
00536                treeName = attribute->GetValue();
00537          }
00538 
00539          REPORT_VERBOSE( "Found regular input tree with name: " << treeName );
00540          inputData.AddTree( decoder->GetXMLCode( "InputTree" ),
00541                             STree( treeName, ( STree::INPUT_TREE |
00542                                                STree::EVENT_TREE ) ) );
00543 
00544       }
00545       // get an output tree
00546       else if( child->GetNodeName() == TString( "OutputTree" ) ) {
00547 
00548          TString treeName = "";
00549          attribute = 0;
00550          while( ( attribute =
00551                   dynamic_cast< TXMLAttr* >( attributes() ) ) != 0 ) {
00552             if( attribute->GetName() == TString( "Name" ) )
00553                treeName = attribute->GetValue();
00554          }
00555 
00556          REPORT_VERBOSE( "Found regular output tree with name: " << treeName );
00557          inputData.AddTree( decoder->GetXMLCode( "OutputTree" ),
00558                             STree( treeName, ( STree::OUTPUT_TREE |
00559                                                STree::EVENT_TREE ) ) );
00560 
00561       }
00562       // get an input metadata tree
00563       else if( child->GetNodeName() == TString( "MetadataInputTree" ) ) {
00564 
00565          TString treeName = "";
00566          attribute = 0;
00567          while( ( attribute =
00568                   dynamic_cast< TXMLAttr* >( attributes() ) ) != 0 ) {
00569             if( attribute->GetName() == TString( "Name" ) )
00570                treeName = attribute->GetValue();
00571          }
00572 
00573          REPORT_VERBOSE( "Found input metadata tree with name: " << treeName );
00574          inputData.AddTree( decoder->GetXMLCode( "MetadataInputTree" ),
00575                             STree( treeName, STree::INPUT_TREE ) );
00576 
00577       }
00578       // get an output metadata tree
00579       else if( child->GetNodeName() == TString( "MetadataOutputTree" ) ) {
00580 
00581          TString treeName = "";
00582          attribute = 0;
00583          while( ( attribute =
00584                   dynamic_cast< TXMLAttr* >( attributes() ) ) != 0 ) {
00585             if( attribute->GetName() == TString( "Name" ) )
00586                treeName = attribute->GetValue();
00587          }
00588 
00589          REPORT_VERBOSE( "Found output metadata tree with name: " << treeName );
00590          inputData.AddTree( decoder->GetXMLCode( "MetadataOutputTree" ),
00591                             STree( treeName, STree::OUTPUT_TREE ) );
00592 
00593       } else {
00594          // Unknown field notification. It's not an ERROR anymore, as this
00595          // function may actually find XML nodes that it doesn't recognise.
00596          m_logger << DEBUG << "Unknown field: " << child->GetNodeName()
00597                   << SLogger::endmsg;
00598       }
00599       child = child->GetNextNode();
00600    }
00601 
00602    return inputData;
00603 }
00604 
00605 void SCycleBaseConfig::InitializeUserConfig( TXMLNode* node ) throw( SError ) {
00606 
00607    REPORT_VERBOSE( "Initializing the user configuration" );
00608 
00609    // Clear the configuration name cache:
00610    m_configuredPrefs.clear();
00611 
00612    TXMLNode* userNode = node->GetChildren();
00613    while( userNode != 0 ) {
00614 
00615       REPORT_VERBOSE( "Node name " << userNode->GetNodeName() << " has attrib "
00616                       << userNode->HasAttributes() );
00617 
00618       if( ! userNode->HasAttributes() ||
00619           ( userNode->GetNodeName() != TString( "Item" ) ) ) {
00620          userNode = userNode->GetNextNode();
00621          continue;
00622       }
00623 
00624       std::string name = "", stringValue = "";
00625       TListIter userAttributes( userNode->GetAttributes() );
00626       TXMLAttr* attribute = 0;
00627       while( ( attribute = dynamic_cast< TXMLAttr* >( userAttributes() ) ) != 0 ) {
00628          if( attribute->GetName() == TString( "Name" ) )
00629             name = attribute->GetValue();
00630          if( attribute->GetName() == TString( "Value" ) )
00631             stringValue = DecodeEnvVar( attribute->GetValue() );
00632       }
00633       m_logger << DEBUG << "Found user property with name \"" << name
00634                << "\" and value \"" << stringValue << "\"" << SLogger::endmsg;
00635 
00636       this->SetProperty( name, stringValue );
00637 
00638       userNode = userNode->GetNextNode();
00639    }
00640 
00641    // Add all user properties to the SCycleConfig object, not just the ones
00642    // which have been set explicitly in the XML file:
00643    AddUserOptions( m_stringPrefs );
00644    AddUserOptions( m_intPrefs );
00645    AddUserOptions( m_doublePrefs );
00646    AddUserOptions( m_boolPrefs );
00647    AddUserOptions( m_stringListPrefs );
00648    AddUserOptions( m_intListPrefs );
00649    AddUserOptions( m_doubleListPrefs );
00650    AddUserOptions( m_boolListPrefs );
00651 
00652    return;
00653 }
00654 
00655 void SCycleBaseConfig::
00656 SetProperty( const std::string& name,
00657              const std::string& stringValue ) throw( SError ) {
00658 
00659    // Check if the user is specifying the same property multiple times.
00660    // XML doesn't guarantee in which order the properties are getting
00661    // read, so print explicitly what's happening.
00662    if( ! m_configuredPrefs.insert( name ).second ) {
00663       m_logger << WARNING << "Property \"" << name
00664                << "\" is getting set multiple times" << SLogger::endmsg;
00665       m_logger << WARNING << "Now taking value: " << stringValue
00666                << SLogger::endmsg;
00667    }
00668 
00669    // If it's a string property:
00670    if( m_stringPrefs.find( name ) != m_stringPrefs.end() ) {
00671       ( *m_stringPrefs[ name ] ) = stringValue;
00672    }
00673    // If it's an integer property:
00674    else if( m_intPrefs.find( name ) != m_intPrefs.end() ) {
00675       int value = atoi( stringValue.c_str() );
00676       ( *m_intPrefs[ name ] ) = value;
00677    }
00678    // If it's a double property:
00679    else if( m_doublePrefs.find( name ) != m_doublePrefs.end() ) {
00680       double value = atof( stringValue.c_str() );
00681       ( *m_doublePrefs[ name ] ) = value;
00682    }
00683    // If it's a boolean property:
00684    else if( m_boolPrefs.find( name ) != m_boolPrefs.end() ) {
00685       ( *m_boolPrefs[ name ] ) = ToBool( stringValue );
00686    }
00687    // If it's a string list property:
00688    else if( m_stringListPrefs.find( name ) != m_stringListPrefs.end() ) {
00689       m_stringListPrefs[ name ]->clear();
00690       std::istringstream stream( stringValue );
00691       while( ! stream.eof() && ( stringValue != "" ) ) {
00692          std::string value;
00693          stream >> value;
00694          m_stringListPrefs[ name ]->push_back( value );
00695       }
00696    }
00697    // If it's an integer list property:
00698    else if( m_intListPrefs.find( name ) != m_intListPrefs.end() ) {
00699       m_intListPrefs[ name ]->clear();
00700       std::istringstream stream( stringValue );
00701       while( ! stream.eof() && ( stringValue != "" ) ) {
00702          int value;
00703          stream >> value;
00704          m_intListPrefs[ name ]->push_back( value );
00705       }
00706    }
00707    // If it's a double list property:
00708    else if( m_doubleListPrefs.find( name ) != m_doubleListPrefs.end() ) {
00709       m_doubleListPrefs[ name ]->clear();
00710       std::istringstream stream( stringValue );
00711       while( ! stream.eof() && ( stringValue != "" ) ) {
00712          double value;
00713          stream >> value;
00714          m_doubleListPrefs[ name ]->push_back( value );
00715       }
00716    }
00717    // If it's a boolean list property:
00718    else if( m_boolListPrefs.find( name ) != m_boolListPrefs.end() ) {
00719       m_boolListPrefs[ name ]->clear();
00720       std::istringstream stream( stringValue );
00721       while( ! stream.eof() && ( stringValue != "" ) ) {
00722          std::string value;
00723          stream >> value;
00724          m_boolListPrefs[ name ]->push_back( ToBool( value ) );
00725       }
00726    }
00727    // If it hasn't been requested by the analysis cycle, issue a warning.
00728    // It might mean a typo somewhere...
00729    else {
00730       m_logger << WARNING << "User property not found: " << name << std::endl
00731                << "  Value not set!" << SLogger::endmsg;
00732    }
00733 
00734    return;
00735 }
00736 
00749 std::string SCycleBaseConfig::DecodeEnvVar( const std::string& value ) const { 
00750 
00751    // If the string doesn't begin with ":exp:", then do nothing:
00752    if( value.find( ":exp:" ) != 0 ) {
00753       return value;
00754    }
00755 
00756    // TSystem operates on TString objects. Note that we remove the ":exp:" from
00757    // the beginning of the string here:
00758    TString result( value.substr( 5, value.npos ) );
00759 
00760    // Let TSystem do the expansion:
00761    if( gSystem->ExpandPathName( result ) ) {
00762       REPORT_ERROR( "Failed 'expanding' property: " << value );
00763       return value;
00764    }
00765 
00766    return result.Data(); 
00767 } 
00768 
00773 bool SCycleBaseConfig::ToBool( const std::string& value ) throw( SError ) {
00774 
00775    TString tvalue( value );
00776    if( tvalue.IsAlpha() ) {
00777       if( tvalue.Contains( "true", TString::kIgnoreCase ) ) {
00778          return true;
00779       } else if( tvalue.Contains( "false", TString::kIgnoreCase ) ) {
00780          return false;
00781       }
00782    } else if( tvalue.IsDigit() ) {
00783       return tvalue.Atoi();
00784    }
00785 
00786    SError error( SError::SkipCycle );
00787    error << "Can't translate \"" << value << "\" to boolean";
00788    throw error;
00789 
00790    return false;
00791 }
00792 
00803 template< typename T >
00804 void SCycleBaseConfig::
00805 AddUserOptions( const std::map< const std::string, T* >& prefs ) {
00806 
00807    // Iterate over all properties of this type:
00808    typename std::map< const std::string, T* >::const_iterator itr =
00809       prefs.begin();
00810    typename std::map< const std::string, T* >::const_iterator end =
00811       prefs.end();
00812    for( ; itr != end; ++itr ) {
00813       // Translate the property value to a string:
00814       std::ostringstream value;
00815       value << *( itr->second );
00816       // Set the property:
00817       m_config.SetProperty( itr->first, value.str() );
00818    }
00819 
00820    return;
00821 }