MIRA
Factory.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
48 #ifndef _MIRA_FACTORY_H_
49 #define _MIRA_FACTORY_H_
50 
51 #include <map>
52 #include <cstdarg>
53 
54 #ifndef Q_MOC_RUN
55 #include <boost/type_traits/is_abstract.hpp>
56 #include <boost/mpl/eval_if.hpp>
57 #include <boost/assign.hpp>
58 #include <boost/preprocessor/seq.hpp>
59 #include <boost/preprocessor/tuple.hpp>
60 #endif
61 
62 #include <utils/Singleton.h>
63 #include <utils/PParam.h>
64 #include <utils/Registrar.h>
65 
66 #include <thread/Thread.h>
67 
68 #include <factory/FactoryMacros.h>
69 #include <factory/Class.h>
70 #include <factory/TClass.h>
71 #include <factory/TemplateClass.h>
72 #include <factory/Object.h>
73 
74 namespace mira {
75 
77 
78 // *****************************************************************************
79 // *** ClassFactory
80 // *****************************************************************************
81 
89 class MIRA_BASE_EXPORT ClassFactory : public LazySingleton<ClassFactory>
90 {
91  friend class ClassProxy;
92  friend class LightFactoryMutexGetter;
93  friend class VacantClass;
94 public:
95 
96  ClassFactory() { mRoot.mIdentifier = "mira::Object"; }
97 
98  ~ClassFactory();
99 
107  template<typename CLASS>
108  static CLASS* newInstance( std::string const& classIdentifier );
109 
118  template<typename CLASS>
119  static CLASS* newInstance( std::string const& classIdentifier,
120  int paramCount, ... );
121 
122  template<typename CLASS>
123  static CLASS* newInstance( std::string const& classIdentifier,
124  int paramCount, std::va_list list );
125 
129  static bool isClassRegistered( std::string const& classIdentifier )
130  {
131  return instance().mRoot.isClassRegistered( classIdentifier );
132  }
133 
138  static ClassProxy getClassByIdentifier(std::string const& classIdentifier )
139  {
140  return instance().mRoot.getClassByIdentifier( classIdentifier );
141  }
142 
148  static std::vector<ClassProxy> getClassByMeta(std::string const& metaKey,
149  std::string const& metaValue )
150  {
151  return instance().mRoot.getClassByMeta( metaKey, metaValue );
152  }
153 
159  template <class T>
160  static std::vector<ClassProxy> getClassByMeta( T funcPtr )
161  {
162  return instance().mRoot.getClassByMeta( funcPtr );
163  }
164 
168  static std::map<std::string, ClassProxy > getDerivedClasses()
169  {
170  return instance().mRoot.getDerivedClasses();
171  }
172 
178  static void registerClass( boost::shared_ptr<Class> iClass );
179 
186  static void registerClass( boost::shared_ptr<Class> iClass,
187  boost::shared_ptr<Class> baseClass );
188 
193  static void unregisterClass( Class* iClass );
194 
200  static void postRegisterBaseClasses( std::string const& iClass,
201  std::vector< std::string> const& parents );
202 
208  static void finalizePostRegister();
209 
210 protected:
214  void propagateChild( ClassProxy& child, Class& parent );
215 
220  bool internalClassRegister( boost::shared_ptr<Class> iClass );
221 
222 private:
223  TClass<Object> mRoot;
225  boost::recursive_mutex mThreadMutex;
226  std::map<std::string, boost::shared_ptr<Class> > mClasses;
227 };
228 
230 
231 // *****************************************************************************
232 // *** FactoryRegisterClass
233 // *****************************************************************************
234 
235 struct FactoryNullDeleter
236 {
237  void operator()(void const *) const
238  { }
239 };
240 
241 template<typename TClassP, typename Base>
242 struct FactoryRegisterClassHelper
243 {
244  static void invoke() {
245  boost::shared_ptr<TClass<TClassP> > tClass( &(TClassP::_CLASS()) , FactoryNullDeleter() );
246  boost::shared_ptr<Class> tClassPtr = boost::dynamic_pointer_cast<Class>( tClass );
247  boost::shared_ptr<TClass<Base> > tBase( &(Base::_CLASS()), FactoryNullDeleter() );
248  boost::shared_ptr<Class> tBasePtr = boost::dynamic_pointer_cast<Class>( tBase );
249  mira::ClassFactory::instance().registerClass(
250  tClassPtr, tBasePtr );
251  }
252 };
253 
254 template<typename TClassP>
255 struct FactoryRegisterClassHelper<TClassP, mira::Object>
256 {
257  static void invoke() {
258  boost::shared_ptr<TClass<TClassP> > tClass( &(TClassP::_CLASS()), FactoryNullDeleter() );
259  boost::shared_ptr<Class> tClassPtr = boost::dynamic_pointer_cast<Class>( tClass );
260  mira::ClassFactory::instance().registerClass( tClassPtr );
261  }
262 };
263 
264 template<typename Class>
265 struct FactoryRegisterClassHelper<Class, bool>
266 {
267  static void invoke() {}
268 };
269 
274 template<typename Class,
275  typename Base0,
276  typename Base1=bool, typename Base2=bool,
277  typename Base3=bool, typename Base4=bool>
278 class FactoryRegisterClass
279 {
280 public:
281  FactoryRegisterClass()
282  {
283  FactoryRegisterClassHelper<Class,Base0>::invoke();
284  FactoryRegisterClassHelper<Class,Base1>::invoke();
285  FactoryRegisterClassHelper<Class,Base2>::invoke();
286  FactoryRegisterClassHelper<Class,Base3>::invoke();
287  FactoryRegisterClassHelper<Class,Base4>::invoke();
288  }
289 };
290 
292 
293 // *****************************************************************************
294 // *** Implementation of ClassFactory
295 // *****************************************************************************
296 
297 // this looks a bit like code duplication but we cannot use the newInstance
298 // function of mRoot since mRoot is of type TClass. The implementation of the
299 // template newInstance() version for TClass is quite useless -> therefore
300 // we need this function...
301 template<typename CLASS>
302 inline CLASS* mira::ClassFactory::newInstance( std::string const& classIdentifier )
303 {
304  Object* tBase = instance().mRoot.newInstance( classIdentifier );
305  return mira_factoryDynamicCast<CLASS>( tBase );
306 }
307 
308 template<typename CLASS>
309 inline CLASS* mira::ClassFactory::newInstance( std::string const& classIdentifier,
310  int paramCount, ... )
311 {
312  std::va_list ap;
313  va_start(ap, paramCount);
314  Object* tObject = instance().mRoot.newVAInstance( classIdentifier,
315  paramCount, ap );
316  return mira_factoryDynamicCast<CLASS>( tObject );
317 }
318 
319 template<typename CLASS>
320 inline CLASS* mira::ClassFactory::newInstance( std::string const& classIdentifier,
321  int paramCount, std::va_list list )
322 {
323  Object* tObject = instance().mRoot.newVAInstance( classIdentifier,
324  paramCount, list );
325  return mira_factoryDynamicCast<CLASS>( tObject );
326 }
327 
328 
329 // *****************************************************************************
330 // *** Implementation of PseudoClass from Object.h
331 // *****************************************************************************
332 
333 inline Object* PseudoClass::newInstance(std::string const& pChildIdentifier ) const
334 {
335  return ClassFactory::newInstance<Object>(pChildIdentifier);
336 }
337 
338 template <class CLASS>
339 inline CLASS* PseudoClass::newInstance(std::string const& pChildIdentifier ) const
340 {
341  return ClassFactory::newInstance<CLASS>(pChildIdentifier);
342 }
343 
345 
346 } // namespace
347 
348 #endif /* FACTORY_H_ */
Registration and unregistration helper class.
$Macros for registering classes$.
$Definition of the Class which supports some kind of class reflection and acts like a class factory$...
static std::vector< ClassProxy > getClassByMeta(std::string const &metaKey, std::string const &metaValue)
Return list of Class objects matching the meta criterion.
Definition: Factory.h:148
$In contrast to the VacantClass this is the "real" class specific implementation which is able to con...
What should i say, the class factory.
Definition: Factory.h:89
The class proxy assures that the pointer to the class object is always valid.
Definition: Class.h:400
static Type & instance()
Returns a reference to the singleton instance.
Definition: Singleton.h:544
Preprocessor workaround to handle single parameters that contain a comma.
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
static std::map< std::string, ClassProxy > getDerivedClasses()
Return list of registered classes.
Definition: Factory.h:168
Class object which supports some kind of class reflection.
Definition: Class.h:97
static bool isClassRegistered(std::string const &classIdentifier)
Return true if a class with the desired identifier is registered.
Definition: Factory.h:129
Provided for convenience.
Definition: Singleton.h:564
static ClassProxy getClassByIdentifier(std::string const &classIdentifier)
Return the Class object for the desired Class.
Definition: Factory.h:138
static std::vector< ClassProxy > getClassByMeta(T funcPtr)
Return list of Class objects returning true for the given comparison function.
Definition: Factory.h:160
ClassProxy getClassByIdentifier(std::string const &classIdentifier) const
Return the Class object for the desired Class.
Includes, defines and functions for threads.
A singleton class that can be freely configured using policies that control the creation, instantiation, lifetime and thread-safety.
The object class acts as a generic base class for classes which should be used with the classFactory...
Definition: Object.h:144
The VacantClass object is the implementation of the Class class for classes which are NOT available s...
Definition: VacantClass.h:68
json_spirit::mObject Object
A representation of an object (class, struct) in JSON.
Definition: JSON.h:183
$Definition of the template class objects which enables the factory to work with template classes$...
The TClass object is the implementation of the class class for classes which are available since the ...
Definition: TClass.h:75
$Defines object class as base class for classFactory compatible classes$.
#define MIRA_BASE_EXPORT
This is required because on windows there is a macro defined called ERROR.
Definition: Platform.h:153
ClassFactory()
Definition: Factory.h:96
static CLASS * newInstance(std::string const &classIdentifier)
Create new instance of the class defined by class identifier.
Definition: Factory.h:302
Object * newInstance(std::string const &childIdentifier) const
Return a new instance of the class with the given identifier.
Definition: Factory.h:333