OpenWalnut  1.5.0dev
WModuleFactory.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WMODULEFACTORY_H
26 #define WMODULEFACTORY_H
27 
28 #include <map>
29 #include <memory>
30 #include <set>
31 #include <string>
32 #include <utility>
33 #include <vector>
34 
35 #include <boost/weak_ptr.hpp>
36 
37 #include "../common/WSharedAssociativeContainer.h"
38 #include "WDataModule.h"
39 #include "WModule.h"
40 #include "WModuleCombinerTypes.h"
41 #include "WModuleLoader.h"
42 
43 /**
44  * Class able to create a new copy of an arbitrary module. It uses the Factory and Prototype design pattern.
45  */
46 class WModuleFactory // NOLINT
47 {
48 friend class WModuleFactoryTest; //!< Access for test class.
49 public:
50  /**
51  * Shared pointer to a WModule.
52  */
53  typedef std::shared_ptr< WModuleFactory > SPtr;
54 
55  /**
56  * Shared pointer to a const WModule.
57  */
58  typedef std::shared_ptr< const WModuleFactory > ConstSPtr;
59 
60  /**
61  * For shortening: a type defining a shared set of WModule pointers.
62  */
63  typedef std::set< std::shared_ptr< WModule > > PrototypeContainerType;
64 
65  /**
66  * Const iterator for the prototype set.
67  */
68  typedef std::set< std::shared_ptr< WModule > >::const_iterator PrototypeContainerConstIteratorType;
69 
70  /**
71  * Iterator for the prototype set.
72  */
73  typedef std::set< std::shared_ptr< WModule > >::iterator PrototypeContainerIteratorType;
74 
75  /**
76  * The alias for a shared container.
77  */
79 
80  /**
81  * Destructor.
82  */
83  virtual ~WModuleFactory();
84 
85  /**
86  * Loads the modules and creates prototypes.
87  */
88  void load();
89 
90  /**
91  * Create a new and initialized module using the specified prototype.
92  *
93  * \param prototype the prototype to clone.
94  * \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
95  * useful for the project loader.
96  *
97  * \return the module created using the prototype.
98  */
99  std::shared_ptr< WModule > create( std::shared_ptr< WModule > prototype, std::string uuid = "" );
100 
101  /**
102  * Create a new and initialized module using the specified prototype. This might fail if the prototype with this name cannot be found. Please
103  * refer to \ref getPrototypeByName.
104  *
105  * \param prototype the prototype to clone as name.
106  * \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
107  * useful for the project loader.
108  *
109  * \return the module created using the prototype.
110  */
111  std::shared_ptr< WModule > create( std::string prototype, std::string uuid = "" );
112 
113  /**
114  * Returns instance of the module factory to use to create modules.
115  *
116  * \return the running module factory.
117  */
118  static SPtr getModuleFactory();
119 
120  /**
121  * Returns instance of the module loader.
122  *
123  * \return the running module loader.
124  */
125  static std::shared_ptr< WModuleLoader > getModuleLoader();
126 
127  /**
128  * Searches a prototype by name. It returns the prototype, or a NULL pointer if it is not found. The difference to
129  * getPrototypeByName() is, that an unavailable prototype does not throw an exception. This is nice for checking whether a
130  * prototype exists or not.
131  *
132  * \param name name of the prototype to search
133  *
134  * \return the prototype if it exists, or NULL if not.
135  */
136  const std::shared_ptr< WModule > isPrototypeAvailable( std::string name );
137 
138  /**
139  * Finds a prototype using the specified name.
140  *
141  * \param name the name.
142  * \throw WPrototypeUnknown if the prototype is not known. Use \ref isPrototypeAvailable first to check.
143  *
144  * \return the prototype whose name is equal to the specified one.
145  */
146  const std::shared_ptr< WModule > getPrototypeByName( std::string name );
147 
148  /**
149  * Finds a prototype using an instance of a module. This uses the type_info to find a proper prototype.
150  *
151  * \param instance the instance to use.
152  *
153  * \return the prototype.
154  * \throw WPrototypeUnknown if prototype can not be found.
155  */
156  const std::shared_ptr< WModule > getPrototypeByInstance( std::shared_ptr< WModule > instance );
157 
158  /**
159  * Finds a prototype using an type.
160  *
161  * \param type the type of module.
162  *
163  * \return the prototypes as list.
164  */
165  std::vector< WModule::ConstSPtr > getPrototypesByType( MODULE_TYPE type );
166 
167  /**
168  * This method gives read access to the list of all prototypes.
169  *
170  * \return the read ticket for the prototype list
171  */
173 
174  /**
175  * Checks whether the first instance can be casted to the second one.
176  *
177  * \param module the module to check.
178  *
179  * \return true if the dynamic_cast is successful
180  */
181  template <typename T>
182  static bool isA( std::shared_ptr< WModule > module );
183 
184  /**
185  * Returns a set of module combiners with module combinations compatible with the specified one.
186  *
187  * \param module the module to find the compatibles for.
188  *
189  * \note as the default parameter denotes, providing a NULL pointer (or calling the method without a parameter) returns the list of modules
190  * which are compatible to every other module. In other words, it returns all modules without input connectors. If the specified module is
191  * not NULL, the modules without input are not listed.
192  *
193  * \return set of compatible combiners.
194  */
195  WCombinerTypes::WCompatiblesList getCompatiblePrototypes(
196  std::shared_ptr< WModule > module = std::shared_ptr< WModule >()
197  );
198 
199  /**
200  * Creates a list of \ref WApplyCombiner for all modules known by the factory.
201  *
202  * \return list of apply combiner.
203  */
204  WCombinerTypes::WCompatiblesList getAllPrototypes();
205 
206  /**
207  * This method uses a newly created instance of WModule and initializes it properly. After using this method, the module is
208  * properly initialized and ready to be used.
209  *
210  * \param module the module to initialize.
211  */
212  static void initializeModule( std::shared_ptr< WModule > module );
213 
214  /**
215  * Checks whether the specified module is a prototype or an instantiated module.
216  *
217  * \param module the module to check
218  *
219  * \return true if it is a prototype
220  */
221  static bool isPrototype( std::shared_ptr< WModule > module );
222 
223  /**
224  * Find a module instance by UUID.
225  *
226  * \param uuid the uuid to search for.
227  *
228  * \return the module, or NULL if not found
229  */
230  static WModule::SPtr findByUUID( std::string uuid );
231 
232  /**
233  * Get all module prototypes which are of a certain type.
234  *
235  * \tparam ModuleType the type
236  *
237  * \return the list of module prototypes.
238  */
239  template< typename ModuleType >
240  std::vector< std::shared_ptr< ModuleType > > getPrototypesByType() const;
241 
242  /**
243  * Query a list of WDataModule prototypes depending on given input.
244  *
245  * \param input the input to use for matching
246  *
247  * \return the list (can be empty).
248  */
249  std::vector< WDataModule::SPtr > getDataModulePrototypesByInput( WDataModuleInput::ConstSPtr input ) const;
250 protected:
251  /**
252  * Constructors are protected because this is a Singleton.
253  */
254  WModuleFactory();
255 
256  /**
257  * The module prototypes available.
258  */
260 
261  /**
262  * Checks whether the specified module is a prototype or an instantiated module. Use isPrototype if no ticket acquired yet.
263  *
264  * \param module the module to check
265  * \param ticket ticket which already has read lock.
266  *
267  * \return true if it is a prototype
268  */
269  bool checkPrototype( std::shared_ptr< WModule > module, PrototypeSharedContainerType::ReadTicket ticket );
270 
271 private:
272  /**
273  * Loader class managing dynamically loaded modules in OpenWalnut.
274  */
276 
277  /**
278  * Singleton instance of WModuleFactory.
279  */
280  static std::shared_ptr< WModuleFactory > m_instance;
281 
282  /**
283  * Mapping between a UUID and a module.
284  */
285  typedef std::map< std::string, std::weak_ptr< WModule > > UuidModuleMap;
286 
287  /**
288  * Keep track of uuids of each created module. This is needed to find module pointers using uuid.
289  */
291 };
292 
293 template <typename T>
294 bool WModuleFactory::isA( std::shared_ptr< WModule > module )
295 {
296  // NOTE: this is RTTI. Everybody says: do not use it. We ignore them.
297  return ( dynamic_cast< T* >( module.get() ) ); // NOLINT
298 }
299 
300 template< typename ModuleType >
301 std::vector< std::shared_ptr< ModuleType > > WModuleFactory::getPrototypesByType() const
302 {
303  std::vector< std::shared_ptr< ModuleType > > results;
304 
305  // for this a read lock is sufficient, gets unlocked if it looses scope
307 
308  // Add all modules.
309  for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end();
310  ++listIter )
311  {
312  std::shared_ptr< ModuleType > asTargetType = std::dynamic_pointer_cast< ModuleType >( *listIter );
313 
314  if( asTargetType )
315  {
316  results.push_back( asTargetType );
317  }
318  }
319 
320  // unlock. No locking needed for further steps.
321  l.reset();
322 
323  return results;
324 }
325 
326 #endif // WMODULEFACTORY_H
327 
std::shared_ptr< const WDataModuleInput > ConstSPtr
Convenience typedef for a std::shared_ptr< const WDataModuleInput >.
Class able to create a new copy of an arbitrary module.
const std::shared_ptr< WModule > isPrototypeAvailable(std::string name)
Searches a prototype by name.
PrototypeSharedContainerType m_prototypes
The module prototypes available.
static std::shared_ptr< WModuleFactory > m_instance
Singleton instance of WModuleFactory.
WSharedAssociativeContainer< UuidModuleMap > m_uuidModuleMap
Keep track of uuids of each created module.
std::shared_ptr< WModuleFactory > SPtr
Shared pointer to a WModule.
WCombinerTypes::WCompatiblesList getCompatiblePrototypes(std::shared_ptr< WModule > module=std::shared_ptr< WModule >())
Returns a set of module combiners with module combinations compatible with the specified one.
WCombinerTypes::WCompatiblesList getAllPrototypes()
Creates a list of WApplyCombiner for all modules known by the factory.
PrototypeSharedContainerType::ReadTicket getPrototypes() const
This method gives read access to the list of all prototypes.
static WModule::SPtr findByUUID(std::string uuid)
Find a module instance by UUID.
std::shared_ptr< WModule > create(std::shared_ptr< WModule > prototype, std::string uuid="")
Create a new and initialized module using the specified prototype.
std::set< std::shared_ptr< WModule > >::const_iterator PrototypeContainerConstIteratorType
Const iterator for the prototype set.
friend class WModuleFactoryTest
Access for test class.
const std::shared_ptr< WModule > getPrototypeByInstance(std::shared_ptr< WModule > instance)
Finds a prototype using an instance of a module.
static bool isA(std::shared_ptr< WModule > module)
Checks whether the first instance can be casted to the second one.
static SPtr getModuleFactory()
Returns instance of the module factory to use to create modules.
std::set< std::shared_ptr< WModule > >::iterator PrototypeContainerIteratorType
Iterator for the prototype set.
std::vector< WDataModule::SPtr > getDataModulePrototypesByInput(WDataModuleInput::ConstSPtr input) const
Query a list of WDataModule prototypes depending on given input.
void load()
Loads the modules and creates prototypes.
WModuleLoader::SPtr m_moduleLoader
Loader class managing dynamically loaded modules in OpenWalnut.
virtual ~WModuleFactory()
Destructor.
static void initializeModule(std::shared_ptr< WModule > module)
This method uses a newly created instance of WModule and initializes it properly.
WSharedAssociativeContainer< PrototypeContainerType > PrototypeSharedContainerType
The alias for a shared container.
const std::shared_ptr< WModule > getPrototypeByName(std::string name)
Finds a prototype using the specified name.
std::set< std::shared_ptr< WModule > > PrototypeContainerType
For shortening: a type defining a shared set of WModule pointers.
std::vector< std::shared_ptr< ModuleType > > getPrototypesByType() const
Get all module prototypes which are of a certain type.
bool checkPrototype(std::shared_ptr< WModule > module, PrototypeSharedContainerType::ReadTicket ticket)
Checks whether the specified module is a prototype or an instantiated module.
std::map< std::string, std::weak_ptr< WModule > > UuidModuleMap
Mapping between a UUID and a module.
static bool isPrototype(std::shared_ptr< WModule > module)
Checks whether the specified module is a prototype or an instantiated module.
std::shared_ptr< const WModuleFactory > ConstSPtr
Shared pointer to a const WModule.
WModuleFactory()
Constructors are protected because this is a Singleton.
static std::shared_ptr< WModuleLoader > getModuleLoader()
Returns instance of the module loader.
std::shared_ptr< WModuleLoader > SPtr
Shared pointer abbreviation.
Definition: WModuleLoader.h:48
std::shared_ptr< WModule > SPtr
Shared pointer to a WModule.
Definition: WModule.h:106
std::shared_ptr< WSharedObjectTicketRead< T > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:65
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.