CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ParameterSetDescription.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: ParameterSet
4 // Class : ParameterSetDescription
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: Chris Jones
10 // Created: Tue Jul 31 15:30:35 EDT 2007
11 //
12 
14 
21 
22 #include "boost/bind.hpp"
23 
24 #include <sstream>
25 #include <ostream>
26 #include <iomanip>
27 #include <algorithm>
28 
29 namespace edm {
30 
32  anythingAllowed_(false),
33  unknown_(false) {
34  }
35 
37  }
38 
39  void
41  { comment_ = value; }
42 
43  void
45  { comment_ = value; }
46 
47  void
49  {
50  anythingAllowed_ = true;
51  }
52 
53  void
55  {
56  unknown_ = true;
57  }
58 
62  std::auto_ptr<ParameterDescriptionNode> clonedNode(node.clone());
63  return addNode(clonedNode, false, true);
64  }
65 
68  addNode(std::auto_ptr<ParameterDescriptionNode> node) {
69  return addNode(node, false, true);
70  }
71 
75  std::auto_ptr<ParameterDescriptionNode> clonedNode(node.clone());
76  return addNode(clonedNode, true, writeToCfi);
77  }
78 
81  addOptionalNode(std::auto_ptr<ParameterDescriptionNode> node, bool writeToCfi) {
82  return addNode(node, true, writeToCfi);
83  }
84 
87  addNode(std::auto_ptr<ParameterDescriptionNode> node,
88  bool optional,
89  bool writeToCfi) {
90 
91  std::set<std::string> nodeLabels;
92  std::set<ParameterTypes> nodeParameterTypes;
93  std::set<ParameterTypes> nodeWildcardTypes;
94  node->checkAndGetLabelsAndTypes(nodeLabels, nodeParameterTypes, nodeWildcardTypes);
95  throwIfLabelsAlreadyUsed(nodeLabels);
96  throwIfWildcardCollision(nodeParameterTypes, nodeWildcardTypes);
97 
98  SetDescriptionEntry entry;
99  entry.setOptional(optional);
100  entry.setWriteToCfi(writeToCfi);
101  entries_.push_back(entry);
102  return entries_.back().setNode(node);
103  }
104 
105  void
107  {
108  if (unknown_) return;
109 
110  std::set<std::string> validatedLabels;
112  boost::bind(&ParameterSetDescription::validateNode, _1, boost::ref(pset), boost::ref(validatedLabels)));
113 
114  std::vector<std::string> parameterNames = pset.getParameterNames();
115  if (validatedLabels.size() != parameterNames.size()) {
116 
117  // Three labels will be magically inserted into the top level
118  // of a module ParameterSet even though they are not in the
119  // python configuration files. If these are present, then
120  // assume they are OK and count them as validated.
121 
122  std::string module_label("@module_label");
123  if (pset.exists(module_label)) {
124  validatedLabels.insert(module_label);
125  }
126 
127  std::string module_type("@module_type");
128  if (pset.exists(module_type)) {
129  validatedLabels.insert(module_type);
130  }
131 
132  std::string module_edm_type("@module_edm_type");
133  if (pset.exists(module_edm_type)) {
134  validatedLabels.insert(module_edm_type);
135  }
136 
137  std::string service_type("@service_type");
138  if (pset.exists(service_type)) {
139  validatedLabels.insert(service_type);
140  }
141 
142  // Try again
143  if (validatedLabels.size() != parameterNames.size()) {
144 
146  throwIllegalParameters(parameterNames, validatedLabels);
147  }
148  }
149  }
150  }
151 
152  void
154  bool startWithComma,
155  int indentation) const {
156  bool wroteSomething = false;
157 
159  _1,
160  boost::ref(os),
161  boost::ref(startWithComma),
162  indentation,
163  boost::ref(wroteSomething)));
164 
165  if (wroteSomething) {
166  char oldFill = os.fill();
167  os << "\n" << std::setfill(' ') << std::setw(indentation - 2) << "" << std::setfill(oldFill);
168  }
169  }
170 
173  ParameterSet & pset,
174  std::set<std::string> & validatedLabels) {
175  entry.node()->validate(pset, validatedLabels, entry.optional());
176  }
177 
179  print(std::ostream & os, DocFormatHelper & dfh) const {
180 
181  if (isUnknown()) {
182  dfh.indent(os);
183  os << "Description is unknown. The configured PSet will not be validated\n";
184  dfh.indent(os);
185  os << "because the plugin has not defined this parameter set description.\n";
186  if (!dfh.brief()) os << "\n";
187  }
188 
189  if (anythingAllowed()) {
190  dfh.indent(os);
191  os << "Description allows anything. If the configured PSet contains illegal parameters,\n";
192  dfh.indent(os);
193  os << "then validation will ignore them instead of throwing an exception.\n";
194  if (!dfh.brief()) os << "\n";
195  }
196 
197  if (entries_.empty()) {
198  dfh.indent(os);
199  os << "Description is empty\n";
200  if (!dfh.brief()) os << "\n";
201  return;
202  }
203 
204  // Zeroth pass is only to calculate column widths in advance of any printing
205  dfh.setPass(0);
206  dfh.setCounter(0);
208  _1,
209  boost::ref(os),
210  boost::ref(dfh)));
211 
212  // First pass prints top level parameters and references to structure
213  dfh.setPass(1);
214  dfh.setCounter(0);
216  _1,
217  boost::ref(os),
218  boost::ref(dfh)));
219 
220  // Second pass prints substructure that goes into different sections of the
221  // output document
222  dfh.setPass(2);
223  dfh.setCounter(0);
225  _1,
226  boost::ref(os),
227  boost::ref(dfh)));
228  }
229 
230  bool
233  return usedLabels_.find(label) == usedLabels_.end();
234  }
235 
236  void
238  std::vector<std::string> const& parameterNames,
239  std::set<std::string> const& validatedLabels) {
240 
241  std::set<std::string> parNames(parameterNames.begin(), parameterNames.end());
242 
243 
244  std::set<std::string> diffNames;
245  std::insert_iterator<std::set<std::string> > insertIter(diffNames, diffNames.begin());
246  std::set_difference(parNames.begin(), parNames.end(),
247  validatedLabels.begin(), validatedLabels.end(),
248  insertIter);
249 
250  std::stringstream ss;
251  for (std::set<std::string>::const_iterator iter = diffNames.begin(),
252  iEnd = diffNames.end();
253  iter != iEnd;
254  ++iter) {
255  ss << " '" << *iter << "'\n";
256  }
257  if (diffNames.size() == 1U) {
259  << "Illegal parameter found in configuration. The parameter is named:\n"
260  << ss.str()
261  << "You could be trying to use a parameter name that is not\n"
262  << "allowed for this plugin or it could be misspelled.\n";
263  }
264  else {
266  << "Illegal parameters found in configuration. The parameters are named:\n"
267  << ss.str()
268  << "You could be trying to use parameter names that are not\n"
269  << "allowed for this plugin or they could be misspelled.\n";
270  }
271  }
272 
273  void
275  std::ostream & os,
276  bool & startWithComma,
277  int indentation,
278  bool & wroteSomething) {
279  if (entry.writeToCfi()) {
280  entry.node()->writeCfi(os, startWithComma, indentation, wroteSomething);
281  }
282  }
283 
284  void
286  std::ostream & os,
287  DocFormatHelper & dfh) {
288  if (dfh.pass() < 2) {
289  entry.node()->print(os, entry.optional(), entry.writeToCfi(), dfh);
290  }
291  else {
292  entry.node()->printNestedContent(os, entry.optional(), dfh);
293  }
294  }
295 
296  void
298  throwIfLabelsAlreadyUsed(std::set<std::string> const& nodeLabels) {
299 
300  std::set<std::string> duplicateLabels;
301  std::insert_iterator<std::set<std::string> > insertIter(duplicateLabels, duplicateLabels.begin());
302  std::set_intersection(nodeLabels.begin(), nodeLabels.end(),
303  usedLabels_.begin(), usedLabels_.end(),
304  insertIter);
305  if (duplicateLabels.empty()) {
306  usedLabels_.insert(nodeLabels.begin(), nodeLabels.end());
307  }
308  else {
309 
310  std::stringstream ss;
311  for (std::set<std::string>::const_iterator iter = duplicateLabels.begin(),
312  iEnd = duplicateLabels.end();
313  iter != iEnd;
314  ++iter) {
315  ss << " \"" << *iter << "\"\n";
316  }
318  << "Labels used in different nodes of a ParameterSetDescription\n"
319  << "must be unique. The following duplicate labels were detected:\n"
320  << ss.str()
321  << "\n";
322  }
323  }
324 
325  void
327  throwIfWildcardCollision(std::set<ParameterTypes> const& nodeParameterTypes,
328  std::set<ParameterTypes> const& nodeWildcardTypes) {
329 
330  // 1. Check that the new wildcard types do not collide with the existing
331  // parameter types.
332  // 2. Check that the new parameter types do not collide with the existing
333  // wildcard types.
334  // 3. Then insert them.
335  // The order of those steps is important because a wildcard with a default
336  // value could insert a type in both sets and this is OK.
337 
338  // We assume the node already checked for collisions between the new parameter
339  // types and the new wildcard types before passing the sets to this function.
340 
341  if (!nodeWildcardTypes.empty()) {
342 
343  std::set<ParameterTypes> duplicateTypes1;
344  std::insert_iterator<std::set<ParameterTypes> > insertIter1(duplicateTypes1, duplicateTypes1.begin());
345  std::set_intersection(typesUsedForParameters_.begin(), typesUsedForParameters_.end(),
346  nodeWildcardTypes.begin(), nodeWildcardTypes.end(),
347  insertIter1);
348 
349  if (!duplicateTypes1.empty()) {
350 
351  std::stringstream ss;
352  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes1.begin(),
353  iEnd = duplicateTypes1.end();
354  iter != iEnd;
355  ++iter) {
356  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
357  }
359  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
360  << "not be the same as the type used for other parameters. This rule\n"
361  << "is violated for the following types:\n"
362  << ss.str()
363  << "\n";
364  }
365  }
366 
367  if (!typesUsedForWildcards_.empty()) {
368 
369  std::set<ParameterTypes> duplicateTypes2;
370  std::insert_iterator<std::set<ParameterTypes> > insertIter2(duplicateTypes2, duplicateTypes2.begin());
371  std::set_intersection(typesUsedForWildcards_.begin(), typesUsedForWildcards_.end(),
372  nodeParameterTypes.begin(), nodeParameterTypes.end(),
373  insertIter2);
374 
375  if (!duplicateTypes2.empty()) {
376 
377  std::stringstream ss;
378  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes2.begin(),
379  iEnd = duplicateTypes2.end();
380  iter != iEnd;
381  ++iter) {
382  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
383  }
385  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
386  << "not be the same as the type used for other parameters. This rule is\n"
387  << "violated for the following types :\n"
388  << ss.str()
389  << "\n";
390  }
391  }
392 
393  typesUsedForParameters_.insert(nodeParameterTypes.begin(), nodeParameterTypes.end());
394  typesUsedForWildcards_.insert(nodeWildcardTypes.begin(), nodeWildcardTypes.end());
395  }
396 
400  ParameterDescriptionNode const& node2,
401  bool optional, bool writeToCfi) {
402  std::auto_ptr<ParameterDescriptionNode> pdIfExists(new IfExistsDescription(node1, node2));
403  return addNode(pdIfExists, optional, writeToCfi);
404  }
405 }
virtual ParameterDescriptionNode * clone() const =0
static void throwIllegalParameters(std::vector< std::string > const &parameterNames, std::set< std::string > const &validatedNames)
edm::value_ptr< ParameterDescriptionNode > const & node() const
void throwIfWildcardCollision(std::set< ParameterTypes > const &nodeParameterTypes, std::set< ParameterTypes > const &nodeWildcardTypes)
void setAllowAnything()
allow any parameter label/value pairs
void validate(ParameterSet &pset) const
std::set< std::string > usedLabels_
bool exists(std::string const &parameterName) const
checks if a parameter exists
static bool throwAnException()
ParameterDescriptionNode * ifExists(ParameterDescriptionNode const &node1, ParameterDescriptionNode const &node2)
ParameterDescriptionNode * addNode(ParameterDescriptionNode const &node)
static void writeNode(SetDescriptionEntry const &entry, std::ostream &os, bool &startWithComma, int indentation, bool &wroteSomething)
void writeCfi(std::ostream &os, bool startWithComma, int indentation) const
std::string parameterTypeEnumToString(ParameterTypes iType)
tuple node
Definition: Node.py:50
void setCounter(int value)
std::set< ParameterTypes > typesUsedForParameters_
Func for_all(ForwardSequence &s, Func f)
wrapper for std::for_each
Definition: Algorithms.h:16
void setComment(std::string const &value)
void throwIfLabelsAlreadyUsed(std::set< std::string > const &nodeLabels)
void print(std::ostream &os, DocFormatHelper &dfh) const
ParameterDescriptionNode * addOptionalNode(ParameterDescriptionNode const &node, bool writeToCfi)
bool isLabelUnused(std::string const &label) const
std::vector< std::string > getParameterNames() const
void setPass(int value)
static void validateNode(SetDescriptionEntry const &entry, ParameterSet &pset, std::set< std::string > &validatedNames)
static void printNode(SetDescriptionEntry const &entry, std::ostream &os, DocFormatHelper &dfh)
static const uint16_t unknown_
Definition: Constants.h:19
std::set< ParameterTypes > typesUsedForWildcards_
void checkAndGetLabelsAndTypes(std::set< std::string > &usedLabels, std::set< ParameterTypes > &parameterTypes, std::set< ParameterTypes > &wildcardTypes) const
volatile std::atomic< bool > shutdown_flag false
void indent(std::ostream &os) const