| # Gaudi Framework, version v20r2
Generated: 18 Jul 2008

- Main Page
- Namespaces
- Classes
- Files
- Directories
- Related Pages

- Search for |

- File List
- File Members

# genconf.cpp

Go to the documentation of this file.

    00001 //$Id: genconf.cpp,v 1.33 2008/04/03 17:56:40 marcocle Exp $    //
    00002
    00003 #ifdef _WIN32
    00004 // Disable a warning in Boost program_options headers:
    00005 // inconsistent linkage in program_options/variables_map.hpp
    00006 #pragma warning ( disable : 4273 )
    00007
    00008 // Avoid conflicts between windows and the message service.
    00009 #define NOMSG
    00010 #define NOGDI
    00011 #endif
    00012
    00013 // Include files----------------------------------------------------------------
    00014 #include "boost/program_options.hpp"
    00015 #include "boost/filesystem/operations.hpp"
    00016 #include "boost/filesystem/exception.hpp"
    00017 #include "boost/filesystem/convenience.hpp"
    00018 #include "boost/algorithm/string/split.hpp"
    00019 #include "boost/algorithm/string/classification.hpp"
    00020 #include "boost/algorithm/string/trim.hpp"
    00021 #include "boost/algorithm/string/case_conv.hpp"
    00022 #include "boost/format.hpp"
    00023
    00024 #include "GaudiKernel/System.h"
    00025 #include "GaudiKernel/ISvcLocator.h"
    00026 #include "GaudiKernel/IProperty.h"
    00027 #include "GaudiKernel/IAppMgrUI.h"
    00028 #include "GaudiKernel/IAlgorithm.h"
    00029 #include "GaudiKernel/IAlgTool.h"
    00030 #include "GaudiKernel/IAuditor.h"
    00031 #include "GaudiKernel/IAppMgrUI.h"
    00032 #include "GaudiKernel/Service.h"
    00033 #include "GaudiKernel/Bootstrap.h"
    00034 #include "GaudiKernel/SmartIF.h"
    00035 #include "GaudiKernel/HashMap.h"
    00036 #include "GaudiKernel/GaudiHandle.h"
    00037
    00038 #include "Reflex/PluginService.h"
    00039 #include "Reflex/Reflex.h"
    00040 #include "Reflex/SharedLibrary.h"
    00041
    00042 #include <algorithm>
    00043 #include <iostream>
    00044 #include <fstream>
    00045 #include <sstream>
    00046 #include <exception>
    00047 #include <ctime>
    00048 #include <set>
    00049 #include <vector>
    00050
    00051
    00052 #include "DsoUtils.h"
    00053
    00054
    00055
    00056 namespace po = boost::program_options;
    00057 namespace fs = boost::filesystem;
    00058
    00059 using namespace std;
    00060 using namespace ROOT::Reflex;
    00061
    00062 // useful typedefs
    00063 typedef std::vector<std::string> Strings_t;
    00064 typedef std::vector<fs::path>    LibPathNames_t;
    00065
    00066 namespace {
    00067   const std::string py_tab = "    ";
    00068 }
    00069
    00070 class configGenerator
    00071 {
    00073   string  m_pkgName;
    00074
    00077   string m_outputDirName;
    00078
    00080   stringstream m_pyBuf;
    00081
    00084   bool    m_importGaudiHandles;
    00085
    00090   stringstream m_dbBuf;
    00091
    00097   GaudiUtils::HashMap<std::string, std::string> m_configurable;
    00098
    00099 public:
    00100   configGenerator( const string& pkgName,
    00101                    const string& outputDirName ) :
    00102     m_pkgName           ( pkgName ),
    00103     m_outputDirName     ( outputDirName ),
    00104     m_pyBuf             ( ),
    00105     m_importGaudiHandles( false ),
    00106     m_dbBuf             ( ),
    00107     m_configurable      ( )
    00108   {}
    00109
    00114   int genConfig( const Strings_t& modules );
    00115
    00117   void setConfigurableModule( const std::string& moduleName )
    00118   {
    00119     m_configurable[ "Module" ] = moduleName;
    00120   }
    00121
    00123   void setConfigurableDefaultName( const std::string& defaultName )
    00124   {
    00125     m_configurable[ "DefaultName" ] = defaultName;
    00126   }
    00127
    00129   void setConfigurableAlgorithm( const std::string& cfgAlgorithm )
    00130   {
    00131     m_configurable[ "Algorithm" ] = cfgAlgorithm;
    00132   }
    00133
    00135   void setConfigurableAlgTool( const std::string& cfgAlgTool )
    00136   {
    00137     m_configurable[ "AlgTool" ] = cfgAlgTool;
    00138   }
    00139
    00141   void setConfigurableAuditor( const std::string& cfgAuditor )
    00142   {
    00143     m_configurable[ "Auditor" ] = cfgAuditor;
    00144   }
    00145
    00147   void setConfigurableService( const std::string& cfgService )
    00148   {
    00149     m_configurable[ "Service" ] = cfgService;
    00150     m_configurable[ "ApplicationMgr" ] = cfgService;
    00151   }
    00152
    00153 private:
    00154   void genComponent( const std::string& libName,
    00155                      const std::string& componentName,
    00156                      const std::string& componentType,
    00157                      const vector<Property*>& properties );
    00158   void genImport( std::ostream& s, const boost::format& frmt,std::string indent);
    00159   void genHeader( std::ostream& pyOut, std::ostream& dbOut );
    00160   void genBody( std::ostream& pyOut,
    00161                 std::ostream& dbOut ) {
    00162     pyOut << m_pyBuf.str() << flush;
    00163     dbOut << m_dbBuf.str() << flush;
    00164   }
    00165   void genTrailer( std::ostream& pyOut,
    00166                    std::ostream& dbOut );
    00167
    00169   void pythonizeValue( const Property* prop,
    00170                        string& pvalue,
    00171                        string& ptype );
    00172
    00174   void pythonizeName( string& name );
    00175 };
    00176
    00177 int createAppMgr();
    00178
    00179 //--- Command main program-----------------------------------------------------
    00180 int main ( int argc, char** argv )
    00181 //-----------------------------------------------------------------------------
    00182 {
    00183   fs::path::default_name_check(fs::native);
    00184   fs::path pwd = fs::initial_path();
    00185   fs::path out;
    00186   Strings_t libs;
    00187   std::string pkgName;
    00188
    00189   // declare a group of options that will be allowed only on command line
    00190   po::options_description generic("Generic options");
    00191   generic.add_options()
    00192     ("help,h",
    00193      "produce this help message")
    00194     ("package-name,p",
    00195      po::value<string>(),
    00196      "name of the package for which we create the configurables file")
    00197     ("input-libraries,i",
    00198      po::value<string>(),
    00199      "libraries to extract the component configurables from")
    00200     ("input-cfg,c",
    00201      po::value<string>(),
    00202      "path to the cfg file holding the description of the Configurable base "
    00203      "classes, the python module holding the Configurable definitions, etc...")
    00204     ("output-dir,o",
    00205      po::value<string>()->default_value("../genConf"),
    00206      "output directory for genconf files.")
    00207     ("debug-level,d",
    00208      po::value<int>()->default_value(0),
    00209      "debug level")
    00210     ("load-library,l",
    00211      po::value< Strings_t >()->composing(),
    00212      "preloading library")
    00213     ;
    00214
    00215   // declare a group of options that will be allowed both on command line
    00216   // _and_ in configuration file
    00217   po::options_description config("Configuration");
    00218   config.add_options()
    00219     ("configurable-module",
    00220      po::value<string>()->default_value("AthenaCommon"),
    00221      "Name of the module holding the configurable classes")
    00222     ("configurable-default-name",
    00223      po::value<string>()->default_value("Configurable.DefaultName"),
    00224      "Default name for the configurable instance")
    00225     ("configurable-algorithm",
    00226      po::value<string>()->default_value("ConfigurableAlgorithm"),
    00227      "Name of the configurable base class for Algorithm components")
    00228     ("configurable-algtool",
    00229      po::value<string>()->default_value("ConfigurableAlgTool"),
    00230      "Name of the configurable base class for AlgTool components")
    00231     ("configurable-auditor",
    00232      po::value<string>()->default_value("ConfigurableAuditor"),
    00233      "Name of the configurable base class for Auditor components")
    00234     ("configurable-service",
    00235      po::value<string>()->default_value("ConfigurableService"),
    00236      "Name of the configurable base class for Service components")
    00237     ;
    00238
    00239   po::options_description cmdline_options;
    00240   cmdline_options.add(generic).add(config);
    00241
    00242   po::options_description config_file_options;
    00243   config_file_options.add(config);
    00244
    00245   po::options_description visible("Allowed options");
    00246   visible.add(generic).add(config);
    00247
    00248   po::variables_map vm;
    00249
    00250   try {
    00251     po::store( po::command_line_parser(argc, argv).
    00252                options(cmdline_options).run(),
    00253                vm );
    00254
    00255     po::notify(vm);
    00256
    00257     // try to read configuration from the optionnally given configuration file
    00258     if( vm.count("input-cfg") ) {
    00259       string cfgFileName = vm["input-cfg"].as<string>();
    00260       cfgFileName = fs::complete( fs::path( cfgFileName,
    00261                                             fs::native ) ).string();
    00262       std::ifstream ifs( cfgFileName.c_str() );
    00263       po::store( parse_config_file( ifs, config_file_options ), vm );
    00264     }
    00265
    00266     po::notify(vm);
    00267   }
    00268   catch ( po::error& err ) {
    00269     cout << "ERR0R: error detected while parsing command options: "<< err.what() << endl;
    00270     return EXIT_FAILURE;
    00271   }
    00272
    00273   //--- Process command options -----------------------------------------------
    00274   if( vm.count("help")) {
    00275     cout << visible << endl;
    00276     return EXIT_FAILURE;
    00277   }
    00278
    00279   if( vm.count("package-name") ) {
    00280     pkgName = vm["package-name"].as<string>();
    00281   }
    00282   else {
    00283     cout << "ERROR: 'package-name' required" << endl;
    00284     cout << visible << endl;
    00285     return EXIT_FAILURE;
    00286   }
    00287
    00288   if( vm.count("input-libraries") ) {
    00289     // re-shape the input arguments:
    00290     //  - removes spurious spaces,
    00291     //  - split into tokens.
    00292     Strings_t inputLibs;
    00293     {
    00294       string tmp = vm["input-libraries"].as<string>();
    00295       boost::trim(tmp);
    00296       boost::split( inputLibs, tmp,
    00297                     boost::is_any_of(" "),
    00298                     boost::token_compress_on );
    00299     }
    00300
    00301     //
    00302     libs.reserve( inputLibs.size() );
    00303     for ( Strings_t::const_iterator iLib = inputLibs.begin();
    00304           iLib != inputLibs.end();
    00305           ++iLib ) {
    00306       fs::path libPath = fs::path( *iLib, fs::native );
    00307       std::string lib = libPath.leaf().substr(0, libPath.leaf().find('.') );
    00308       if ( 0 == lib.find("lib") ) {
    00309         lib = lib.substr(3); // For *NIX remove "lib"
    00310       }
    00311       // remove duplicates
    00312       if ( !lib.empty() &&
    00313           std::find( libs.begin(), libs.end(), lib ) == libs.end() ) {
    00314         libs.push_back( lib );
    00315       }
    00316     } //> end loop over input-libraries
    00317     if ( libs.empty() ) {
    00318       cout << "ERROR: input component library(ies) required !\n"
    00319            << "ERROR: 'input-libraries' argument was ["
    00320            << vm["input-libraries"].as<string>()
    00321            << "]"
    00322            << endl;
    00323       return EXIT_FAILURE;
    00324     }
    00325   }
    00326   else {
    00327     cout << "ERROR: input component library(ies) required" << endl;
    00328     cout << visible << endl;
    00329     return EXIT_FAILURE;
    00330   }
    00331
    00332   if( vm.count("output-dir") ) {
    00333     out = fs::complete( fs::path( vm["output-dir"].as<string>(),
    00334                                   fs::native ) );
    00335   }
    00336
    00337   if ( vm.count("debug-level") ) {
    00338     PluginService::SetDebug( vm["debug-level"].as<int>() );
    00339   }
    00340
    00341   if ( vm.count("load-library") ) {
    00342     Strings_t lLib_list = vm["load-library"].as< Strings_t >();
    00343     for (Strings_t::const_iterator lLib=lLib_list.begin();
    00344          lLib != lLib_list.end();
    00345          ++lLib) {
    00346       // load done through ROOT::Reflex helper class
    00347       SharedLibrary tmplib(*lLib) ;
    00348       tmplib.Load() ;
    00349     }
    00350   }
    00351
    00352
    00353   if ( !fs::exists( out ) ) {
    00354     try {
    00355       fs::create_directory(out);
    00356     }
    00357     catch ( fs::filesystem_error err ) {
    00358       cout << "ERR0R: error creating directory: "<< err.what() << endl;
    00359       return EXIT_FAILURE;
    00360     }
    00361   }
    00362
    00363   cout << ":::::: libraries : [ ";
    00364   copy( libs.begin(), libs.end(), ostream_iterator<string>(cout, " ") );
    00365   cout << "] ::::::" << endl;
    00366
    00367   configGenerator py( pkgName, out.string() );
    00368   py.setConfigurableModule     (vm["configurable-module"].as<string>());
    00369   py.setConfigurableDefaultName(vm["configurable-default-name"].as<string>());
    00370   py.setConfigurableAlgorithm  (vm["configurable-algorithm"].as<string>());
    00371   py.setConfigurableAlgTool    (vm["configurable-algtool"].as<string>());
    00372   py.setConfigurableAuditor    (vm["configurable-auditor"].as<string>());
    00373   py.setConfigurableService    (vm["configurable-service"].as<string>());
    00374
    00375   int sc = EXIT_FAILURE;
    00376   try {
    00377     sc = py.genConfig( libs );
    00378   }
    00379   catch ( exception& e ) {
    00380     cout << "ERROR: Could not generate Configurable(s) !\n"
    00381          << "ERROR: Got exception: " << e.what() << endl;
    00382     return EXIT_FAILURE;
    00383   }
    00384
    00385   if ( EXIT_SUCCESS == sc ) {
    00386     // create an empty __init__.py file in the output dir
    00387     fstream initPy( ( out / fs::path( "__init__.py" ) ).string().c_str(),
    00388         std::ios_base::out|std::ios_base::trunc );
    00389     initPy << "## Hook for " << pkgName << " genConf module\n" << flush;
    00390   }
    00391
    00392   cout << ":::::: libraries : [ ";
    00393   copy( libs.begin(), libs.end(), ostream_iterator<string>(cout, " ") );
    00394   cout << "] :::::: [DONE]" << endl;
    00395
    00396   return sc;
    00397 }
    00398
    00399 //-----------------------------------------------------------------------------
    00400 int configGenerator::genConfig( const Strings_t& libs )
    00401 //-----------------------------------------------------------------------------
    00402 {
    00403   //--- Disable checking StatusCode -------------------------------------------
    00404   StatusCode::disableChecking();
    00405
    00406   const Strings_t::const_iterator endLib = libs.end();
    00407
    00408   const std::string gaudiSvc = "GaudiSvc";
    00409   const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib );
    00410
    00411   //--- Instantiate ApplicationMgr --------------------------------------------
    00412   if ( !isGaudiSvc && createAppMgr() ) {
    00413     cout << "ERROR: ApplicationMgr can not be created. Check environment" << endl;
    00414     return EXIT_FAILURE;
    00415   }
    00416
    00417   //--- Iterate over component factories --------------------------------------
    00418   Scope factories = Scope::ByName(PLUGINSVC_FACTORY_NS);
    00419   if ( !factories ) {
    00420     cout << "ERROR: No PluginSvc factory namespace could be found" << endl;
    00421     return EXIT_FAILURE;
    00422   }
    00423
    00424   ISvcLocator* svcLoc = Gaudi::svcLocator();
    00425   IService*    dummySvc = new Service( "DummySvc", svcLoc );
    00426   dummySvc->addRef();
    00427
    00428   bool allGood = true;
    00429
    00430   // iterate over all the requested libraries
    00431   for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) {
    00432
    00433     std::cout << ":::: processing library: " << *iLib << "..." << std::endl;
    00434
    00435     // reset state
    00436     m_importGaudiHandles = false;
    00437     m_pyBuf.str("");
    00438     m_dbBuf.str("");
    00439
    00440     // Scan the pluginSvc namespace and store the "background" of already
    00441     // alived components, so we can extract our signal later on
    00442     set<string> bkgNames;
    00443     if ( !isGaudiSvc ) {
    00444       for ( Member_Iterator it = factories.FunctionMember_Begin();
    00445             it != factories.FunctionMember_End(); ++it ) {
    00446         string ident = it->Properties().PropertyAsString("name");
    00447         if ( PluginService::Debug() > 0 ) {
    00448           cout << "::: " << ident << endl;
    00449         }
    00450         bkgNames.insert( ident );
    00451       }
    00452     }
    00453     const set<string>::const_iterator bkgNamesEnd = bkgNames.end();
    00454
    00455     //--- Load component library ----------------------------------------------
    00456     System::ImageHandle handle;
    00457     unsigned long err = System::loadDynamicLib( *iLib, &handle );
    00458     if ( err != 1 ) {
    00459       cout << "ERROR: " << System::getLastErrorString() << endl;
    00460       allGood = false;
    00461       continue;
    00462     }
    00463
    00464     for ( Member_Iterator it = factories.FunctionMember_Begin();
    00465           it != factories.FunctionMember_End();
    00466           ++it ) {
    00467       const string ident = it->Properties().PropertyAsString("name");
    00468       if ( bkgNames.find(ident) != bkgNamesEnd ) {
    00469         if ( PluginService::Debug() > 0 ) {
    00470           cout << "\t==> skipping [" << ident << "]..." << endl;
    00471         }
    00472         continue;
    00473       }
    00474
    00475       // Atlas contributed code (patch #1247)
    00476       // Skip the generation of configurables if the component does not come
    00477       // from the same library we are processing (i.e. we found a symbol that
    00478       // is coming from a library loaded by the linker).
    00479       // Windows implementation is empty.
    00480       if ( !DsoUtils::inDso( *it, DsoUtils::libNativeName(*iLib) ) ) {
    00481         cout << "WARNING: library [" << *iLib << "] requested factory "
    00482         << "from another library ["
    00483         << DsoUtils::dsoName(*it) << "]"
    00484         << " ==> [" << ident << "] !!"
    00485         << endl;
    00486         continue;
    00487       }
    00488
    00489       const string rtype = it->TypeOf().ReturnType().Name();
    00490       string type;
    00491       bool known = true;
    00492       if      ( ident == "ApplicationMgr" ) type = "ApplicationMgr";
    00493       else if ( rtype == "IInterface*" )    type = "IInterface";
    00494       else if ( rtype == "IAlgorithm*" )    type = "Algorithm";
    00495       else if ( rtype == "IService*" )      type = "Service";
    00496       else if ( rtype == "IAlgTool*" )      type = "AlgTool";
    00497       else if ( rtype == "IAuditor*" )      type = "Auditor";
    00498       else if ( rtype == "IConverter*" )    type = "Converter";
    00499       else if ( rtype == "DataObject*" )    type = "DataObject";
    00500       else                                  type = "Unknown", known = false;
    00501       string name = ident;
    00502       // handle possible problems with templated components
    00503       boost::trim(name);
    00504
    00505       cout << " - component: " << name << endl;
    00506
    00507       if ( type == "IInterface" ) {
    00510         continue;
    00511       }
    00512
    00513       if ( type == "Converter" || type == "DataObject" ) {
    00515         continue;
    00516       }
    00517
    00518       //if ( type == "ApplicationMgr" ) {
    00521       //}
    00522
    00523       if ( !known ) {
    00524         cout << "WARNING: Unknown (return) type [" << rtype << "] !!\n"
    00525              << "WARNING: component [" << ident << "] is skipped !"
    00526              << endl;
    00527         allGood = false;
    00528         continue;
    00529       }
    00530
    00531       string cname = "DefaultName";
    00532       Object dummy;
    00533       vector<void*>  args;
    00534       args.reserve( 3 );
    00535       if ( type == "AlgTool" ) {
    00536         args.resize( 3 );
    00537         args[0] = &cname;
    00538         args[1] = &type;
    00539         args[2] = dummySvc;
    00540       }
    00541       else {
    00542         args.resize( 2 );
    00543         args[0] = &cname;
    00544         args[1] = svcLoc;
    00545       }
    00546       IProperty* prop = 0;
    00547       try {
    00548         if ( type == "Algorithm" ) {
    00549           IAlgorithm* obj = static_cast<IAlgorithm*>(it->Invoke(dummy,args).Address());
    00550           prop = dynamic_cast<IProperty*>(obj);
    00551         }
    00552         else if ( type == "Service") {
    00553           IService* obj = static_cast<IService*>(it->Invoke(dummy,args).Address());
    00554           prop = dynamic_cast<IProperty*>(obj);
    00555         }
    00556         else if ( type == "AlgTool") {
    00557           IAlgTool* obj = static_cast<IAlgTool*>(it->Invoke(dummy,args).Address());
    00558           prop = dynamic_cast<IProperty*>(obj);
    00559         }
    00560         else if ( type == "Auditor") {
    00561           IAuditor* obj = static_cast<IAuditor*>(it->Invoke(dummy,args).Address());
    00562           prop = dynamic_cast<IProperty*>(obj);
    00563         }
    00564         else if ( type == "ApplicationMgr") {
    00565           //svcLoc->queryInterface(IProperty::interfaceID(), pp_cast<void>(&prop));
    00566           svcLoc->queryInterface(IProperty::interfaceID(), (void**)(&prop));
    00567         }
    00568         else {
    00569           IInterface* obj = static_cast<IInterface*>(it->Invoke(dummy,args).Address());
    00570           prop = dynamic_cast<IProperty*>(obj);
    00571         }
    00572       }
    00573       catch ( exception& e ) {
    00574         cout << "ERROR: Error instantiating " << name
    00575              << " from " << *iLib << endl;
    00576         cout << "ERROR: Got exception: " << e.what() << endl;
    00577         allGood = false;
    00578         continue;
    00579       }
    00580       catch ( ... ) {
    00581         cout << "ERROR: Error instantiating " << name
    00582              << " from " << *iLib << endl;
    00583         allGood = false;
    00584         continue;
    00585       }
    00586       if( prop ) {
    00587         genComponent( *iLib, name, type, prop->getProperties() );
    00588         prop->release();
    00589       } else {
    00590         cout << "ERROR: could not cast IInterface* object to an IProperty* !\n"
    00591              << "ERROR: return type from PluginSvc is [" << rtype << "]...\n"
    00592              << "ERROR: NO Configurable will be generated for ["
    00593              << name << "] !"
    00594              << endl;
    00595         allGood = false;
    00596       }
    00597     } //> end loop over factories
    00598
    00602     const std::string pyName = ( fs::path(m_outputDirName) /
    00603                   fs::path(*iLib+"Conf.py") ).string();
    00604     const std::string dbName = ( fs::path(m_outputDirName) /
    00605                   fs::path(*iLib+"_confDb.py") ).string();
    00606
    00607     std::fstream py( pyName.c_str(),
    00608               std::ios_base::out|std::ios_base::trunc );
    00609     std::fstream db( dbName.c_str(),
    00610               std::ios_base::out|std::ios_base::trunc );
    00611
    00612     genHeader ( py, db );
    00613     genBody   ( py, db );
    00614     genTrailer( py, db );
    00615
    00616   } //> end loop over libraries
    00617
    00618   dummySvc->release();
    00619   dummySvc = 0;
    00620
    00621   return allGood ? EXIT_SUCCESS : EXIT_FAILURE;
    00622 }
    00623
    00624 void configGenerator::genImport( std::ostream& s,
    00625                                  const boost::format& frmt,
    00626                                  std::string indent = ""){
    00627
    00628   std::string::size_type pos = 0, nxtpos = 0;
    00629   std::string mod;
    00630
    00631   while ( std::string::npos != pos ){
    00632     // find end of module name
    00633     nxtpos = m_configurable["Module"].find_first_of(',',pos);
    00634
    00635     // Prepare import string
    00636     mod = m_configurable["Module"].substr(pos,nxtpos-pos);
    00637     std::ostringstream import;
    00638     import << boost::format(frmt) % mod;
    00639
    00640     // append a normal import or a try/excpet enclosed one depending
    00641     // on availability of a fall-back bodule (next in the list)
    00642     if ( std::string::npos == nxtpos ) {
    00643       // last possible module
    00644       s << indent << import.str() << "\n" << flush;
    00645       pos = std::string::npos;
    00646     } else {
    00647       // we have a fallback for this
    00648       s << indent << "try:\n"
    00649         << indent << py_tab << import.str() << "\n"
    00650         << indent << "except ImportError:\n"
    00651         << flush;
    00652       pos = nxtpos+1;
    00653     }
    00654     // increase indentation level for next iteration
    00655     indent += py_tab;
    00656   }
    00657 }
    00658
    00659 //-----------------------------------------------------------------------------
    00660 void configGenerator::genHeader( std::ostream& py,
    00661                                  std::ostream& db )
    00662 //-----------------------------------------------------------------------------
    00663 {
    00664   // python file part
    00665   time_t rawtime;
    00666   time( &rawtime );
    00667   py << "#" << ctime(&rawtime) //<< "\n"
    00668      << "\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
    00669   if ( m_importGaudiHandles ) {
    00670     py << "from GaudiKernel.GaudiHandles import *\n";
    00671   }
    00672
    00673   genImport(py,boost::format("from %1%.Configurable import *"));
    00674
    00675   // db file part
    00676   db << "##  -*- python -*-  \n"
    00677      << "# db file automatically generated by genconf on: "
    00678      << ctime(&rawtime); // << "\n";
    00679   db << "## insulates outside world against anything bad that could happen\n"
    00680      << "## also prevents global scope pollution\n"
    00681      << "def _fillCfgDb():\n";
    00682   genImport(db,boost::format("from %1%.ConfigurableDb import CfgDb"),py_tab);
    00683
    00684   db << "\n"
    00685      << py_tab << "# get a handle on the repository of Configurables\n"
    00686      << py_tab << "cfgDb = CfgDb()\n"
    00687      << "\n"
    00688      << py_tab << "# populate the repository with informations on Configurables \n"
    00689      << "\n"
    00690      << flush;
    00691 }
    00692 //-----------------------------------------------------------------------------
    00693 void configGenerator::genTrailer( std::ostream& /*py*/,
    00694                                   std::ostream& db )
    00695 //-----------------------------------------------------------------------------
    00696 {
    00697   // db file part
    00698   db << py_tab << "return #_fillCfgDb\n"
    00699      << "# fill cfgDb at module import...\n"
    00700      << "try:\n"
    00701      << py_tab << "_fillCfgDb()\n"
    00702      << py_tab << "#house cleaning...\n"
    00703      << py_tab << "del _fillCfgDb\n"
    00704      << "except Exception,err:\n"
    00705      << py_tab << "print \"Py:ConfigurableDb   ERROR Problem with [%s] content!"
    00706                << "\" % __name__\n"
    00707      << py_tab << "print \"Py:ConfigurableDb   ERROR\",err\n"
    00708      << py_tab << "print \"Py:ConfigurableDb   ERROR   ==> culprit is package ["
    00709                << m_pkgName << "] !\"\n"
    00710      << std::flush;
    00711 }
    00712
    00713 //-----------------------------------------------------------------------------
    00714 void configGenerator::genComponent( const std::string& libName,
    00715                                     const std::string& componentName,
    00716                                     const std::string& componentType,
    00717                                     const vector<Property*>& properties )
    00718 //-----------------------------------------------------------------------------
    00719 {
    00720   string cname = componentName;
    00721   pythonizeName(cname);
    00722
    00723   typedef GaudiUtils::HashMap<std::string, std::string> PropertyDoc_t;
    00724   PropertyDoc_t propDoc;
    00725
    00726   m_pyBuf << "\n";
    00727   m_pyBuf << "class " << cname
    00728           << "( " << m_configurable[componentType] << " ) :"
    00729           << "\n";
    00730   m_pyBuf << "  __slots__ = { \n";
    00731   for ( vector<Property*>::const_iterator it = properties.begin() ;
    00732         it != properties.end(); ++it ) {
    00733     const string pname  = (*it)->name();
    00734     string pvalue, ptype;
    00735     pythonizeValue( (*it), pvalue, ptype );
    00736     m_pyBuf << "    '" << pname << "' : " << pvalue <<", # " << ptype << "\n";
    00737
    00738     if ( (*it)->documentation() != "none" ) {
    00739       propDoc[pname] = (*it)->documentation();
    00740     }
    00741
    00742   }
    00743   m_pyBuf << "  }\n";
    00744   m_pyBuf << "  _propertyDocDct = { \n";
    00745   for ( PropertyDoc_t::const_iterator iProp = propDoc.begin();
    00746         iProp != propDoc.end();
    00747         ++iProp ) {
    00748     m_pyBuf << std::setw(5)
    00749             << "'"       << iProp->first  << "' : "
    00750             << "\"\"\" "  << iProp->second << " \"\"\",\n";
    00751   }
    00752   m_pyBuf << "  }\n";
    00753
    00754   m_pyBuf
    00755     << "  def __init__(self, name = " << m_configurable["DefaultName"]
    00756                                       << ", **kwargs):\n"
    00757     << "      super(" << cname << ", self).__init__(name)\n"
    00758     << "      for n,v in kwargs.items():\n"
    00759     << "         setattr(self, n, v)\n"
    00760     << "  def getDlls( self ):\n"
    00761     << "      return '" << libName << "'\n"
    00762     << "  def getType( self ):\n"
    00763     << "      return '" << componentName  << "'\n"
    00764     << "  pass # class " << cname << "\n"
    00765     << flush;
    00766
    00767   // name of the auto-generated module
    00768   const string pyName = ( fs::path(m_outputDirName) /
    00769                           fs::path(libName+"Conf.py") ).string();
    00770   const string modName = fs::basename( fs::path( pyName ).leaf() );
    00771
    00772   // now the db part
    00773   m_dbBuf
    00774     << py_tab << "cfgDb.add( configurable = '" << cname << "',\n"
    00775     << py_tab << "           package = '" << m_pkgName << "',\n"
    00776     << py_tab << "           module  = '" << m_pkgName << "." << modName << "',\n"
    00777     << py_tab << "           lib     = '" << libName << "' )\n"
    00778     << flush;
    00779
    00780 }
    00781 //-----------------------------------------------------------------------------
    00782 void configGenerator::pythonizeName( string& name )
    00783 //-----------------------------------------------------------------------------
    00784 {
    00785   static string  in("<>&*,: ().");
    00786   static string out("__rp__s___");
    00787   for ( string::iterator i = name.begin(); i != name.end(); ++i ) {
    00788     if ( in.find(*i) != string::npos ) *i = out[in.find(*i)];
    00789   }
    00790 }
    00791
    00792 //-----------------------------------------------------------------------------
    00793 void configGenerator::pythonizeValue( const Property* p,
    00794                                       string& pvalue, string& ptype )
    00795 //-----------------------------------------------------------------------------
    00796 {
    00797   const std::string cvalue = p->toString();
    00798   const type_info& ti = *p->type_info();
    00799   if ( ti == typeid(bool) ) {
    00800     pvalue = ( cvalue == "0" || cvalue == "False" || cvalue == "false" )
    00801            ? "False"
    00802            : "True";
    00803     ptype  = "bool";
    00804   }
    00805   else if ( ti == typeid(char)  || ti == typeid(signed char)
    00806             || ti == typeid(unsigned char)  ||
    00807             ti == typeid(short) || ti == typeid(unsigned short) ||
    00808             ti == typeid(int)   || ti == typeid(unsigned int)   ||
    00809             ti == typeid(long)  || ti == typeid(unsigned long) ) {
    00810     pvalue = cvalue;
    00811     ptype  = "int";
    00812   }
    00813   else if ( ti == typeid(long long) || ti == typeid(unsigned long long) ) {
    00814     pvalue = cvalue + "L";
    00815     ptype  = "long";
    00816   }
    00817   else if ( ti == typeid(float) || ti == typeid(double) ) {
    00818     // forces python to handle this as a float: put a dot in there...
    00819     pvalue = boost::to_lower_copy(cvalue);
    00820     if ( pvalue == "nan" ) {
    00821       pvalue = "float('nan')";
    00822       std::cout << "WARNING: default value for ["
    00823                 << p->name() << "] is NaN !!"
    00824                 << std::endl;
    00825     } else if ( std::string::npos == pvalue.find(".") &&
    00826                 std::string::npos == pvalue.find("e")  ) {
    00827       pvalue = cvalue + ".0";
    00828     }
    00829     ptype  = "float";
    00830   }
    00831   else if ( ti == typeid(string) ) {
    00832
    00833     pvalue = "'"+cvalue+"'";
    00834     ptype  = "str";
    00835   }
    00836   else if ( ti == typeid(GaudiHandleBase) ) {
    00837     m_importGaudiHandles = true;
    00838     const GaudiHandleProperty& hdl
    00839       = dynamic_cast<const GaudiHandleProperty&>(*p);
    00840     const GaudiHandleBase&     base = hdl.value();
    00841
    00842     pvalue = base.pythonRepr();
    00843     ptype  = "GaudiHandle";
    00844   }
    00845   else if ( ti == typeid(GaudiHandleArrayBase) ) {
    00846     m_importGaudiHandles = true;
    00847     const GaudiHandleArrayProperty& hdl
    00848       = dynamic_cast<const GaudiHandleArrayProperty&>(*p);
    00849     const GaudiHandleArrayBase&     base = hdl.value();
    00850
    00851     pvalue = base.pythonRepr();
    00852     ptype  = "GaudiHandleArray";
    00853   }
    00854   else {
    00855     pvalue = cvalue;
    00856     ptype  = "list";
    00857   }
    00858 }
    00859
    00860 //-----------------------------------------------------------------------------
    00861 int createAppMgr()
    00862 //-----------------------------------------------------------------------------
    00863 {
    00864   IInterface* iface = Gaudi::createApplicationMgr();
    00865   SmartIF<IProperty> propMgr ( IID_IProperty, iface );
    00866   SmartIF<IAppMgrUI> appUI  ( IID_IAppMgrUI, iface );
    00867
    00868   if ( propMgr.isValid() && appUI.isValid() ) {
    00869     propMgr->setProperty( "JobOptionsType", "NONE" );  // No joboptions
    00870     propMgr->setProperty( "AppName", "");              // No initial printout message
    00871     propMgr->setProperty( "OutputLevel", "7");         // No other printout messages
    00872     appUI->configure();
    00873     return EXIT_SUCCESS;
    00874   }
    00875   else {
    00876     return EXIT_FAILURE;
    00877   }
    00878 }