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/assign.hpp>
57 #include <boost/preprocessor/seq.hpp>
58 #include <boost/preprocessor/tuple.hpp>
59 #endif
60 
61 #include <utils/Singleton.h>
62 #include <utils/PParam.h>
63 #include <utils/Registrar.h>
64 
65 #include <thread/Thread.h>
66 
67 #include <factory/FactoryMacros.h>
68 #include <factory/Class.h>
69 #include <factory/TClass.h>
70 #include <factory/TemplateClass.h>
71 #include <factory/Object.h>
72 
73 namespace mira {
74 
76 
77 // *****************************************************************************
78 // *** ClassFactory
79 // *****************************************************************************
80 
88 class MIRA_BASE_EXPORT ClassFactory : public LazySingleton<ClassFactory>
89 {
90  friend class ClassProxy;
91  friend class LightFactoryMutexGetter;
92  friend class VacantClass;
93 public:
94 
95  ClassFactory() { mRoot.mIdentifier = "mira::Object"; }
96 
97  ~ClassFactory();
98 
106  template<typename CLASS>
107  static CLASS* newInstance( std::string const& classIdentifier );
108 
117  template<typename CLASS>
118  static CLASS* newInstance( std::string const& classIdentifier,
119  int paramCount, ... );
120 
121  template<typename CLASS>
122  static CLASS* newInstance( std::string const& classIdentifier,
123  int paramCount, std::va_list list );
124 
128  static bool isClassRegistered( std::string const& classIdentifier )
129  {
130  return instance().mRoot.isClassRegistered( classIdentifier );
131  }
132 
137  static ClassProxy getClassByIdentifier(std::string const& classIdentifier )
138  {
139  return instance().mRoot.getClassByIdentifier( classIdentifier );
140  }
141 
147  static std::vector<ClassProxy> getClassByMeta(std::string const& metaKey,
148  std::string const& metaValue )
149  {
150  return instance().mRoot.getClassByMeta( metaKey, metaValue );
151  }
152 
158  template <class T>
159  static std::vector<ClassProxy> getClassByMeta( T funcPtr )
160  {
161  return instance().mRoot.getClassByMeta( funcPtr );
162  }
163 
167  static std::map<std::string, ClassProxy > getDerivedClasses()
168  {
169  return instance().mRoot.getDerivedClasses();
170  }
171 
177  static void registerClass( boost::shared_ptr<Class> iClass );
178 
185  static void registerClass( boost::shared_ptr<Class> iClass,
186  boost::shared_ptr<Class> baseClass );
187 
192  static void unregisterClass( Class* iClass );
193 
199  static void postRegisterBaseClasses( std::string const& iClass,
200  std::vector< std::string> const& parents );
201 
207  static void finalizePostRegister();
208 
209 protected:
213  void propagateChild( ClassProxy& child, Class& parent );
214 
219  bool internalClassRegister( boost::shared_ptr<Class> iClass );
220 
221 private:
222  TClass<Object> mRoot;
224  boost::recursive_mutex mThreadMutex;
225  std::map<std::string, boost::shared_ptr<Class> > mClasses;
226 };
227 
229 
230 // *****************************************************************************
231 // *** FactoryRegisterClass
232 // *****************************************************************************
233 
234 struct FactoryNullDeleter
235 {
236  void operator()(void const *) const
237  { }
238 };
239 
240 template<typename TClassP, typename Base>
241 struct FactoryRegisterClassHelper
242 {
243  static void invoke() {
244  boost::shared_ptr<TClass<TClassP> > tClass( &(TClassP::_CLASS()) , FactoryNullDeleter() );
245  boost::shared_ptr<Class> tClassPtr = boost::dynamic_pointer_cast<Class>( tClass );
246  boost::shared_ptr<TClass<Base> > tBase( &(Base::_CLASS()), FactoryNullDeleter() );
247  boost::shared_ptr<Class> tBasePtr = boost::dynamic_pointer_cast<Class>( tBase );
248  mira::ClassFactory::instance().registerClass(
249  tClassPtr, tBasePtr );
250  }
251 };
252 
253 template<typename TClassP>
254 struct FactoryRegisterClassHelper<TClassP, mira::Object>
255 {
256  static void invoke() {
257  boost::shared_ptr<TClass<TClassP> > tClass( &(TClassP::_CLASS()), FactoryNullDeleter() );
258  boost::shared_ptr<Class> tClassPtr = boost::dynamic_pointer_cast<Class>( tClass );
259  mira::ClassFactory::instance().registerClass( tClassPtr );
260  }
261 };
262 
263 template<typename Class>
264 struct FactoryRegisterClassHelper<Class, bool>
265 {
266  static void invoke() {}
267 };
268 
273 template<typename Class,
274  typename Base0,
275  typename Base1=bool, typename Base2=bool,
276  typename Base3=bool, typename Base4=bool>
277 class FactoryRegisterClass
278 {
279 public:
280  FactoryRegisterClass()
281  {
282  FactoryRegisterClassHelper<Class,Base0>::invoke();
283  FactoryRegisterClassHelper<Class,Base1>::invoke();
284  FactoryRegisterClassHelper<Class,Base2>::invoke();
285  FactoryRegisterClassHelper<Class,Base3>::invoke();
286  FactoryRegisterClassHelper<Class,Base4>::invoke();
287  }
288 };
289 
291 
292 // *****************************************************************************
293 // *** Implementation of ClassFactory
294 // *****************************************************************************
295 
296 // this looks a bit like code duplication but we cannot use the newInstance
297 // function of mRoot since mRoot is of type TClass. The implementation of the
298 // template newInstance() version for TClass is quite useless -> therefore
299 // we need this function...
300 template<typename CLASS>
301 inline CLASS* mira::ClassFactory::newInstance( std::string const& classIdentifier )
302 {
303  Object* tBase = instance().mRoot.newInstance( classIdentifier );
304  return mira_factoryDynamicCast<CLASS>( tBase );
305 }
306 
307 template<typename CLASS>
308 inline CLASS* mira::ClassFactory::newInstance( std::string const& classIdentifier,
309  int paramCount, ... )
310 {
311  std::va_list ap;
312  va_start(ap, paramCount);
313  Object* tObject = instance().mRoot.newVAInstance( classIdentifier,
314  paramCount, ap );
315  return mira_factoryDynamicCast<CLASS>( tObject );
316 }
317 
318 template<typename CLASS>
319 inline CLASS* mira::ClassFactory::newInstance( std::string const& classIdentifier,
320  int paramCount, std::va_list list )
321 {
322  Object* tObject = instance().mRoot.newVAInstance( classIdentifier,
323  paramCount, list );
324  return mira_factoryDynamicCast<CLASS>( tObject );
325 }
326 
327 
328 // *****************************************************************************
329 // *** Implementation of PseudoClass from Object.h
330 // *****************************************************************************
331 
332 inline Object* PseudoClass::newInstance(std::string const& pChildIdentifier ) const
333 {
334  return ClassFactory::newInstance<Object>(pChildIdentifier);
335 }
336 
337 template <class CLASS>
338 inline CLASS* PseudoClass::newInstance(std::string const& pChildIdentifier ) const
339 {
340  return ClassFactory::newInstance<CLASS>(pChildIdentifier);
341 }
342 
344 
345 } // namespace
346 
347 #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:147
$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:88
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:167
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:128
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:137
static std::vector< ClassProxy > getClassByMeta(T funcPtr)
Return list of Class objects returning true for the given comparison function.
Definition: Factory.h:159
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:95
static CLASS * newInstance(std::string const &classIdentifier)
Create new instance of the class defined by class identifier.
Definition: Factory.h:301
Object * newInstance(std::string const &childIdentifier) const
Return a new instance of the class with the given identifier.
Definition: Factory.h:332