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 <factory/FactoryMacros.h>
66 #include <factory/Class.h>
67 #include <factory/TClass.h>
68 #include <factory/TemplateClass.h>
69 #include <factory/Object.h>
70 
71 namespace mira {
72 
74 
75 // *****************************************************************************
76 // *** ClassFactory
77 // *****************************************************************************
78 
86 class ClassFactory : public LazySingleton<ClassFactory>
87 {
88  friend class ClassProxy;
90  friend class VacantClass;
91 public:
92 
93  ClassFactory() { mRoot.mIdentifier = "mira::Object"; }
94 
95  ~ClassFactory();
96 
104  template<typename CLASS>
105  static CLASS* newInstance( std::string const& classIdentifier );
106 
115  template<typename CLASS>
116  static CLASS* newInstance( std::string const& classIdentifier,
117  int paramCount, ... );
118 
119  template<typename CLASS>
120  static CLASS* newInstance( std::string const& classIdentifier,
121  int paramCount, std::va_list list );
122 
126  static bool isClassRegistered( std::string const& classIdentifier )
127  {
128  return instance().mRoot.isClassRegistered( classIdentifier );
129  }
130 
135  static ClassProxy getClassByIdentifier(std::string const& classIdentifier )
136  {
137  return instance().mRoot.getClassByIdentifier( classIdentifier );
138  }
139 
145  static std::vector<ClassProxy> getClassByMeta(std::string const& metaKey,
146  std::string const& metaValue )
147  {
148  return instance().mRoot.getClassByMeta( metaKey, metaValue );
149  }
150 
156  template <class T>
157  static std::vector<ClassProxy> getClassByMeta( T funcPtr )
158  {
159  return instance().mRoot.getClassByMeta( funcPtr );
160  }
161 
165  static std::map<std::string, ClassProxy > getDerivedClasses()
166  {
167  return instance().mRoot.getDerivedClasses();
168  }
169 
175  static void registerClass( boost::shared_ptr<Class> iClass );
176 
183  static void registerClass( boost::shared_ptr<Class> iClass,
184  boost::shared_ptr<Class> baseClass );
185 
190  static void unregisterClass( Class* iClass );
191 
197  static void postRegisterBaseClasses( std::string const& iClass,
198  std::vector< std::string> const& parents );
199 
205  static void finalizePostRegister();
206 
207 protected:
211  void propagateChild( ClassProxy& child, Class& parent );
212 
217  bool internalClassRegister( boost::shared_ptr<Class> iClass );
218 
219 private:
220  TClass<Object> mRoot;
222  boost::recursive_mutex mThreadMutex;
223  std::map<std::string, boost::shared_ptr<Class> > mClasses;
224 };
225 
227 
228 // *****************************************************************************
229 // *** FactoryRegisterClass
230 // *****************************************************************************
231 
232 struct FactoryNullDeleter
233 {
234  void operator()(void const *) const
235  { }
236 };
237 
238 template<typename TClassP, typename Base>
239 struct FactoryRegisterClassHelper
240 {
241  static void invoke() {
242  boost::shared_ptr<TClass<TClassP> > tClass( &(TClassP::_CLASS()) , FactoryNullDeleter() );
243  boost::shared_ptr<Class> tClassPtr = boost::dynamic_pointer_cast<Class>( tClass );
244  boost::shared_ptr<TClass<Base> > tBase( &(Base::_CLASS()), FactoryNullDeleter() );
245  boost::shared_ptr<Class> tBasePtr = boost::dynamic_pointer_cast<Class>( tBase );
246  mira::ClassFactory::instance().registerClass(
247  tClassPtr, tBasePtr );
248  }
249 };
250 
251 template<typename TClassP>
252 struct FactoryRegisterClassHelper<TClassP, mira::Object>
253 {
254  static void invoke() {
255  boost::shared_ptr<TClass<TClassP> > tClass( &(TClassP::_CLASS()), FactoryNullDeleter() );
256  boost::shared_ptr<Class> tClassPtr = boost::dynamic_pointer_cast<Class>( tClass );
257  mira::ClassFactory::instance().registerClass( tClassPtr );
258  }
259 };
260 
261 template<typename Class>
262 struct FactoryRegisterClassHelper<Class, bool>
263 {
264  static void invoke() {}
265 };
266 
271 template<typename Class,
272  typename Base0,
273  typename Base1=bool, typename Base2=bool,
274  typename Base3=bool, typename Base4=bool>
275 class FactoryRegisterClass
276 {
277 public:
278  FactoryRegisterClass()
279  {
280  FactoryRegisterClassHelper<Class,Base0>::invoke();
281  FactoryRegisterClassHelper<Class,Base1>::invoke();
282  FactoryRegisterClassHelper<Class,Base2>::invoke();
283  FactoryRegisterClassHelper<Class,Base3>::invoke();
284  FactoryRegisterClassHelper<Class,Base4>::invoke();
285  }
286 };
287 
289 
290 // *****************************************************************************
291 // *** Implementation of ClassFactory
292 // *****************************************************************************
293 
294 // this looks a bit like code duplication but we cannot use the newInstance
295 // function of mRoot since mRoot is of type TClass. The implementation of the
296 // template newInstance() version for TClass is quite useless -> therefore
297 // we need this function...
298 template<typename CLASS>
299 inline CLASS* mira::ClassFactory::newInstance( std::string const& classIdentifier )
300 {
301  Object* tBase = instance().mRoot.newInstance( classIdentifier );
302  return mira_factoryDynamicCast<CLASS>( tBase );
303 }
304 
305 template<typename CLASS>
306 inline CLASS* mira::ClassFactory::newInstance( std::string const& classIdentifier,
307  int paramCount, ... )
308 {
309  std::va_list ap;
310  va_start(ap, paramCount);
311  Object* tObject = instance().mRoot.newVAInstance( classIdentifier,
312  paramCount, ap );
313  return mira_factoryDynamicCast<CLASS>( tObject );
314 }
315 
316 template<typename CLASS>
317 inline CLASS* mira::ClassFactory::newInstance( std::string const& classIdentifier,
318  int paramCount, std::va_list list )
319 {
320  Object* tObject = instance().mRoot.newVAInstance( classIdentifier,
321  paramCount, list );
322  return mira_factoryDynamicCast<CLASS>( tObject );
323 }
324 
325 
326 // *****************************************************************************
327 // *** Implementation of PseudoClass from Object.h
328 // *****************************************************************************
329 
330 inline Object* PseudoClass::newInstance(std::string const& pChildIdentifier ) const
331 {
332  return ClassFactory::newInstance<Object>(pChildIdentifier);
333 }
334 
335 template <class CLASS>
336 inline CLASS* PseudoClass::newInstance(std::string const& pChildIdentifier ) const
337 {
338  return ClassFactory::newInstance<CLASS>(pChildIdentifier);
339 }
340 
342 
343 } // namespace
344 
345 #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:145
static void finalizePostRegister()
Propagate all children to indirect parents and add meta information of parent classes to children...
$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:86
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:508
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
void propagateChild(ClassProxy &child, Class &parent)
Auxiliary function to propagate child classes to indirect parents.
static std::map< std::string, ClassProxy > getDerivedClasses()
Return list of registered classes.
Definition: Factory.h:165
Class object which supports some kind of class reflection.
Definition: Class.h:97
friend class LightFactoryMutexGetter
Definition: Factory.h:89
static bool isClassRegistered(std::string const &classIdentifier)
Return true if a class with the desired identifier is registered.
Definition: Factory.h:126
Provided for convenience.
Definition: Singleton.h:528
static ClassProxy getClassByIdentifier(std::string const &classIdentifier)
Return the Class object for the desired Class.
Definition: Factory.h:135
static void postRegisterBaseClasses(std::string const &iClass, std::vector< std::string > const &parents)
Register Parent - Child relationship.
static std::vector< ClassProxy > getClassByMeta(T funcPtr)
Return list of Class objects returning true for the given comparison function.
Definition: Factory.h:157
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:181
$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$.
bool internalClassRegister(boost::shared_ptr< Class > iClass)
Internal function to register a class.
static void registerClass(boost::shared_ptr< Class > iClass)
Register Class.
static void unregisterClass(Class *iClass)
Unregister Class.
ClassFactory()
Definition: Factory.h:93
static CLASS * newInstance(std::string const &classIdentifier)
Create new instance of the class defined by class identifier.
Definition: Factory.h:299
Object * newInstance(std::string const &childIdentifier) const
Return a new instance of the class with the given identifier.
Definition: Factory.h:330