Gaudi Framework, version v22r4

Home   Generated: Fri Sep 2 2011

genconf.cpp

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

Generated at Fri Sep 2 2011 16:24:45 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004