LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
AllowedConfiguration.cc
Go to the documentation of this file.
7 #include "cetlib/HorizontalRule.h"
8 #include "cetlib/bold_fontify.h"
9 #include "cetlib/container_algorithms.h"
11 
12 #include <iomanip>
13 #include <iostream>
14 
15 using namespace art::detail;
16 using std::cout;
17 
18 namespace {
19 
20  std::map<std::string,
21  std::pair<std::string, std::string>> const block_parameters = {
22  {art::Suffixes::module(), {"module_type", "module_type"}},
23  {art::Suffixes::service(), {"", ""}},
24  {art::Suffixes::source(), {"module_type", "module_type"}},
25  {art::Suffixes::mfPlugin(), {"Destination type ", "type"}},
26  {art::Suffixes::mfStatsPlugin(), {"Statistics destination type ", "type"}},
27  {art::Suffixes::plugin(), {"plugin_type", "plugin_type"}},
28  {art::Suffixes::tool(), {"tool_type", "tool_type"}}};
29 
30  constexpr cet::HorizontalRule fixed_rule{100};
31 
32  std::vector<art::detail::PluginMetadata>
33  matchesBySpec(std::string const& specified_plugin_type,
34  std::string const& instance_pattern)
35  {
36  std::vector<PluginMetadata> result;
37  auto collect_metadata = [&result,
38  &instance_pattern](std::string const& suffix) {
39  auto mc = get_MetadataCollector(suffix);
40  // FIXME: Should the header label and and param_to_replace have
41  // defaults?
42  std::string header_label{"plugin_type"};
43  std::string param_to_replace{"plugin_type"};
44  auto params = block_parameters.find(suffix);
45  if (params != cend(block_parameters)) {
46  header_label = params->second.first;
47  param_to_replace = params->second.second;
48  }
49  cet::transform_all(
50  get_LibraryInfoCollection(suffix, instance_pattern),
51  back_inserter(result),
52  [&mc, &header_label, &param_to_replace](auto const& info) {
53  return mc->collect(info, indent__2(), header_label, param_to_replace);
54  });
55  };
56 
57  if (specified_plugin_type.empty()) {
58  // Search through all plugin types known to art if the user has
59  // not specified one.
60  for (auto const& suffix : art::Suffixes::all()) {
61  collect_metadata(suffix);
62  }
63  } else {
64  collect_metadata(specified_plugin_type);
65  }
66  return result;
67  }
68 
69  using Duplicates_t = std::map<std::string, std::vector<std::string>>;
70  void
71  duplicates_message(std::string const& suffix, Duplicates_t const& duplicates)
72  {
73  using namespace art;
74  std::string const type_spec =
75  (suffix == Suffixes::plugin()) ? "plugin_type" : "module_type";
76  cout
77  << indent0() << "The " << suffix
78  << "s marked '*' above are degenerate--i.e. specifying the short\n"
79  << indent0() << type_spec
80  << " value leads to an ambiguity. In order to use a degenerate\n"
81  << indent0() << suffix
82  << ", in your configuration file, give the long specification (as\n"
83  << indent0()
84  << "shown in the table below), surrounded by quotation (\") marks.\n\n";
85  std::size_t const firstColW{
86  columnWidth(duplicates, &Duplicates_t::value_type::first, "module_type")};
87  cout << indent0() << std::setw(firstColW + 4) << std::left << type_spec
88  << std::left << "Long specification" << '\n';
89  cout << indent0() << fixed_rule('-') << '\n';
90  for (auto const& dup : duplicates) {
91  auto const& long_specs = dup.second;
92  cout << indent0() << std::setw(firstColW + 4) << std::left << dup.first
93  << std::left << long_specs[0] << '\n';
94  for (auto it = long_specs.begin() + 1, end = long_specs.end(); it != end;
95  ++it) {
96  cout << indent0() << std::setw(firstColW + 4) << "\"\"" << std::left
97  << *it << '\n';
98  }
99  }
100  }
101 
102 } // namespace
103 
104 void
105 art::detail::print_available_plugins(std::string const& suffix,
106  std::string const& spec,
107  bool const verbose)
108 {
109  auto coll = get_LibraryInfoCollection(suffix, spec, verbose);
110  if (coll.empty()) {
111  cout << "Unable to find any plugins with suffix '" << suffix << "'.\n";
112  return;
113  }
114 
115  auto ms = get_MetadataSummary(suffix, coll);
116 
117  cet::HorizontalRule const rule{rule_size(ms->widths())};
118  cout << '\n'
119  << rule('=') << '\n'
120  << ms->header() << '\n'
121  << rule('-') << '\n';
122 
123  std::size_t i{};
124  Duplicates_t duplicates;
125  for (auto const& info : coll) {
126  auto summary = ms->summary(info, ++i);
127  cout << summary.message;
128  if (summary.is_duplicate)
129  duplicates[info.short_spec()].push_back(info.long_spec());
130  }
131  cout << rule('=') << "\n\n";
132 
133  if (duplicates.empty())
134  return;
135 
136  duplicates_message(suffix, duplicates);
137  cout << '\n';
138 }
139 
140 bool
141 art::detail::supports_key(std::string const& suffix,
142  std::string const& spec,
143  std::string const& key)
144 {
145  art::Exception e{art::errors::LogicError, "art::detail::supports_key"};
146  auto coll = get_LibraryInfoCollection(suffix, spec);
147  if (coll.empty()) {
148  throw e << (spec.empty() ? "[Missing specification]" :
149  cet::bold_fontify(spec))
150  << " did not match any plugin.\n";
151  } else if (coll.size() > 1ull) {
152  throw e << cet::bold_fontify(spec) << " matched more than one plugin.\n"
153  << "When querying plugin configurations, the plugin specification\n"
154  << "must resolve to a unique library.\n";
155  }
156  if (auto config = coll.begin()->allowed_config()) {
158  *config->parameter_base(), key);
159  }
160  return false;
161 }
162 
163 void
164 art::detail::print_description(std::vector<PluginMetadata> const& matches)
165 {
166  for (auto const& m : matches) {
167  cout << m.header() << m.details() << m.allowed_configuration();
168  cout << '\n' << fixed_rule('=') << "\n\n";
169  }
170 }
171 
172 namespace {
173  std::pair<std::string, std::string>
174  parse_specified_plugin(std::string const& spec)
175  {
176  // The specified plugin can be of the pattern:
177  //
178  // [<plugin_type>:]<regex corresponding to plugin instance>
179  //
180  // If '<plugin_type>:' is omitted, then all plugin types are searched.
181  std::string specified_plugin_type{};
182  std::string instance_pattern{spec};
183  auto const pos = spec.find(":");
184  if (pos != std::string::npos) {
185  specified_plugin_type = spec.substr(0, pos);
186  if (specified_plugin_type.empty()) {
188  "Error while parsing specified plugins:\n"}
189  << "The specification '" << spec
190  << "' is missing a module type before the colon (':').\n"
191  "If you intend to search through all plugin types, remove the "
192  "colon; otherwise specify\n"
193  "one of the following plugin types:"
194  << art::Suffixes::print() << '\n';
195  }
196  instance_pattern = spec.substr(pos + 1);
197  }
198  return std::make_pair(std::move(specified_plugin_type),
199  std::move(instance_pattern));
200  }
201 } // namespace
202 
203 void
204 art::detail::print_descriptions(std::vector<std::string> const& specs)
205 {
206  cout << '\n' << fixed_rule('=') << "\n\n";
207  for (auto const& spec : specs) {
208  auto const [plugin_type, instance_pattern] = parse_specified_plugin(spec);
209 
210  auto matches = matchesBySpec(plugin_type, instance_pattern);
211  if (matches.empty()) {
212  cout << indent0()
213  << (instance_pattern.empty() ? "[Missing specification]" :
214  cet::bold_fontify(instance_pattern))
215  << " did not match any plugin";
216  cout << (plugin_type.empty() ? "" : " of type '" + plugin_type + "'");
217  cout << ".\n";
218  cout << '\n' << fixed_rule('=') << "\n\n";
219  continue;
220  }
221  print_description(matches);
222  }
223 }
static std::string const & mfStatsPlugin()
LibraryInfoCollection get_LibraryInfoCollection(std::string const &suffix, std::string const &pattern, bool verbose=false)
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
Definition: StdUtils.h:93
std::size_t columnWidth(T const &coll, std::string const Elem::*cp, std::string const &header)
static std::vector< std::string > const & all()
static std::string print()
static std::string const & source()
std::size_t rule_size(Widths const &widths)
bool supports_key(std::string const &suffix, std::string const &spec, std::string const &key)
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::unique_ptr< MetadataSummary > get_MetadataSummary(std::string const &suffix, LibraryInfoCollection const &coll)
std::string indent__2()
void print_available_plugins(std::string const &suffix, std::string const &spec, bool verbose)
static std::string const & plugin()
static std::string const & tool()
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
void print_descriptions(std::vector< std::string > const &plugins)
static std::string const & mfPlugin()
static std::string const & service()
std::unique_ptr< MetadataCollector > get_MetadataCollector(std::string const &suffix)
std::string indent0()
Definition: MVAAlg.h:12
void print_description(std::vector< PluginMetadata > const &matches)
static std::string const & module()
Float_t e
Definition: plot.C:35
static bool supports_key(ParameterBase const &pb, std::string const &searched_for_key)