CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/FWCore/ParameterSet/src/ConfigurationDescriptions.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     ParameterSet
00004 // Class  :     ConfigurationDescriptions
00005 // 
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  W. David Dagenhart
00010 //         Created:  17 December 2008
00011 //
00012 
00013 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00014 #include "FWCore/ParameterSet/interface/DocFormatHelper.h"
00015 #include "FWCore/Utilities/interface/Algorithms.h"
00016 #include "FWCore/Utilities/interface/EDMException.h"
00017 
00018 #include "boost/bind.hpp"
00019 
00020 #include <fstream>
00021 #include <iostream>
00022 #include <iomanip>
00023 #include <sstream>
00024 
00025 namespace {
00026   void matchLabel(std::pair<std::string, edm::ParameterSetDescription> const& thePair,
00027                   std::string const& moduleLabel,
00028                   edm::ParameterSetDescription const*& psetDesc) {
00029     if (thePair.first == moduleLabel) {
00030       psetDesc = &thePair.second;
00031     }
00032   }
00033 }         
00034 
00035 namespace edm {
00036 
00037   ConfigurationDescriptions::ConfigurationDescriptions(std::string const& baseType) :
00038     baseType_(baseType),
00039     defaultDescDefined_(false)
00040   { }
00041 
00042   ConfigurationDescriptions::~ConfigurationDescriptions() {} 
00043 
00044   void
00045   ConfigurationDescriptions::setComment(std::string const & value)
00046   { comment_ = value; }
00047 
00048   void
00049   ConfigurationDescriptions::setComment(char const* value)
00050   { comment_ = value; }
00051 
00052   void
00053   ConfigurationDescriptions::add(char const* label,
00054                                  ParameterSetDescription const& psetDescription) {
00055     std::string labelString(label);
00056     add(labelString, psetDescription);
00057   }
00058 
00059   void
00060   ConfigurationDescriptions::add(std::string const& label,
00061                                  ParameterSetDescription const& psetDescription) {
00062 
00063     if (baseType_ == std::string("Source")) {
00064       if (label != std::string("source")) {
00065         throw edm::Exception(edm::errors::LogicError,
00066           "ConfigurationDescriptions::add, when adding a ParameterSetDescription for a source the label must be \"source\"\n");
00067       }
00068       if (descriptions_.size() != 0U ||
00069           defaultDescDefined_ == true) {
00070         throw edm::Exception(edm::errors::LogicError,
00071           "ConfigurationDescriptions::add, for a source only 1 ParameterSetDescription may be added\n");
00072       }
00073     }
00074     else if (baseType_ == std::string("Service")) {
00075       if (descriptions_.size() != 0U ||
00076           defaultDescDefined_ == true) {
00077         throw edm::Exception(edm::errors::LogicError,
00078           "ConfigurationDescriptions::add, for a service only 1 ParameterSetDescription may be added\n");
00079       }
00080     }
00081 
00082     // To minimize the number of copies involved create an empty description first
00083     // and push it into the vector.  Then perform the copy.
00084     std::pair<std::string, ParameterSetDescription> pairWithEmptyDescription;
00085     descriptions_.push_back(pairWithEmptyDescription);
00086     std::pair<std::string, ParameterSetDescription> & pair = descriptions_.back();
00087 
00088     pair.first = label;
00089     pair.second = psetDescription;
00090   }
00091 
00092   void
00093   ConfigurationDescriptions::addDefault(ParameterSetDescription const& psetDescription) {
00094 
00095     if (baseType_ == std::string("Source") || baseType_ == std::string("Service")) {
00096       if (descriptions_.size() != 0U ||
00097           defaultDescDefined_ == true) {
00098         throw edm::Exception(edm::errors::LogicError,
00099           "ConfigurationDescriptions::addDefault, for a source or service only 1 ParameterSetDescription may be added\n");
00100       }
00101     }
00102 
00103     defaultDescDefined_ = true;
00104     defaultDesc_ = psetDescription;
00105   }
00106 
00107   void
00108   ConfigurationDescriptions::validate(ParameterSet & pset,
00109                                       std::string const& moduleLabel) const {
00110     
00111     ParameterSetDescription const* psetDesc = 0;
00112     for_all(descriptions_, boost::bind(&matchLabel,
00113                                        _1,
00114                                        boost::cref(moduleLabel),
00115                                        boost::ref(psetDesc)));
00116 
00117     // If there is a matching label
00118     if (psetDesc != 0) {
00119       psetDesc->validate(pset);
00120     }
00121     // Is there an explicit description to be used for a non standard label
00122     else if (defaultDescDefined_) {
00123       defaultDesc_.validate(pset);
00124     }
00125     // Otherwise use the first one.
00126     else if (descriptions_.size() > 0U) {
00127       descriptions_[0].second.validate(pset);
00128     }
00129     // It is possible for no descriptions to be defined and no validation occurs
00130     // for this module ever.
00131   }
00132 
00133   void
00134   ConfigurationDescriptions::writeCfis(std::string const& baseType,
00135                                        std::string const& pluginName) const {
00136 
00137     for_all(descriptions_, boost::bind(&ConfigurationDescriptions::writeCfiForLabel,
00138                                        _1,
00139                                        boost::cref(baseType),
00140                                        boost::cref(pluginName)));
00141   }
00142 
00143 
00144   void
00145   ConfigurationDescriptions::writeCfiForLabel(std::pair<std::string, ParameterSetDescription> const& labelAndDesc,
00146                                               std::string const& baseType,
00147                                               std::string const& pluginName)
00148   {
00149     if (baseType == std::string("Service") && labelAndDesc.first != pluginName) {
00150       throw edm::Exception(edm::errors::LogicError,
00151         "ConfigurationDescriptions::writeCfiForLabel\nFor a service the label and the plugin name must be the same.\n")
00152         << "This error probably is caused by an incorrect label being passed\nto the ConfigurationDescriptions::add function earlier.\n"
00153         << "plugin name = \"" << pluginName << "\"  label name = \"" << labelAndDesc.first << "\"\n";
00154     }
00155 
00156     std::string cfi_filename;
00157     if (baseType == std::string("Source")) {
00158       cfi_filename = pluginName + "_cfi.py";
00159     }
00160     else {
00161       cfi_filename = labelAndDesc.first + "_cfi.py";
00162     }
00163     std::ofstream outFile(cfi_filename.c_str());
00164 
00165 
00166     outFile << "import FWCore.ParameterSet.Config as cms\n\n";
00167     outFile << labelAndDesc.first << " = cms." << baseType << "('" << pluginName << "'";
00168 
00169     bool startWithComma = true;
00170     int indentation = 2;
00171     labelAndDesc.second.writeCfi(outFile, startWithComma, indentation);
00172 
00173     outFile << ")\n";
00174   
00175     outFile.close();
00176 
00177     if (baseType == std::string("Source")) {
00178       std::cout << pluginName << "\n";
00179     }
00180     else {
00181       std::cout << labelAndDesc.first << "\n";
00182     }
00183   }
00184 
00185   void ConfigurationDescriptions::print(std::ostream & os,
00186                                         std::string const& moduleLabel,
00187                                         bool brief,
00188                                         bool printOnlyLabels,
00189                                         size_t lineWidth,
00190                                         int indentation,
00191                                         int iPlugin) const {
00192     if (!brief) {
00193       if (!comment().empty()) {
00194         DocFormatHelper::wrapAndPrintText(os, comment(), indentation, lineWidth);
00195       }
00196       os << "\n";
00197     }
00198 
00199     char oldFill = os.fill();
00200     if (descriptions_.empty() && !defaultDescDefined_) {
00201       indentation += DocFormatHelper::offsetModuleLabel();
00202       os << std::setfill(' ') << std::setw(indentation) << "";
00203       os << "There are no PSet descriptions defined for this plugin.\n";
00204       os << std::setfill(' ') << std::setw(indentation) << "";
00205       os << "PSets will not be validated and no cfi files will be generated.\n";
00206       if (!brief) os << "\n";
00207       os.fill(oldFill);
00208       return;
00209     }
00210 
00211     if (descriptions_.empty() && defaultDescDefined_ && defaultDesc_.isUnknown()) {
00212       indentation += DocFormatHelper::offsetModuleLabel();
00213       os << std::setfill(' ') << std::setw(indentation) << "";
00214       os << "This plugin has not implemented the function which defines its\n";
00215       os << std::setfill(' ') << std::setw(indentation) << "";
00216       os << "configuration descriptions yet. No descriptions are available.\n";
00217       os << std::setfill(' ') << std::setw(indentation) << "";
00218       os << "Its PSets will not be validated, and no cfi files will be generated.\n";
00219       if (!brief) os << "\n";
00220       os.fill(oldFill);
00221       return;
00222     }
00223 
00224     if (!brief) {
00225       std::stringstream ss;
00226       if (defaultDescDefined_) {
00227         if (descriptions_.empty()) {
00228           ss << "This plugin has only one PSet description. "
00229              << "This description is always used to validate configurations. "
00230              << "Because this configuration has no label, no cfi files will be generated.";
00231         }
00232         else {
00233           ss << "This plugin has " << (descriptions_.size() + 1U) << " PSet descriptions. "
00234              << "The description used to validate a configuration is selected by "
00235              << "matching the module labels. If none match, then the last description, "
00236              << "which has no label, is selected. "
00237              << "A cfi file will be generated for each configuration with a module label.";
00238         }
00239       }
00240       else {
00241         if (descriptions_.size() == 1U) {
00242           ss << "This plugin has " << descriptions_.size() << " PSet description. "
00243              << "This description is always used to validate configurations. "
00244              << "The label below is used when generating the cfi file.";
00245         }
00246         else {
00247           ss << "This plugin has " << descriptions_.size() << " PSet descriptions. "
00248              << "The description used to validate a configuration is selected by "
00249              << "matching the module labels. If none match the first description below is used. "
00250              << "The module labels below are also used when generating the cfi files.";
00251         }
00252       }
00253       DocFormatHelper::wrapAndPrintText(os, ss.str(), indentation, lineWidth);
00254       os << "\n";
00255     }
00256 
00257     indentation += DocFormatHelper::offsetModuleLabel();
00258 
00259     DescriptionCounter counter;
00260     counter.iPlugin = iPlugin;
00261     counter.iSelectedModule = 0;
00262     counter.iModule = 0;
00263 
00264     for_all(descriptions_, boost::bind(&ConfigurationDescriptions::printForLabel,
00265                                        this,
00266                                        _1,
00267                                        boost::ref(os),
00268                                        boost::cref(moduleLabel),
00269                                        brief,
00270                                        printOnlyLabels,
00271                                        lineWidth,
00272                                        indentation,
00273                                        boost::ref(counter)));
00274 
00275     if (defaultDescDefined_) {
00276       printForLabel(os,
00277                     std::string("@default"),
00278                     defaultDesc_,
00279                     moduleLabel,
00280                     brief,
00281                     printOnlyLabels,
00282                     lineWidth,
00283                     indentation,
00284                     counter);
00285     }
00286   }
00287 
00288   void
00289   ConfigurationDescriptions::printForLabel(std::pair<std::string, ParameterSetDescription> const& labelAndDesc,
00290                                            std::ostream & os,
00291                                            std::string const& moduleLabel,
00292                                            bool brief,
00293                                            bool printOnlyLabels,
00294                                            size_t lineWidth,
00295                                            int indentation,
00296                                            DescriptionCounter & counter) const
00297   {
00298     printForLabel(os,
00299                   labelAndDesc.first,
00300                   labelAndDesc.second,
00301                   moduleLabel,
00302                   brief,
00303                   printOnlyLabels,
00304                   lineWidth,
00305                   indentation,
00306                   counter);
00307   }
00308 
00309   void
00310   ConfigurationDescriptions::printForLabel(std::ostream & os,
00311                                            std::string const& label,
00312                                            ParameterSetDescription const& description,
00313                                            std::string const& moduleLabel,
00314                                            bool brief,
00315                                            bool printOnlyLabels,
00316                                            size_t lineWidth,
00317                                            int indentation,
00318                                            DescriptionCounter & counter) const
00319   {
00320     ++counter.iModule;
00321     if (!moduleLabel.empty() && label != moduleLabel) return;
00322     ++counter.iSelectedModule;
00323 
00324     std::stringstream ss;
00325     ss << counter.iPlugin << "." << counter.iSelectedModule;
00326     std::string section = ss.str();
00327 
00328     char oldFill = os.fill();
00329     os << std::setfill(' ') << std::setw(indentation) << "";
00330     os.fill(oldFill);
00331     os << section << " ";
00332     if (label == std::string("@default")) {
00333       os << "description without a module label\n";
00334     }
00335     else {
00336       if (!brief) {
00337         if (baseType_ == std::string("Source") || baseType_ == std::string("Service")) {
00338           os << "label: ";
00339         }
00340         else {
00341           os << "module label: ";
00342         }
00343       }
00344       os << label << "\n";      
00345     }
00346 
00347     if (!brief) {
00348       if (!description.comment().empty()) {
00349         DocFormatHelper::wrapAndPrintText(os, description.comment(), indentation, lineWidth - indentation);        
00350       }
00351       os << "\n";
00352     }
00353     if (printOnlyLabels) return;
00354 
00355     DocFormatHelper dfh;
00356     dfh.setBrief(brief);
00357     dfh.setLineWidth(lineWidth);
00358     dfh.setIndentation(indentation + DocFormatHelper::offsetTopLevelPSet());
00359     dfh.setSection(section);
00360     dfh.setParent(DocFormatHelper::TOP);
00361 
00362     description.print(os, dfh);
00363   }
00364 }