IODA Bundle
Export.cpp
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020 NOAA/NWS/NCEP/EMC
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
8 #include "Export.h"
9 
10 #include <ostream>
11 #include <iostream>
12 
13 #include "eckit/exception/Exceptions.h"
14 
15 #include "Filters/BoundingFilter.h"
16 #include "Splits/CategorySplit.h"
21 
22 
23 namespace
24 {
25  namespace ConfKeys
26  {
27  const char* Filters = "filters";
28  const char* Splits = "splits";
29  const char* Variables = "variables";
30 
31  namespace Variable
32  {
33  const char* Datetime = "datetime";
34  const char* Mnemonic = "mnemonic";
35  } // namespace Variable
36 
37  namespace Split
38  {
39  const char* Category = "category";
40  const char* Mnemonic = "mnemonic";
41  const char* NameMap = "map";
42  } // namespace Split
43 
44  namespace Filter
45  {
46  const char* Mnemonic = "mnemonic";
47  const char* Bounding = "bounding";
48  const char* UpperBound = "upperBound";
49  const char* LowerBound = "lowerBound";
50  }
51 
52  } // namespace ConfKeys
53 } // namespace
54 
55 namespace Ingester
56 {
57  Export::Export(const eckit::Configuration &conf)
58  {
59  if (conf.has(ConfKeys::Filters)) // Optional
60  {
61  addFilters(conf.getSubConfiguration(ConfKeys::Filters));
62  }
63 
64  if (conf.has(ConfKeys::Splits)) // Optional
65  {
66  addSplits(conf.getSubConfiguration(ConfKeys::Splits));
67  }
68 
69  if (conf.has(ConfKeys::Variables))
70  {
71  addVariables(conf.getSubConfiguration(ConfKeys::Variables));
72  }
73  else
74  {
75  throw eckit::BadParameter("Missing export::variables section in configuration.");
76  }
77  }
78 
79  void Export::addVariables(const eckit::Configuration &conf)
80  {
81  if (conf.keys().size() == 0)
82  {
83  std::stringstream errStr;
84  errStr << "bufr::exports::variables must contain a dictionary of variables!";
85  throw eckit::BadParameter(errStr.str());
86  }
87 
88  for (const auto& key : conf.keys())
89  {
90  std::shared_ptr<Variable> variable;
91 
92  auto subConf = conf.getSubConfiguration(key);
93  if (subConf.has(ConfKeys::Variable::Datetime))
94  {
95  auto dtconf = subConf.getSubConfiguration(ConfKeys::Variable::Datetime);
96  variable = std::make_shared<DatetimeVariable>(dtconf);
97  }
98  else if (subConf.has(ConfKeys::Variable::Mnemonic))
99  {
100  Transforms transforms = TransformBuilder::makeTransforms(subConf);
101  variable = std::make_shared<MnemonicVariable>(
102  subConf.getString(ConfKeys::Variable::Mnemonic), transforms);
103  }
104  else
105  {
106  std::ostringstream errMsg;
107  errMsg << "Unknown bufr::exports::variable of type " << key;
108  throw eckit::BadParameter(errMsg.str());
109  }
110 
111  variables_.insert({key, variable});
112  }
113  }
114 
115  void Export::addSplits(const eckit::Configuration &conf)
116  {
117  if (conf.keys().size() == 0)
118  {
119  std::stringstream errStr;
120  errStr << "bufr::exports::splits must contain a dictionary of splits!";
121  throw eckit::BadParameter(errStr.str());
122  }
123 
124  for (const auto& key : conf.keys())
125  {
126  std::shared_ptr<Split> split;
127 
128  auto subConf = conf.getSubConfiguration(key);
129 
130  if (subConf.has(ConfKeys::Split::Category))
131  {
132  auto catConf = subConf.getSubConfiguration(ConfKeys::Split::Category);
133 
134  auto nameMap = CategorySplit::NameMap();
135  if (catConf.has(ConfKeys::Split::NameMap))
136  {
137  const auto& mapConf = catConf.getSubConfiguration(ConfKeys::Split::NameMap);
138  for (const std::string& mapKey : mapConf.keys())
139  {
140  auto intKey = mapKey.substr(1, mapKey.size());
141  nameMap.insert({std::stoi(intKey), mapConf.getString(mapKey)});
142  }
143  }
144 
145  split = std::make_shared<CategorySplit>(
146  catConf.getString(ConfKeys::Split::Mnemonic),
147  nameMap);
148  }
149  else
150  {
151  std::ostringstream errMsg;
152  errMsg << "Unknown bufr::exports::splits of type " << key;
153  throw eckit::BadParameter(errMsg.str());
154  }
155 
156  splits_.insert({key, split});
157  }
158  }
159 
160  void Export::addFilters(const eckit::Configuration &conf)
161  {
162  auto subConfs = conf.getSubConfigurations();
163  if (subConfs.size() == 0)
164  {
165  std::stringstream errStr;
166  errStr << "bufr::exports::filters must contain a list of filters!";
167  throw eckit::BadParameter(errStr.str());
168  }
169 
170  for (const auto& subConf : subConfs)
171  {
172  std::shared_ptr<Filter> filter;
173 
174  if (subConf.has(ConfKeys::Filter::Bounding))
175  {
176  auto filterConf = subConf.getSubConfiguration(ConfKeys::Filter::Bounding);
177 
178  std::shared_ptr<float> lowerBound = nullptr;
179  if (filterConf.has(ConfKeys::Filter::LowerBound))
180  {
181  lowerBound = std::make_shared<float>(
182  filterConf.getFloat(ConfKeys::Filter::LowerBound));
183  }
184 
185  std::shared_ptr<float> upperBound = nullptr;
186  if (filterConf.has(ConfKeys::Filter::UpperBound))
187  {
188  upperBound = std::make_shared<float>(
189  filterConf.getFloat(ConfKeys::Filter::UpperBound));
190  }
191 
192  filter = std::make_shared<BoundingFilter>(
193  filterConf.getString(ConfKeys::Filter::Mnemonic),
194  lowerBound,
195  upperBound);
196  }
197  else
198  {
199  std::ostringstream errMsg;
200  errMsg << "bufr::exports::filters Unknown filter of type ";
201  errMsg << subConf.keys()[0] << ".";
202  throw eckit::BadParameter(errMsg.str());
203  }
204 
205  filters_.push_back(filter);
206  }
207  }
208 
209 } // namespace Ingester
std::map< int, std::string > NameMap
Map of integers to strings where the key represents the split mnemonics integer value and the value i...
Definition: CategorySplit.h:40
void addVariables(const eckit::Configuration &conf)
Create Variables exports from config.
Definition: Export.cpp:79
Filters filters_
Definition: Export.h:43
Splits splits_
Definition: Export.h:41
void addSplits(const eckit::Configuration &conf)
Create Splits exports from config.
Definition: Export.cpp:115
Variables variables_
Definition: Export.h:42
Export(const eckit::Configuration &conf)
Constructor.
Definition: Export.cpp:57
void addFilters(const eckit::Configuration &conf)
Create Filters exports from config.
Definition: Export.cpp:160
static Transforms makeTransforms(const eckit::Configuration &conf)
Uses makeTransform to loop through the list of transforms in the configuration.
std::vector< std::shared_ptr< Transform > > Transforms
character(maxvarlen) function variable(this, jj)