00001 #ifndef FWCore_ParameterSet_ParameterSwitch_h 00002 #define FWCore_ParameterSet_ParameterSwitch_h 00003 00004 #include "FWCore/ParameterSet/interface/ParameterSwitchBase.h" 00005 #include "FWCore/ParameterSet/interface/ParameterDescriptionNode.h" 00006 #include "FWCore/Utilities/interface/value_ptr.h" 00007 #include "FWCore/ParameterSet/interface/ParameterDescription.h" 00008 #include "FWCore/ParameterSet/interface/ParameterDescriptionCases.h" 00009 #include "FWCore/ParameterSet/interface/ParameterSet.h" 00010 #include "FWCore/Utilities/interface/Algorithms.h" 00011 #include "FWCore/ParameterSet/interface/DocFormatHelper.h" 00012 00013 #include "boost/bind.hpp" 00014 00015 #include <map> 00016 #include <memory> 00017 #include <set> 00018 #include <string> 00019 #include <utility> 00020 #include <sstream> 00021 #include <ostream> 00022 #include <iomanip> 00023 00024 namespace edm { 00025 00026 template<class T> 00027 class ParameterSwitch : public ParameterSwitchBase { 00028 00029 public: 00030 typedef std::map<T, edm::value_ptr<ParameterDescriptionNode> > CaseMap; 00031 typedef typename std::map<T, edm::value_ptr<ParameterDescriptionNode> >::const_iterator CaseMapConstIter; 00032 00033 ParameterSwitch(ParameterDescription<T> const& switchParameter, 00034 std::auto_ptr<ParameterDescriptionCases<T> > cases) : 00035 switch_(switchParameter), 00036 cases_(*cases->caseMap()) 00037 { 00038 if (cases->duplicateCaseValues()) { 00039 throwDuplicateCaseValues(switchParameter.label()); 00040 } 00041 } 00042 00043 virtual ParameterDescriptionNode* clone() const { 00044 return new ParameterSwitch(*this); 00045 } 00046 00047 private: 00048 00049 virtual void checkAndGetLabelsAndTypes_(std::set<std::string> & usedLabels, 00050 std::set<ParameterTypes> & parameterTypes, 00051 std::set<ParameterTypes> & wildcardTypes) const { 00052 00053 std::set<std::string> caseLabels; 00054 std::set<ParameterTypes> caseParameterTypes; 00055 std::set<ParameterTypes> caseWildcardTypes; 00056 for_all(cases_, boost::bind(&ParameterSwitch::checkCaseLabels, 00057 _1, 00058 boost::ref(caseLabels), 00059 boost::ref(caseParameterTypes), 00060 boost::ref(caseWildcardTypes))); 00061 00062 insertAndCheckLabels(switch_.label(), 00063 usedLabels, 00064 caseLabels); 00065 00066 insertAndCheckTypes(switch_.type(), 00067 caseParameterTypes, 00068 caseWildcardTypes, 00069 parameterTypes, 00070 wildcardTypes); 00071 00072 if (cases_.find(switch_.getDefaultValue()) == cases_.end()) { 00073 throwNoCaseForDefault(switch_.label()); 00074 } 00075 } 00076 00077 virtual void validate_(ParameterSet & pset, 00078 std::set<std::string> & validatedLabels, 00079 bool optional) const { 00080 00081 switch_.validate(pset, validatedLabels, optional); 00082 if (switch_.exists(pset)) { 00083 T switchValue; 00084 if (switch_.isTracked()) { 00085 switchValue = pset.getParameter<T>(switch_.label()); 00086 } 00087 else { 00088 switchValue = pset.getUntrackedParameter<T>(switch_.label()); 00089 } 00090 typename CaseMap::const_iterator selectedCase = cases_.find(switchValue); 00091 if (selectedCase != cases_.end()) { 00092 selectedCase->second->validate(pset, validatedLabels, false); 00093 } 00094 else { 00095 std::stringstream ss; 00096 ss << "The switch parameter with label \"" 00097 << switch_.label() 00098 << "\" has been assigned an illegal value.\n" 00099 << "The value from the configuration is \"" 00100 << switchValue 00101 << "\".\n" 00102 << "The allowed values are:\n"; 00103 00104 for (CaseMapConstIter iter = cases_.begin(), iEnd = cases_.end(); 00105 iter != iEnd; 00106 ++iter) { 00107 ss << " " << iter->first << "\n"; 00108 } 00109 throwNoCaseForSwitchValue(ss.str()); 00110 } 00111 } 00112 } 00113 00114 virtual void writeCfi_(std::ostream & os, 00115 bool & startWithComma, 00116 int indentation, 00117 bool & wroteSomething) const { 00118 switch_.writeCfi(os, startWithComma, indentation, wroteSomething); 00119 00120 typename CaseMap::const_iterator selectedCase = cases_.find(switch_.getDefaultValue()); 00121 if (selectedCase != cases_.end()) { 00122 selectedCase->second->writeCfi(os, startWithComma, indentation, wroteSomething); 00123 } 00124 } 00125 00126 virtual void print_(std::ostream & os, 00127 bool optional, 00128 bool writeToCfi, 00129 DocFormatHelper & dfh) { 00130 printBase(os, optional, writeToCfi, dfh, switch_.label(), switch_.isTracked(), parameterTypeEnumToString(switch_.type())); 00131 } 00132 00133 virtual void printNestedContent_(std::ostream & os, 00134 bool optional, 00135 DocFormatHelper & dfh) { 00136 00137 DocFormatHelper new_dfh(dfh); 00138 printNestedContentBase(os, dfh, new_dfh, switch_.label()); 00139 00140 switch_.print(os, optional, true, new_dfh); 00141 for_all(cases_, boost::bind(&ParameterSwitchBase::printCaseT<T>, 00142 _1, 00143 boost::ref(os), 00144 optional, 00145 boost::ref(new_dfh), 00146 boost::cref(switch_.label()))); 00147 00148 new_dfh.setPass(1); 00149 new_dfh.setCounter(0); 00150 00151 new_dfh.indent(os); 00152 os << "switch:\n"; 00153 switch_.print(os, optional, true, new_dfh); 00154 for_all(cases_, boost::bind(&ParameterSwitchBase::printCaseT<T>, 00155 _1, 00156 boost::ref(os), 00157 optional, 00158 boost::ref(new_dfh), 00159 boost::cref(switch_.label()))); 00160 00161 new_dfh.setPass(2); 00162 new_dfh.setCounter(0); 00163 00164 switch_.printNestedContent(os, optional, new_dfh); 00165 for_all(cases_, boost::bind(&ParameterSwitchBase::printCaseT<T>, 00166 _1, 00167 boost::ref(os), 00168 optional, 00169 boost::ref(new_dfh), 00170 boost::cref(switch_.label()))); 00171 } 00172 00173 virtual bool exists_(ParameterSet const& pset) const { return switch_.exists(pset); } 00174 00175 static void checkCaseLabels(std::pair<T, edm::value_ptr<ParameterDescriptionNode> > const& thePair, 00176 std::set<std::string> & labels, 00177 std::set<ParameterTypes> & parameterTypes, 00178 std::set<ParameterTypes> & wildcardTypes) { 00179 thePair.second->checkAndGetLabelsAndTypes(labels, parameterTypes, wildcardTypes); 00180 } 00181 00182 ParameterDescription<T> switch_; 00183 CaseMap cases_; 00184 }; 00185 } 00186 #endif