1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#ifndef PluginManager_hh_included
#define PluginManager_hh_included 1
#include <map>
#include <string>
#include <vector>
namespace hcal {
/** \brief Base class for classes to be managed by the PluginManager.
This class is provided to enable appropriate use of the dynamic_cast<> operator and
to defince clearly the newInstance() operator of the plugin factory.
\ingroup hcalBase
*/
class Pluggable {
public:
/// A virtual destructor is required to establish the inheritance tree
virtual ~Pluggable() = default;
};
/** \brief Class which is able to create instances of another class.
The AbstractPluginFactory defines the interface of a Factory
class used by the PluginManager. In general, factories are
defined in terms of an abstract base class (derived from
Pluggable), and a concrete implementation class. This
architecture is used in the database interface, where
ConfigurationDatabaseImpl is the base class and
ConfigurationDatabaseImplMySQL is a concrete implementation.
\ingroup hcalBase
*/
class AbstractPluginFactory {
public:
virtual ~AbstractPluginFactory() = default;
/** \brief Create a new instance of the class which this factory provides */
virtual Pluggable* newInstance() = 0;
/** \brief Get the name of the class which is considered the base for this factory's class.
In the example, this would be ConfigurationDatabaseImpl
*/
virtual const char* getBaseClass() const = 0;
/** \brief Get the name of the concrete class provided directly by this factory.
In the example, this would be ConfigurationDatabaseImplMySQL
*/
virtual const char* getDerivedClass() const = 0;
};
/** \brief Global resource for managing implementations of abstract interface classes.
The PluginManager class is a central repository to register factory
objects. Each factory object can create objects of a class derived
from Pluggable. Such factories can be easily created from the
PluginFactoryTemplate using the DECLARE_PLUGGABLE macro. The user
of the PluginManager should know what base class is required and may
obtain a specific factory or get a list of all factories capable of
supplying concrete objects derived from the specified base class.
\ingroup hcalBase
*/
class PluginManager {
public:
/** \brief Register a new factory with the singleton plugin manager. Each factory provides objects of a single class.
\param baseClass Name of the abstract base class for objects provided by the factory.
\param derivedClass Name of the concrete class for objects provided by the factory.
\param factory Pointer to the factory object itself
*/
static void registerFactory(const char* baseClass, const char* derivedClass, AbstractPluginFactory* factory);
/** \brief Lookup a specific factory by base class and derived class name
\return NULL if the specified factory is not found
*/
static AbstractPluginFactory* getFactory(const char* baseClass, const char* derivedClass);
/** \brief Lookup all factories providing concrete objects from the specified base class
*/
static void getFactories(const char* baseClass, std::vector<AbstractPluginFactory*>& factories);
private:
static std::map<std::string, std::map<std::string, AbstractPluginFactory*> >& factories();
};
/** \brief Templated generic plugin factory used by the DECLARE_PLUGGABLE macro
\ingroup hcalBase
*/
template <class T>
class PluginFactoryTemplate : public AbstractPluginFactory {
public:
PluginFactoryTemplate(const char* bc, const char* dc) : m_baseClass(bc), m_derivedClass(dc) {
PluginManager::registerFactory(bc, dc, this);
}
~PluginFactoryTemplate() override = default;
Pluggable* newInstance() override { return new T; }
const char* getBaseClass() const override { return m_baseClass; }
const char* getDerivedClass() const override { return m_derivedClass; }
private:
const char* m_baseClass;
const char* m_derivedClass;
};
} // namespace hcal
/** \def DECLARE_PLUGGABLE(BASECLASS,MYCLASS)
\brief Utility macro which creates a static object specializing PluginFactoryTemplate for a specific class (base and concrete).
\param BASECLASS Base class for the factory (not in quotes)
\param MYCLASS Derived concrete class for the factory (not in quotes)
\b Example:
\code
DECLARE_PLUGGABLE(hcal::ConfigurationDatabaseImpl,ConfigurationDatabaseImplMySQL)
\endcode
\ingroup hcalBase
*/
#define DECLARE_PLUGGABLE(BASECLASS, MYCLASS) \
static hcal::PluginFactoryTemplate<MYCLASS> hcal_plugin_##MYCLASS(#BASECLASS, #MYCLASS);
#endif // PluginManager_hh_included
|