OpenWalnut 1.3.1
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 <set>
00029 #include <string>
00030 #include <utility>
00031 #include <vector>
00032 
00033 #include <boost/shared_ptr.hpp>
00034 #include <boost/thread.hpp>
00035 
00036 #include "../common/WSharedAssociativeContainer.h"
00037 #include "WModuleCombinerTypes.h"
00038 #include "WModule.h"
00039 #include "WModuleLoader.h"
00040 
00041 
00042 
00043 /**
00044  * Class able to create a new copy of an arbitrary module. It uses the Factory and Prototype design pattern.
00045  */
00046 class  WModuleFactory // NOLINT
00047 {
00048 friend class WModuleFactoryTest;
00049 public:
00050     /**
00051      * For shortening: a type defining a shared set of WModule pointers.
00052      */
00053     typedef std::set< boost::shared_ptr< WModule > > PrototypeContainerType;
00054 
00055     /**
00056      * Const iterator for the prototype set.
00057      */
00058     typedef std::set< boost::shared_ptr< WModule > >::const_iterator PrototypeContainerConstIteratorType;
00059 
00060     /**
00061      * Iterator for the prototype set.
00062      */
00063     typedef std::set< boost::shared_ptr< WModule > >::iterator PrototypeContainerIteratorType;
00064 
00065     /**
00066      * The alias for a shared container.
00067      */
00068     typedef WSharedAssociativeContainer< PrototypeContainerType > PrototypeSharedContainerType;
00069 
00070     /**
00071      * Destructor.
00072      */
00073     virtual ~WModuleFactory();
00074 
00075     /**
00076      * Loads the modules and creates prototypes.
00077      */
00078     void load();
00079 
00080     /**
00081      * Create a new and initialized module using the specified prototype.
00082      *
00083      * \param prototype the prototype to clone.
00084      *
00085      * \return the module created using the prototype.
00086      */
00087     boost::shared_ptr< WModule > create( boost::shared_ptr< WModule > prototype );
00088 
00089     /**
00090      * Returns instance of the module factory to use to create modules.
00091      *
00092      * \return the running module factory.
00093      */
00094     static boost::shared_ptr< WModuleFactory > getModuleFactory();
00095 
00096     /**
00097      * Searches a prototype by name. It returns the prototype, or a NULL pointer if it is not found. The difference to
00098      * getPrototypeByName() is, that an unavailable prototype does not throw an exception. This is nice for checking whether a
00099      * prototype exists or not.
00100      *
00101      * \param name name of the prototype to search
00102      *
00103      * \return the prototype if it exists, or NULL if not.
00104      */
00105     const boost::shared_ptr< WModule > isPrototypeAvailable( std::string name );
00106 
00107     /**
00108      * Finds a prototype using the specified name.
00109      *
00110      * \param name the name.
00111      *
00112      * \return the prototype whose name is equal to the specified one.
00113      */
00114     const boost::shared_ptr< WModule > getPrototypeByName( std::string name );
00115 
00116     /**
00117      * Finds a prototype using an instance of a module. This uses the type_info to find a proper prototype.
00118      *
00119      * \param instance the instance to use.
00120      *
00121      * \return the prototype.
00122      * \throw WPrototypeUnknown if prototype can not be found.
00123      */
00124     const boost::shared_ptr< WModule > getPrototypeByInstance( boost::shared_ptr< WModule > instance );
00125 
00126     /**
00127      * Finds a prototype using an type.
00128      *
00129      * \param type the type of module.
00130      *
00131      * \return the prototypes as list.
00132      */
00133     std::vector< WModule::ConstSPtr > getPrototypesByType( MODULE_TYPE type );
00134 
00135     /**
00136      * This method gives read access to the list of all prototypes.
00137      *
00138      * \return the read ticket for the prototype list
00139      */
00140     PrototypeSharedContainerType::ReadTicket getPrototypes() const;
00141 
00142     /**
00143      * Checks whether the first instance can be casted to the second one.
00144      *
00145      * \param module the module to check.
00146      *
00147      * \return true if the dynamic_cast is successful
00148      */
00149     template <typename T>
00150     static bool isA( boost::shared_ptr< WModule > module );
00151 
00152     /**
00153      * Returns a set of module combiners with module combinations compatible with the specified one.
00154      *
00155      * \param module the module to find the compatibles for.
00156      *
00157      * \note as the default parameter denotes, providing a NULL pointer (or calling the method without a parameter) returns the list of modules
00158      * which are compatible to every other module. In other words, it returns all modules without input connectors. If the specified module is
00159      * not NULL, the modules without input are not listed.
00160      *
00161      * \return set of compatible combiners.
00162      */
00163     WCombinerTypes::WCompatiblesList getCompatiblePrototypes(
00164             boost::shared_ptr< WModule > module = boost::shared_ptr< WModule >()
00165     );
00166 
00167     /**
00168      * Creates a list of \ref WApplyCombiner for all modules known by the factory.
00169      *
00170      * \return list of apply combiner.
00171      */
00172     WCombinerTypes::WCompatiblesList getAllPrototypes();
00173 
00174     /**
00175      * This method uses a newly created instance of WModule and initializes it properly. After using this method, the module is
00176      * properly initialized and ready to be used.
00177      *
00178      * \param module the module to initialize.
00179      */
00180     static void initializeModule( boost::shared_ptr< WModule > module );
00181 
00182     /**
00183      * Checks whether the specified module is a prototype or an instantiated module.
00184      *
00185      * \param module the module to check
00186      *
00187      * \return true if it is a prototype
00188      */
00189     static bool isPrototype( boost::shared_ptr< WModule > module );
00190 
00191 protected:
00192     /**
00193      * Constructors are protected because this is a Singleton.
00194      */
00195     WModuleFactory();
00196 
00197     /**
00198      * The module prototypes available.
00199      */
00200     PrototypeSharedContainerType m_prototypes;
00201 
00202     /**
00203      * Checks whether the specified module is a prototype or an instantiated module. Use isPrototype if no ticket acquired yet.
00204      *
00205      * \param module the module to check
00206      * \param ticket ticket which already has read lock.
00207      *
00208      * \return true if it is a prototype
00209      */
00210     bool checkPrototype( boost::shared_ptr< WModule > module, PrototypeSharedContainerType::ReadTicket ticket );
00211 
00212 private:
00213     /**
00214      * Loader class managing dynamically loaded modules in OpenWalnut.
00215      */
00216     WModuleLoader m_moduleLoader;
00217 
00218     /**
00219      * Singleton instance of WModuleFactory.
00220      */
00221     static boost::shared_ptr< WModuleFactory > m_instance;
00222 };
00223 
00224 template <typename T>
00225 bool WModuleFactory::isA( boost::shared_ptr< WModule > module )
00226 {
00227     // NOTE: this is RTTI. Everybody says: do not use it. We ignore them.
00228     return ( dynamic_cast< T* >( module.get() ) );  // NOLINT
00229 }
00230 
00231 #endif  // WMODULEFACTORY_H
00232