CMS 3D CMS Logo

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 
134  _1,
135  std::ref(os),
136  std::ref(startWithComma),
137  indentation,
138  std::ref(wroteSomething)));
139 
140  if (wroteSomething) {
141  char oldFill = os.fill();
142  os << "\n" << std::setfill(' ') << std::setw(indentation - 2) << "" << std::setfill(oldFill);
143  }
144  }
145 
148  std::set<std::string>& validatedLabels) {
149  entry.node()->validate(pset, validatedLabels, entry.optional());
150  }
151 
152  void ParameterSetDescription::print(std::ostream& os, DocFormatHelper& dfh) const {
153  using std::placeholders::_1;
154  if (isUnknown()) {
155  dfh.indent(os);
156  os << "Description is unknown. The configured PSet will not be validated\n";
157  dfh.indent(os);
158  os << "because the plugin has not defined this parameter set description.\n";
159  if (!dfh.brief())
160  os << "\n";
161  }
162 
163  if (anythingAllowed()) {
164  dfh.indent(os);
165  os << "Description allows anything. If the configured PSet contains illegal parameters,\n";
166  dfh.indent(os);
167  os << "then validation will ignore them instead of throwing an exception.\n";
168  if (!dfh.brief())
169  os << "\n";
170  }
171 
172  if (entries_.empty()) {
173  dfh.indent(os);
174  os << "Description is empty\n";
175  if (!dfh.brief())
176  os << "\n";
177  return;
178  }
179 
180  // Zeroth pass is only to calculate column widths in advance of any printing
181  dfh.setPass(0);
182  dfh.setCounter(0);
183  for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
184 
185  // First pass prints top level parameters and references to structure
186  dfh.setPass(1);
187  dfh.setCounter(0);
188  for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
189 
190  // Second pass prints substructure that goes into different sections of the
191  // output document
192  dfh.setPass(2);
193  dfh.setCounter(0);
194  for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
195  }
196 
198  return usedLabels_.find(label) == usedLabels_.end();
199  }
200 
201  void ParameterSetDescription::throwIllegalParameters(std::vector<std::string> const& parameterNames,
202  std::set<std::string> const& validatedLabels) {
203  std::set<std::string> parNames(parameterNames.begin(), parameterNames.end());
204 
205  std::set<std::string> diffNames;
206  std::insert_iterator<std::set<std::string> > insertIter(diffNames, diffNames.begin());
207  std::set_difference(parNames.begin(), parNames.end(), validatedLabels.begin(), validatedLabels.end(), insertIter);
208 
209  std::stringstream ss;
210  for (std::set<std::string>::const_iterator iter = diffNames.begin(), iEnd = diffNames.end(); iter != iEnd; ++iter) {
211  ss << " '" << *iter << "'\n";
212  }
213  if (diffNames.size() == 1U) {
215  << "Illegal parameter found in configuration. The parameter is named:\n"
216  << ss.str() << "You could be trying to use a parameter name that is not\n"
217  << "allowed for this plugin or it could be misspelled.\n";
218  } else {
220  << "Illegal parameters found in configuration. The parameters are named:\n"
221  << ss.str() << "You could be trying to use parameter names that are not\n"
222  << "allowed for this plugin or they could be misspelled.\n";
223  }
224  }
225 
227  SetDescriptionEntry const& entry, std::ostream& os, bool& startWithComma, int indentation, bool& wroteSomething) {
228  if (entry.writeToCfi()) {
229  entry.node()->writeCfi(os, entry.optional(), startWithComma, indentation, wroteSomething);
230  }
231  }
232 
234  if (dfh.pass() < 2) {
235  entry.node()->print(os, entry.optional(), entry.writeToCfi(), dfh);
236  } else {
237  entry.node()->printNestedContent(os, entry.optional(), dfh);
238  }
239  }
240 
241  void ParameterSetDescription::throwIfLabelsAlreadyUsed(std::set<std::string> const& nodeLabels) {
242  std::set<std::string> duplicateLabels;
243  std::insert_iterator<std::set<std::string> > insertIter(duplicateLabels, duplicateLabels.begin());
244  std::set_intersection(nodeLabels.begin(), nodeLabels.end(), usedLabels_.begin(), usedLabels_.end(), insertIter);
245  if (duplicateLabels.empty()) {
246  usedLabels_.insert(nodeLabels.begin(), nodeLabels.end());
247  } else {
248  std::stringstream ss;
249  for (std::set<std::string>::const_iterator iter = duplicateLabels.begin(), iEnd = duplicateLabels.end();
250  iter != iEnd;
251  ++iter) {
252  ss << " \"" << *iter << "\"\n";
253  }
254  throw edm::Exception(errors::LogicError) << "Labels used in different nodes of a ParameterSetDescription\n"
255  << "must be unique. The following duplicate labels were detected:\n"
256  << ss.str() << "\n";
257  }
258  }
259 
260  void ParameterSetDescription::throwIfWildcardCollision(std::set<ParameterTypes> const& nodeParameterTypes,
261  std::set<ParameterTypes> const& nodeWildcardTypes) {
262  // 1. Check that the new wildcard types do not collide with the existing
263  // parameter types.
264  // 2. Check that the new parameter types do not collide with the existing
265  // wildcard types.
266  // 3. Then insert them.
267  // The order of those steps is important because a wildcard with a default
268  // value could insert a type in both sets and this is OK.
269 
270  // We assume the node already checked for collisions between the new parameter
271  // types and the new wildcard types before passing the sets to this function.
272 
273  if (!nodeWildcardTypes.empty()) {
274  std::set<ParameterTypes> duplicateTypes1;
275  std::insert_iterator<std::set<ParameterTypes> > insertIter1(duplicateTypes1, duplicateTypes1.begin());
278  nodeWildcardTypes.begin(),
279  nodeWildcardTypes.end(),
280  insertIter1);
281 
282  if (!duplicateTypes1.empty()) {
283  std::stringstream ss;
284  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes1.begin(), iEnd = duplicateTypes1.end();
285  iter != iEnd;
286  ++iter) {
287  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
288  }
290  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
291  << "not be the same as the type used for other parameters. This rule\n"
292  << "is violated for the following types:\n"
293  << ss.str() << "\n";
294  }
295  }
296 
297  if (!typesUsedForWildcards_.empty()) {
298  std::set<ParameterTypes> duplicateTypes2;
299  std::insert_iterator<std::set<ParameterTypes> > insertIter2(duplicateTypes2, duplicateTypes2.begin());
302  nodeParameterTypes.begin(),
303  nodeParameterTypes.end(),
304  insertIter2);
305 
306  if (!duplicateTypes2.empty()) {
307  std::stringstream ss;
308  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes2.begin(), iEnd = duplicateTypes2.end();
309  iter != iEnd;
310  ++iter) {
311  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
312  }
314  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
315  << "not be the same as the type used for other parameters. This rule is\n"
316  << "violated for the following types :\n"
317  << ss.str() << "\n";
318  }
319  }
320 
321  typesUsedForParameters_.insert(nodeParameterTypes.begin(), nodeParameterTypes.end());
322  typesUsedForWildcards_.insert(nodeWildcardTypes.begin(), nodeWildcardTypes.end());
323  }
324 
326  ParameterDescriptionNode const& node2,
327  bool optional,
328  bool writeToCfi) {
329  std::unique_ptr<ParameterDescriptionNode> pdIfExists = std::make_unique<IfExistsDescription>(node1, node2);
330  return addNode(std::move(pdIfExists), optional, writeToCfi);
331  }
332 } // 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:239
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)