00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00083
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 if (baseType_ == std::string("ESSource") || baseType_ == std::string("ESProducer")) {
00092 std::string name("appendToDataLabel");
00093 if (pair.second.isLabelUnused(name)) {
00094 pair.second.add<std::string>(name, std::string(""));
00095 }
00096 }
00097 }
00098
00099 void
00100 ConfigurationDescriptions::addDefault(ParameterSetDescription const& psetDescription) {
00101
00102 if (baseType_ == std::string("Source") || baseType_ == std::string("Service")) {
00103 if (descriptions_.size() != 0U ||
00104 defaultDescDefined_ == true) {
00105 throw edm::Exception(edm::errors::LogicError,
00106 "ConfigurationDescriptions::addDefault, for a source or service only 1 ParameterSetDescription may be added\n");
00107 }
00108 }
00109
00110 defaultDescDefined_ = true;
00111 defaultDesc_ = psetDescription;
00112
00113 if (baseType_ == std::string("ESSource") || baseType_ == std::string("ESProducer")) {
00114 std::string name("appendToDataLabel");
00115 if (defaultDesc_.isLabelUnused(name)) {
00116 defaultDesc_.add<std::string>(name, std::string(""));
00117 }
00118 }
00119 }
00120
00121 void
00122 ConfigurationDescriptions::validate(ParameterSet & pset,
00123 std::string const& moduleLabel) const {
00124
00125 ParameterSetDescription const* psetDesc = 0;
00126 for_all(descriptions_, boost::bind(&matchLabel,
00127 _1,
00128 boost::cref(moduleLabel),
00129 boost::ref(psetDesc)));
00130
00131
00132 if (psetDesc != 0) {
00133 psetDesc->validate(pset);
00134 }
00135
00136 else if (defaultDescDefined_) {
00137 defaultDesc_.validate(pset);
00138 }
00139
00140 else if (descriptions_.size() > 0U) {
00141 descriptions_[0].second.validate(pset);
00142 }
00143
00144
00145 }
00146
00147 void
00148 ConfigurationDescriptions::writeCfis(std::string const& baseType,
00149 std::string const& pluginName) const {
00150
00151 for_all(descriptions_, boost::bind(&ConfigurationDescriptions::writeCfiForLabel,
00152 _1,
00153 boost::cref(baseType),
00154 boost::cref(pluginName)));
00155 }
00156
00157
00158 void
00159 ConfigurationDescriptions::writeCfiForLabel(std::pair<std::string, ParameterSetDescription> const& labelAndDesc,
00160 std::string const& baseType,
00161 std::string const& pluginName)
00162 {
00163 if (baseType == std::string("Service") && labelAndDesc.first != pluginName) {
00164 throw edm::Exception(edm::errors::LogicError,
00165 "ConfigurationDescriptions::writeCfiForLabel\nFor a service the label and the plugin name must be the same.\n")
00166 << "This error probably is caused by an incorrect label being passed\nto the ConfigurationDescriptions::add function earlier.\n"
00167 << "plugin name = \"" << pluginName << "\" label name = \"" << labelAndDesc.first << "\"\n";
00168 }
00169
00170 std::string cfi_filename;
00171 if (baseType == std::string("Source")) {
00172 cfi_filename = pluginName + "_cfi.py";
00173 }
00174 else {
00175 cfi_filename = labelAndDesc.first + "_cfi.py";
00176 }
00177 std::ofstream outFile(cfi_filename.c_str());
00178
00179
00180 outFile << "import FWCore.ParameterSet.Config as cms\n\n";
00181 outFile << labelAndDesc.first << " = cms." << baseType << "('" << pluginName << "'";
00182
00183 bool startWithComma = true;
00184 int indentation = 2;
00185 labelAndDesc.second.writeCfi(outFile, startWithComma, indentation);
00186
00187 outFile << ")\n";
00188
00189 outFile.close();
00190
00191 if (baseType == std::string("Source")) {
00192 std::cout << pluginName << "\n";
00193 }
00194 else {
00195 std::cout << labelAndDesc.first << "\n";
00196 }
00197 }
00198
00199 void ConfigurationDescriptions::print(std::ostream & os,
00200 std::string const& moduleLabel,
00201 bool brief,
00202 bool printOnlyLabels,
00203 size_t lineWidth,
00204 int indentation,
00205 int iPlugin) const {
00206 if (!brief) {
00207 if (!comment().empty()) {
00208 DocFormatHelper::wrapAndPrintText(os, comment(), indentation, lineWidth);
00209 }
00210 os << "\n";
00211 }
00212
00213 char oldFill = os.fill();
00214 if (descriptions_.empty() && !defaultDescDefined_) {
00215 indentation += DocFormatHelper::offsetModuleLabel();
00216 os << std::setfill(' ') << std::setw(indentation) << "";
00217 os << "There are no PSet descriptions defined for this plugin.\n";
00218 os << std::setfill(' ') << std::setw(indentation) << "";
00219 os << "PSets will not be validated and no cfi files will be generated.\n";
00220 if (!brief) os << "\n";
00221 os.fill(oldFill);
00222 return;
00223 }
00224
00225 if (descriptions_.empty() && defaultDescDefined_ && defaultDesc_.isUnknown()) {
00226 indentation += DocFormatHelper::offsetModuleLabel();
00227 os << std::setfill(' ') << std::setw(indentation) << "";
00228 os << "This plugin has not implemented the function which defines its\n";
00229 os << std::setfill(' ') << std::setw(indentation) << "";
00230 os << "configuration descriptions yet. No descriptions are available.\n";
00231 os << std::setfill(' ') << std::setw(indentation) << "";
00232 os << "Its PSets will not be validated, and no cfi files will be generated.\n";
00233 if (!brief) os << "\n";
00234 os.fill(oldFill);
00235 return;
00236 }
00237
00238 if (!brief) {
00239 std::stringstream ss;
00240 if (defaultDescDefined_) {
00241 if (descriptions_.empty()) {
00242 ss << "This plugin has only one PSet description. "
00243 << "This description is always used to validate configurations. "
00244 << "Because this configuration has no label, no cfi files will be generated.";
00245 }
00246 else {
00247 ss << "This plugin has " << (descriptions_.size() + 1U) << " PSet descriptions. "
00248 << "The description used to validate a configuration is selected by "
00249 << "matching the module labels. If none match, then the last description, "
00250 << "which has no label, is selected. "
00251 << "A cfi file will be generated for each configuration with a module label.";
00252 }
00253 }
00254 else {
00255 if (descriptions_.size() == 1U) {
00256 ss << "This plugin has " << descriptions_.size() << " PSet description. "
00257 << "This description is always used to validate configurations. "
00258 << "The label below is used when generating the cfi file.";
00259 }
00260 else {
00261 ss << "This plugin has " << descriptions_.size() << " PSet descriptions. "
00262 << "The description used to validate a configuration is selected by "
00263 << "matching the module labels. If none match the first description below is used. "
00264 << "The module labels below are also used when generating the cfi files.";
00265 }
00266 }
00267 DocFormatHelper::wrapAndPrintText(os, ss.str(), indentation, lineWidth);
00268 os << "\n";
00269 }
00270
00271 indentation += DocFormatHelper::offsetModuleLabel();
00272
00273 DescriptionCounter counter;
00274 counter.iPlugin = iPlugin;
00275 counter.iSelectedModule = 0;
00276 counter.iModule = 0;
00277
00278 for_all(descriptions_, boost::bind(&ConfigurationDescriptions::printForLabel,
00279 this,
00280 _1,
00281 boost::ref(os),
00282 boost::cref(moduleLabel),
00283 brief,
00284 printOnlyLabels,
00285 lineWidth,
00286 indentation,
00287 boost::ref(counter)));
00288
00289 if (defaultDescDefined_) {
00290 printForLabel(os,
00291 std::string("@default"),
00292 defaultDesc_,
00293 moduleLabel,
00294 brief,
00295 printOnlyLabels,
00296 lineWidth,
00297 indentation,
00298 counter);
00299 }
00300 }
00301
00302 void
00303 ConfigurationDescriptions::printForLabel(std::pair<std::string, ParameterSetDescription> const& labelAndDesc,
00304 std::ostream & os,
00305 std::string const& moduleLabel,
00306 bool brief,
00307 bool printOnlyLabels,
00308 size_t lineWidth,
00309 int indentation,
00310 DescriptionCounter & counter) const
00311 {
00312 printForLabel(os,
00313 labelAndDesc.first,
00314 labelAndDesc.second,
00315 moduleLabel,
00316 brief,
00317 printOnlyLabels,
00318 lineWidth,
00319 indentation,
00320 counter);
00321 }
00322
00323 void
00324 ConfigurationDescriptions::printForLabel(std::ostream & os,
00325 std::string const& label,
00326 ParameterSetDescription const& description,
00327 std::string const& moduleLabel,
00328 bool brief,
00329 bool printOnlyLabels,
00330 size_t lineWidth,
00331 int indentation,
00332 DescriptionCounter & counter) const
00333 {
00334 ++counter.iModule;
00335 if (!moduleLabel.empty() && label != moduleLabel) return;
00336 ++counter.iSelectedModule;
00337
00338 std::stringstream ss;
00339 ss << counter.iPlugin << "." << counter.iSelectedModule;
00340 std::string section = ss.str();
00341
00342 char oldFill = os.fill();
00343 os << std::setfill(' ') << std::setw(indentation) << "";
00344 os.fill(oldFill);
00345 os << section << " ";
00346 if (label == std::string("@default")) {
00347 os << "description without a module label\n";
00348 }
00349 else {
00350 if (!brief) {
00351 if (baseType_ == std::string("Source") || baseType_ == std::string("Service")) {
00352 os << "label: ";
00353 }
00354 else {
00355 os << "module label: ";
00356 }
00357 }
00358 os << label << "\n";
00359 }
00360
00361 if (!brief) {
00362 if (!description.comment().empty()) {
00363 DocFormatHelper::wrapAndPrintText(os, description.comment(), indentation, lineWidth - indentation);
00364 }
00365 os << "\n";
00366 }
00367 if (printOnlyLabels) return;
00368
00369 DocFormatHelper dfh;
00370 dfh.setBrief(brief);
00371 dfh.setLineWidth(lineWidth);
00372 dfh.setIndentation(indentation + DocFormatHelper::offsetTopLevelPSet());
00373 dfh.setSection(section);
00374 dfh.setParent(DocFormatHelper::TOP);
00375
00376 description.print(os, dfh);
00377 }
00378 }