OpenWalnut  1.4.0
WModuleFactory.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WMODULEFACTORY_H
00026 #define WMODULEFACTORY_H
00027 
00028 #include <map>
00029 #include <set>
00030 #include <string>
00031 #include <utility>
00032 #include <vector>
00033 
00034 #include <boost/shared_ptr.hpp>
00035 #include <boost/weak_ptr.hpp>
00036 
00037 #include "../common/WSharedAssociativeContainer.h"
00038 #include "WModuleCombinerTypes.h"
00039 #include "WModule.h"
00040 #include "WModuleLoader.h"
00041 
00042 /**
00043  * Class able to create a new copy of an arbitrary module. It uses the Factory and Prototype design pattern.
00044  */
00045 class  WModuleFactory // NOLINT
00046 {
00047 friend class WModuleFactoryTest;
00048 public:
00049     /**
00050      * Shared pointer to a WModule.
00051      */
00052     typedef boost::shared_ptr< WModuleFactory > SPtr;
00053 
00054     /**
00055      * Shared pointer to a const WModule.
00056      */
00057     typedef boost::shared_ptr< const WModuleFactory > ConstSPtr;
00058 
00059     /**
00060      * For shortening: a type defining a shared set of WModule pointers.
00061      */
00062     typedef std::set< boost::shared_ptr< WModule > > PrototypeContainerType;
00063 
00064     /**
00065      * Const iterator for the prototype set.
00066      */
00067     typedef std::set< boost::shared_ptr< WModule > >::const_iterator PrototypeContainerConstIteratorType;
00068 
00069     /**
00070      * Iterator for the prototype set.
00071      */
00072     typedef std::set< boost::shared_ptr< WModule > >::iterator PrototypeContainerIteratorType;
00073 
00074     /**
00075      * The alias for a shared container.
00076      */
00077     typedef WSharedAssociativeContainer< PrototypeContainerType > PrototypeSharedContainerType;
00078 
00079     /**
00080      * Destructor.
00081      */
00082     virtual ~WModuleFactory();
00083 
00084     /**
00085      * Loads the modules and creates prototypes.
00086      */
00087     void load();
00088 
00089     /**
00090      * Create a new and initialized module using the specified prototype.
00091      *
00092      * \param prototype the prototype to clone.
00093      * \param uuid the uuid to use for the created module. If you specify an empty string (default), a uuid will be created. This parameter is
00094      *             useful for the project loader.
00095      *
00096      * \return the module created using the prototype.
00097      */
00098     boost::shared_ptr< WModule > create( boost::shared_ptr< WModule > prototype, std::string uuid = "" );
00099 
00100     /**
00101      * Returns instance of the module factory to use to create modules.
00102      *
00103      * \return the running module factory.
00104      */
00105     static SPtr getModuleFactory();
00106 
00107     /**
00108      * Returns instance of the module loader.
00109      *
00110      * \return the running module loader.
00111      */
00112     static boost::shared_ptr< WModuleLoader > getModuleLoader();
00113 
00114     /**
00115      * Searches a prototype by name. It returns the prototype, or a NULL pointer if it is not found. The difference to
00116      * getPrototypeByName() is, that an unavailable prototype does not throw an exception. This is nice for checking whether a
00117      * prototype exists or not.
00118      *
00119      * \param name name of the prototype to search
00120      *
00121      * \return the prototype if it exists, or NULL if not.
00122      */
00123     const boost::shared_ptr< WModule > isPrototypeAvailable( std::string name );
00124 
00125     /**
00126      * Finds a prototype using the specified name.
00127      *
00128      * \param name the name.
00129      *
00130      * \return the prototype whose name is equal to the specified one.
00131      */
00132     const boost::shared_ptr< WModule > getPrototypeByName( std::string name );
00133 
00134     /**
00135      * Finds a prototype using an instance of a module. This uses the type_info to find a proper prototype.
00136      *
00137      * \param instance the instance to use.
00138      *
00139      * \return the prototype.
00140      * \throw WPrototypeUnknown if prototype can not be found.
00141      */
00142     const boost::shared_ptr< WModule > getPrototypeByInstance( boost::shared_ptr< WModule > instance );
00143 
00144     /**
00145      * Finds a prototype using an type.
00146      *
00147      * \param type the type of module.
00148      *
00149      * \return the prototypes as list.
00150      */
00151     std::vector< WModule::ConstSPtr > getPrototypesByType( MODULE_TYPE type );
00152 
00153     /**
00154      * This method gives read access to the list of all prototypes.
00155      *
00156      * \return the read ticket for the prototype list
00157      */
00158     PrototypeSharedContainerType::ReadTicket getPrototypes() const;
00159 
00160     /**
00161      * Checks whether the first instance can be casted to the second one.
00162      *
00163      * \param module the module to check.
00164      *
00165      * \return true if the dynamic_cast is successful
00166      */
00167     template <typename T>
00168     static bool isA( boost::shared_ptr< WModule > module );
00169 
00170     /**
00171      * Returns a set of module combiners with module combinations compatible with the specified one.
00172      *
00173      * \param module the module to find the compatibles for.
00174      *
00175      * \note as the default parameter denotes, providing a NULL pointer (or calling the method without a parameter) returns the list of modules
00176      * which are compatible to every other module. In other words, it returns all modules without input connectors. If the specified module is
00177      * not NULL, the modules without input are not listed.
00178      *
00179      * \return set of compatible combiners.
00180      */
00181     WCombinerTypes::WCompatiblesList getCompatiblePrototypes(
00182             boost::shared_ptr< WModule > module = boost::shared_ptr< WModule >()
00183     );
00184 
00185     /**
00186      * Creates a list of \ref WApplyCombiner for all modules known by the factory.
00187      *
00188      * \return list of apply combiner.
00189      */
00190     WCombinerTypes::WCompatiblesList getAllPrototypes();
00191 
00192     /**
00193      * This method uses a newly created instance of WModule and initializes it properly. After using this method, the module is
00194      * properly initialized and ready to be used.
00195      *
00196      * \param module the module to initialize.
00197      */
00198     static void initializeModule( boost::shared_ptr< WModule > module );
00199 
00200     /**
00201      * Checks whether the specified module is a prototype or an instantiated module.
00202      *
00203      * \param module the module to check
00204      *
00205      * \return true if it is a prototype
00206      */
00207     static bool isPrototype( boost::shared_ptr< WModule > module );
00208 
00209     /**
00210      * Find a module instance by UUID.
00211      *
00212      * \param uuid the uuid to search for.
00213      *
00214      * \return the module, or NULL if not found
00215      */
00216     static WModule::SPtr findByUUID( std::string uuid );
00217 
00218 protected:
00219     /**
00220      * Constructors are protected because this is a Singleton.
00221      */
00222     WModuleFactory();
00223 
00224     /**
00225      * The module prototypes available.
00226      */
00227     PrototypeSharedContainerType m_prototypes;
00228 
00229     /**
00230      * Checks whether the specified module is a prototype or an instantiated module. Use isPrototype if no ticket acquired yet.
00231      *
00232      * \param module the module to check
00233      * \param ticket ticket which already has read lock.
00234      *
00235      * \return true if it is a prototype
00236      */
00237     bool checkPrototype( boost::shared_ptr< WModule > module, PrototypeSharedContainerType::ReadTicket ticket );
00238 
00239 private:
00240     /**
00241      * Loader class managing dynamically loaded modules in OpenWalnut.
00242      */
00243     WModuleLoader::SPtr m_moduleLoader;
00244 
00245     /**
00246      * Singleton instance of WModuleFactory.
00247      */
00248     static boost::shared_ptr< WModuleFactory > m_instance;
00249 
00250     /**
00251      * Mapping between a UUID and a module.
00252      */
00253     typedef std::map< std::string, boost::weak_ptr< WModule > > UuidModuleMap;
00254 
00255     /**
00256      * Keep track of uuids of each created module. This is needed to find module pointers using uuid.
00257      */
00258     WSharedAssociativeContainer< UuidModuleMap > m_uuidModuleMap;
00259 };
00260 
00261 template <typename T>
00262 bool WModuleFactory::isA( boost::shared_ptr< WModule > module )
00263 {
00264     // NOTE: this is RTTI. Everybody says: do not use it. We ignore them.
00265     return ( dynamic_cast< T* >( module.get() ) );  // NOLINT
00266 }
00267 
00268 #endif  // WMODULEFACTORY_H
00269