Configuration.h
Go to the documentation of this file.
1 #ifndef WIRECELL_CONFIGURATION
2 #define WIRECELL_CONFIGURATION
3 
4 #include <json/json.h>
5 #include <boost/algorithm/string/split.hpp>
6 #include <boost/algorithm/string/classification.hpp>
7 
8 #include <sstream>
9 #include <vector>
10 
11 namespace WireCell {
12 
13  /** The Wire Cell Toolkit configuration layer uses Json::Value
14  objects for its transient data model.
15 
16  The Configuration type is a recursive in that one
17  Configuration object may contain others.
18 
19  The WCT assumes an Object Configuration Protocol is
20  implemented by the "client" code that uses the toolkit. See
21  for example the reference implementation in the wire-cell
22  command line program. This protocol consists of:
23 
24  1) Creation of the list of Configuration objects,
25  typically via WireCell::Persist::load().
26 
27  2) Iterating this list and for each suitable Configuration
28  object instantiating the appropriately matching IConfigurable
29  via the WireCell::NamedFactory facility.
30 
31  3) Obtaining the default Configuration object from the
32  IConfigurable and merging the user-supplied on top of it.
33 
34  4) Passing the resulting Configuration object to the
35  IConfigurable::configure() method.
36 
37  A suitable Configuration object must have two top level keys
38  and may have a third optional key:
39 
40  - type :: must match the "component class name" (as given as
41  first argument to the WIRECELL_FACTORY() macro in the
42  implementation file)
43 
44  - data :: an object which follows a schema which is specific to
45  each IConfigurable implementation.
46 
47  - name :: an optional Instance Name. If not given, the default instance of the type will be used.
48  */
49 
51 
52  /// For persistence use WireCell::Persist::load() and
53  /// WireCell::Persist::dump().
54 
55 
56  /// The following functions provide some access methods which add
57  /// some value beyond what Json::Value provides including some
58  /// support for basic WCT types.
59 
60 
61  /// Convert a configuration value to a particular type.
62  template<typename T>
63  T convert(const Configuration& cfg, const T& def = T()) {
64  return def;
65  }
66  template<>
67  inline
68  bool convert<bool>(const Configuration& cfg, const bool& def) {
69  if (cfg.isNull()) return def;
70  return cfg.asBool();
71  }
72  template<>
73  inline
74  int convert<int>(const Configuration& cfg, const int& def) {
75  if (cfg.isNull()) return def;
76  return cfg.asInt();
77  }
78  template<>
79  inline
80  float convert<float>(const Configuration& cfg, const float& def) {
81  if (cfg.isNull()) return def;
82  return cfg.asDouble();
83  }
84  template<>
85  inline
86  double convert<double>(const Configuration& cfg, const double& def) {
87  if (cfg.isNull()) return def;
88  return cfg.asDouble();
89  }
90  template<>
91  inline
92  std::string convert<std::string>(const Configuration& cfg, const std::string& def) {
93  if (cfg.isNull()) return def;
94  return cfg.asString();
95  }
96  template<>
97  inline // fixme: ignores default
98  std::vector<std::string> convert< std::vector<std::string> >(const Configuration& cfg, const std::vector<std::string>& def) {
99  std::vector<std::string> ret;
100  for (auto v : cfg) {
101  ret.push_back(convert<std::string>(v));
102  }
103  return ret;
104  }
105  template<>
106  inline // fixme: ignores default
107  std::vector<int> convert< std::vector<int> >(const Configuration& cfg, const std::vector<int>& def) {
108  std::vector<int> ret;
109  for (auto v : cfg) {
110  ret.push_back(convert<int>(v));
111  }
112  return ret;
113  }
114  template<>
115  inline // fixme: ignores default
116  std::vector<double> convert< std::vector<double> >(const Configuration& cfg, const std::vector<double>& def) {
117  std::vector<double> ret;
118  for (auto v : cfg) {
119  ret.push_back(convert<double>(v));
120  }
121  return ret;
122  }
123  // for Point and Ray converters, see Point.h
124 
125 
126  /// Follow a dot.separated.path and return the branch there.
127  Configuration branch(Configuration cfg, const std::string& dotpath);
128 
129  /// Merge dictionary b into a, return a
130  Configuration update(Configuration& a, Configuration& b);
131 
132  /// Return an array which is composed of the array b appended to the array a.
133  // fixme: this should be called "extend".
134  Configuration append(Configuration& a, Configuration& b);
135 
136  /// Return dictionary in given list if it value at dotpath matches
137  template<typename T>
138  Configuration find(Configuration& lst, const std::string& dotpath, const T& val) {
139  for (auto ent : lst) {
140  auto maybe = branch(ent, dotpath);
141  if (maybe.isNull()) { continue; }
142  if (convert<T>(maybe) == val) { return maybe; }
143  }
144  return Configuration();
145  }
146 
147  /// Get value in configuration at the dotted path from or return default.
148  template<typename T>
149  T get(Configuration cfg, const std::string& dotpath, const T& def = T()) {
150  return convert(branch(cfg, dotpath), def);
151  }
152 
153  /// Put value in configuration at the dotted path.
154  template<typename T>
155  void put(Configuration& cfg, const std::string& dotpath, const T& val) {
156  Configuration* ptr = &cfg;
157  std::vector<std::string> path;
158  boost::algorithm::split(path, dotpath, boost::algorithm::is_any_of("."));
159  for (auto name : path) {
160  ptr = &(*ptr)[name];
161  }
162  *ptr = val;
163  }
164 
165 
166 } // namespace WireCell
167 
168 #endif
static QCString name
Definition: declinfo.cpp:673
Configuration update(Configuration &a, Configuration &b)
Merge dictionary b into a, return a.
T convert(const Configuration &cfg, const T &def=T())
Convert a configuration value to a particular type.
Definition: Configuration.h:63
std::string string
Definition: nybbler.cc:12
void put(Configuration &cfg, const std::string &dotpath, const T &val)
Put value in configuration at the dotted path.
cfg
Definition: dbjson.py:29
Configuration branch(Configuration cfg, const std::string &dotpath)
Follow a dot.separated.path and return the branch there.
Configuration find(Configuration &lst, const std::string &dotpath, const T &val)
Return dictionary in given list if it value at dotpath matches.
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Definition: document.h:2106
float convert< float >(const Configuration &cfg, const float &def)
Definition: Configuration.h:80
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
Definition: Main.h:22
bool convert< bool >(const Configuration &cfg, const bool &def)
Definition: Configuration.h:68
const void * ptr(const T *p)
Definition: format.h:3138
Configuration append(Configuration &a, Configuration &b)
Return an array which is composed of the array b appended to the array a.
Json::Value Configuration
Definition: Configuration.h:50
static bool * b
Definition: config.cpp:1043
int convert< int >(const Configuration &cfg, const int &def)
Definition: Configuration.h:74
void split(std::string const &s, char c, OutIter dest)
Definition: split.h:35
double convert< double >(const Configuration &cfg, const double &def)
Definition: Configuration.h:86