CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
GroupSelectorRules.cc
Go to the documentation of this file.
1 #include <algorithm>
2 #include <iterator>
3 #include <ostream>
4 #include <cctype>
5 
6 #include "boost/algorithm/string.hpp"
7 
13 
14 namespace edm {
15 // The following typedef is used only in this implementation file, in
16 // order to shorten several lines of code.
17 typedef std::vector<edm::BranchDescription const*> VCBDP;
18 
19  namespace
20  {
21 
22  //--------------------------------------------------
23  // function partial_match is a helper for Rule. It encodes the
24  // matching of std::strings, and knows about wildcarding rules.
25  inline
26  bool
27  partial_match(const boost::regex& regularExpression,
28  const std::string& branchstring)
29  {
30  if (regularExpression.empty()) {
31  if (branchstring == "") return true;
32  else return false;
33  }
34  return boost::regex_match(branchstring, regularExpression);
35  }
36  }
37 
38  //--------------------------------------------------
39  // Class Rule is used to determine whether or not a given branch
40  // (really a Group, as described by the BranchDescription object
41  // that specifies that Group) matches a 'rule' specified by the
42  // configuration. Each Rule is configured with a single std::string from
43  // the configuration file.
44  //
45  // The configuration std::string is of the form:
46  //
47  // 'keep <spec>' ** or **
48  // 'drop <spec>'
49  //
50  // where '<spec>' is of the form:
51  //
52  // <product type>_<module label>_<instance name>_<process name>
53  //
54  // The 3 underscores must always be present. The four fields can
55  // be empty or composed of alphanumeric characters. "*" is an
56  // allowed wildcard that will match 0 or more of any characters.
57  // "?" is the other allowed wilcard that will match exactly one
58  // character. There is one exception to this, the entire '<spec>'
59  // can be one single "*" without any underscores and this is
60  // interpreted as "*_*_*_*". Anything else will lead to an exception
61  // being thrown.
62  //
63  // This class has much room for optimization. This should be
64  // revisited as soon as profiling data are available.
65 
66  GroupSelectorRules::Rule::Rule(std::string const& s, std::string const& parameterName, std::string const& owner) :
67  selectflag_(),
68  productType_(),
69  moduleLabel_(),
70  instanceName_(),
71  processName_()
72  {
73  if (s.size() < 6)
75  << "Invalid statement in configuration file\n"
76  << "In " << owner << " parameter named '" << parameterName << "'\n"
77  << "Rule must have at least 6 characters because it must\n"
78  << "specify 'keep ' or 'drop ' and also supply a pattern.\n"
79  << "This is the invalid output configuration rule:\n"
80  << " " << s << "\n"
81  << "Exception thrown from GroupSelectorRules::Rule\n";
82 
83  if (s.substr(0,4) == "keep")
84  selectflag_ = true;
85  else if (s.substr(0,4) == "drop")
86  selectflag_ = false;
87  else
89  << "Invalid statement in configuration file\n"
90  << "In " << owner << " parameter named '" << parameterName << "'\n"
91  << "Rule must specify 'keep ' or 'drop ' and also supply a pattern.\n"
92  << "This is the invalid output configuration rule:\n"
93  << " " << s << "\n"
94  << "Exception thrown from GroupSelectorRules::Rule\n";
95 
96  if ( !std::isspace(s[4]) ) {
97 
99  << "Invalid statement in configuration file\n"
100  << "In " << owner << " parameter named '" << parameterName << "'\n"
101  << "In each rule, 'keep' or 'drop' must be followed by a space\n"
102  << "This is the invalid output configuration rule:\n"
103  << " " << s << "\n"
104  << "Exception thrown from GroupSelectorRules::Rule\n";
105  }
106 
107  // Now pull apart the std::string to get at the bits and pieces of the
108  // specification...
109 
110  // Grab from after 'keep/drop ' (note the space!) to the end of
111  // the std::string...
112  std::string spec(s.begin()+5, s.end());
113 
114  // Trim any leading and trailing whitespace from spec
115  boost::trim(spec);
116 
117  if (spec == "*") // special case for wildcard
118  {
119  productType_ = ".*";
120  moduleLabel_ = ".*";
121  instanceName_ = ".*";
122  processName_ = ".*";
123  return;
124  }
125  else
126  {
127  std::vector<std::string> parts;
128  boost::split(parts, spec, boost::is_any_of("_"));
129 
130  // The std::vector must contain at least 4 parts
131  // and none may be empty.
132  bool good = (parts.size() == 4);
133 
134  // Require all the std::strings to contain only alphanumberic
135  // characters or "*" or "?"
136  if (good)
137  {
138  for (int i = 0; i < 4; ++i) {
139  std::string& field = parts[i];
140  int size = field.size();
141  for (int j = 0; j < size; ++j) {
142  if ( !(isalnum(field[j]) || field[j] == '*' || field[j] == '?') ) {
143  good = false;
144  }
145  }
146 
147  // We are using the boost regex library to deal with the wildcards.
148  // The configuration file uses a syntax that accepts "*" and "?"
149  // as wildcards so we need to convert these to the syntax used in
150  // regular expressions.
151  boost::replace_all(parts[i], "*", ".*");
152  boost::replace_all(parts[i], "?", ".");
153  }
154  }
155 
156  if (!good)
157  {
159  << "Invalid statement in configuration file\n"
160  << "In " << owner << " parameter named '" << parameterName << "'\n"
161  << "In each rule, after 'keep ' or 'drop ' there must\n"
162  << "be a branch specification of the form 'type_label_instance_process'\n"
163  << "There must be 4 fields separated by underscores\n"
164  << "The fields can only contain alphanumeric characters and the wildcards * or ?\n"
165  << "Alternately, a single * is also allowed for the branch specification\n"
166  << "This is the invalid output configuration rule:\n"
167  << " " << s << "\n"
168  << "Exception thrown from GroupSelectorRules::Rule\n";
169  }
170 
171  // Assign the std::strings to the regex (regular expression) objects
172  // If the std::string is empty we skip the assignment and leave
173  // the regular expression also empty.
174 
175  if (parts[0] != "") productType_ = parts[0];
176  if (parts[1] != "") moduleLabel_ = parts[1];
177  if (parts[2] != "") instanceName_ = parts[2];
178  if (parts[3] != "") processName_ = parts[3];
179  }
180  }
181 
182  void
183  GroupSelectorRules::Rule::applyToAll(std::vector<BranchSelectState>& branchstates) const {
184  std::vector<BranchSelectState>::iterator it = branchstates.begin();
185  std::vector<BranchSelectState>::iterator end = branchstates.end();
186  for (; it != end; ++it) applyToOne(it->desc, it->selectMe);
187  }
188 
189  void
190  GroupSelectorRules::applyToAll(std::vector<BranchSelectState>& branchstates) const {
191  std::vector<Rule>::const_iterator it = rules_.begin();
192  std::vector<Rule>::const_iterator end = rules_.end();
193  for (; it != end; ++it) it->applyToAll(branchstates);
194  }
195 
196 // bool
197 // Rule::applyToOne(edm::BranchDescription const* branch) const
198 // {
199 // bool match =
200 // partial_match(productType_, branch->friendlyClassName()) &&
201 // partial_match(moduleLabel_, branch->moduleLabel()) &&
202 // partial_match(instanceName_, branch->productInstanceName()) &&
203 // partial_match(processName_, branch->processName());
204 
205 // return match ? selectflag_ : !selectflag_;
206 // }
207 
208  void
210  bool& result) const
211  {
212  if (this->appliesTo(branch)) result = selectflag_;
213  }
214 
215  bool
217  {
218  return
219  partial_match(productType_, branch->friendlyClassName()) &&
220  partial_match(moduleLabel_, branch->moduleLabel()) &&
221  partial_match(instanceName_, branch->productInstanceName()) &&
222  partial_match(processName_, branch->processName());
223  }
224 
225  void
227  std::vector<std::string> defaultStrings(1U, std::string("keep *"));
228  desc.addUntracked<std::vector<std::string> >(parameterName, defaultStrings)
229  ->setComment("Specifies which branches are kept or dropped.");
230  }
231 
233  std::string const& parameterName,
234  std::string const& parameterOwnerName) :
235  rules_(),
236  parameterName_(parameterName),
237  parameterOwnerName_(parameterOwnerName)
238  {
239  // Fill the rules.
240  // If there is no parameter whose name is parameterName_ in the
241  // ParameterSet we are given, we use the following default.
242  std::vector<std::string> defaultCommands(1U, std::string("keep *"));
243 
244  std::vector<std::string> commands =
245  pset.getUntrackedParameter<std::vector<std::string> >(parameterName,
246  defaultCommands);
247  if (commands.empty()) {
248  commands.push_back(defaultCommands[0]);
249  }
250  rules_.reserve(commands.size());
251  for(std::vector<std::string>::const_iterator it = commands.begin(), end = commands.end();
252  it != end; ++it) {
253  rules_.push_back(Rule(*it, parameterName, parameterOwnerName));
254  }
255  keepAll_ = commands.size() == 1 && commands[0] == defaultCommands[0];
256  }
257 
258 
259 }
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
std::string const & processName() const
static void fillDescription(ParameterSetDescription &desc, char const *parameterName)
void applyToOne(BranchDescription const *branch, bool &result) const
std::string const & moduleLabel() const
std::string const & productInstanceName() const
tuple result
Definition: query.py:137
int j
Definition: DBlmapReader.cc:9
std::string const & friendlyClassName() const
#define end
Definition: vmac.h:38
void applyToAll(std::vector< BranchSelectState > &branchstates) const
std::vector< edm::BranchDescription const * > VCBDP
Rule(std::string const &s, std::string const &parameterName, std::string const &owner)
GroupSelectorRules(ParameterSet const &pset, std::string const &parameterName, std::string const &parameterOwnerName)
bool appliesTo(BranchDescription const *branch) const
std::vector< Rule > rules_
void applyToAll(std::vector< BranchSelectState > &branchstates) const
double split
Definition: MVATrainer.cc:139
tuple size
Write out results.