| # Gaudi Framework, version v21r9 |

Home |  | Generated: 3 May 2010

# genconf.cpp

Go to the documentation of this file.

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