IODA Bundle
ParserFactory.h
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 #pragma once
9 
10 #include <map>
11 #include <memory>
12 #include <string>
13 #include <ostream>
14 
15 #include "eckit/config/LocalConfiguration.h"
16 #include "eckit/exception/Exceptions.h"
17 
18 #include "Parser.h"
19 
20 namespace
21 {
22  namespace ConfKeys
23  {
24  const char* ParserName = "name";
25  }
26 }
27 
28 namespace Ingester
29 {
30  /// \brief Base class for all ParserMakers. Makes it possible to store all types of parsers
31  /// inside a std data structure like a map.
33  {
34  public:
35  /// \brief Instantiate a Parser instance
36  /// \param conf Configuration to base the Parser on (obs space)
37  virtual std::shared_ptr<Parser> make(const eckit::Configuration &conf) = 0;
38  };
39 
40  /// \brief ParserMaker class template definition
41  /// \tparam T The Parser class this Maker will make
42  template <class T>
44  {
45  public:
46  std::shared_ptr<Parser> make(const eckit::Configuration &conf) override
47  {
48  return std::make_shared<T>(conf);
49  }
50  };
51 
52  /// \brief Factory that is used to create Parsers
54  {
55  public:
56  /// \brief Create a Parser
57  /// \param conf Provides the name of the parser we want to create
58  static std::shared_ptr<Parser> create(const eckit::Configuration &conf)
59  {
60  if (!conf.has(ConfKeys::ParserName))
61  {
62  throw eckit::BadParameter("Parser configuration has no \"name\".");
63  }
64  else if (getMakers().find(conf.getString(ConfKeys::ParserName)) == getMakers().end())
65  {
66  std::ostringstream errStr;
67  errStr << "Trying to use unregistered parser named ";
68  errStr << conf.getString(ConfKeys::ParserName);
69  throw eckit::BadParameter(errStr.str());
70  }
71 
72  return getMakers()[conf.getString(ConfKeys::ParserName)]->make(conf);
73  }
74 
75  /// \brief Register a new Parser type we want to be able to create
76  /// \tparam T The Parser class
77  /// \param name The name to associate with the parser class.
78  template<class T>
79  static void registerParser(const std::string& name)
80  {
81  if (getMakers().find(name) != getMakers().end())
82  {
83  std::ostringstream errStr;
84  errStr << "Trying to add parser with a duplicate name ";
85  errStr << name;
86  errStr << ". Name must be unique.";
87 
88  throw eckit::BadParameter(errStr.str());
89  }
90 
91  getMakers().insert({name, std::make_shared<ParserMaker<T>>()});
92  }
93 
94  private:
95  /// \brief Internal method that returns a map of Parser Makers that were registered
96  /// with registerParser
97  static std::map<std::string, std::shared_ptr<ParserMakerBase>>& getMakers()
98  {
99  static std::map<std::string, std::shared_ptr<ParserMakerBase>> makers;
100  return makers;
101  }
102  };
103 } // namespace Ingester
Factory that is used to create Parsers.
Definition: ParserFactory.h:54
static void registerParser(const std::string &name)
Register a new Parser type we want to be able to create.
Definition: ParserFactory.h:79
static std::shared_ptr< Parser > create(const eckit::Configuration &conf)
Create a Parser.
Definition: ParserFactory.h:58
static std::map< std::string, std::shared_ptr< ParserMakerBase > > & getMakers()
Internal method that returns a map of Parser Makers that were registered with registerParser.
Definition: ParserFactory.h:97
Base class for all ParserMakers. Makes it possible to store all types of parsers inside a std data st...
Definition: ParserFactory.h:33
virtual std::shared_ptr< Parser > make(const eckit::Configuration &conf)=0
Instantiate a Parser instance.
ParserMaker class template definition.
Definition: ParserFactory.h:44
std::shared_ptr< Parser > make(const eckit::Configuration &conf) override
Instantiate a Parser instance.
Definition: ParserFactory.h:46