- Main Page
- Namespaces
- Classes
- Files
- Related Pages

# /Users/fpy/titan-1-5-MBARI/Mers/Utils/Lang/Factory.h

    00001
    00002 //
    00003 // Copyright (c) 2005           Model-based Embedded and Robotic Systems Group
    00004 // All Rights Reserved          Massachusetts Institute of Technology
    00005 //
    00006 // This software is provided as is. Model-based Embedded and Robotic Systems
    00007 // (MERS) group does not assume any responsibility.
    00008 //
    00010
    00011 #ifndef MERS_UTILS_LANG_FACTORY
    00012 #define MERS_UTILS_LANG_FACTORY
    00013
    00015
    00016 #include <typeinfo>
    00017 #include <map>
    00018 #include "String.h"
    00019 #include "PointerCompare.h"
    00020 #include <Mers/Utils/Exceptions/RuntimeException.h>
    00021 #include <cassert>
    00022
    00024
    00025 namespace Mers {
    00026 namespace Utils {
    00027 namespace Lang {
    00028
    00030
    00031 bool operator<( const std::type_info &t1, const std::type_info &t2 );
    00032
    00034
    00035 namespace FactoryOps {
    00042         template< class t_Object, typename t_NameMap >
    00043         const std::type_info * supportName( const char * className, t_NameMap &typeNames )
    00044         {
    00045                 // Record the typeid of this object.
    00046                 const std::type_info * objectType = &typeid( t_Object );
    00047
    00048                 // Only allow supporting a single name.
    00049                 assert( typeNames[ className ] == NULL );
    00050                 // Add support for this name
    00051                 typeNames[ className ] = objectType;
    00052
    00053                 // Return the typeid we just got.
    00054                 return objectType;
    00055         }
    00056
    00063         template< typename t_NameMap >
    00064         void unsupportNames( const std::type_info * objectType, t_NameMap &typeNames )
    00065         {
    00066                 // Remove it from the m_TypeNames list.
    00067                 typename t_NameMap::iterator itName( typeNames.begin() );
    00068                 while( itName != typeNames.end() ) {
    00069                         if( *itName->second == *objectType ) {
    00070                                 // Found an instance of objectType, remove it.
    00071                                 // Record the object to erase.
    00072                                 typename t_NameMap::iterator erase( itName );
    00073                                 // Get the next iterator.
    00074                                 ++itName;
    00075                                 // Erase this object.
    00076                                 typeNames.erase( erase );
    00077                         } else {
    00078                                 // Didn't find anything yet.
    00079                                 ++itName;
    00080                         }
    00081                 }
    00082         }
    00083
    00084
    00095         template< class t_Object, typename t_NameMap, typename t_Map, typename t_Constructor >
    00096         void supportHelper( const char * className, t_NameMap &typeNames, t_Map &constructors )
    00097         {
    00098                 // Record the typeid of this object.
    00099                 const std::type_info * objectType = supportName< t_Object, t_NameMap >( className, typeNames );
    00100
    00101                 // If this is a new type_info, and not just an alias, register
    00102                 // a constructor.
    00103                 if( constructors[ objectType ] == NULL ) {
    00104                         t_Constructor * constructor = new t_Constructor();
    00105                         constructors[ objectType ] = constructor;
    00106                 }
    00107         }
    00108
    00116         template< typename t_NameMap, typename t_Map >
    00117         void unsupportHelper( const std::type_info * objectType, t_NameMap &typeNames, t_Map &constructors )
    00118         {
    00119                 // Remove it from the name map
    00120                 unsupportNames( objectType, typeNames );
    00121
    00122                 // Remove it from the m_Constructors list.
    00123                 typename t_Map::iterator itID
    00124                         ( constructors.find( objectType ) );
    00125                 if( itID != constructors.end() ) {
    00126                         // We found it.  Remove it.  Clean-up the constructor object.
    00127                         delete itID->second;
    00128                         // Erase it from the map.
    00129                         constructors.erase( itID );
    00130                 }
    00131         }
    00132 }
    00133
    00140 template< class t_Base >
    00141 class FactoryBase
    00142 {
    00143 public:
    00147         virtual ~FactoryBase()
    00148         {}
    00149
    00150 protected:
    00152         typedef std::map< String, const std::type_info * > t_MapTypeNameToTypeID;
    00153
    00154 protected:
    00159         const std::type_info * find( const char * objTypeName ) {
    00160                 t_MapTypeNameToTypeID::const_iterator iter;
    00161                 String name( objTypeName );
    00162                 iter = m_TypeNames.find( name );
    00163
    00164                 if( iter != m_TypeNames.end() )
    00165                         return iter->second;
    00166                 return NULL;
    00167         }
    00168
    00169 public:
    00174         template< class t_Object >
    00175         void unsupport()
    00176         {
    00177                 // Look-up the typeid of this object.
    00178                 const std::type_info * objectType = &typeid( t_Object );
    00179
    00180                 // Remove support of this id.
    00181                 unsupport( objectType );
    00182         }
    00183
    00190         virtual void unsupport( const std::type_info * objectType ) = 0;
    00191
    00192 protected:
    00196         t_MapTypeNameToTypeID m_TypeNames;
    00197
    00198 protected:
    00205         FactoryBase() {
    00206         }
    00207 };
    00208
    00210
    00216 template< class t_Base >
    00217 class FactoryArg0 : public FactoryBase< t_Base >
    00218 {
    00219 public:
    00226         class ConstructorBase {
    00227         public:
    00228                 virtual t_Base * create() = 0;
    00229         };
    00230
    00231 protected:
    00236         template< class t_Class >
    00237         class Constructor : public ConstructorBase {
    00238         public:
    00239                 virtual t_Base * create() {
    00240                         return new t_Class();
    00241                 }
    00242         };
    00243
    00245         typedef std::map< const std::type_info *, ConstructorBase *,
    00246                 PointerCompare<std::type_info> > t_MapTypeIDToConstructor;
    00247
    00248 protected:
    00253         template< class t_Object, typename t_NameMap, typename t_Map, typename t_Constructor >
    00254         void supportHelper( const char * className, t_NameMap &typeNames, t_Map &constructors )
    00255         {
    00256                 FactoryOps::supportHelper< t_Object, t_NameMap, t_Map, t_Constructor >( className, typeNames, constructors );
    00257         }
    00258
    00263         template< typename t_NameMap, typename t_Map >
    00264         void unsupportHelper( const std::type_info * objectType, t_NameMap &typeNames, t_Map &constructors )
    00265         {
    00266                 FactoryOps::unsupportHelper< t_NameMap, t_Map >( objectType, typeNames, constructors );
    00267         }
    00268
    00269 public:
    00273         static FactoryArg0 & getSingleton() {
    00274                 // Our singleton factory.  There exists a single factory
    00275                 // instance for each base class.  By declaring it in this
    00276                 // manner, we guarantee that the factory's constructor is
    00277                 // called before we start using it.
    00278                 static FactoryArg0< t_Base > s_factory;
    00279                 return s_factory;
    00280         }
    00281
    00285         t_Base * create( const std::type_info * objType ) {
    00286                 typename t_MapTypeIDToConstructor::const_iterator iter;
    00287                 iter = m_Constructors.find( objType );
    00288
    00289                 if( iter != m_Constructors.end() )
    00290                         return iter->second->create();
    00291
    00292                 throw Mers::Utils::Exceptions::RuntimeException(
    00293                         "Could not create object", __FILE__, __LINE__);
    00294         }
    00295
    00300         t_Base * create( const char * objTypeName ) {
    00301                 // Find this object type by name.
    00302                 const std::type_info * objType = FactoryBase<t_Base>::find( objTypeName );
    00303                 // If we find it, create an object of that type.
    00304                 if( objType != NULL )
    00305                         return create( objType );
    00306
    00307                 // Throw an excpetion?
    00308                 return NULL;
    00309         }
    00310
    00314         template< class t_Object > t_Base * create() {
    00315                 return create( &typeid( t_Object ) );
    00316         }
    00317
    00327         template< class t_Object >
    00328         void support( const char * className )
    00329         {
    00330                 supportHelper< t_Object, typename FactoryBase<t_Base>::t_MapTypeNameToTypeID, t_MapTypeIDToConstructor, Constructor< t_Object > >( className, FactoryBase<t_Base>::m_TypeNames, m_Constructors );
    00331         }
    00332
    00339         template< class t_Object >
    00340         inline void unsupport()
    00341         {
    00342                 FactoryBase<t_Base> * factBase = this;
    00343                 factBase->unsupport< t_Object >();
    00344         }
    00345
    00352         virtual void unsupport( const std::type_info * objectType )
    00353         {
    00354                 unsupportHelper< typename FactoryBase<t_Base>::t_MapTypeNameToTypeID, t_MapTypeIDToConstructor >( objectType, FactoryBase<t_Base>::m_TypeNames, m_Constructors );
    00355         }
    00356
    00357 protected:
    00361         t_MapTypeIDToConstructor m_Constructors;
    00362
    00363 private:
    00370         FactoryArg0() : FactoryBase<t_Base>() {
    00371         }
    00372 };
    00373
    00375
    00381 template< class t_Base, typename t_Arg1 >
    00382 class FactoryArg1 : public FactoryBase< t_Base >
    00383 {
    00384 public:
    00391         class ConstructorBase {
    00392         public:
    00393                 virtual t_Base * create( t_Arg1 arg1 ) = 0;
    00394         };
    00395
    00396 protected:
    00401         template< class t_Class >
    00402         class Constructor : public ConstructorBase {
    00403         public:
    00404                 virtual t_Base * create( t_Arg1 arg1 ) {
    00405                         return new t_Class( arg1 );
    00406                 }
    00407         };
    00408
    00410         typedef std::map< const std::type_info *, ConstructorBase *,
    00411                 PointerCompare<std::type_info> > t_MapTypeIDToConstructor;
    00412
    00413 protected:
    00414         typedef t_Base t_BaseClass2;
    00419         template< class t_Object, typename t_NameMap, typename t_Map, typename t_Constructor >
    00420         void supportHelper( const char * className, t_NameMap &typeNames, t_Map &constructors )
    00421         {
    00422                 FactoryOps::supportHelper< t_Object, t_NameMap, t_Map, t_Constructor >( className, typeNames, constructors );
    00423         }
    00424
    00429         template< typename t_NameMap, typename t_Map >
    00430         void unsupportHelper( const std::type_info * objectType, t_NameMap &typeNames, t_Map &constructors )
    00431         {
    00432                 FactoryOps::unsupportHelper< t_NameMap, t_Map >( objectType, typeNames, constructors );
    00433         }
    00434
    00435 public:
    00439         static FactoryArg1 & getSingleton() {
    00440                 // Our singleton factory.  There exists a single factory
    00441                 // instance for each base class.  By declaring it in this
    00442                 // manner, we guarantee that the factory's constructor is
    00443                 // called before we start using it.
    00444                 static FactoryArg1< t_Base, t_Arg1 > s_factory;
    00445                 return s_factory;
    00446         }
    00447
    00451         t_Base * create( const std::type_info * objType, t_Arg1 arg1 ) {
    00452                 typename t_MapTypeIDToConstructor::const_iterator iter;
    00453                 iter = m_Constructors.find( objType );
    00454
    00455                 if( iter != m_Constructors.end() )
    00456                         return iter->second->create( arg1 );
    00457
    00458                 throw Mers::Utils::Exceptions::RuntimeException(
    00459                         "Could not create object", __FILE__, __LINE__);
    00460         }
    00461
    00466         t_Base * create( const char * objTypeName, t_Arg1 arg1 ) {
    00467                 // Find this object type by name.
    00468                 const std::type_info * objType = FactoryBase<t_Base>::find( objTypeName );
    00469                 // If we find it, create an object of that type.
    00470                 if( objType != NULL )
    00471                         return create( objType, arg1 );
    00472
    00473                 // Throw an excpetion?
    00474                 return NULL;
    00475         }
    00476
    00480         template< class t_Object > t_Base * create( t_Arg1 arg1 ) {
    00481                 return create( &typeid( t_Object ), arg1 );
    00482         }
    00483
    00493         template< class t_Object >
    00494         void support( const char * className )
    00495         {
    00496                 supportHelper< t_Object, typename FactoryBase<t_Base>::t_MapTypeNameToTypeID, t_MapTypeIDToConstructor, Constructor< t_Object > >( className, FactoryBase<t_Base>::m_TypeNames, m_Constructors );
    00497         }
    00498
    00505         template< class t_Object >
    00506         inline void unsupport()
    00507         {
    00508                 FactoryBase<t_Base> * factBase = this;
    00509                 factBase->unsupport< t_Object >();
    00510         }
    00511
    00518         virtual void unsupport( const std::type_info * objectType )
    00519         {
    00520                 unsupportHelper< typename FactoryBase<t_Base>::t_MapTypeNameToTypeID, t_MapTypeIDToConstructor >( objectType, FactoryBase<t_Base>::m_TypeNames, m_Constructors );
    00521         }
    00522
    00523 protected:
    00527         t_MapTypeIDToConstructor m_Constructors;
    00528
    00529 private:
    00536         FactoryArg1() : FactoryBase<t_Base>() {
    00537         }
    00538 };
    00539
    00541
    00542 } // Lang
    00543 } // Utils
    00544 } // Mers
    00545
    00547
    00548 #endif