Gaudi Framework, version v22r2

Home   Generated: Tue May 10 2011

genconf.cpp

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

Generated at Tue May 10 2011 18:53:47 for Gaudi Framework, version v22r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004