CMS 3D CMS Logo

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