LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
ValidateThenSet.cc
Go to the documentation of this file.
2 #include "cetlib/container_algorithms.h"
3 #include "fhiclcpp/exception.h"
13 
14 #include <iomanip>
15 #include <regex>
16 
17 //====================================================================
18 
19 bool
21 {
22  // 'ConfigPredicate' condition must be satisfied to continue.
23  if (!p.should_use())
24  return false;
25 
26  // Check that key exists; allow defaulted or optional keys to be
27  // absent.
28  std::string const& k = strip_first_containing_name(p.key());
29  if (!pset_.has_key(k) && !cet::search_all(ignorableKeys_, k)) {
30  if (!p.has_default() && !p.is_optional()) {
31  missingParameters_.emplace_back(&p);
32  }
33  return false;
34  }
35 
36  auto erase_from = std::remove(userKeys_.begin(), userKeys_.end(), k);
37  userKeys_.erase(erase_from, userKeys_.cend());
38  return true;
39 }
40 
41 void
43 {
44  p.set_value(pset_, true);
45 }
46 
47 //====================================================================
48 
49 void
51 {
52  // Ensure that the supplied parameter represents a sequence.
53  auto const& key = strip_first_containing_name(s.key());
54  if (!pset_.is_key_to_sequence(key)) {
55  throw fhicl::exception(type_mismatch, "error converting to sequence:\n")
56  << "The supplied value of the parameter:\n"
57  << " " << s.key() << '\n'
58  << "does not represent a sequence.\n";
59  }
60 
61  std::regex const r{fhicl::Name::regex_safe(key) + "\\[\\d+\\]"};
62  std::size_t const nElems =
63  std::count_if(userKeys_.begin(), userKeys_.end(), [&r](auto const& k) {
64  return std::regex_match(k, r);
65  });
67 }
68 
69 //====================================================================
70 
71 void
73 {
74  // A delegated parameter must itself be present, but any nested
75  // parameters do not need to be present since the nested parameters
76  // are potentially validated elsewhere.
77  auto const& name = dp.name();
78  std::string const pattern{fhicl::Name::regex_safe(name) + R"((\.|\[))"};
79  std::regex const r{pattern};
80  auto erase_from =
81  std::remove_if(userKeys_.begin(), userKeys_.end(), [&r](auto const& k) {
82  return std::regex_search(k, r);
83  });
84  userKeys_.erase(erase_from, userKeys_.end());
85 }
86 
87 //====================================================================
88 
89 namespace {
90 
94  using key_set = std::set<std::string>;
95 
96  void
97  removeIgnorableKeys(key_set const& ignorable,
98  std::vector<std::string>& extra,
99  std::vector<cet::exempt_ptr<ParameterBase>>& missing)
100  {
101  for (auto const& key : ignorable) {
102 
103  auto const& subkey = strip_first_containing_name(key);
104 
105  // Allow erasure globbing for extra keys (if "parameter" is an
106  // ignorable key, then "parameter.a" is also ignorable)
107  auto it = cet::find_in_all(extra, subkey);
108  if (it != extra.cend()) {
109  auto match = [&subkey](std::string const& key) {
110  return key.find(subkey) == 0ul;
111  };
112  auto const end = std::find_if_not(it, extra.end(), match);
113  extra.erase(it, end);
114  }
115 
116  // Since all ignorable missing keys are set explicitly, we do
117  // not glob erasures.
118  auto mit =
119  std::remove_if(missing.begin(), missing.end(), [&subkey](auto p) {
120  return p->key() == subkey;
121  });
122 
123  missing.erase(mit, missing.end());
124  }
125  }
126 
127  inline bool
128  show_parents(std::string const& k)
129  {
130  std::size_t const freq =
131  std::count(k.begin(), k.end(), '.') + std::count(k.begin(), k.end(), '[');
132  return freq > 1;
133  }
134 
135  std::string
136  fillMissingKeysMsg(
137  std::vector<cet::exempt_ptr<ParameterBase>> const& missingParams)
138  {
139  if (missingParams.empty())
140  return "";
141 
142  std::string const prefix{" - " + std::string(3, ' ')};
143 
144  std::ostringstream oss;
145  oss << "Missing parameters:\n";
146  for (auto p : missingParams) {
147 
148  // If the key is nested (e.g. pset1.pset2[0] ), show the
149  // parents
150  PrintAllowedConfiguration pc{oss, show_parents(p->key()), prefix, true};
151  pc.walk_over(*p);
152  }
153  oss << "\n";
154 
155  return oss.str();
156  }
157 
158  std::string
159  fillExtraKeysMsg(fhicl::ParameterSet const& pset,
160  std::vector<std::string> const& extraKeys)
161  {
162  if (extraKeys.empty())
163  return "";
164 
165  std::ostringstream oss;
166  oss << "Unsupported parameters:\n\n";
167  for (auto const& key : extraKeys) {
168  oss << " + " << std::setw(30) << std::left << key << " [ "
169  << pset.get_src_info(key) << " ]\n";
170  }
171  oss << '\n';
172 
173  return oss.str();
174  }
175 }
176 
177 void
179 {
180  removeIgnorableKeys(ignorableKeys_, userKeys_, missingParameters_);
181  std::string errmsg;
182  errmsg += fillMissingKeysMsg(missingParameters_);
183  errmsg += fillExtraKeysMsg(pset_, userKeys_);
184  if (!errmsg.empty()) {
185  std::string fullmsg{detail::optional_parameter_message(false)};
186  fullmsg += "\n";
187  fullmsg += errmsg;
188  throw validationException{fullmsg.c_str()};
189  }
190 }
Float_t s
Definition: plot.C:23
void prepare_elements_for_validation(std::size_t const n)
Definition: SequenceBase.h:40
void enter_sequence(SequenceBase &p) override
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:155
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
std::string strip_first_containing_name(std::string const &key)
void walk_over(tt::maybe_const_t< ParameterBase, C > &)
ParameterSet const & pset_
void delegated_parameter(DelegateBase &) override
bool has_key(std::string const &key) const
std::vector< cet::exempt_ptr< ParameterBase > > missingParameters_
void set_value(fhicl::ParameterSet const &ps, bool trimParents)
Definition: ParameterBase.h:96
static std::string regex_safe(std::string const &key)
Definition: Name.h:32
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:104
std::string get_src_info(std::string const &key) const
std::string name() const
Definition: ParameterBase.h:49
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void after_action(ParameterBase &p) override
std::string key() const
Definition: ParameterBase.h:44
bool before_action(ParameterBase &p) override
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33