CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/src/Fireworks/Core/src/FWConfigurationManager.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Core
00004 // Class  :     FWConfigurationManager
00005 //
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Sun Feb 24 14:42:32 EST 2008
00011 // $Id: FWConfigurationManager.cc,v 1.16 2011/02/22 18:37:31 amraktad Exp $
00012 //
00013 
00014 // system include files
00015 #include <fstream>
00016 #include <iostream>
00017 #include <memory>
00018 #include <stdexcept>
00019 #include "TROOT.h"
00020 
00021 // user include files
00022 #include "Fireworks/Core/interface/FWConfigurationManager.h"
00023 #include "Fireworks/Core/interface/FWConfiguration.h"
00024 #include "Fireworks/Core/interface/FWConfigurable.h"
00025 #include "Fireworks/Core/interface/fwLog.h"
00026 #include "Fireworks/Core/src/SimpleSAXParser.h"
00027 
00028 //
00029 // constants, enums and typedefs
00030 //
00031 
00032 //
00033 // static data member definitions
00034 //
00035 
00036 //
00037 // constructors and destructor
00038 //
00039 FWConfigurationManager::FWConfigurationManager()
00040 {
00041 }
00042 
00043 // FWConfigurationManager::FWConfigurationManager(const FWConfigurationManager& rhs)
00044 // {
00045 //    // do actual copying here;
00046 // }
00047 
00048 FWConfigurationManager::~FWConfigurationManager()
00049 {
00050 }
00051 
00052 //
00053 // assignment operators
00054 //
00055 // const FWConfigurationManager& FWConfigurationManager::operator=(const FWConfigurationManager& rhs)
00056 // {
00057 //   //An exception safe implementation is
00058 //   FWConfigurationManager temp(rhs);
00059 //   swap(rhs);
00060 //
00061 //   return *this;
00062 // }
00063 
00064 //
00065 // member functions
00066 //
00067 void
00068 FWConfigurationManager::add(const std::string& iName, FWConfigurable* iConf)
00069 {
00070    assert(0!=iConf);
00071    m_configurables[iName]=iConf;
00072 }
00073 
00074 //
00075 // const member functions
00076 //
00077 void
00078 FWConfigurationManager::setFrom(const FWConfiguration& iConfig) const
00079 {
00080    assert(0!=iConfig.keyValues());
00081    for(FWConfiguration::KeyValues::const_iterator it = iConfig.keyValues()->begin(),
00082                                                   itEnd = iConfig.keyValues()->end();
00083        it != itEnd;
00084        ++it) {
00085       std::map<std::string,FWConfigurable*>::const_iterator itFound = m_configurables.find(it->first);
00086       assert(itFound != m_configurables.end());
00087       itFound->second->setFrom(it->second);
00088    }
00089 }
00090 
00091 void
00092 FWConfigurationManager::to(FWConfiguration& oConfig) const
00093 {
00094    FWConfiguration config;
00095    for(std::map<std::string,FWConfigurable*>::const_iterator it = m_configurables.begin(),
00096                                                              itEnd = m_configurables.end();
00097        it != itEnd;
00098        ++it) {
00099       it->second->addTo(config);
00100       oConfig.addKeyValue(it->first, config, true);
00101    }
00102 }
00103 
00104 
00105 void
00106 FWConfigurationManager::writeToFile(const std::string& iName) const
00107 {
00108    try
00109    {
00110       ofstream file(iName.c_str());
00111       if(not file) {
00112          std::string message("unable to open file %s ", iName.c_str());
00113          fflush(stdout);
00114          message += iName;
00115          throw std::runtime_error(message.c_str());
00116       }
00117       FWConfiguration top;
00118       to(top);
00119       fwLog(fwlog::kInfo) << "Writing to file "<< iName.c_str() << "...\n";
00120       fflush(stdout);
00121 
00122       streamTo(file, top, "top");
00123    }
00124    catch (std::runtime_error &e) { std::cout << e.what() << std::endl; }
00125 }
00126 
00127 void
00128 FWConfigurationManager::readFromOldFile(const std::string& iName) const
00129 {
00130    Int_t error=0;
00131    // Int_t value =
00132    gROOT->LoadMacro( iName.c_str(), &error );
00133    if(0 != error) {
00134       std::string message("unable to load macro file ");
00135       message += iName;
00136       throw std::runtime_error(message.c_str());
00137    }
00138 
00139    const std::string command("(Long_t)(fwConfig() )");
00140 
00141    error = 0;
00142    Long_t lConfig = gROOT->ProcessLineFast(command.c_str(),
00143                                            &error);
00144 
00145    {
00146       //need to unload this macro so that we can load a new configuration
00147       // which uses the same function name in the macro
00148       Int_t error = 0;
00149       gROOT->ProcessLineSync((std::string(".U ")+iName).c_str(), &error);
00150    }
00151    if(0 != error) {
00152       std::string message("unable to properly parse configuration file ");
00153       message += iName;
00154       throw std::runtime_error(message.c_str());
00155    }
00156    std::auto_ptr<FWConfiguration> config( reinterpret_cast<FWConfiguration*>(lConfig) );
00157 
00158    setFrom( *config);
00159 }
00160 
00161 void
00162 debug_config_state_machine(const char *where, const std::string &tag, int state)
00163 {
00164 #ifdef FW_CONFIG_PARSER_DEBUG
00165   static char *debug_states[] = {
00166      "IN_BEGIN_DOCUMENT",
00167      "IN_PUSHED_CONFIG",
00168      "IN_POPPED_CONFIG",
00169      "IN_BEGIN_STRING",
00170      "IN_STORED_STRING"
00171    };
00172 
00173   std::cerr << "  " << where << " tag/data " << tag << "in state " << debug_states[state] << std::endl;
00174 #endif
00175 }
00176 
00200 class FWXMLConfigParser : public SimpleSAXParser
00201 {
00202    enum STATES {
00203         IN_BEGIN_DOCUMENT,
00204         IN_PUSHED_CONFIG,
00205         IN_POPPED_CONFIG,
00206         IN_BEGIN_STRING,
00207         IN_STORED_STRING
00208       };
00209 
00210 public:
00211    FWXMLConfigParser(istream &f) 
00212    : SimpleSAXParser(f),
00213      m_state(IN_BEGIN_DOCUMENT),
00214      m_first(0)
00215    {}
00216 
00218    void pushConfig(Attributes &attributes)
00219    {
00220       std::string name;
00221       int version = 0;
00222       for (size_t i = 0, e = attributes.size(); i != e; ++i)
00223       {
00224          Attribute &attr = attributes[i];
00225          if (attr.key == "name")
00226             name = attr.value;
00227          else if (attr.key == "version")
00228          {
00229            char *endptr;
00230            version = strtol(attr.value.c_str(), &endptr, 10);
00231            if (endptr == attr.value.c_str())
00232              throw ParserError("Version must be an integer.");
00233          }
00234          else
00235             throw ParserError("Unexpected attribute " + attr.key);
00236       }
00237       m_configs.push_back(std::make_pair(name, new FWConfiguration(version)));
00238    }
00239    
00240    
00244    virtual void startElement(const std::string &tag, Attributes &attributes)
00245    {
00246       debug_config_state_machine("start", tag, m_state);
00247       if (m_state == IN_BEGIN_DOCUMENT)
00248       {
00249          if (tag != "config")
00250             throw ParserError("Expecting toplevel <config> tag");
00251          pushConfig(attributes);
00252          m_first.reset(m_configs.back().second);
00253          m_state = IN_PUSHED_CONFIG;
00254       }
00255       else if (m_state == IN_PUSHED_CONFIG)
00256       {
00257          if (tag == "config")
00258             pushConfig(attributes);
00259          else if (tag == "string")
00260             m_state = IN_BEGIN_STRING;
00261          else
00262             throw ParserError("Unexpected element " + tag);
00263       }
00264       else if (m_state == IN_POPPED_CONFIG)
00265       {
00266          if (tag != "config")
00267             throw ParserError("Unexpected element " + tag);
00268          pushConfig(attributes);
00269          m_state = IN_PUSHED_CONFIG;
00270       }
00271       else
00272          throw ParserError("Wrong opening tag found " + tag);
00273    }
00274 
00283    virtual void endElement(const std::string &tag)
00284    {
00285       debug_config_state_machine("end", tag, m_state);
00286       if (m_state == IN_PUSHED_CONFIG || m_state == IN_POPPED_CONFIG)
00287       {
00288          if (tag != "config")
00289             throw ParserError("Wrong closing tag found " + tag);
00290          
00291          FWConfiguration *current = m_configs.back().second;
00292          std::string key = m_configs.back().first;
00293          m_configs.pop_back();
00294          if (!m_configs.empty())
00295             m_configs.back().second->addKeyValue(key, *current);
00296          m_state = IN_POPPED_CONFIG;
00297       }
00298       else if (m_state == IN_BEGIN_STRING && tag == "string")
00299       {
00300          m_configs.back().second->addValue("");
00301          m_state = IN_PUSHED_CONFIG;
00302       }       
00303       else if (m_state == IN_STORED_STRING && tag == "string")
00304          m_state = IN_PUSHED_CONFIG;
00305       else
00306          throw ParserError("Wrong closing tag found " + tag);
00307    }
00308 
00314    virtual void data(const std::string &data)
00315    {
00316       debug_config_state_machine("data", data, m_state);
00317       // We ignore whitespace but complain about any text which is not 
00318       // in the <string> tag.
00319       if (m_state == IN_BEGIN_STRING)
00320       {
00321          m_configs.back().second->addValue(data);
00322          m_state = IN_STORED_STRING;
00323       }
00324       else if (strspn(data.c_str(), " \t\n") != data.size())
00325          throw ParserError("Unexpected text " + data);
00326    }
00327    
00331    FWConfiguration *config(void)
00332    {
00333       return m_first.get();
00334    }
00335    
00336 private:
00337    std::vector<std::pair<std::string, FWConfiguration *> > m_configs;
00338    enum STATES                                             m_state;
00339    std::auto_ptr<FWConfiguration>                          m_first;
00340    //   unsigned int                                            m_currentConfigVersion;
00341    std::string                                             m_currentConfigName;
00342 };
00343 
00350 void
00351 FWConfigurationManager::readFromFile(const std::string& iName) const
00352 {
00353    std::ifstream f(iName.c_str());
00354    if (f.peek() != (int) '<')
00355       return readFromOldFile(iName);
00356    
00357    // Check that the syntax is correct.
00358    SimpleSAXParser syntaxTest(f);
00359    syntaxTest.parse();
00360    f.close();
00361    
00362    // Read again, this time actually parse.
00363    std::ifstream g(iName.c_str());
00364    // Actually parse the results.
00365    FWXMLConfigParser parser(g);
00366    parser.parse();
00367    setFrom(*parser.config());
00368 }
00369 
00370 //
00371 // static member functions
00372 //