CMS 3D CMS Logo

ConfigurationDescriptions.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: ParameterSet
4 // Class : ConfigurationDescriptions
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: W. David Dagenhart
10 // Created: 17 December 2008
11 //
12 
18 
19 #include <fstream>
20 #include <iostream>
21 #include <iomanip>
22 #include <sstream>
23 #include <cstring>
24 
25 namespace {
26  void matchLabel(std::pair<std::string, edm::ParameterSetDescription> const& thePair,
27  std::string const& moduleLabel,
28  edm::ParameterSetDescription const*& psetDesc) {
29  if (thePair.first == moduleLabel) {
30  psetDesc = &thePair.second;
31  }
32  }
33 }
34 
35 static const char* const kSource ="Source";
36 static const char* const kService = "Service";
37 static const char* const k_source = "source";
38 
39 namespace edm {
40 
42  baseType_(baseType),
43  pluginName_(pluginName),
44  defaultDescDefined_(false)
45  { }
46 
48 
49  void
51  { comment_ = value; }
52 
53  void
55  { comment_ = value; }
56 
57  void
59  ParameterSetDescription const& psetDescription) {
60  std::string labelString(label);
61  add(labelString, psetDescription);
62  }
63 
64  void
66  ParameterSetDescription const& psetDescription) {
67 
68  if (0==strcmp(baseType_.c_str(),kSource)) {
69  if (0!=strcmp(label.c_str(),k_source)) {
71  "ConfigurationDescriptions::add, when adding a ParameterSetDescription for a source the label must be \"source\"\n");
72  }
73  if (!descriptions_.empty() ||
74  defaultDescDefined_ == true) {
76  "ConfigurationDescriptions::add, for a source only 1 ParameterSetDescription may be added\n");
77  }
78  }
79  else if (0==strcmp(baseType_.c_str(),kService)) {
80  if (!descriptions_.empty() ||
81  defaultDescDefined_ == true) {
83  "ConfigurationDescriptions::add, for a service only 1 ParameterSetDescription may be added\n");
84  }
85  }
86 
87  // To minimize the number of copies involved create an empty description first
88  // and push it into the vector. Then perform the copy.
89  std::pair<std::string, ParameterSetDescription> pairWithEmptyDescription;
90  descriptions_.push_back(pairWithEmptyDescription);
91  std::pair<std::string, ParameterSetDescription> & pair = descriptions_.back();
92 
93  pair.first = label;
94  pair.second = psetDescription;
95 
96  }
97 
98  void
101  if(kService == baseType_) {
102  label = pluginName_;
103  }
104  else if(kSource == baseType_) {
105  label = "source";
106  }
107  else {
109  }
110  add(label, psetDescription);
111  }
112 
113  void
115 
116  if (0==strcmp(baseType_.c_str(),kSource) || 0==strcmp(baseType_.c_str(),kService)) {
117  if (!descriptions_.empty() ||
118  defaultDescDefined_ == true) {
120  "ConfigurationDescriptions::addDefault, for a source or service only 1 ParameterSetDescription may be added\n");
121  }
122  }
123 
124  defaultDescDefined_ = true;
125  defaultDesc_ = psetDescription;
126 
127  }
128 
131  if (defaultDescDefined_) {
132  return &defaultDesc_;
133  }
134  return nullptr;
135  }
136 
139 
142 
143 
144  void
146  std::string const& moduleLabel) const {
147 
148  ParameterSetDescription const* psetDesc = nullptr;
149  for_all(descriptions_, std::bind(&matchLabel,
150  std::placeholders::_1,
151  std::cref(moduleLabel),
152  std::ref(psetDesc)));
153 
154  // If there is a matching label
155  if (psetDesc != nullptr) {
156  psetDesc->validate(pset);
157  }
158  // Is there an explicit description to be used for a non standard label
159  else if (defaultDescDefined_) {
160  defaultDesc_.validate(pset);
161  }
162  // Otherwise use the first one.
163  else if (!descriptions_.empty()) {
164  descriptions_[0].second.validate(pset);
165  }
166  // It is possible for no descriptions to be defined and no validation occurs
167  // for this module ever.
168  }
169 
170  void
171  ConfigurationDescriptions::writeCfis(std::set<std::string>& usedCfiFileNames) const {
172 
174  std::placeholders::_1,
175  std::cref(baseType_),
176  std::cref(pluginName_),
177  std::ref(usedCfiFileNames)));
178  }
179 
180 
181  void
182  ConfigurationDescriptions::writeCfiForLabel(std::pair<std::string, ParameterSetDescription> const& labelAndDesc,
183  std::string const& baseType,
184  std::string const& pluginName,
185  std::set<std::string>& usedCfiFileNames)
186  {
187  if (0 == strcmp(baseType.c_str(),kService) && labelAndDesc.first != pluginName) {
189  "ConfigurationDescriptions::writeCfiForLabel\nFor a service the label and the plugin name must be the same.\n")
190  << "This error is probably caused by an incorrect label being passed\nto the ConfigurationDescriptions::add function earlier.\n"
191  << "plugin name = \"" << pluginName << "\" label name = \"" << labelAndDesc.first << "\"\n";
192  }
193 
194  std::string cfi_filename;
195  if (0 == strcmp(baseType.c_str(),kSource)) {
196  cfi_filename = pluginName + "_cfi.py";
197  }
198  else {
199  cfi_filename = labelAndDesc.first + "_cfi.py";
200  }
201  if (!usedCfiFileNames.insert(cfi_filename).second) {
203  "Two cfi files are being generated with the same name in the same directory.\n");
204  ex << "The cfi file name is '" << cfi_filename << "' and\n"
205  << "the module label is \'" << labelAndDesc.first << "\'.\n"
206  << "This error is probably caused by an error in one or more fillDescriptions functions\n"
207  << "where duplicate module labels are being passed to the ConfigurationDescriptions::add\n"
208  << "function. All such module labels must be unique within a package.\n"
209  << "If you do not want the generated cfi file and do not need more than one\n"
210  << "description for a plugin, then a way to fix this is to use the addDefault\n"
211  << "function instead of the add function.\n"
212  << "There are 3 common ways this problem can happen.\n"
213  << "1. This can happen when a module label is explicitly duplicated in one or more\n"
214  << "fillDescriptions functions. Fix these by changing the module labels to be unique.\n"
215  << "2. This can also happen when a module class is a template class and plugins are\n"
216  << "defined by instantiations with differing template parameters and these plugins\n"
217  << "share the same fillDescriptions function. Fix these by specializing the fillDescriptions\n"
218  << "function for each template instantiation.\n"
219  << "3. This can also happen when there is an inheritance heirarchy and multiple plugin modules\n"
220  << "are defined using derived classes and the base class which share the same fillDescriptions\n"
221  << "function. Fix these by redefining the fillDescriptions function in each derived class.\n";
222  ex.addContext("Executing function ConfigurationDescriptions::writeCfiForLabel");
223  throw ex;
224  }
225  std::ofstream outFile(cfi_filename.c_str());
226 
227  outFile << "import FWCore.ParameterSet.Config as cms\n\n";
228  outFile << labelAndDesc.first << " = cms." << baseType << "('" << pluginName << "'";
229 
230  bool startWithComma = true;
231  int indentation = 2;
232  labelAndDesc.second.writeCfi(outFile, startWithComma, indentation);
233 
234  outFile << ")\n";
235 
236  outFile.close();
237 
238  if (0 == strcmp(baseType.c_str(),kSource)) {
239  std::cout << pluginName << "\n";
240  }
241  else {
242  std::cout << labelAndDesc.first << "\n";
243  }
244  }
245 
246  void ConfigurationDescriptions::print(std::ostream & os,
247  std::string const& moduleLabel,
248  bool brief,
249  bool printOnlyLabels,
250  size_t lineWidth,
251  int indentation,
252  int iPlugin) const {
253  if (!brief) {
254  if (!comment().empty()) {
255  DocFormatHelper::wrapAndPrintText(os, comment(), indentation, lineWidth);
256  }
257  os << "\n";
258  }
259 
260  if (descriptions_.empty() && !defaultDescDefined_) {
261  char oldFill = os.fill();
262  indentation += DocFormatHelper::offsetModuleLabel();
263  os << std::setfill(' ') << std::setw(indentation) << "";
264  os << "There are no PSet descriptions defined for this plugin.\n";
265  os << std::setfill(' ') << std::setw(indentation) << "";
266  os << "PSets will not be validated and no cfi files will be generated.\n";
267  os << std::setfill(oldFill);
268  if (!brief) os << "\n";
269  return;
270  }
271 
273  indentation += DocFormatHelper::offsetModuleLabel();
274  char oldFill = os.fill();
275  os << std::setfill(' ') << std::setw(indentation) << "";
276  os << "This plugin has not implemented the function which defines its\n";
277  os << std::setfill(' ') << std::setw(indentation) << "";
278  os << "configuration descriptions yet. No descriptions are available.\n";
279  os << std::setfill(' ') << std::setw(indentation) << "";
280  os << "Its PSets will not be validated, and no cfi files will be generated.\n";
281  os << std::setfill(oldFill);
282  if (!brief) os << "\n";
283  return;
284  }
285 
286  if (!brief) {
287  std::stringstream ss;
288  if (defaultDescDefined_) {
289  if (descriptions_.empty()) {
290  ss << "This plugin has only one PSet description. "
291  << "This description is always used to validate configurations. "
292  << "Because this configuration has no label, no cfi files will be generated.";
293  }
294  else {
295  ss << "This plugin has " << (descriptions_.size() + 1U) << " PSet descriptions. "
296  << "The description used to validate a configuration is selected by "
297  << "matching the module labels. If none match, then the last description, "
298  << "which has no label, is selected. "
299  << "A cfi file will be generated for each configuration with a module label.";
300  }
301  }
302  else {
303  if (descriptions_.size() == 1U) {
304  ss << "This plugin has " << descriptions_.size() << " PSet description. "
305  << "This description is always used to validate configurations. "
306  << "The label below is used when generating the cfi file.";
307  }
308  else {
309  ss << "This plugin has " << descriptions_.size() << " PSet descriptions. "
310  << "The description used to validate a configuration is selected by "
311  << "matching the module labels. If none match the first description below is used. "
312  << "The module labels below are also used when generating the cfi files.";
313  }
314  }
315  DocFormatHelper::wrapAndPrintText(os, ss.str(), indentation, lineWidth);
316  os << "\n";
317  }
318 
319  indentation += DocFormatHelper::offsetModuleLabel();
320 
322  counter.iPlugin = iPlugin;
323  counter.iSelectedModule = 0;
324  counter.iModule = 0;
325 
326  for(auto const& d: descriptions_) {
327  printForLabel(d,os, moduleLabel,brief, printOnlyLabels,lineWidth,indentation, counter);
328  }
329 
330  if (defaultDescDefined_) {
331  printForLabel(os,
332  std::string("@default"),
333  defaultDesc_,
334  moduleLabel,
335  brief,
336  printOnlyLabels,
337  lineWidth,
338  indentation,
339  counter);
340  }
341  }
342 
343  void
344  ConfigurationDescriptions::printForLabel(std::pair<std::string, ParameterSetDescription> const& labelAndDesc,
345  std::ostream & os,
346  std::string const& moduleLabel,
347  bool brief,
348  bool printOnlyLabels,
349  size_t lineWidth,
350  int indentation,
351  DescriptionCounter & counter) const
352  {
353  printForLabel(os,
354  labelAndDesc.first,
355  labelAndDesc.second,
356  moduleLabel,
357  brief,
358  printOnlyLabels,
359  lineWidth,
360  indentation,
361  counter);
362  }
363 
364  void
366  std::string const& label,
368  std::string const& moduleLabel,
369  bool brief,
370  bool printOnlyLabels,
371  size_t lineWidth,
372  int indentation,
373  DescriptionCounter & counter) const
374  {
375  ++counter.iModule;
376  if (!moduleLabel.empty() && label != moduleLabel) return;
377  ++counter.iSelectedModule;
378 
379  std::stringstream ss;
380  ss << counter.iPlugin << "." << counter.iSelectedModule;
381  std::string section = ss.str();
382 
383  char oldFill = os.fill();
384  os << std::setfill(' ') << std::setw(indentation) << "" << std::setfill(oldFill);
385  os << section << " ";
386  if (label == std::string("@default")) {
387  os << "description without a module label\n";
388  }
389  else {
390  if (!brief) {
391  if (0 == strcmp(baseType_.c_str(),kSource) || 0 == strcmp(baseType_.c_str(),kService)) {
392  os << "label: ";
393  }
394  else {
395  os << "module label: ";
396  }
397  }
398  os << label << "\n";
399  }
400 
401  if (!brief) {
402  if (!description.comment().empty()) {
403  DocFormatHelper::wrapAndPrintText(os, description.comment(), indentation, lineWidth - indentation);
404  }
405  os << "\n";
406  }
407  if (printOnlyLabels) return;
408 
409  DocFormatHelper dfh;
410  dfh.setBrief(brief);
411  dfh.setLineWidth(lineWidth);
413  dfh.setSection(section);
415 
416  description.print(os, dfh);
417  }
418 }
ConfigurationDescriptions(std::string const &baseType, std::string const &pluginName)
static void writeCfiForLabel(std::pair< std::string, ParameterSetDescription > const &labelAndDesc, std::string const &baseType, std::string const &pluginName, std::set< std::string > &usedCfiFileNames)
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
void printForLabel(std::pair< std::string, ParameterSetDescription > const &labelAndDesc, std::ostream &os, std::string const &moduleLabel, bool brief, bool printOnlyLabels, size_t lineWidth, int indentationn, DescriptionCounter &counter) const
static const char *const kService
void validate(ParameterSet &pset) const
static void wrapAndPrintText(std::ostream &os, std::string const &text, size_t indent, size_t suggestedWidth)
ParameterSetDescription * defaultDescription()
Returns 0 if no default has been assigned.
static const char *const kSource
Func for_all(ForwardSequence &s, Func f)
wrapper for std::for_each
Definition: Algorithms.h:16
static int offsetModuleLabel()
void addDefault(ParameterSetDescription const &psetDescription)
void setBrief(bool value)
std::vector< std::pair< std::string, ParameterSetDescription > > descriptions_
void print(std::ostream &os, DocFormatHelper &dfh) const
std::string defaultModuleLabel(std::string label)
Definition: value.py:1
void setComment(std::string const &value)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void addContext(std::string const &context)
Definition: Exception.cc:227
HLT enums.
static std::atomic< unsigned int > counter
void print(std::ostream &os, std::string const &moduleLabel, bool brief, bool printOnlyLabels, size_t lineWidth, int indentation, int iPlugin) const
void validate(ParameterSet &pset, std::string const &moduleLabel) const
std::string const & comment() const
std::string const & comment() const
static const char *const k_source
static int offsetTopLevelPSet()
void setSection(std::string const &value)
std::vector< std::pair< std::string, ParameterSetDescription > >::iterator iterator
void setParent(DescriptionParent value)
void setIndentation(int value)
void writeCfis(std::set< std::string > &usedCfiFileNames) const
void setLineWidth(size_t value)