Gaudi Framework, version v21r8

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

Generated at Wed Mar 17 18:06:36 2010 for Gaudi Framework, version v21r8 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004