Gaudi Framework, version v20r4

Generated: 8 Jan 2009

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

Generated at Thu Jan 8 17:44:22 2009 for Gaudi Framework, version v20r4 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004