ValidateThenSet.cc
Go to the documentation of this file.
3 #include "fhiclcpp/exception.h"
10 
11 #include <iomanip>
12 #include <regex>
13 
14 //====================================================================
15 
16 bool
18 {
19  // 'ConfigPredicate' condition must be satisfied to continue.
20  if (!p.should_use())
21  return false;
22 
23  // Check that key exists; allow defaulted or optional keys to be
24  // absent.
26  if (!pset_.has_key(k) and !cet::search_all(ignorableKeys_, k)) {
27  if (!p.has_default() and !p.is_optional()) {
28  missingParameters_.emplace_back(&p);
29  }
30  return false;
31  }
32 
33  // Sometimes we are able to short-circuit walking the parameters
34  // that belong to a sequence. This is especially helpful for
35  // sequences with many entries of atomic type.
36  if (is_sequence(p.parameter_type()) and p.preset_value(pset_)) {
37  // Remove all entries that match the sequence key and any elements
38  // of that sequence.
39  auto erase_from =
40  std::remove_if(userKeys_.begin(), userKeys_.end(), [&k](auto const& e) {
41  return e.find(k + '[') == 0ull or e == k;
42  });
43  userKeys_.erase(erase_from, userKeys_.cend());
44  return false;
45  }
46 
47  auto erase_from = std::remove(userKeys_.begin(), userKeys_.end(), k);
48  userKeys_.erase(erase_from, userKeys_.cend());
49  return true;
50 }
51 
52 void
54 {
55  p.set_value(pset_);
56 }
57 
58 //====================================================================
59 
60 void
62 {
63  // Ensure that the supplied parameter represents a sequence.
64  auto const& key = strip_first_containing_name(s.key());
66  throw fhicl::exception(type_mismatch, "error converting to sequence:\n")
67  << "The supplied value of the parameter:\n"
68  << " " << s.key() << '\n'
69  << "does not represent a sequence.\n";
70  }
71 
72  std::regex const r{fhicl::Name::regex_safe(key) + "\\[\\d+\\]"};
73  std::size_t const nElems =
74  std::count_if(userKeys_.begin(), userKeys_.end(), [&r](auto const& k) {
75  return std::regex_match(k, r);
76  });
78 }
79 
80 //====================================================================
81 
82 void
84 {
85  // A delegated parameter must itself be present, but any nested
86  // parameters do not need to be present since the nested parameters
87  // are potentially validated elsewhere.
88  auto const& name = dp.name();
89  std::string const pattern{fhicl::Name::regex_safe(name) + R"((\.|\[))"};
90  std::regex const r{pattern};
91  auto erase_from =
92  std::remove_if(userKeys_.begin(), userKeys_.end(), [&r](auto const& k) {
93  return std::regex_search(k, r);
94  });
95  userKeys_.erase(erase_from, userKeys_.end());
96 }
97 
98 //====================================================================
99 
100 namespace {
101 
105  using key_set = std::set<std::string>;
106 
107  void
108  removeIgnorableKeys(key_set const& ignorable,
109  std::vector<std::string>& extra,
111  {
112  for (auto const& key : ignorable) {
113 
114  auto const& subkey = strip_first_containing_name(key);
115 
116  // Allow erasure globbing for extra keys (if "parameter" is an
117  // ignorable key, then "parameter.a" is also ignorable)
118  auto it = cet::find_in_all(extra, subkey);
119  if (it != extra.cend()) {
120  auto match = [&subkey](std::string const& key) {
121  return key.find(subkey) == 0ul;
122  };
123  auto const end = std::find_if_not(it, extra.end(), match);
124  extra.erase(it, end);
125  }
126 
127  // Since all ignorable missing keys are set explicitly, we do
128  // not glob erasures.
129  auto mit =
130  std::remove_if(missing.begin(), missing.end(), [&subkey](auto p) {
131  return p->key() == subkey;
132  });
133 
134  missing.erase(mit, missing.end());
135  }
136  }
137 
138  inline bool
139  show_parents(std::string const& k)
140  {
141  std::size_t const freq =
142  std::count(k.begin(), k.end(), '.') + std::count(k.begin(), k.end(), '[');
143  return freq > 1;
144  }
145 
147  fillMissingKeysMsg(
148  std::vector<cet::exempt_ptr<ParameterBase>> const& missingParams)
149  {
150  if (missingParams.empty())
151  return "";
152 
153  std::string const prefix{" - " + std::string(3, ' ')};
154 
155  std::ostringstream oss;
156  oss << "Missing parameters:\n";
157  for (auto p : missingParams) {
158 
159  // If the key is nested (e.g. pset1.pset2[0] ), show the
160  // parents
161  PrintAllowedConfiguration pc{oss, show_parents(p->key()), prefix, true};
162  pc.walk_over(*p);
163  }
164  oss << "\n";
165 
166  return oss.str();
167  }
168 
170  fillExtraKeysMsg(fhicl::ParameterSet const& pset,
171  std::vector<std::string> const& extraKeys)
172  {
173  if (extraKeys.empty())
174  return "";
175 
176  std::ostringstream oss;
177  oss << "Unsupported parameters:\n\n";
178  for (auto const& key : extraKeys) {
179  oss << " + " << std::setw(30) << std::left << key << " [ "
180  << pset.get_src_info(key) << " ]\n";
181  }
182  oss << '\n';
183 
184  return oss.str();
185  }
186 }
187 
188 void
190 {
191  removeIgnorableKeys(ignorableKeys_, userKeys_, missingParameters_);
192  std::string errmsg;
193  errmsg += fillMissingKeysMsg(missingParameters_);
194  errmsg += fillExtraKeysMsg(pset_, userKeys_);
195  if (!errmsg.empty()) {
197  fullmsg += "\n";
198  fullmsg += errmsg;
199  throw validationException{fullmsg.c_str()};
200  }
201 }
static QCString name
Definition: declinfo.cpp:673
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
void prepare_elements_for_validation(std::size_t const n)
Definition: SequenceBase.h:39
std::string const & name() const
Definition: ParameterBase.h:43
void enter_sequence(SequenceBase &p) override
void set_value(fhicl::ParameterSet const &ps)
Definition: ParameterBase.h:90
bool preset_value(fhicl::ParameterSet const &ps)
Definition: ParameterBase.h:95
std::string string
Definition: nybbler.cc:12
struct vector vector
std::set< std::string > ignorableKeys_
std::vector< std::string > userKeys_
std::string optional_parameter_message(bool const with_comment=true)
bool is_key_to_sequence(std::string const &key) const
Definition: ParameterSet.h:171
std::string strip_first_containing_name(std::string const &key)
bool search_all(FwdCont const &, Datum const &)
const double e
ParameterSet const & pset_
def key(type, name=None)
Definition: graph.py:13
par_type parameter_type() const
Definition: ParameterBase.h:68
p
Definition: test.py:223
void delegated_parameter(DelegateBase &) override
bool has_key(std::string const &key) const
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
std::string const & key() const
Definition: ParameterBase.h:38
std::vector< cet::exempt_ptr< ParameterBase > > missingParameters_
static std::string regex_safe(std::string const &key)
Definition: Name.h:31
std::string get_src_info(std::string const &key) const
std::string pattern
Definition: regex_t.cc:35
auto find_in_all(FwdCont &, Datum const &)
void after_action(ParameterBase &p) override
static QCString * s
Definition: config.cpp:1042
bool before_action(ParameterBase &p) override
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool is_sequence(std::any const &val)
Definition: coding.h:49