| # 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