File indexing completed on 2023-03-17 11:03:28
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), false, true);
0044 }
0045
0046 ParameterDescriptionNode* ParameterSetDescription::addNode(std::unique_ptr<ParameterDescriptionNode> node) {
0047 return addNode(std::move(node), false, 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), true, writeToCfi);
0054 }
0055
0056 ParameterDescriptionNode* ParameterSetDescription::addOptionalNode(std::unique_ptr<ParameterDescriptionNode> node,
0057 bool writeToCfi) {
0058 return addNode(std::move(node), true, writeToCfi);
0059 }
0060
0061 ParameterDescriptionNode* ParameterSetDescription::addNode(std::unique_ptr<ParameterDescriptionNode> node,
0062 bool optional,
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.setOptional(optional);
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 if (validatedLabels.size() != parameterNames.size()) {
0115 if (IllegalParameters::throwAnException() && !anythingAllowed()) {
0116 throwIllegalParameters(parameterNames, validatedLabels);
0117 }
0118 }
0119 }
0120 }
0121
0122 void ParameterSetDescription::writeCfi(std::ostream& os, bool startWithComma, int indentation) const {
0123 using std::placeholders::_1;
0124 bool wroteSomething = false;
0125
0126 for_all(entries_,
0127 std::bind(&ParameterSetDescription::writeNode,
0128 _1,
0129 std::ref(os),
0130 std::ref(startWithComma),
0131 indentation,
0132 std::ref(wroteSomething)));
0133
0134 if (wroteSomething) {
0135 char oldFill = os.fill();
0136 os << "\n" << std::setfill(' ') << std::setw(indentation - 2) << "" << std::setfill(oldFill);
0137 }
0138 }
0139
0140 void ParameterSetDescription::validateNode(SetDescriptionEntry const& entry,
0141 ParameterSet& pset,
0142 std::set<std::string>& validatedLabels) {
0143 entry.node()->validate(pset, validatedLabels, entry.optional());
0144 }
0145
0146 void ParameterSetDescription::print(std::ostream& os, DocFormatHelper& dfh) const {
0147 using std::placeholders::_1;
0148 if (isUnknown()) {
0149 dfh.indent(os);
0150 os << "Description is unknown. The configured PSet will not be validated\n";
0151 dfh.indent(os);
0152 os << "because the plugin has not defined this parameter set description.\n";
0153 if (!dfh.brief())
0154 os << "\n";
0155 }
0156
0157 if (anythingAllowed()) {
0158 dfh.indent(os);
0159 os << "Description allows anything. If the configured PSet contains illegal parameters,\n";
0160 dfh.indent(os);
0161 os << "then validation will ignore them instead of throwing an exception.\n";
0162 if (!dfh.brief())
0163 os << "\n";
0164 }
0165
0166 if (entries_.empty()) {
0167 dfh.indent(os);
0168 os << "Description is empty\n";
0169 if (!dfh.brief())
0170 os << "\n";
0171 return;
0172 }
0173
0174
0175 dfh.setPass(0);
0176 dfh.setCounter(0);
0177 for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
0178
0179
0180 dfh.setPass(1);
0181 dfh.setCounter(0);
0182 for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
0183
0184
0185
0186 dfh.setPass(2);
0187 dfh.setCounter(0);
0188 for_all(entries_, std::bind(&ParameterSetDescription::printNode, _1, std::ref(os), std::ref(dfh)));
0189 }
0190
0191 bool ParameterSetDescription::isLabelUnused(std::string const& label) const {
0192 return usedLabels_.find(label) == usedLabels_.end();
0193 }
0194
0195 void ParameterSetDescription::throwIllegalParameters(std::vector<std::string> const& parameterNames,
0196 std::set<std::string> const& validatedLabels) {
0197 std::set<std::string> parNames(parameterNames.begin(), parameterNames.end());
0198
0199 std::set<std::string> diffNames;
0200 std::insert_iterator<std::set<std::string> > insertIter(diffNames, diffNames.begin());
0201 std::set_difference(parNames.begin(), parNames.end(), validatedLabels.begin(), validatedLabels.end(), insertIter);
0202
0203 std::stringstream ss;
0204 for (std::set<std::string>::const_iterator iter = diffNames.begin(), iEnd = diffNames.end(); iter != iEnd; ++iter) {
0205 ss << " '" << *iter << "'\n";
0206 }
0207 if (diffNames.size() == 1U) {
0208 throw edm::Exception(errors::Configuration)
0209 << "Illegal parameter found in configuration. The parameter is named:\n"
0210 << ss.str() << "You could be trying to use a parameter name that is not\n"
0211 << "allowed for this plugin or it could be misspelled.\n";
0212 } else {
0213 throw edm::Exception(errors::Configuration)
0214 << "Illegal parameters found in configuration. The parameters are named:\n"
0215 << ss.str() << "You could be trying to use parameter names that are not\n"
0216 << "allowed for this plugin or they could be misspelled.\n";
0217 }
0218 }
0219
0220 void ParameterSetDescription::writeNode(
0221 SetDescriptionEntry const& entry, std::ostream& os, bool& startWithComma, int indentation, bool& wroteSomething) {
0222 if (entry.writeToCfi()) {
0223 entry.node()->writeCfi(os, entry.optional(), startWithComma, indentation, wroteSomething);
0224 }
0225 }
0226
0227 void ParameterSetDescription::printNode(SetDescriptionEntry const& entry, std::ostream& os, DocFormatHelper& dfh) {
0228 if (dfh.pass() < 2) {
0229 entry.node()->print(os, entry.optional(), entry.writeToCfi(), dfh);
0230 } else {
0231 entry.node()->printNestedContent(os, entry.optional(), dfh);
0232 }
0233 }
0234
0235 void ParameterSetDescription::throwIfLabelsAlreadyUsed(std::set<std::string> const& nodeLabels) {
0236 std::set<std::string> duplicateLabels;
0237 std::insert_iterator<std::set<std::string> > insertIter(duplicateLabels, duplicateLabels.begin());
0238 std::set_intersection(nodeLabels.begin(), nodeLabels.end(), usedLabels_.begin(), usedLabels_.end(), insertIter);
0239 if (duplicateLabels.empty()) {
0240 usedLabels_.insert(nodeLabels.begin(), nodeLabels.end());
0241 } else {
0242 std::stringstream ss;
0243 for (std::set<std::string>::const_iterator iter = duplicateLabels.begin(), iEnd = duplicateLabels.end();
0244 iter != iEnd;
0245 ++iter) {
0246 ss << " \"" << *iter << "\"\n";
0247 }
0248 throw edm::Exception(errors::LogicError) << "Labels used in different nodes of a ParameterSetDescription\n"
0249 << "must be unique. The following duplicate labels were detected:\n"
0250 << ss.str() << "\n";
0251 }
0252 }
0253
0254 void ParameterSetDescription::throwIfWildcardCollision(std::set<ParameterTypes> const& nodeParameterTypes,
0255 std::set<ParameterTypes> const& nodeWildcardTypes) {
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 if (!nodeWildcardTypes.empty()) {
0268 std::set<ParameterTypes> duplicateTypes1;
0269 std::insert_iterator<std::set<ParameterTypes> > insertIter1(duplicateTypes1, duplicateTypes1.begin());
0270 std::set_intersection(typesUsedForParameters_.begin(),
0271 typesUsedForParameters_.end(),
0272 nodeWildcardTypes.begin(),
0273 nodeWildcardTypes.end(),
0274 insertIter1);
0275
0276 if (!duplicateTypes1.empty()) {
0277 std::stringstream ss;
0278 for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes1.begin(), iEnd = duplicateTypes1.end();
0279 iter != iEnd;
0280 ++iter) {
0281 ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
0282 }
0283 throw edm::Exception(errors::LogicError)
0284 << "Within a ParameterSetDescription, the type used for a wildcard must\n"
0285 << "not be the same as the type used for other parameters. This rule\n"
0286 << "is violated for the following types:\n"
0287 << ss.str() << "\n";
0288 }
0289 }
0290
0291 if (!typesUsedForWildcards_.empty()) {
0292 std::set<ParameterTypes> duplicateTypes2;
0293 std::insert_iterator<std::set<ParameterTypes> > insertIter2(duplicateTypes2, duplicateTypes2.begin());
0294 std::set_intersection(typesUsedForWildcards_.begin(),
0295 typesUsedForWildcards_.end(),
0296 nodeParameterTypes.begin(),
0297 nodeParameterTypes.end(),
0298 insertIter2);
0299
0300 if (!duplicateTypes2.empty()) {
0301 std::stringstream ss;
0302 for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes2.begin(), iEnd = duplicateTypes2.end();
0303 iter != iEnd;
0304 ++iter) {
0305 ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
0306 }
0307 throw edm::Exception(errors::LogicError)
0308 << "Within a ParameterSetDescription, the type used for a wildcard must\n"
0309 << "not be the same as the type used for other parameters. This rule is\n"
0310 << "violated for the following types :\n"
0311 << ss.str() << "\n";
0312 }
0313 }
0314
0315 typesUsedForParameters_.insert(nodeParameterTypes.begin(), nodeParameterTypes.end());
0316 typesUsedForWildcards_.insert(nodeWildcardTypes.begin(), nodeWildcardTypes.end());
0317 }
0318
0319 ParameterDescriptionNode* ParameterSetDescription::ifExists(ParameterDescriptionNode const& node1,
0320 ParameterDescriptionNode const& node2,
0321 bool optional,
0322 bool writeToCfi) {
0323 std::unique_ptr<ParameterDescriptionNode> pdIfExists = std::make_unique<IfExistsDescription>(node1, node2);
0324 return addNode(std::move(pdIfExists), optional, writeToCfi);
0325 }
0326 }