00001
00002 #include "FWCore/ParameterSet/interface/ORGroupDescription.h"
00003 #include "FWCore/Utilities/interface/EDMException.h"
00004 #include "FWCore/ParameterSet/interface/DocFormatHelper.h"
00005
00006 #include <algorithm>
00007 #include <sstream>
00008 #include <ostream>
00009 #include <iomanip>
00010
00011 namespace edm {
00012
00013 ORGroupDescription::
00014 ORGroupDescription(ParameterDescriptionNode const& node_left,
00015 ParameterDescriptionNode const& node_right) :
00016 node_left_(node_left.clone()),
00017 node_right_(node_right.clone()) {
00018 }
00019
00020 ORGroupDescription::
00021 ORGroupDescription(std::auto_ptr<ParameterDescriptionNode> node_left,
00022 ParameterDescriptionNode const& node_right) :
00023 node_left_(node_left),
00024 node_right_(node_right.clone()) {
00025 }
00026
00027 ORGroupDescription::
00028 ORGroupDescription(ParameterDescriptionNode const& node_left,
00029 std::auto_ptr<ParameterDescriptionNode> node_right) :
00030 node_left_(node_left.clone()),
00031 node_right_(node_right) {
00032 }
00033
00034 ORGroupDescription::
00035 ORGroupDescription(std::auto_ptr<ParameterDescriptionNode> node_left,
00036 std::auto_ptr<ParameterDescriptionNode> node_right) :
00037 node_left_(node_left),
00038 node_right_(node_right) {
00039 }
00040
00041 void
00042 ORGroupDescription::
00043 checkAndGetLabelsAndTypes_(std::set<std::string> & usedLabels,
00044 std::set<ParameterTypes> & parameterTypes,
00045 std::set<ParameterTypes> & wildcardTypes) const {
00046
00047 std::set<std::string> labelsLeft;
00048 std::set<ParameterTypes> parameterTypesLeft;
00049 std::set<ParameterTypes> wildcardTypesLeft;
00050 node_left_->checkAndGetLabelsAndTypes(labelsLeft, parameterTypesLeft, wildcardTypesLeft);
00051
00052 std::set<std::string> labelsRight;
00053 std::set<ParameterTypes> parameterTypesRight;
00054 std::set<ParameterTypes> wildcardTypesRight;
00055 node_right_->checkAndGetLabelsAndTypes(labelsRight, parameterTypesRight, wildcardTypesRight);
00056
00057 throwIfDuplicateLabels(labelsLeft, labelsRight);
00058 throwIfDuplicateTypes(wildcardTypesLeft, parameterTypesRight);
00059 throwIfDuplicateTypes(wildcardTypesRight, parameterTypesLeft);
00060
00061 usedLabels.insert(labelsLeft.begin(), labelsLeft.end());
00062 usedLabels.insert(labelsRight.begin(), labelsRight.end());
00063
00064 parameterTypes.insert(parameterTypesRight.begin(), parameterTypesRight.end());
00065 parameterTypes.insert(parameterTypesLeft.begin(), parameterTypesLeft.end());
00066
00067 wildcardTypes.insert(wildcardTypesRight.begin(), wildcardTypesRight.end());
00068 wildcardTypes.insert(wildcardTypesLeft.begin(), wildcardTypesLeft.end());
00069 }
00070
00071 void
00072 ORGroupDescription::
00073 validate_(ParameterSet & pset,
00074 std::set<std::string> & validatedLabels,
00075 bool optional) const {
00076
00077 bool leftExists = node_left_->exists(pset);
00078 bool rightExists = node_right_->exists(pset);
00079
00080 if (leftExists || rightExists) {
00081 if (leftExists) node_left_->validate(pset, validatedLabels, false);
00082 if (rightExists) node_right_->validate(pset, validatedLabels, false);
00083 return;
00084 }
00085
00086 if (optional) return;
00087
00088 node_left_->validate(pset, validatedLabels, false);
00089 }
00090
00091 void
00092 ORGroupDescription::
00093 writeCfi_(std::ostream & os,
00094 bool & startWithComma,
00095 int indentation,
00096 bool & wroteSomething) const {
00097 node_left_->writeCfi(os, startWithComma, indentation, wroteSomething);
00098 }
00099
00100 void
00101 ORGroupDescription::
00102 print_(std::ostream & os,
00103 bool optional,
00104 bool writeToCfi,
00105 DocFormatHelper & dfh) {
00106
00107 if (dfh.parent() == DocFormatHelper::OR) {
00108 dfh.decrementCounter();
00109 node_left_->print(os, false, true, dfh);
00110 node_right_->print(os, false, true, dfh);
00111 return;
00112 }
00113
00114 if (dfh.pass() == 1) {
00115
00116 dfh.indent(os);
00117 os << "OR group:";
00118
00119 if (dfh.brief()) {
00120
00121 if (optional) os << " optional";
00122
00123 if (!writeToCfi) os << " (do not write to cfi)";
00124
00125 os << " see Section " << dfh.section() << "." << dfh.counter() << "\n";
00126 }
00127
00128 else {
00129
00130 os << "\n";
00131 dfh.indent2(os);
00132
00133 if (optional) os << "optional";
00134 if (!writeToCfi) os << " (do not write to cfi)";
00135 if (optional || !writeToCfi) {
00136 os << "\n";
00137 dfh.indent2(os);
00138 }
00139
00140 os << "see Section " << dfh.section() << "." << dfh.counter() << "\n";
00141
00142 if (!comment().empty()) {
00143 DocFormatHelper::wrapAndPrintText(os,
00144 comment(),
00145 dfh.startColumn2(),
00146 dfh.commentWidth());
00147 }
00148 os << "\n";
00149 }
00150 }
00151 }
00152
00153 void
00154 ORGroupDescription::
00155 printNestedContent_(std::ostream & os,
00156 bool optional,
00157 DocFormatHelper & dfh) {
00158
00159 if (dfh.parent() == DocFormatHelper::OR) {
00160 dfh.decrementCounter();
00161 node_left_->printNestedContent(os, false, dfh);
00162 node_right_->printNestedContent(os, false, dfh);
00163 return;
00164 }
00165
00166 int indentation = dfh.indentation();
00167 if (dfh.parent() != DocFormatHelper::TOP) {
00168 indentation -= DocFormatHelper::offsetSectionContent();
00169 }
00170
00171 std::stringstream ss;
00172 ss << dfh.section() << "." << dfh.counter();
00173 std::string newSection = ss.str();
00174
00175 printSpaces(os, indentation);
00176 os << "Section " << newSection
00177 << " OR group description:\n";
00178 printSpaces(os, indentation);
00179 if (optional) {
00180
00181
00182
00183 os << "This optional OR group requires at least one or none of the following to be in the PSet\n";
00184 }
00185 else {
00186 os << "This OR group requires at least one of the following to be in the PSet\n";
00187 }
00188 if (!dfh.brief()) os << "\n";
00189
00190 DocFormatHelper new_dfh(dfh);
00191 new_dfh.init();
00192 new_dfh.setSection(newSection);
00193 new_dfh.setIndentation(indentation + DocFormatHelper::offsetSectionContent());
00194 new_dfh.setParent(DocFormatHelper::OR);
00195
00196 node_left_->print(os, false, true, new_dfh);
00197 node_right_->print(os, false, true, new_dfh);
00198
00199 new_dfh.setPass(1);
00200 new_dfh.setCounter(0);
00201
00202 node_left_->print(os, false, true, new_dfh);
00203 node_right_->print(os, false, true, new_dfh);
00204
00205 new_dfh.setPass(2);
00206 new_dfh.setCounter(0);
00207
00208 node_left_->printNestedContent(os, false, new_dfh);
00209 node_right_->printNestedContent(os, false, new_dfh);
00210 }
00211
00212 bool
00213 ORGroupDescription::
00214 exists_(ParameterSet const& pset) const {
00215 return node_left_->exists(pset) ||
00216 node_right_->exists(pset);
00217 }
00218
00219 bool
00220 ORGroupDescription::
00221 partiallyExists_(ParameterSet const& pset) const {
00222 return exists(pset);
00223 }
00224
00225 int
00226 ORGroupDescription::
00227 howManyXORSubNodesExist_(ParameterSet const& pset) const {
00228 return exists(pset) ? 1 : 0;
00229 }
00230
00231 void
00232 ORGroupDescription::
00233 throwIfDuplicateLabels(std::set<std::string> const& labelsLeft,
00234 std::set<std::string> const& labelsRight) const {
00235
00236 std::set<std::string> duplicateLabels;
00237 std::insert_iterator<std::set<std::string> > insertIter(duplicateLabels, duplicateLabels.begin());
00238 std::set_intersection(labelsLeft.begin(), labelsLeft.end(),
00239 labelsRight.begin(), labelsRight.end(),
00240 insertIter);
00241 if (!duplicateLabels.empty()) {
00242 std::stringstream ss;
00243 for (std::set<std::string>::const_iterator iter = duplicateLabels.begin(),
00244 iEnd = duplicateLabels.end();
00245 iter != iEnd;
00246 ++iter) {
00247 ss << " \"" << *iter << "\"\n";
00248 }
00249 throw edm::Exception(errors::LogicError)
00250 << "Labels used in a node of a ParameterSetDescription\n"
00251 << "\"or\" expression must be not be the same as labels used\n"
00252 << "in other nodes of the expression. The following duplicate\n"
00253 << "labels were detected:\n"
00254 << ss.str()
00255 << "\n";
00256 }
00257 }
00258
00259 void
00260 ORGroupDescription::
00261 throwIfDuplicateTypes(std::set<ParameterTypes> const& types1,
00262 std::set<ParameterTypes> const& types2) const
00263 {
00264 if (!types1.empty()) {
00265 std::set<ParameterTypes> duplicateTypes;
00266 std::insert_iterator<std::set<ParameterTypes> > insertIter(duplicateTypes, duplicateTypes.begin());
00267 std::set_intersection(types1.begin(), types1.end(),
00268 types2.begin(), types2.end(),
00269 insertIter);
00270 if (!duplicateTypes.empty()) {
00271 std::stringstream ss;
00272 for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes.begin(),
00273 iEnd = duplicateTypes.end();
00274 iter != iEnd;
00275 ++iter) {
00276 ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
00277 }
00278 throw edm::Exception(errors::LogicError)
00279 << "Types used for wildcards in a node of a ParameterSetDescription\n"
00280 << "\"or\" expression must be different from types used for other parameters\n"
00281 << "in other nodes. The following duplicate types were detected:\n"
00282 << ss.str()
00283 << "\n";
00284 }
00285 }
00286 }
00287 }