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 
129  bool startWithComma,
130  int indentation,
131  CfiOptions& options) const {
132  bool wroteSomething = false;
133 
134  bool seenWildcard = false;
135  bool seenMultipleWildcards = false;
136  for (auto const& entry : entries_) {
137  //only add the first seen wildcard to the cfi. This avoids possible ambiguities.
138  if (entry.node()->isWildcard()) {
139  if (seenWildcard == true) {
140  seenMultipleWildcards = true;
141  continue;
142  }
143  seenWildcard = true;
144  }
145  writeNode(entry, os, startWithComma, indentation, options, wroteSomething);
146  }
147 
148  if ((anythingAllowed() or seenMultipleWildcards)) {
150  }
151 
152  if (wroteSomething) {
153  char oldFill = os.fill();
154  os << "\n" << std::setfill(' ') << std::setw(indentation - 2) << "" << std::setfill(oldFill);
155  }
156  }
157 
160  std::set<std::string>& validatedLabels) {
161  entry.node()->validate(pset, validatedLabels, entry.optional());
162  }
163 
164  void ParameterSetDescription::print(std::ostream& os, DocFormatHelper& dfh) const {
165  using std::placeholders::_1;
166  if (isUnknown()) {
167  dfh.indent(os);
168  os << "Description is unknown. The configured PSet will not be validated\n";
169  dfh.indent(os);
170  os << "because the plugin has not defined this parameter set description.\n";
171  if (!dfh.brief())
172  os << "\n";
173  }
174 
175  if (anythingAllowed()) {
176  dfh.indent(os);
177  os << "Description allows anything. If the configured PSet contains illegal parameters,\n";
178  dfh.indent(os);
179  os << "then validation will ignore them instead of throwing an exception.\n";
180  if (!dfh.brief())
181  os << "\n";
182  }
183 
184  if (entries_.empty()) {
185  dfh.indent(os);
186  os << "Description is empty\n";
187  if (!dfh.brief())
188  os << "\n";
189  return;
190  }
191 
192  // Zeroth pass is only to calculate column widths in advance of any printing
193  dfh.setPass(0);
194  dfh.setCounter(0);
195  for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
196 
197  // First pass prints top level parameters and references to structure
198  dfh.setPass(1);
199  dfh.setCounter(0);
200  for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
201 
202  // Second pass prints substructure that goes into different sections of the
203  // output document
204  dfh.setPass(2);
205  dfh.setCounter(0);
206  for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
207  }
208 
210  return usedLabels_.find(label) == usedLabels_.end();
211  }
212 
213  void ParameterSetDescription::throwIllegalParameters(std::vector<std::string> const& parameterNames,
214  std::set<std::string> const& validatedLabels) {
215  std::set<std::string> parNames(parameterNames.begin(), parameterNames.end());
216 
217  std::set<std::string> diffNames;
218  std::insert_iterator<std::set<std::string> > insertIter(diffNames, diffNames.begin());
219  std::set_difference(parNames.begin(), parNames.end(), validatedLabels.begin(), validatedLabels.end(), insertIter);
220 
221  std::stringstream ss;
222  for (std::set<std::string>::const_iterator iter = diffNames.begin(), iEnd = diffNames.end(); iter != iEnd; ++iter) {
223  ss << " '" << *iter << "'\n";
224  }
225  if (diffNames.size() == 1U) {
227  << "Illegal parameter found in configuration. The parameter is named:\n"
228  << ss.str() << "You could be trying to use a parameter name that is not\n"
229  << "allowed for this plugin or it could be misspelled.\n";
230  } else {
232  << "Illegal parameters found in configuration. The parameters are named:\n"
233  << ss.str() << "You could be trying to use parameter names that are not\n"
234  << "allowed for this plugin or they could be misspelled.\n";
235  }
236  }
237 
239  std::ostream& os,
240  bool& startWithComma,
241  int indentation,
243  bool& wroteSomething) {
244  if (entry.writeToCfi()) {
245  entry.node()->writeCfi(os, entry.optional(), startWithComma, indentation, options, wroteSomething);
246  } else {
247  //The simplest way to handle this is to force all items to be full in this PSet
249  }
250  }
251 
253  if (dfh.pass() < 2) {
254  entry.node()->print(os, entry.optional(), entry.writeToCfi(), dfh);
255  } else {
256  entry.node()->printNestedContent(os, entry.optional(), dfh);
257  }
258  }
259 
260  void ParameterSetDescription::throwIfLabelsAlreadyUsed(std::set<std::string> const& nodeLabels) {
261  std::set<std::string> duplicateLabels;
262  std::insert_iterator<std::set<std::string> > insertIter(duplicateLabels, duplicateLabels.begin());
263  std::set_intersection(nodeLabels.begin(), nodeLabels.end(), usedLabels_.begin(), usedLabels_.end(), insertIter);
264  if (duplicateLabels.empty()) {
265  usedLabels_.insert(nodeLabels.begin(), nodeLabels.end());
266  } else {
267  std::stringstream ss;
268  for (std::set<std::string>::const_iterator iter = duplicateLabels.begin(), iEnd = duplicateLabels.end();
269  iter != iEnd;
270  ++iter) {
271  ss << " \"" << *iter << "\"\n";
272  }
273  throw edm::Exception(errors::LogicError) << "Labels used in different nodes of a ParameterSetDescription\n"
274  << "must be unique. The following duplicate labels were detected:\n"
275  << ss.str() << "\n";
276  }
277  }
278 
279  void ParameterSetDescription::throwIfWildcardCollision(std::set<ParameterTypes> const& nodeParameterTypes,
280  std::set<ParameterTypes> const& nodeWildcardTypes) {
281  // 1. Check that the new wildcard types do not collide with the existing
282  // parameter types.
283  // 2. Check that the new parameter types do not collide with the existing
284  // wildcard types.
285  // 3. Then insert them.
286  // The order of those steps is important because a wildcard with a default
287  // value could insert a type in both sets and this is OK.
288 
289  // We assume the node already checked for collisions between the new parameter
290  // types and the new wildcard types before passing the sets to this function.
291 
292  if (!nodeWildcardTypes.empty()) {
293  std::set<ParameterTypes> duplicateTypes1;
294  std::insert_iterator<std::set<ParameterTypes> > insertIter1(duplicateTypes1, duplicateTypes1.begin());
297  nodeWildcardTypes.begin(),
298  nodeWildcardTypes.end(),
299  insertIter1);
300 
301  if (!duplicateTypes1.empty()) {
302  std::stringstream ss;
303  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes1.begin(), iEnd = duplicateTypes1.end();
304  iter != iEnd;
305  ++iter) {
306  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
307  }
309  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
310  << "not be the same as the type used for other parameters. This rule\n"
311  << "is violated for the following types:\n"
312  << ss.str() << "\n";
313  }
314  }
315 
316  if (!typesUsedForWildcards_.empty()) {
317  std::set<ParameterTypes> duplicateTypes2;
318  std::insert_iterator<std::set<ParameterTypes> > insertIter2(duplicateTypes2, duplicateTypes2.begin());
321  nodeParameterTypes.begin(),
322  nodeParameterTypes.end(),
323  insertIter2);
324 
325  if (!duplicateTypes2.empty()) {
326  std::stringstream ss;
327  for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes2.begin(), iEnd = duplicateTypes2.end();
328  iter != iEnd;
329  ++iter) {
330  ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
331  }
333  << "Within a ParameterSetDescription, the type used for a wildcard must\n"
334  << "not be the same as the type used for other parameters. This rule is\n"
335  << "violated for the following types :\n"
336  << ss.str() << "\n";
337  }
338  }
339 
340  typesUsedForParameters_.insert(nodeParameterTypes.begin(), nodeParameterTypes.end());
341  typesUsedForWildcards_.insert(nodeWildcardTypes.begin(), nodeWildcardTypes.end());
342  }
343 
345  ParameterDescriptionNode const& node2,
346  bool optional,
347  bool writeToCfi) {
348  std::unique_ptr<ParameterDescriptionNode> pdIfExists = std::make_unique<IfExistsDescription>(node1, node2);
349  return addNode(std::move(pdIfExists), optional, writeToCfi);
350  }
351 } // 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)
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:14
char const * label
void setComment(std::string const &value)
void parameterMustBeTyped(CfiOptions &iOps) noexcept
void throwIfLabelsAlreadyUsed(std::set< std::string > const &nodeLabels)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
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_
static void writeNode(SetDescriptionEntry const &entry, std::ostream &os, bool &startWithComma, int indentation, CfiOptions &, bool &wroteSomething)
HLT enums.
void indent(std::ostream &os) const
void writeCfi(std::ostream &os, bool startWithComma, int indentation, CfiOptions &) 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
cfi::CfiOptions CfiOptions
std::vector< std::string > set_intersection(std::vector< std::string > const &v1, std::vector< std::string > const &v2)