CMS 3D CMS Logo

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules 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 
32 
34 
36 
38 
40 
42  std::unique_ptr<ParameterDescriptionNode> clonedNode(node.clone());
43  return addNode(std::move(clonedNode), false, true);
44  }
45 
46  ParameterDescriptionNode* ParameterSetDescription::addNode(std::unique_ptr<ParameterDescriptionNode> node) {
47  return addNode(std::move(node), false, true);
48  }
49 
51  bool writeToCfi) {
52  std::unique_ptr<ParameterDescriptionNode> clonedNode(node.clone());
53  return addNode(std::move(clonedNode), true, writeToCfi);
54  }
55 
56  ParameterDescriptionNode* ParameterSetDescription::addOptionalNode(std::unique_ptr<ParameterDescriptionNode> node,
57  bool writeToCfi) {
58  return addNode(std::move(node), true, writeToCfi);
59  }
60 
61  ParameterDescriptionNode* ParameterSetDescription::addNode(std::unique_ptr<ParameterDescriptionNode> node,
62  bool optional,
63  bool writeToCfi) {
64  std::set<std::string> nodeLabels;
65  std::set<ParameterTypes> nodeParameterTypes;
66  std::set<ParameterTypes> nodeWildcardTypes;
67  node->checkAndGetLabelsAndTypes(nodeLabels, nodeParameterTypes, nodeWildcardTypes);
68  throwIfLabelsAlreadyUsed(nodeLabels);
69  throwIfWildcardCollision(nodeParameterTypes, nodeWildcardTypes);
70 
72  entry.setOptional(optional);
73  entry.setWriteToCfi(writeToCfi);
74  entries_.push_back(entry);
75  return entries_.back().setNode(std::move(node));
76  }
77 
79  using std::placeholders::_1;
80  if (unknown_)
81  return;
82 
83  std::set<std::string> validatedLabels;
84  for_all(entries_, std::bind(&ParameterSetDescription::validateNode, _1, std::ref(pset), std::ref(validatedLabels)));
85 
86  std::vector<std::string> parameterNames = pset.getParameterNames();
87  if (validatedLabels.size() != parameterNames.size()) {
88  // These labels will be magically inserted into the top level
89  // of a module ParameterSet even though they are not in the
90  // python configuration files. If these are present, then
91  // assume they are OK and count them as validated.
92 
93  std::string module_label("@module_label");
94  if (pset.exists(module_label)) {
95  validatedLabels.insert(module_label);
96  }
97 
98  std::string module_type("@module_type");
99  if (pset.exists(module_type)) {
100  validatedLabels.insert(module_type);
101  }
102 
103  std::string module_edm_type("@module_edm_type");
104  if (pset.exists(module_edm_type)) {
105  validatedLabels.insert(module_edm_type);
106  }
107 
108  std::string service_type("@service_type");
109  if (pset.exists(service_type)) {
110  validatedLabels.insert(service_type);
111  }
112 
113  {
114  std::string tryToContinue("@shouldTryToContinue");
115  if (pset.exists(tryToContinue)) {
116  validatedLabels.insert(tryToContinue);
117  }
118  }
119  // Try again
120  if (validatedLabels.size() != parameterNames.size()) {
122  throwIllegalParameters(parameterNames, validatedLabels);
123  }
124  }
125  }
126  }
127 
128  void ParameterSetDescription::writeCfi(std::ostream& os, bool startWithComma, int indentation) const {
129  using std::placeholders::_1;
130  bool wroteSomething = false;
131 
132  bool seenWildcard = false;
133  for (auto const& entry : entries_) {
134  //only add the first seen wildcard to the cfi. This avoids possible ambiguities.
135  if (entry.node()->isWildcard()) {
136  if (seenWildcard == true) {
137  continue;
138  }
139  seenWildcard = true;
140  }
141  writeNode(entry, os, startWithComma, indentation, wroteSomething);
142  }
143 
144  if (wroteSomething) {
145  char oldFill = os.fill();
146  os << "\n" << std::setfill(' ') << std::setw(indentation - 2) << "" << std::setfill(oldFill);
147  }
148  }
149 
152  std::set<std::string>& validatedLabels) {
153  entry.node()->validate(pset, validatedLabels, entry.optional());
154  }
155 
156  void ParameterSetDescription::print(std::ostream& os, DocFormatHelper& dfh) const {
157  using std::placeholders::_1;
158  if (isUnknown()) {
159  dfh.indent(os);
160  os << "Description is unknown. The configured PSet will not be validated\n";
161  dfh.indent(os);
162  os << "because the plugin has not defined this parameter set description.\n";
163  if (!dfh.brief())
164  os << "\n";
165  }
166 
167  if (anythingAllowed()) {
168  dfh.indent(os);
169  os << "Description allows anything. If the configured PSet contains illegal parameters,\n";
170  dfh.indent(os);
171  os << "then validation will ignore them instead of throwing an exception.\n";
172  if (!dfh.brief())
173  os << "\n";
174  }
175 
176  if (entries_.empty()) {
177  dfh.indent(os);
178  os << "Description is empty\n";
179  if (!dfh.brief())
180  os << "\n";
181  return;
182  }
183 
184  // Zeroth pass is only to calculate column widths in advance of any printing
185  dfh.setPass(0);
186  dfh.setCounter(0);
187  for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
188 
189  // First pass prints top level parameters and references to structure
190  dfh.setPass(1);
191  dfh.setCounter(0);
192  for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
193 
194  // Second pass prints substructure that goes into different sections of the
195  // output document
196  dfh.setPass(2);
197  dfh.setCounter(0);
198  for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
199  }
200 
202  return usedLabels_.find(label) == usedLabels_.end();
203  }
204 
205  void ParameterSetDescription::throwIllegalParameters(std::vector<std::string> const& parameterNames,
206  std::set<std::string> const& validatedLabels) {
207  std::set<std::string> parNames(parameterNames.begin(), parameterNames.end());
208 
209  std::set<std::string> diffNames;
210  std::insert_iterator<std::set<std::string> > insertIter(diffNames, diffNames.begin());
211  std::set_difference(parNames.begin(), parNames.end(), validatedLabels.begin(), validatedLabels.end(), insertIter);
212 
213  std::stringstream ss;
214  for (std::set<std::string>::const_iterator iter = diffNames.begin(), iEnd = diffNames.end(); iter != iEnd; ++iter) {
215  ss << " '" << *iter << "'\n";
216  }
217  if (diffNames.size() == 1U) {
219  << "Illegal parameter found in configuration. The parameter is named:\n"
220  << ss.str() << "You could be trying to use a parameter name that is not\n"
221  << "allowed for this plugin or it could be misspelled.\n";
222  } else {
224  << "Illegal parameters found in configuration. The parameters are named:\n"
225  << ss.str() << "You could be trying to use parameter names that are not\n"
226  << "allowed for this plugin or they could be misspelled.\n";
227  }
228  }
229 
231  SetDescriptionEntry const& entry, std::ostream& os, bool& startWithComma, int indentation, bool& wroteSomething) {
232  if (entry.writeToCfi()) {
233  entry.node()->writeCfi(os, entry.optional(), startWithComma, indentation, wroteSomething);
234  }
235  }
236 
238  if (dfh.pass() < 2) {
239  entry.node()->print(os, entry.optional(), entry.writeToCfi(), dfh);
240  } else {
241  entry.node()->printNestedContent(os, entry.optional(), dfh);
242  }
243  }
244 
245  void ParameterSetDescription::throwIfLabelsAlreadyUsed(std::set<std::string> const& nodeLabels) {
246  std::set<std::string> duplicateLabels;
247  std::insert_iterator<std::set<std::string> > insertIter(duplicateLabels, duplicateLabels.begin());
248  std::set_intersection(nodeLabels.begin(), nodeLabels.end(), usedLabels_.begin(), usedLabels_.end(), insertIter);
249  if (duplicateLabels.empty()) {
250  usedLabels_.insert(nodeLabels.begin(), nodeLabels.end());
251  } else {
252  std::stringstream ss;
253  for (std::set<std::string>::const_iterator iter = duplicateLabels.begin(), iEnd = duplicateLabels.end();
254  iter != iEnd;
255  ++iter) {
256  ss << " \"" << *iter << "\"\n";
257  }
258  throw edm::Exception(errors::LogicError) << "Labels used in different nodes of a ParameterSetDescription\n"
259  << "must be unique. The following duplicate labels were detected:\n"
260  << ss.str() << "\n";
261  }
262  }
263 
264  void ParameterSetDescription::throwIfWildcardCollision(std::set<ParameterTypes> const& nodeParameterTypes,
265  std::set<ParameterTypes> const& nodeWildcardTypes) {
266  // 1. Check that the new wildcard types do not collide with the existing
267  // parameter types.
268  // 2. Check that the new parameter types do not collide with the existing
269  // wildcard types.
270  // 3. Then insert them.
271  // The order of those steps is important because a wildcard with a default
272  // value could insert a type in both sets and this is OK.
273 
274  // We assume the node already checked for collisions between the new parameter
275  // types and the new wildcard types before passing the sets to this function.
276 
277  if (!nodeWildcardTypes.empty()) {
278  std::set<ParameterTypes> duplicateTypes1;
279  std::insert_iterator<std::set<ParameterTypes> > insertIter1(duplicateTypes1, duplicateTypes1.begin());
282  nodeWildcardTypes.begin(),
283  nodeWildcardTypes.end(),
284  insertIter1);
285 
286  if (!duplicateTypes1.empty()) {
287  std::stringstream ss;
288  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes1.begin(), iEnd = duplicateTypes1.end();
289  iter != iEnd;
290  ++iter) {
291  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
292  }
294  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
295  << "not be the same as the type used for other parameters. This rule\n"
296  << "is violated for the following types:\n"
297  << ss.str() << "\n";
298  }
299  }
300 
301  if (!typesUsedForWildcards_.empty()) {
302  std::set<ParameterTypes> duplicateTypes2;
303  std::insert_iterator<std::set<ParameterTypes> > insertIter2(duplicateTypes2, duplicateTypes2.begin());
306  nodeParameterTypes.begin(),
307  nodeParameterTypes.end(),
308  insertIter2);
309 
310  if (!duplicateTypes2.empty()) {
311  std::stringstream ss;
312  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes2.begin(), iEnd = duplicateTypes2.end();
313  iter != iEnd;
314  ++iter) {
315  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
316  }
318  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
319  << "not be the same as the type used for other parameters. This rule is\n"
320  << "violated for the following types :\n"
321  << ss.str() << "\n";
322  }
323  }
324 
325  typesUsedForParameters_.insert(nodeParameterTypes.begin(), nodeParameterTypes.end());
326  typesUsedForWildcards_.insert(nodeWildcardTypes.begin(), nodeWildcardTypes.end());
327  }
328 
330  ParameterDescriptionNode const& node2,
331  bool optional,
332  bool writeToCfi) {
333  std::unique_ptr<ParameterDescriptionNode> pdIfExists = std::make_unique<IfExistsDescription>(node1, node2);
334  return addNode(std::move(pdIfExists), optional, writeToCfi);
335  }
336 } // namespace edm
bool isLabelUnused(std::string const &label) const
virtual ParameterDescriptionNode * clone() const =0
static void throwIllegalParameters(std::vector< std::string > const &parameterNames, std::set< std::string > const &validatedNames)
void print(std::ostream &os, DocFormatHelper &dfh) const
void throwIfWildcardCollision(std::set< ParameterTypes > const &nodeParameterTypes, std::set< ParameterTypes > const &nodeWildcardTypes)
void setAllowAnything()
allow any parameter label/value pairs
std::set< std::string > usedLabels_
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)
std::string parameterTypeEnumToString(ParameterTypes iType)
void writeCfi(std::ostream &os, bool startWithComma, int indentation) const
void setCounter(int value)
std::set< ParameterTypes > typesUsedForParameters_
Func for_all(ForwardSequence &s, Func f)
wrapper for std::for_each
Definition: Algorithms.h:14
char const * label
void setComment(std::string const &value)
void throwIfLabelsAlreadyUsed(std::set< std::string > const &nodeLabels)
ParameterDescriptionNode * addOptionalNode(ParameterDescriptionNode const &node, bool writeToCfi)
optional
Definition: Types.py:245
Definition: value.py:1
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)
void checkAndGetLabelsAndTypes(std::set< std::string > &usedLabels, std::set< ParameterTypes > &parameterTypes, std::set< ParameterTypes > &wildcardTypes) const
void validate(ParameterSet &pset) const
static const uint16_t unknown_
Definition: Constants.h:19
std::set< ParameterTypes > typesUsedForWildcards_
HLT enums.
void indent(std::ostream &os) const
std::vector< std::string > set_difference(std::vector< std::string > const &v1, std::vector< std::string > const &v2)
def move(src, dest)
Definition: eostools.py:511
std::vector< std::string > set_intersection(std::vector< std::string > const &v1, std::vector< std::string > const &v2)