LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
GroupSelectorRules.cc
Go to the documentation of this file.
2 
4 #include "boost/algorithm/string.hpp"
7 
8 #include <algorithm>
9 #include <cassert>
10 #include <regex>
11 #include <string>
12 
13 using namespace art;
14 using namespace cet;
15 using namespace fhicl;
16 using namespace std;
17 
18 using VCBDMP = vector<BranchDescription const*>;
19 
20 namespace {
21 
22  // The partial_match() functions are helpers for Rule(). They
23  // ascertain matches between criterion and candidate value for
24  // components of the branch description, with appropriate wildcard
25  // rules.
26  inline bool
27  partial_match(string const& regularExpression, string const& branchstring)
28  {
29  return regularExpression.empty() ?
30  branchstring == "" :
31  std::regex_match(branchstring, std::regex(regularExpression));
32  }
33 
34  inline bool
35  partial_match(art::BranchType wanted, art::BranchType candidate)
36  {
37  bool result = (wanted == art::NumBranchTypes) || (wanted == candidate);
38  return result;
39  }
40 
41  using namespace std::string_literals;
42  static auto const branchTypeString =
43  "[Ii]n(?:(Event)|(SubRun)|(Run)|(Results))"s;
44  static std::regex const branchTypeRE(branchTypeString);
45 
46  static std::string const rulesMsg =
47  "Syntax: keep|drop <spec> [<branchtype]>\n"
48  "where <spec> is EITHER \"*\" OR:\n"
49  "<friendly-type>_<module-label>_<instance-name>_<process-name>\n"
50  "Wildcards are permissible within each field: * (any number of "
51  "characters), or\n"
52  "? (any single permissible character).\n"
53  "Permissible non-wildcard characters in all fields: [A-Za-z0-9].\n"
54  "Additionally, \"::\" is permissible in friendly type names, and\n"
55  "\"#\" is permissible in module labels.\n";
56 
58  parseComponents(std::string s,
59  std::string const& parameterName,
60  std::string const& owner,
61  bool& selectflag)
62  {
63  BranchKey components;
64  std::smatch ruleMatch;
65  static std::regex const re(
66  "(keep|drop)\\s+(\\*|(?:[^_]*)_(?:[^_]*)_(?:[^_]*)"
67  "_(?:[^_\\s]*))(?:\\s+(.*))?");
68  boost::trim(s); // Removing leading / trailing whitespace.
69  if (!std::regex_match(s, ruleMatch, re)) { // Failed preliminary check.
71  << "Illegal product selection rule \"" << s
72  << "\" failed initial checks in " << owner << '.' << parameterName
73  << ".\n"
74  << rulesMsg;
75  }
76  selectflag = (ruleMatch[1].str() == "keep");
77  if (ruleMatch[2].str() == "*") { // special case for wildcard
78  components.friendlyClassName_ = ".*";
79  components.moduleLabel_ = ".*";
80  components.productInstanceName_ = ".*";
81  components.processName_ = ".*";
82  } else {
83  std::string errMsg;
84 
85  components = art::detail::splitToComponents(ruleMatch[2], errMsg);
86 
87  if (!errMsg.empty()) {
89  << errMsg << "Error occurred in " << owner << '.' << parameterName
90  << " (exactly four components required if not \"*\").\n"
91  << rulesMsg;
92  }
93 
94  bool good = art::detail::checkBranchNameSelector(components, errMsg);
95 
96  if (!good) {
98  << errMsg << "Error occurred in " << owner << '.' << parameterName
99  << ".\n"
100  << rulesMsg;
101  }
102  boost::replace_all(components.friendlyClassName_, "*", ".*");
103  boost::replace_all(components.friendlyClassName_, "?", ".");
104  boost::replace_all(components.moduleLabel_, "*", ".*");
105  boost::replace_all(components.moduleLabel_, "?", ".");
106  boost::replace_all(components.productInstanceName_, "*", ".*");
107  boost::replace_all(components.productInstanceName_, "?", ".");
108  boost::replace_all(components.processName_, "*", ".*");
109  boost::replace_all(components.processName_, "?", ".");
110  }
111  if ((ruleMatch[3].length() > 0) && // Have a BranchType specification.
112  (ruleMatch[3] != "*")) { // Wildcard is NOP, here.
113  std::smatch btMatch;
114  auto const foundBT = ruleMatch[3].str();
115  if (std::regex_match(foundBT, btMatch, branchTypeRE)) {
116  // Should be true by construction.
117  assert(btMatch.size() ==
118  static_cast<size_t>(art::NumBranchTypes) + 1ul);
119  auto itFirstMatch = btMatch.begin();
120  ++itFirstMatch;
121  auto it = std::find_if(itFirstMatch, btMatch.end(), [](auto& s) {
122  return (s.length() > 0);
123  });
124  assert(it != btMatch.end()); // Should be true by construction.
125  components.branchType_ = std::distance(itFirstMatch, it);
126  } else {
128  << "Invalid branch type specification \"" << ruleMatch[3] << "\" in "
129  << owner << " parameter named '" << parameterName
130  << "'\n"
131  "If the optional branch type is specified, it must satisfy the "
132  "following regex: \"^"
133  << branchTypeString << "$\".\n"
134  << rulesMsg;
135  }
136  }
137  return components;
138  }
139 
140 } // namespace
141 
143  string const& parameterName,
144  string const& owner)
145  : components_{parseComponents(s, parameterName, owner, selectflag_)}
146 {}
147 
148 void
150  vector<BranchSelectState>& branchstates) const
151 {
152  for (auto& state : branchstates)
153  applyToOne(state.desc, state.selectMe);
154 }
155 
156 void
157 GroupSelectorRules::applyToAll(vector<BranchSelectState>& branchstates) const
158 {
159  for (auto const& rule : rules_)
160  rule.applyToAll(branchstates);
161 }
162 
163 void
165  bool& result) const
166 {
167  if (this->appliesTo(branch))
168  result = selectflag_;
169 }
170 
171 bool
173 {
174  return partial_match(components_.friendlyClassName_,
175  branch->friendlyClassName()) &&
176  partial_match(components_.moduleLabel_, branch->moduleLabel()) &&
177  partial_match(components_.productInstanceName_,
178  branch->productInstanceName()) &&
179  partial_match(components_.processName_, branch->processName()) &&
180  partial_match(static_cast<BranchType>(components_.branchType_),
181  branch->branchType());
182 }
183 
184 GroupSelectorRules::GroupSelectorRules(vector<string> const& commands,
185  string const& parameterName,
186  string const& parameterOwnerName)
187 {
188  rules_.reserve(commands.size());
189  for (auto const& cmd : commands) {
190  rules_.emplace_back(cmd, parameterName, parameterOwnerName);
191  }
192  keepAll_ = commands.size() == 1 && commands[0] == "keep *";
193 }
194 
195 // ======================================================================
bool appliesTo(BranchDescription const *branch) const
bool checkBranchNameSelector(std::string const &branchNameSelector, std::string &errMsg)
GroupSelectorRules(std::vector< std::string > const &commands, std::string const &parameterName, std::string const &parameterOwnerName)
STL namespace.
BranchKey splitToComponents(std::string const &branchName, std::string &errMsg)
vector< BranchDescription const * > VCBDMP
std::string productInstanceName_
Definition: BranchKey.h:45
void applyToAll(std::vector< BranchSelectState > &branchstates) const
std::string const & processName() const noexcept
BranchType branchType() const noexcept
std::string friendlyClassName_
Definition: BranchKey.h:43
void applyToAll(std::vector< BranchSelectState > &branchstates) const
parameter set interface
std::string const & moduleLabel() const noexcept
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::string const & productInstanceName() const noexcept
std::string processName_
Definition: BranchKey.h:46
BranchType
Definition: BranchType.h:20
std::vector< Rule > rules_
Definition: MVAAlg.h:12
void applyToOne(BranchDescription const *branch, bool &result) const
std::string moduleLabel_
Definition: BranchKey.h:44
std::string const & friendlyClassName() const noexcept
Rule(std::string const &s, std::string const &parameterName, std::string const &owner)