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 <sstream>
23 #include <ostream>
24 #include <iomanip>
25 #include <algorithm>
26 
27 namespace edm {
28 
30  anythingAllowed_(false),
31  unknown_(false) {
32  }
33 
35  }
36 
37  void
39  { comment_ = value; }
40 
41  void
43  { comment_ = value; }
44 
45  void
47  {
48  anythingAllowed_ = true;
49  }
50 
51  void
53  {
54  unknown_ = true;
55  }
56 
60  std::auto_ptr<ParameterDescriptionNode> clonedNode(node.clone());
61  return addNode(clonedNode, false, true);
62  }
63 
66  addNode(std::auto_ptr<ParameterDescriptionNode> node) {
67  return addNode(node, false, true);
68  }
69 
72  addOptionalNode(ParameterDescriptionNode const& node, bool writeToCfi) {
73  std::auto_ptr<ParameterDescriptionNode> clonedNode(node.clone());
74  return addNode(clonedNode, true, writeToCfi);
75  }
76 
79  addOptionalNode(std::auto_ptr<ParameterDescriptionNode> node, bool writeToCfi) {
80  return addNode(node, true, writeToCfi);
81  }
82 
85  addNode(std::auto_ptr<ParameterDescriptionNode> node,
86  bool optional,
87  bool writeToCfi) {
88 
89  std::set<std::string> nodeLabels;
90  std::set<ParameterTypes> nodeParameterTypes;
91  std::set<ParameterTypes> nodeWildcardTypes;
92  node->checkAndGetLabelsAndTypes(nodeLabels, nodeParameterTypes, nodeWildcardTypes);
93  throwIfLabelsAlreadyUsed(nodeLabels);
94  throwIfWildcardCollision(nodeParameterTypes, nodeWildcardTypes);
95 
97  entry.setOptional(optional);
98  entry.setWriteToCfi(writeToCfi);
99  entries_.push_back(entry);
100  return entries_.back().setNode(node);
101  }
102 
103  void
105  {
106  using std::placeholders::_1;
107  if (unknown_) return;
108 
109  std::set<std::string> validatedLabels;
111  std::bind(&ParameterSetDescription::validateNode, _1, std::ref(pset), std::ref(validatedLabels)));
112 
113  std::vector<std::string> parameterNames = pset.getParameterNames();
114  if (validatedLabels.size() != parameterNames.size()) {
115 
116  // Three labels will be magically inserted into the top level
117  // of a module ParameterSet even though they are not in the
118  // python configuration files. If these are present, then
119  // assume they are OK and count them as validated.
120 
121  std::string module_label("@module_label");
122  if (pset.exists(module_label)) {
123  validatedLabels.insert(module_label);
124  }
125 
126  std::string module_type("@module_type");
127  if (pset.exists(module_type)) {
128  validatedLabels.insert(module_type);
129  }
130 
131  std::string module_edm_type("@module_edm_type");
132  if (pset.exists(module_edm_type)) {
133  validatedLabels.insert(module_edm_type);
134  }
135 
136  std::string service_type("@service_type");
137  if (pset.exists(service_type)) {
138  validatedLabels.insert(service_type);
139  }
140 
141  // Try again
142  if (validatedLabels.size() != parameterNames.size()) {
143 
145  throwIllegalParameters(parameterNames, validatedLabels);
146  }
147  }
148  }
149  }
150 
151  void
153  bool startWithComma,
154  int indentation) const {
155  using std::placeholders::_1;
156  bool wroteSomething = false;
157 
159  _1,
160  std::ref(os),
161  std::ref(startWithComma),
162  indentation,
163  std::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  using std::placeholders::_1;
182  if (isUnknown()) {
183  dfh.indent(os);
184  os << "Description is unknown. The configured PSet will not be validated\n";
185  dfh.indent(os);
186  os << "because the plugin has not defined this parameter set description.\n";
187  if (!dfh.brief()) os << "\n";
188  }
189 
190  if (anythingAllowed()) {
191  dfh.indent(os);
192  os << "Description allows anything. If the configured PSet contains illegal parameters,\n";
193  dfh.indent(os);
194  os << "then validation will ignore them instead of throwing an exception.\n";
195  if (!dfh.brief()) os << "\n";
196  }
197 
198  if (entries_.empty()) {
199  dfh.indent(os);
200  os << "Description is empty\n";
201  if (!dfh.brief()) os << "\n";
202  return;
203  }
204 
205  // Zeroth pass is only to calculate column widths in advance of any printing
206  dfh.setPass(0);
207  dfh.setCounter(0);
209  _1,
210  std::ref(os),
211  std::ref(dfh)));
212 
213  // First pass prints top level parameters and references to structure
214  dfh.setPass(1);
215  dfh.setCounter(0);
217  _1,
218  std::ref(os),
219  std::ref(dfh)));
220 
221  // Second pass prints substructure that goes into different sections of the
222  // output document
223  dfh.setPass(2);
224  dfh.setCounter(0);
226  _1,
227  std::ref(os),
228  std::ref(dfh)));
229  }
230 
231  bool
234  return usedLabels_.find(label) == usedLabels_.end();
235  }
236 
237  void
239  std::vector<std::string> const& parameterNames,
240  std::set<std::string> const& validatedLabels) {
241 
242  std::set<std::string> parNames(parameterNames.begin(), parameterNames.end());
243 
244 
245  std::set<std::string> diffNames;
246  std::insert_iterator<std::set<std::string> > insertIter(diffNames, diffNames.begin());
247  std::set_difference(parNames.begin(), parNames.end(),
248  validatedLabels.begin(), validatedLabels.end(),
249  insertIter);
250 
251  std::stringstream ss;
252  for (std::set<std::string>::const_iterator iter = diffNames.begin(),
253  iEnd = diffNames.end();
254  iter != iEnd;
255  ++iter) {
256  ss << " '" << *iter << "'\n";
257  }
258  if (diffNames.size() == 1U) {
260  << "Illegal parameter found in configuration. The parameter is named:\n"
261  << ss.str()
262  << "You could be trying to use a parameter name that is not\n"
263  << "allowed for this plugin or it could be misspelled.\n";
264  }
265  else {
267  << "Illegal parameters found in configuration. The parameters are named:\n"
268  << ss.str()
269  << "You could be trying to use parameter names that are not\n"
270  << "allowed for this plugin or they could be misspelled.\n";
271  }
272  }
273 
274  void
276  std::ostream & os,
277  bool & startWithComma,
278  int indentation,
279  bool & wroteSomething) {
280  if (entry.writeToCfi()) {
281  entry.node()->writeCfi(os, startWithComma, indentation, wroteSomething);
282  }
283  }
284 
285  void
287  std::ostream & os,
288  DocFormatHelper & dfh) {
289  if (dfh.pass() < 2) {
290  entry.node()->print(os, entry.optional(), entry.writeToCfi(), dfh);
291  }
292  else {
293  entry.node()->printNestedContent(os, entry.optional(), dfh);
294  }
295  }
296 
297  void
299  throwIfLabelsAlreadyUsed(std::set<std::string> const& nodeLabels) {
300 
301  std::set<std::string> duplicateLabels;
302  std::insert_iterator<std::set<std::string> > insertIter(duplicateLabels, duplicateLabels.begin());
303  std::set_intersection(nodeLabels.begin(), nodeLabels.end(),
304  usedLabels_.begin(), usedLabels_.end(),
305  insertIter);
306  if (duplicateLabels.empty()) {
307  usedLabels_.insert(nodeLabels.begin(), nodeLabels.end());
308  }
309  else {
310 
311  std::stringstream ss;
312  for (std::set<std::string>::const_iterator iter = duplicateLabels.begin(),
313  iEnd = duplicateLabels.end();
314  iter != iEnd;
315  ++iter) {
316  ss << " \"" << *iter << "\"\n";
317  }
319  << "Labels used in different nodes of a ParameterSetDescription\n"
320  << "must be unique. The following duplicate labels were detected:\n"
321  << ss.str()
322  << "\n";
323  }
324  }
325 
326  void
328  throwIfWildcardCollision(std::set<ParameterTypes> const& nodeParameterTypes,
329  std::set<ParameterTypes> const& nodeWildcardTypes) {
330 
331  // 1. Check that the new wildcard types do not collide with the existing
332  // parameter types.
333  // 2. Check that the new parameter types do not collide with the existing
334  // wildcard types.
335  // 3. Then insert them.
336  // The order of those steps is important because a wildcard with a default
337  // value could insert a type in both sets and this is OK.
338 
339  // We assume the node already checked for collisions between the new parameter
340  // types and the new wildcard types before passing the sets to this function.
341 
342  if (!nodeWildcardTypes.empty()) {
343 
344  std::set<ParameterTypes> duplicateTypes1;
345  std::insert_iterator<std::set<ParameterTypes> > insertIter1(duplicateTypes1, duplicateTypes1.begin());
346  std::set_intersection(typesUsedForParameters_.begin(), typesUsedForParameters_.end(),
347  nodeWildcardTypes.begin(), nodeWildcardTypes.end(),
348  insertIter1);
349 
350  if (!duplicateTypes1.empty()) {
351 
352  std::stringstream ss;
353  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes1.begin(),
354  iEnd = duplicateTypes1.end();
355  iter != iEnd;
356  ++iter) {
357  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
358  }
360  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
361  << "not be the same as the type used for other parameters. This rule\n"
362  << "is violated for the following types:\n"
363  << ss.str()
364  << "\n";
365  }
366  }
367 
368  if (!typesUsedForWildcards_.empty()) {
369 
370  std::set<ParameterTypes> duplicateTypes2;
371  std::insert_iterator<std::set<ParameterTypes> > insertIter2(duplicateTypes2, duplicateTypes2.begin());
372  std::set_intersection(typesUsedForWildcards_.begin(), typesUsedForWildcards_.end(),
373  nodeParameterTypes.begin(), nodeParameterTypes.end(),
374  insertIter2);
375 
376  if (!duplicateTypes2.empty()) {
377 
378  std::stringstream ss;
379  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes2.begin(),
380  iEnd = duplicateTypes2.end();
381  iter != iEnd;
382  ++iter) {
383  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
384  }
386  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
387  << "not be the same as the type used for other parameters. This rule is\n"
388  << "violated for the following types :\n"
389  << ss.str()
390  << "\n";
391  }
392  }
393 
394  typesUsedForParameters_.insert(nodeParameterTypes.begin(), nodeParameterTypes.end());
395  typesUsedForWildcards_.insert(nodeWildcardTypes.begin(), nodeWildcardTypes.end());
396  }
397 
401  ParameterDescriptionNode const& node2,
402  bool optional, bool writeToCfi) {
403  std::auto_ptr<ParameterDescriptionNode> pdIfExists(new IfExistsDescription(node1, node2));
404  return addNode(pdIfExists, optional, writeToCfi);
405  }
406 }
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)
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_
list entry
Definition: mps_splice.py:62
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