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