All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NameSelector.cxx
Go to the documentation of this file.
1 /**
2  * @file NameSelector.cxx
3  * @brief A class providing a selection list: implementation file
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date July 24, 2015
6  * @see NameSelector.h
7  */
8 
9 // our library
11 
12 // framework libraries
13 #include "canvas/Utilities/Exception.h"
14 
15 #include <ostream>
16 
17 namespace testing {
18 
19  //----------------------------------------------------------------------------
20  //--- testing::NameSelector
21  //----------------------------------------------------------------------------
24 
25  //----------------------------------------------------------------------------
27  ProcessItem(known_names, name);
28  } // NameSelector::ParseName()
29 
30 
31  //----------------------------------------------------------------------------
33  ++(query_registry[name]);
34  return LookupResponse(name);
35  } // NameSelector::Query()
36 
37 
38  //----------------------------------------------------------------------------
40  Response_t response = Query(name);
41  if (response == rsThrow) {
42  throw art::Exception(art::errors::Configuration)
43  << "NameSelector: name '" << name << "' not configured.";
44  }
45  return response == rsAccepted;
46  } // NameSelector::Accepted()
47 
48 
49  //----------------------------------------------------------------------------
50  void NameSelector::PrintConfiguration(std::ostream& out) const {
51 
52  // resort the known elements
53  std::map<Response_t, Names_t> elements;
54  for (KnownNames_t::value_type const& element: known_names)
55  if (element.first != DefaultName)
56  elements[element.second.response].insert(element.first);
57 
58  size_t nKnownElements = 0;
59  if (!elements[rsAccepted].empty()) {
60  auto const& selected_elements = elements[rsAccepted];
61  Names_t::const_iterator iName = selected_elements.cbegin(),
62  nend = selected_elements.cend();
63  out << " accept " << selected_elements.size()
64  << ": '" << *(iName++) << "'";
65  while (iName != nend) out << ", '" << *(iName++) << "'";
66  out << ";";
67  nKnownElements += selected_elements.size();
68  } // if accepting anything
69  if (!elements[rsRejected].empty()) {
70  auto const& selected_elements = elements[rsRejected];
71  Names_t::const_iterator iName = selected_elements.cbegin(),
72  nend = selected_elements.cend();
73  out << " reject " << selected_elements.size()
74  << ": '" << *(iName++) << "'";
75  while (iName != nend) out << ", '" << *(iName++) << "'";
76  out << ";";
77  nKnownElements += selected_elements.size();
78  } // if accepting anything
79  if (!elements[rsThrow].empty()) {
80  auto const& selected_elements = elements[rsThrow];
81  Names_t::const_iterator iName = selected_elements.cbegin(),
82  nend = selected_elements.cend();
83  out << " throw on " << selected_elements.size()
84  << ": '" << *(iName++) << "'";
85  while (iName != nend) out << ", '" << *(iName++) << "'";
86  out << ";";
87  nKnownElements += selected_elements.size();
88  } // if accepting anything
89  if (nKnownElements > 0) out << " otherwise,";
90  switch (DefaultResponse()) {
91  case rsAccepted: out << " accept everything"; break;
92  case rsRejected: out << " reject everything"; break;
93  case rsThrow: out << " throw on anything"; break;
94  default: out << " I don't know";
95  } // switch
96  } // NameSelector::PrintConfiguration()
97 
98 
99  //----------------------------------------------------------------------------
101  KnownNames_t::const_iterator iResponse = known_names.find(name);
102  return (iResponse == known_names.end())?
103  DefaultResponse(): iResponse->second.response;
104  } // NameSelector::LookupResponse()
105 
106 
107  //----------------------------------------------------------------------------
108  template <>
109  void NameSelector::AddFirstName<>(KnownNames_t& name_set, Name_t name) {
110  ProcessItem(name_set, name);
111  } // NameSelector::AddFirstName<>()
112 
113 
114  //----------------------------------------------------------------------------
116  (KnownNames_t& name_set, Name_t item, Response_t response) const
117  {
118  name_set[item] = { response };
119  } // NameSelector::InsertItem()
120 
121 
122  //----------------------------------------------------------------------------
124  (KnownNames_t& name_set, KnownNames_t::value_type item, Response_t response)
125  const
126  {
127  // response is the instruction we have about how to add the item
128  // item.second.response is what the default answer for that item is
129  Response_t final_response; // uninitialized
130  switch (response) {
131  case rsAccepted:
132  final_response = item.second.response; // respect the response
133  break;
134  case rsRejected: // flip the response
135  switch (item.second.response) {
136  case rsAccepted: final_response = rsRejected; break;
137  case rsRejected: final_response = rsAccepted; break;
138  default:
139  throw art::Exception(art::errors::LogicError)
140  << __func__ << ": unexpected code flow: invalid added response";
141  } // switch item response
142  break;
143  default:
144  throw art::Exception(art::errors::LogicError)
145  << __func__ << ": unexpected code flow: invalid response";
146  } // switch response
147  InsertItem(name_set, item.first, final_response);
148  } // NameSelector::InsertItem(KnownNames_t::value_type)
149 
150 
151  //----------------------------------------------------------------------------
152  void NameSelector::ProcessItem(KnownNames_t& name_set, Name_t item) const {
153  // special: if this name is actually a directive to clear all
154  if (item == ClearAllName) {
155  ClearNameSet(name_set); // clear everything except the default
156  return;
157  } // if clear all
158  Response_t response = ParseMode(item);
159  Definitions_t::const_iterator iDefinition = FindDefinition(item);
160  if (iDefinition == definitions.end()) InsertItem(name_set, item, response);
161  else {
162  for (KnownNames_t::value_type const& element: iDefinition->second)
163  InsertItem(name_set, element, response);
164  }
165  } // NameSelector::ProcessItem()
166 
167 
168  //----------------------------------------------------------------------------
169  NameSelector::Definitions_t::const_iterator NameSelector::FindDefinition
170  (Name_t& item) const
171  {
172  bool bForceDef = false;
173  if (!item.empty()) {
174  if (item[0] == '@') {
175  bForceDef = true;
176  item.erase(0, 1);
177  }
178  }
179  Definitions_t::const_iterator iDefinition = definitions.find(item);
180  if ((iDefinition == definitions.end()) && bForceDef) {
181  throw art::Exception(art::errors::LogicError)
182  << "no set named '" << item << "'\n";
183  }
184  return iDefinition;
185  } // NameSelector::FindDefinition()
186 
187 
188  //----------------------------------------------------------------------------
189  void NameSelector::ClearNameSet(KnownNames_t& name_set) const {
190  KnownNames_t::iterator iName = name_set.begin(), nend = name_set.end();
191  while (iName != nend) {
192  if (iName->first == DefaultName) ++iName;
193  else iName = name_set.erase(iName);
194  } // while
195  } // NameSelector::ClearNameSet()
196 
197 
198  //----------------------------------------------------------------------------
200  (Response_t answer) const
201  {
203  for (auto const& query_info: query_registry) {
204  if (query_info.first == DefaultName) continue;
205  if (LookupResponse(query_info.first) != answer) continue;
206  names.insert(query_info.first);
207  } // for
208  return names;
209  } // NameSelector::QueriedWithStatus()
210 
211 
212  //----------------------------------------------------------------------------
214  (std::ostream* out /* = nullptr */) const
215  {
216  Names_t missing;
217  for (auto const& elem: known_names) {
218  if (query_registry[elem.first] > 0U) continue;
219  if (elem.first == DefaultName) continue;
220  missing.insert(elem.first);
221  } // for
222  if (out && !missing.empty()) {
223  (*out) << missing.size() << " items not queried:";
224  for (Name_t const& name: missing) (*out) << " " << name;
225  (*out) << std::endl;
226  }
227  return missing.empty();
228  } // NameSelector::CheckQueryRegistry()
229 
230 
231  //----------------------------------------------------------------------------
233  (Name_t& item, Response_t default_mode /* = rsAccepted */)
234  {
235  if (item[0] == '+') {
236  item.erase(0, 1);
237  return rsAccepted;
238  }
239  if (item[0] == '-') {
240  item.erase(0, 1);
241  return rsRejected;
242  }
243  return default_mode;
244  } // NameSelector::ParseMode()
245 
246 
247  //----------------------------------------------------------------------------
248 
249 } // namespace testing
static Name_t const ClearAllName
name instructing to delete all names
Definition: NameSelector.h:168
std::set< Name_t > Names_t
list of names
Definition: NameSelector.h:41
bool DoCheckQueryRegistry(std::ostream *out=nullptr) const
static Response_t ParseMode(Name_t &item, Response_t default_answer=rsAccepted)
Strips the mode specifier from item and returns the insertion mode.
Definitions_t::const_iterator FindDefinition(Name_t &item) const
Strips set specifier and returns iterator to the definition, or end()
std::map< Name_t, NameResponse_t > KnownNames_t
Information about known names.
Definition: NameSelector.h:178
Response_t DefaultResponse() const
Returns the default answer for names that are not registered.
Definition: NameSelector.h:141
bool Accepted(Name_t name) const
Returns whether the name is accepted as good.
void PrintConfiguration(std::ostream &) const
Prints the configuration into a stream.
Response_t LookupResponse(Name_t name) const
Returns the response for the specified name (does not register query)
void ParseName(Name_t name)
Parses a name and adds it to the selector.
A class providing a selection list.
Definitions_t definitions
a set of definitions
Definition: NameSelector.h:188
void ProcessItem(KnownNames_t &name_set, Name_t item) const
Fills name_set with an item.
Response_t
Possible responses.
Definition: NameSelector.h:44
KnownNames_t known_names
list of known names, with category
Definition: NameSelector.h:186
static const std::vector< std::string > names
static Name_t const DefaultName
name representing the default
Definition: NameSelector.h:167
Names_t QueriedWithStatus(Response_t answer) const
Returns the list of queried names whose response is answer.
void ClearNameSet(KnownNames_t &name_set) const
Erases all the names in the selector (default answer is unchanged)
QueryRegistry_t query_registry
record of all the queries
Definition: NameSelector.h:190
throw art::Exception (art::errors::Configuration)
Definition: NameSelector.h:47
then echo fcl name
bool empty(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:555
void InsertItem(KnownNames_t &name_set, Name_t item, Response_t response) const
Adds an item to the name set, working in specified mode.
std::string Name_t
type representing a name
Definition: NameSelector.h:40
Response_t Query(Name_t name) const
Returns the response for the specified name (does not throw)