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