00001
00002 #include "FWCore/ParameterSet/interface/ANDGroupDescription.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 ANDGroupDescription::
00014 ANDGroupDescription(ParameterDescriptionNode const& node_left,
00015 ParameterDescriptionNode const& node_right) :
00016 node_left_(node_left.clone()),
00017 node_right_(node_right.clone()) {
00018 }
00019
00020 ANDGroupDescription::
00021 ANDGroupDescription(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 ANDGroupDescription::
00028 ANDGroupDescription(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 ANDGroupDescription::
00035 ANDGroupDescription(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 ANDGroupDescription::
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 ANDGroupDescription::
00073 validate_(ParameterSet & pset,
00074 std::set<std::string> & validatedLabels,
00075 bool optional) const {
00076 if (partiallyExists(pset) || !optional) {
00077 node_left_->validate(pset, validatedLabels, false);
00078 node_right_->validate(pset, validatedLabels, false);
00079 }
00080 }
00081
00082 void
00083 ANDGroupDescription::
00084 writeCfi_(std::ostream & os,
00085 bool & startWithComma,
00086 int indentation,
00087 bool & wroteSomething) const {
00088 node_left_->writeCfi(os, startWithComma, indentation, wroteSomething);
00089 node_right_->writeCfi(os, startWithComma, indentation, wroteSomething);
00090 }
00091
00092 void
00093 ANDGroupDescription::
00094 print_(std::ostream & os,
00095 bool optional,
00096 bool writeToCfi,
00097 DocFormatHelper & dfh) {
00098
00099 if (dfh.parent() == DocFormatHelper::AND) {
00100 dfh.decrementCounter();
00101 node_left_->print(os, false, true, dfh);
00102 node_right_->print(os, false, true, dfh);
00103 return;
00104 }
00105
00106 if (dfh.pass() == 1) {
00107
00108 dfh.indent(os);
00109 os << "AND group:";
00110
00111 if (dfh.brief()) {
00112
00113 if (optional) os << " optional";
00114
00115 if (!writeToCfi) os << " (do not write to cfi)";
00116
00117 os << " see Section " << dfh.section() << "." << dfh.counter() << "\n";
00118 }
00119
00120 else {
00121
00122 os << "\n";
00123 dfh.indent2(os);
00124
00125 if (optional) os << "optional";
00126 if (!writeToCfi) os << " (do not write to cfi)";
00127 if (optional || !writeToCfi) {
00128 os << "\n";
00129 dfh.indent2(os);
00130 }
00131
00132 os << "see Section " << dfh.section() << "." << dfh.counter() << "\n";
00133
00134 if (!comment().empty()) {
00135 DocFormatHelper::wrapAndPrintText(os,
00136 comment(),
00137 dfh.startColumn2(),
00138 dfh.commentWidth());
00139 }
00140 os << "\n";
00141 }
00142 }
00143 }
00144
00145 void
00146 ANDGroupDescription::
00147 printNestedContent_(std::ostream & os,
00148 bool optional,
00149 DocFormatHelper & dfh) {
00150
00151 if (dfh.parent() == DocFormatHelper::AND) {
00152 dfh.decrementCounter();
00153 node_left_->printNestedContent(os, false, dfh);
00154 node_right_->printNestedContent(os, false, dfh);
00155 return;
00156 }
00157
00158 int indentation = dfh.indentation();
00159 if (dfh.parent() != DocFormatHelper::TOP) {
00160 indentation -= DocFormatHelper::offsetSectionContent();
00161 }
00162
00163 std::stringstream ss;
00164 ss << dfh.section() << "." << dfh.counter();
00165 std::string newSection = ss.str();
00166
00167 printSpaces(os, indentation);
00168 os << "Section " << newSection
00169 << " AND group description:\n";
00170 printSpaces(os, indentation);
00171 if (optional) {
00172 os << "This optional AND group requires all or none of the following to be in the PSet\n";
00173 }
00174 else {
00175 os << "This AND group requires all of the following to be in the PSet\n";
00176 }
00177 if (!dfh.brief()) os << "\n";
00178
00179 DocFormatHelper new_dfh(dfh);
00180 new_dfh.init();
00181 new_dfh.setSection(newSection);
00182 new_dfh.setIndentation(indentation + DocFormatHelper::offsetSectionContent());
00183 new_dfh.setParent(DocFormatHelper::AND);
00184
00185 node_left_->print(os, false, true, new_dfh);
00186 node_right_->print(os, false, true, new_dfh);
00187
00188 new_dfh.setPass(1);
00189 new_dfh.setCounter(0);
00190
00191 node_left_->print(os, false, true, new_dfh);
00192 node_right_->print(os, false, true, new_dfh);
00193
00194 new_dfh.setPass(2);
00195 new_dfh.setCounter(0);
00196
00197 node_left_->printNestedContent(os, false, new_dfh);
00198 node_right_->printNestedContent(os, false, new_dfh);
00199 }
00200
00201 bool
00202 ANDGroupDescription::
00203 exists_(ParameterSet const& pset) const {
00204 return node_left_->exists(pset) && node_right_->exists(pset);
00205 }
00206
00207 bool
00208 ANDGroupDescription::
00209 partiallyExists_(ParameterSet const& pset) const {
00210 return node_left_->partiallyExists(pset) || node_right_->partiallyExists(pset);
00211 }
00212
00213 int
00214 ANDGroupDescription::
00215 howManyXORSubNodesExist_(ParameterSet const& pset) const {
00216 return exists(pset) ? 1 : 0;
00217 }
00218
00219 void
00220 ANDGroupDescription::
00221 throwIfDuplicateLabels(std::set<std::string> const& labelsLeft,
00222 std::set<std::string> const& labelsRight) const {
00223
00224 std::set<std::string> duplicateLabels;
00225 std::insert_iterator<std::set<std::string> > insertIter(duplicateLabels, duplicateLabels.begin());
00226 std::set_intersection(labelsLeft.begin(), labelsLeft.end(),
00227 labelsRight.begin(), labelsRight.end(),
00228 insertIter);
00229 if (!duplicateLabels.empty()) {
00230 std::stringstream ss;
00231 for (std::set<std::string>::const_iterator iter = duplicateLabels.begin(),
00232 iEnd = duplicateLabels.end();
00233 iter != iEnd;
00234 ++iter) {
00235 ss << " \"" << *iter << "\"\n";
00236 }
00237 throw edm::Exception(errors::LogicError)
00238 << "Labels used in different nodes of a ParameterSetDescription\n"
00239 << "\"and\" expression must be unique. The following duplicate\n"
00240 << "labels were detected:\n"
00241 << ss.str()
00242 << "\n";
00243 }
00244 }
00245
00246 void
00247 ANDGroupDescription::
00248 throwIfDuplicateTypes(std::set<ParameterTypes> const& types1,
00249 std::set<ParameterTypes> const& types2) const
00250 {
00251 if (!types1.empty()) {
00252 std::set<ParameterTypes> duplicateTypes;
00253 std::insert_iterator<std::set<ParameterTypes> > insertIter(duplicateTypes, duplicateTypes.begin());
00254 std::set_intersection(types1.begin(), types1.end(),
00255 types2.begin(), types2.end(),
00256 insertIter);
00257 if (!duplicateTypes.empty()) {
00258 std::stringstream ss;
00259 for (std::set<ParameterTypes>::const_iterator iter = duplicateTypes.begin(),
00260 iEnd = duplicateTypes.end();
00261 iter != iEnd;
00262 ++iter) {
00263 ss << " \"" << parameterTypeEnumToString(*iter) << "\"\n";
00264 }
00265 throw edm::Exception(errors::LogicError)
00266 << "Types used for wildcards in different nodes of a ParameterSetDescription\n"
00267 << "\"and\" expression must be different from types used for other parameters.\n"
00268 << "The following duplicate types were detected:\n"
00269 << ss.str()
00270 << "\n";
00271 }
00272 }
00273 }
00274 }