Gaudi Framework, version v20r3

Generated: 24 Nov 2008

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

Generated at Mon Nov 24 14:38:47 2008 for Gaudi Framework, version v20r3 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004