File indexing completed on 2025-03-26 01:51:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0014
0015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0016 #include "FWCore/ParameterSet/interface/IfExistsDescription.h"
0017 #include "FWCore/ParameterSet/interface/IllegalParameters.h"
0018 #include "FWCore/ParameterSet/interface/DocFormatHelper.h"
0019 #include "FWCore/Utilities/interface/Algorithms.h"
0020 #include "FWCore/Utilities/interface/EDMException.h"
0021
0022 #include <sstream>
0023 #include <ostream>
0024 #include <iomanip>
0025 #include <algorithm>
0026
0027 namespace edm {
0028
0029 ParameterSetDescription::ParameterSetDescription() : anythingAllowed_(false), unknown_(false) {}
0030
0031 ParameterSetDescription::~ParameterSetDescription() {}
0032
0033 void ParameterSetDescription::setComment(std::string const& value) { comment_ = value; }
0034
0035 void ParameterSetDescription::setComment(char const* value) { comment_ = value; }
0036
0037 void ParameterSetDescription::setAllowAnything() { anythingAllowed_ = true; }
0038
0039 void ParameterSetDescription::setUnknown() { unknown_ = true; }
0040
0041 ParameterDescriptionNode* ParameterSetDescription::addNode(ParameterDescriptionNode const& node) {
0042 std::unique_ptr<ParameterDescriptionNode> clonedNode(node.clone());
0043 return addNode(std::move(clonedNode), Modifier::kNone, true);
0044 }
0045
0046 ParameterDescriptionNode* ParameterSetDescription::addNode(std::unique_ptr<ParameterDescriptionNode> node) {
0047 return addNode(std::move(node), Modifier::kNone, true);
0048 }
0049
0050 ParameterDescriptionNode* ParameterSetDescription::addOptionalNode(ParameterDescriptionNode const& node,
0051 bool writeToCfi) {
0052 std::unique_ptr<ParameterDescriptionNode> clonedNode(node.clone());
0053 return addNode(std::move(clonedNode), Modifier::kOptional, writeToCfi);
0054 }
0055
0056 ParameterDescriptionNode* ParameterSetDescription::addOptionalNode(std::unique_ptr<ParameterDescriptionNode> node,
0057 bool writeToCfi) {
0058 return addNode(std::move(node), Modifier::kOptional, writeToCfi);
0059 }
0060
0061 ParameterDescriptionNode* ParameterSetDescription::addNode(std::unique_ptr<ParameterDescriptionNode> node,
0062 Modifier modifier,
0063 bool writeToCfi) {
0064 std::set<std::string> nodeLabels;
0065 std::set<ParameterTypes> nodeParameterTypes;
0066 std::set<ParameterTypes> nodeWildcardTypes;
0067 node->checkAndGetLabelsAndTypes(nodeLabels, nodeParameterTypes, nodeWildcardTypes);
0068 throwIfLabelsAlreadyUsed(nodeLabels);
0069 throwIfWildcardCollision(nodeParameterTypes, nodeWildcardTypes);
0070
0071 SetDescriptionEntry entry;
0072 entry.setModifier(modifier);
0073 entry.setWriteToCfi(writeToCfi);
0074 entries_.push_back(entry);
0075 return entries_.back().setNode(std::move(node));
0076 }
0077
0078 void ParameterSetDescription::validate(ParameterSet& pset) const {
0079 using std::placeholders::_1;
0080 if (unknown_)
0081 return;
0082
0083 std::set<std::string> validatedLabels;
0084 for_all(entries_, std::bind(&ParameterSetDescription::validateNode, _1, std::ref(pset), std::ref(validatedLabels)));
0085
0086 std::vector<std::string> parameterNames = pset.getParameterNames();
0087 if (validatedLabels.size() != parameterNames.size()) {
0088
0089
0090
0091
0092
0093 std::string module_label("@module_label");
0094 if (pset.exists(module_label)) {
0095 validatedLabels.insert(module_label);
0096 }
0097
0098 std::string module_type("@module_type");
0099 if (pset.exists(module_type)) {
0100 validatedLabels.insert(module_type);
0101 }
0102
0103 std::string module_edm_type("@module_edm_type");
0104 if (pset.exists(module_edm_type)) {
0105 validatedLabels.insert(module_edm_type);
0106 }
0107
0108 std::string service_type("@service_type");
0109 if (pset.exists(service_type)) {
0110 validatedLabels.insert(service_type);
0111 }
0112
0113 {
0114 std::string tryToContinue("@shouldTryToContinue");
0115 if (pset.exists(tryToContinue)) {
0116 validatedLabels.insert(tryToContinue);
0117 }
0118 }
0119
0120 if (validatedLabels.size() != parameterNames.size()) {
0121 if (IllegalParameters::throwAnException() && !anythingAllowed()) {
0122 throwIllegalParameters(parameterNames, validatedLabels);
0123 }
0124 }
0125 }
0126 }
0127
0128 void ParameterSetDescription::writeCfi(std::ostream& os,
0129 bool startWithComma,
0130 int indentation,
0131 CfiOptions& options) const {
0132 bool wroteSomething = false;
0133
0134 bool seenWildcard = false;
0135 bool seenMultipleWildcards = false;
0136 for (auto const& entry : entries_) {
0137
0138 if (entry.node()->isWildcard()) {
0139 if (seenWildcard == true) {
0140 seenMultipleWildcards = true;
0141 continue;
0142 }
0143 seenWildcard = true;
0144 }
0145 writeNode(entry, os, startWithComma, indentation, options, wroteSomething);
0146 }
0147
0148 if ((anythingAllowed() or seenMultipleWildcards)) {
0149 cfi::parameterMustBeTyped(options);
0150 }
0151
0152 if (wroteSomething) {
0153 char oldFill = os.fill();
0154 os << "\n" << std::setfill(' ') << std::setw(indentation - 2) << "" << std::setfill(oldFill);
0155 }
0156 }
0157
0158 void ParameterSetDescription::validateNode(SetDescriptionEntry const& entry,
0159 ParameterSet& pset,
0160 std::set<std::string>& validatedLabels) {
0161 entry.node()->validate(pset, validatedLabels, entry.modifier());
0162 }
0163
0164 void ParameterSetDescription::print(std::ostream& os, DocFormatHelper& dfh) const {
0165 using std::placeholders::_1;
0166 if (isUnknown()) {
0167 dfh.indent(os);
0168 os << "Description is unknown. The configured PSet will not be validated\n";
0169 dfh.indent(os);
0170 os << "because the plugin has not defined this parameter set description.\n";
0171 if (!dfh.brief())
0172 os << "\n";
0173 }
0174
0175 if (anythingAllowed()) {
0176 dfh.indent(os);
0177 os << "Description allows anything. If the configured PSet contains illegal parameters,\n";
0178 dfh.indent(os);
0179 os << "then validation will ignore them instead of throwing an exception.\n";
0180 if (!dfh.brief())
0181 os << "\n";
0182 }
0183
0184 if (entries_.empty()) {
0185 dfh.indent(os);
0186 os << "Description is empty\n";
0187 if (!dfh.brief())
0188 os << "\n";
0189 return;
0190 }
0191
0192
0193 dfh.setPass(0);
0194 dfh.setCounter(0);
0195 for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
0196
0197
0198 dfh.setPass(1);
0199 dfh.setCounter(0);
0200 for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
0201
0202
0203
0204 dfh.setPass(2);
0205 dfh.setCounter(0);
0206 for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
0207 }
0208
0209 bool ParameterSetDescription::isLabelUnused(std::string const& label) const {
0210 return usedLabels_.find(label) == usedLabels_.end();
0211 }
0212
0213 void ParameterSetDescription::throwIllegalParameters(std::vector<std::string> const& parameterNames,
0214 std::set<std::string> const& validatedLabels) {
0215 std::set<std::string> parNames(parameterNames.begin(), parameterNames.end());
0216
0217 std::set<std::string> diffNames;
0218 std::insert_iterator<std::set<std::string> > insertIter(diffNames, diffNames.begin());
0219 std::set_difference(parNames.begin(), parNames.end(), validatedLabels.begin(), validatedLabels.end(), insertIter);
0220
0221 std::stringstream ss;
0222 for (std::set<std::string>::const_iterator iter = diffNames.begin(), iEnd = diffNames.end(); iter != iEnd; ++iter) {
0223 ss << " '" << *iter << "'\n";
0224 }
0225 if (diffNames.size() == 1U) {
0226 throw edm::Exception(errors::Configuration)
0227 << "Illegal parameter found in configuration. The parameter is named:\n"
0228 << ss.str() << "You could be trying to use a parameter name that is not\n"
0229 << "allowed for this plugin or it could be misspelled.\n";
0230 } else {
0231 throw edm::Exception(errors::Configuration)
0232 << "Illegal parameters found in configuration. The parameters are named:\n"
0233 << ss.str() << "You could be trying to use parameter names that are not\n"
0234 << "allowed for this plugin or they could be misspelled.\n";
0235 }
0236 }
0237
0238 void ParameterSetDescription::writeNode(SetDescriptionEntry const& entry,
0239 std::ostream& os,
0240 bool& startWithComma,
0241 int indentation,
0242 CfiOptions& options,
0243 bool& wroteSomething) {
0244 if (entry.writeToCfi()) {
0245 entry.node()->writeCfi(os, entry.modifier(), startWithComma, indentation, options, wroteSomething);
0246 } else {
0247
0248 cfi::parameterMustBeTyped(options);
0249 }
0250 }
0251
0252 void ParameterSetDescription::printNode(SetDescriptionEntry const& entry, std::ostream& os, DocFormatHelper& dfh) {
0253 if (dfh.pass() < 2) {
0254 entry.node()->print(os, entry.modifier(), entry.writeToCfi(), dfh);
0255 } else {
0256 entry.node()->printNestedContent(os, entry.optional(), dfh);
0257 }
0258 }
0259
0260 void ParameterSetDescription::throwIfLabelsAlreadyUsed(std::set<std::string> const& nodeLabels) {
0261 std::set<std::string> duplicateLabels;
0262 std::insert_iterator<std::set<std::string> > insertIter(duplicateLabels, duplicateLabels.begin());
0263 std::set_intersection(nodeLabels.begin(), nodeLabels.end(), usedLabels_.begin(), usedLabels_.end(), insertIter);
0264 if (duplicateLabels.empty()) {
0265 usedLabels_.insert(nodeLabels.begin(), nodeLabels.end());
0266 } else {
0267 std::stringstream ss;
0268 for (std::set<std::string>::const_iterator iter = duplicateLabels.begin(), iEnd = duplicateLabels.end();
0269 iter != iEnd;
0270 ++iter) {
0271 ss << " \"" << *iter << "\"\n";
0272 }
0273 throw edm::Exception(errors::LogicError) << "Labels used in different nodes of a ParameterSetDescription\n"
0274 << "must be unique. The following duplicate labels were detected:\n"
0275 << ss.str() << "\n";
0276 }
0277 }
0278
0279 void ParameterSetDescription::throwIfWildcardCollision(std::set<ParameterTypes> const& nodeParameterTypes,
0280 std::set<ParameterTypes> const& nodeWildcardTypes) {
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292 if (!nodeWildcardTypes.empty()) {
0293 std::set<ParameterTypes> duplicateTypes1;
0294 std::insert_iterator<std::set<ParameterTypes> > insertIter1(duplicateTypes1, duplicateTypes1.begin());
0295 std::set_intersection(typesUsedForParameters_.begin(),
0296 typesUsedForParameters_.end(),
0297 nodeWildcardTypes.begin(),
0298 nodeWildcardTypes.end(),
0299 insertIter1);
0300
0301 if (!duplicateTypes1.empty()) {
0302 std::stringstream ss;
0303 for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes1.begin(), iEnd = duplicateTypes1.end();
0304 iter != iEnd;
0305 ++iter) {
0306 ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
0307 }
0308 throw edm::Exception(errors::LogicError)
0309 << "Within a ParameterSetDescription, the type used for a wildcard must\n"
0310 << "not be the same as the type used for other parameters. This rule\n"
0311 << "is violated for the following types:\n"
0312 << ss.str() << "\n";
0313 }
0314 }
0315
0316 if (!typesUsedForWildcards_.empty()) {
0317 std::set<ParameterTypes> duplicateTypes2;
0318 std::insert_iterator<std::set<ParameterTypes> > insertIter2(duplicateTypes2, duplicateTypes2.begin());
0319 std::set_intersection(typesUsedForWildcards_.begin(),
0320 typesUsedForWildcards_.end(),
0321 nodeParameterTypes.begin(),
0322 nodeParameterTypes.end(),
0323 insertIter2);
0324
0325 if (!duplicateTypes2.empty()) {
0326 std::stringstream ss;
0327 for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes2.begin(), iEnd = duplicateTypes2.end();
0328 iter != iEnd;
0329 ++iter) {
0330 ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
0331 }
0332 throw edm::Exception(errors::LogicError)
0333 << "Within a ParameterSetDescription, the type used for a wildcard must\n"
0334 << "not be the same as the type used for other parameters. This rule is\n"
0335 << "violated for the following types :\n"
0336 << ss.str() << "\n";
0337 }
0338 }
0339
0340 typesUsedForParameters_.insert(nodeParameterTypes.begin(), nodeParameterTypes.end());
0341 typesUsedForWildcards_.insert(nodeWildcardTypes.begin(), nodeWildcardTypes.end());
0342 }
0343
0344 ParameterDescriptionNode* ParameterSetDescription::ifExists(ParameterDescriptionNode const& node1,
0345 ParameterDescriptionNode const& node2,
0346 Modifier modifier,
0347 bool writeToCfi) {
0348 std::unique_ptr<ParameterDescriptionNode> pdIfExists = std::make_unique<IfExistsDescription>(node1, node2);
0349 return addNode(std::move(pdIfExists), modifier, writeToCfi);
0350 }
0351 }