Line data Source code
1 : /*
2 : * Copyright (c) 2016: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG_factory
34 : #define __H__UG_factory
35 :
36 : #include <boost/static_assert.hpp>
37 : #include <boost/mpl/for_each.hpp>
38 : #include <boost/mpl/vector.hpp>
39 : #include <boost/type_traits/is_base_of.hpp>
40 : #include "../boost_serialization.h"
41 : #include "detail/register_type_pair_functor.h"
42 :
43 : namespace ug{
44 :
45 : namespace detail{
46 : namespace factory{
47 : /// used internally to construct derived classes of a given type
48 : template <class TBase, class TDerived>
49 0 : TBase* DerivedClassFactory ()
50 : {
51 0 : return new TDerived;
52 : }
53 : }
54 : }
55 :
56 :
57 : /// A factory class which creates instances given a class-name
58 : /** Given a base-class 'TBase' and an optional boost::mpl sequence of pairs of
59 : * derived classes and strings 'TPairSeq', the ug::Factory class allows for the
60 : * creation of instances ofderived classes given a name. Additionally to the
61 : * classes contained in 'TPairSeq', one may register derived classes at runtime
62 : * through the 'register_class' method.
63 : *
64 : * Besides creation of registered classes through the 'create' method,
65 : * one can iterate over all registered classes or obtain a registered class-name
66 : * given a pointer to the base class.
67 : *
68 : * \note This factory class is somewhat limited compared to e.g. to boost::factory and
69 : * is not meant as a replacement. It's main purpose is to allow iteration
70 : * over registered classes and to perform automatic registration through
71 : * a type list.
72 : */
73 : template <class TBase, class TPairSeq = boost::mpl::vector<> >
74 : class Factory
75 : {
76 : public:
77 0 : Factory()
78 : {
79 : detail::RegisterTypePairFunctor<Factory> func(this);
80 : boost::mpl::for_each<TPairSeq>(func);
81 0 : }
82 :
83 : SmartPtr<TBase> create(const std::string& className)
84 : {
85 0 : return create(className.c_str());
86 : }
87 :
88 0 : SmartPtr<TBase> create(const char* className)
89 : {
90 0 : return SmartPtr<TBase>(create_raw(className));
91 : }
92 :
93 : TBase* create_raw(const std::string& className)
94 : {
95 : return create_raw(className.c_str());
96 : }
97 :
98 0 : TBase* create_raw(const char* className)
99 : {
100 0 : typename class_map_t::iterator iclass = m_classMap.find(std::string(className));
101 0 : UG_COND_THROW(iclass == m_classMap.end(),
102 : "Unregistered class-name used in 'Factory::create_raw': " << className);
103 0 : return iclass->second.factory();
104 : }
105 :
106 : template <class TDerived>
107 0 : void register_class(const char* name)
108 : {
109 : // UG_LOG("registering derived class: " << className << std::endl);
110 : BOOST_STATIC_ASSERT((boost::is_base_of<TBase, TDerived>::value));
111 :
112 0 : std::string className(name);
113 :
114 0 : m_classMap[className] = ClassInfo(
115 : name,
116 : &detail::factory::DerivedClassFactory<TBase, TDerived>);
117 :
118 0 : std::string typeName(typeid(TDerived).name());
119 0 : m_classNameMap[typeName] = className;
120 :
121 0 : m_classNames.push_back(className);
122 0 : }
123 :
124 : size_t num_classes() const {return m_classNames.size();}
125 : const std::string& class_name(const size_t i) const {return m_classNames.at(i);}
126 0 : const std::string& class_name(const TBase& cls) const
127 : {
128 0 : std::string typeName = typeid(cls).name();
129 : class_name_map_t::const_iterator i = m_classNameMap.find(typeName);
130 0 : if(i != m_classNameMap.end())
131 0 : return i->second;
132 0 : static const std::string defaultName ("");
133 : return defaultName;
134 : }
135 :
136 : private:
137 : typedef TBase* (*factory_sig)();
138 :
139 : struct ClassInfo {
140 0 : ClassInfo () {}
141 : ClassInfo (const char* _name,
142 : factory_sig _factory) :
143 : name(_name),
144 : factory(_factory)
145 : {}
146 :
147 : const char* name;
148 : factory_sig factory;
149 : };
150 :
151 : typedef std::map<std::string, ClassInfo> class_map_t;
152 : typedef std::map<std::string, std::string> class_name_map_t;
153 : class_map_t m_classMap;///< contains ClassInfo objects accessible by class-name.
154 : class_name_map_t m_classNameMap;///< key: type-name, value: class-names
155 : std::vector<std::string> m_classNames;
156 : };
157 :
158 : }// end of namespace
159 :
160 : #endif //__H__UG_factory
|