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
10 #include "TestUtils/NameSelector.h"
11 
12 // framework libraries
14 
15 
16 namespace testing {
17 
18  //----------------------------------------------------------------------------
19  //--- testing::NameSelector
20  //----------------------------------------------------------------------------
23 
24  //----------------------------------------------------------------------------
26  ProcessItem(known_names, name);
27  } // NameSelector::ParseName()
28 
29 
30  //----------------------------------------------------------------------------
32  ++(query_registry[name]);
33  return LookupResponse(name);
34  } // NameSelector::Query()
35 
36 
37  //----------------------------------------------------------------------------
39  Response_t response = Query(name);
40  if (response == rsThrow) {
42  << "NameSelector: name '" << name << "' not configured.";
43  }
44  return response == rsAccepted;
45  } // NameSelector::Accepted()
46 
47 
48  //----------------------------------------------------------------------------
49  void NameSelector::PrintConfiguration(std::ostream& out) const {
50 
51  // resort the known elements
52  std::map<Response_t, Names_t> elements;
53  for (KnownNames_t::value_type const& element: known_names)
54  if (element.first != DefaultName)
55  elements[element.second.response].insert(element.first);
56 
57  size_t nKnownElements = 0;
58  if (!elements[rsAccepted].empty()) {
59  auto const& selected_elements = elements[rsAccepted];
60  Names_t::const_iterator iName = selected_elements.cbegin(),
61  nend = selected_elements.cend();
62  out << " accept " << selected_elements.size()
63  << ": '" << *(iName++) << "'";
64  while (iName != nend) out << ", '" << *(iName++) << "'";
65  out << ";";
66  nKnownElements += selected_elements.size();
67  } // if accepting anything
68  if (!elements[rsRejected].empty()) {
69  auto const& selected_elements = elements[rsRejected];
70  Names_t::const_iterator iName = selected_elements.cbegin(),
71  nend = selected_elements.cend();
72  out << " reject " << selected_elements.size()
73  << ": '" << *(iName++) << "'";
74  while (iName != nend) out << ", '" << *(iName++) << "'";
75  out << ";";
76  nKnownElements += selected_elements.size();
77  } // if accepting anything
78  if (!elements[rsThrow].empty()) {
79  auto const& selected_elements = elements[rsThrow];
80  Names_t::const_iterator iName = selected_elements.cbegin(),
81  nend = selected_elements.cend();
82  out << " throw on " << selected_elements.size()
83  << ": '" << *(iName++) << "'";
84  while (iName != nend) out << ", '" << *(iName++) << "'";
85  out << ";";
86  nKnownElements += selected_elements.size();
87  } // if accepting anything
88  if (nKnownElements > 0) out << " otherwise,";
89  switch (DefaultResponse()) {
90  case rsAccepted: out << " accept everything"; break;
91  case rsRejected: out << " reject everything"; break;
92  case rsThrow: out << " throw on anything"; break;
93  default: out << " I don't know";
94  } // switch
95  } // NameSelector::PrintConfiguration()
96 
97 
98  //----------------------------------------------------------------------------
100  KnownNames_t::const_iterator iResponse = known_names.find(name);
101  return (iResponse == known_names.end())?
102  DefaultResponse(): iResponse->second.response;
103  } // NameSelector::LookupResponse()
104 
105 
106  //----------------------------------------------------------------------------
107  template <>
108  void NameSelector::AddFirstName<>(KnownNames_t& name_set, Name_t name) {
109  ProcessItem(name_set, name);
110  } // NameSelector::AddFirstName<>()
111 
112 
113  //----------------------------------------------------------------------------
115  (KnownNames_t& name_set, Name_t item, Response_t response) const
116  {
117  name_set[item] = { response };
118  } // NameSelector::InsertItem()
119 
120 
121  //----------------------------------------------------------------------------
123  KnownNames_t::value_type item,
124  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:
140  << __func__ << ": unexpected code flow: invalid added response";
141  } // switch item response
142  break;
143  default:
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  //----------------------------------------------------------------------------
170  {
171  bool bForceDef = false;
172  if (!item.empty()) {
173  if (item[0] == '@') {
174  bForceDef = true;
175  item.erase(0, 1);
176  }
177  }
178  Definitions_t::const_iterator iDefinition = definitions.find(item);
179  if ((iDefinition == definitions.end()) && bForceDef) {
181  << "no set named '" << item << "'\n";
182  }
183  return iDefinition;
184  } // NameSelector::FindDefinition()
185 
186 
187  //----------------------------------------------------------------------------
188  void NameSelector::ClearNameSet(KnownNames_t& name_set) const {
189  KnownNames_t::iterator iName = name_set.begin(), nend = name_set.end();
190  while (iName != nend) {
191  if (iName->first == DefaultName) ++iName;
192  else iName = name_set.erase(iName);
193  } // while
194  } // NameSelector::ClearNameSet()
195 
196 
197  //----------------------------------------------------------------------------
199  (Response_t answer) const
200  {
202  for (auto const& query_info: query_registry) {
203  if (query_info.first == DefaultName) continue;
204  if (LookupResponse(query_info.first) != answer) continue;
205  names.insert(query_info.first);
206  } // for
207  return names;
208  } // NameSelector::QueriedWithStatus()
209 
210 
211  //----------------------------------------------------------------------------
213  (std::ostream* out /* = nullptr */) const
214  {
215  Names_t missing;
216  for (auto const& elem: known_names) {
217  if (query_registry[elem.first] > 0U) continue;
218  if (elem.first == DefaultName) continue;
219  missing.insert(elem.first);
220  } // for
221  if (out && !missing.empty()) {
222  (*out) << missing.size() << " items not queried:";
223  for (Name_t const& name: missing) (*out) << " " << name;
224  (*out) << std::endl;
225  }
226  return missing.empty();
227  } // NameSelector::CheckQueryRegistry()
228 
229 
230  //----------------------------------------------------------------------------
232  (Name_t& item, Response_t default_mode /* = rsAccepted */)
233  {
234  if (item[0] == '+') {
235  item.erase(0, 1);
236  return rsAccepted;
237  }
238  if (item[0] == '-') {
239  item.erase(0, 1);
240  return rsRejected;
241  }
242  return default_mode;
243  } // NameSelector::ParseMode()
244 
245 
246  //----------------------------------------------------------------------------
247 
248 } // namespace testing
static QCString name
Definition: declinfo.cpp:673
intermediate_table::iterator iterator
LArSoft test utilities.
std::set< Name_t > Names_t
list of names
Definition: NameSelector.h:40
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:177
Response_t DefaultResponse() const
Returns the default answer for names that are not registered.
Definition: NameSelector.h:140
bool Accepted(Name_t name) const
Returns whether the name is accepted as good.
intermediate_table::const_iterator const_iterator
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.
Definitions_t definitions
a set of definitions
Definition: NameSelector.h:187
void ProcessItem(KnownNames_t &name_set, Name_t item) const
Fills name_set with an item.
Response_t
Possible responses.
Definition: NameSelector.h:43
static Name_t const DefaultName
name representing the default
Definition: NameSelector.h:166
throw art::Exception (art::errors::Configuration)
Definition: NameSelector.h:46
KnownNames_t known_names
list of known names, with category
Definition: NameSelector.h:185
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
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:189
static Name_t const ClearAllName
name instructing to delete all names
Definition: NameSelector.h:167
static std::vector< std::string > const names
Definition: FragmentType.hh:8
void InsertItem(KnownNames_t &name_set, Name_t item, Response_t response) const
Adds an item to the name set, working in specified mode.
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
QTextStream & endl(QTextStream &s)
std::string Name_t
type representing a name
Definition: NameSelector.h:39
Response_t Query(Name_t name) const
Returns the response for the specified name (does not throw)