RSC  0.17.1
Factory.h
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is part of the RSC project
4  *
5  * Copyright (C) 2010, 2011 Jan Moringen
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #pragma once
28 
29 #include <stdexcept>
30 #include <utility>
31 #include <algorithm>
32 #include <map>
33 
34 #include <boost/function.hpp>
35 #include <boost/format.hpp>
36 
37 #include "../runtime/TypeStringTools.h"
38 #include "../runtime/Properties.h"
39 #include "Singleton.h"
40 #include "NoSuchImpl.h"
41 #include "ConstructError.h"
42 #include "AssociativeProxy.h"
43 
44 namespace rsc {
45 namespace patterns {
46 
67 template<typename Key>
68 class FactoryBase {
69 public:
70  typedef Key KeyType;
71  typedef boost::function1<void*, const runtime::Properties&> CreateFunction;
72  typedef std::pair<const std::type_info*, void*> type_and_storage;
73 
74  typedef std::map<Key, CreateFunction> ImplMap;
75 
76  class ImplMapProxy: public AssociativeProxy<ImplMap> {
77  protected:
78  template<typename K, typename I>
79  friend class Factory;
80 
82 
83  ImplMapProxy(ImplMap& container) :
84  base(container) {
85  }
86  };
87 
91  virtual const std::type_info&
92  GetInterfaceType() const throw () = 0;
93 
99  virtual const ImplMapProxy&
100  implsBase() const throw () = 0;
101 
115  virtual type_and_storage
116  createBase(const Key& key, const runtime::Properties& properties_ =
117  runtime::Properties()) = 0;
118 };
119 
128 template<typename Key, typename Interface>
129 class Factory: public FactoryBase<Key> {
130 public:
132 
133  typedef typename base::KeyType KeyType;
134  typedef Interface InterfaceType;
135 
136  typedef boost::function1<InterfaceType*, const runtime::Properties&>
138 
139  typedef std::map<Key, CreateFunction> ImplMap;
140 
141  typedef typename base::ImplMap ImplMapBase;
143 
144 public:
145 
153  class ImplMapProxy: public AssociativeProxy<ImplMap> {
154  friend class Factory<Key, Interface> ;
155  public:
159  void register_(const KeyType& key,
160  const CreateFunction& create_function_);
161 
165  void unregister(const KeyType& key);
166  private:
168 
170 
172  };
173 
174  friend class ImplMapProxy;
175 
176  Factory();
177 
178  virtual
179  ~Factory();
180 
181  const std::type_info&
182  GetInterfaceType() const throw ();
183 
184  const ImplMapBaseProxy&
185  implsBase() const throw ();
186 
190  ImplMapProxy&
191  impls() throw ();
192 
196  const ImplMapProxy&
197  impls() const throw ();
198 
203  typename FactoryBase<Key>::type_and_storage // TODO we should inherit that
204  createBase(const Key& key, const runtime::Properties& properties_ =
205  runtime::Properties());
206 
220  Interface*
221  createInst(const Key& key, const runtime::Properties& properties_ =
222  runtime::Properties());
223 protected:
224  ImplMapBase impl_map_base_;
225  ImplMapBaseProxy impl_map_base_proxy_;
226 
227  ImplMap impl_map_;
228  ImplMapProxy impl_map_proxy_;
229 
233  virtual void register_(const Key& key,
234  const CreateFunction& create_function_);
235 
239  virtual void unregister(const Key& key);
240 };
241 
245 template<typename Key, typename Interface>
246 class SingletonFactory: public Singleton<SingletonFactory<Key, Interface> > ,
247  public Factory<Key, Interface> {
248  friend class Singleton<SingletonFactory<Key, Interface> > ;
249 protected:
251 };
252 
253 // Factory::impl_list_proxy implementation
254 
255 template<typename Key, typename Interface>
257  Factory<Key, Interface>& owner) :
258  base_type(owner.impl_map_), owner(owner) {
259 }
260 
261 template<typename Key, typename Interface>
263  const CreateFunction& create_function_) {
264  this->owner.register_(key, create_function_);
265 }
266 
267 template<typename Key, typename Interface>
269  this->owner.unregister(key);
270 }
271 
272 // Factory implementation
273 
274 template<typename Key, typename Interface>
277 }
278 
279 template<typename Key, typename Interface>
281 }
282 
283 template<typename Key, typename Interface>
284 const std::type_info&
286  return typeid(Interface);
287 }
288 
289 template<typename Key, typename Interface>
292  return this->impl_map_base_proxy_;
293 }
294 
295 template<typename Key, typename Interface>
298  return this->impl_map_proxy_;
299 }
300 
301 template<typename Key, typename Interface>
304  return this->impl_map_proxy_;
305 }
306 
307 template<typename Key, typename Interface>
309  const CreateFunction& create_function_) {
310  //
311  if (this->impl_map_.find(key) != this->impl_map_.end()) {
312  throw std::invalid_argument(runtime::typeString("duplicate key `%1%'",
313  "duplicate key", key));
314  }
315 
316  //
317  this->impl_map_base_[key] = create_function_;
318  this->impl_map_[key] = create_function_;
319 }
320 
321 template<typename Key, typename Interface>
323  //
324  typename ImplMap::iterator it;
325  if ((it = this->impl_map_.find(key)) == this->impl_map_.end()) {
326  throw NoSuchImpl(
327  boost::str(
328  boost::format(
330  "no implementation of interface `%%1%%' found for specified key `%1%'",
331  "no implementation of interface `%%1%%' found for specified key",
332  key)) % runtime::typeName<Interface>()));
333  }
334 
335  //
336  this->impl_map_base_.erase(key);
337  this->impl_map_.erase(it);
338 }
339 
340 template<typename Key, typename Interface>
342  const Key& key, const runtime::Properties& properties_) {
343  Interface* instance = createInst(key, properties_);
344 
345  return std::make_pair(&typeid(*instance), instance);
346 }
347 
348 template<typename Key, typename Interface>
349 Interface*
351  const runtime::Properties& properties_) {
352  // Try to find the implementation specified by key.
353  typename ImplMap::const_iterator it;
354  if ((it = this->impl_map_.find(key)) == this->impl_map_.end()) {
355  throw NoSuchImpl(
356  boost::str(
357  boost::format(
359  "no implementation of interface `%%1%%' found for specified key `%1%'",
360  "no implementation of interface `%%1%%' found for specified key",
361  key)) % runtime::typeName<Interface>()));
362  }
363 
364  // Try to create an instance of that implementation.
365  Interface* instance = 0;
366  try {
367  instance = reinterpret_cast<Interface*> (it->second(properties_));
368  } catch (const std::exception& exception_) {
369  throw ConstructError(runtime::typeName(typeid(exception_)) + ": "
370  + exception_.what());
371  // TODO use boost exception stuff and rethrow
372  } catch (...) {
374  "could not construct implementation instance for key `%1%'",
375  "could not construct implementation instance", key));
376  }
377 
378  // Return the constructed instance.
379  return instance;
380 }
381 
382 // SingletonFactory implementation
383 
384 template<typename Key, typename Interface>
386 }
387 
388 // free function implementations
389 
390 template<typename Ch, typename Tr, typename Key, typename Interface>
391 std::basic_ostream<Ch, Tr>&
392 operator<<(std::basic_ostream<Ch, Tr>& stream,
393  const Factory<Key, Interface>& factory) {
394  typedef typename Factory<Key, Interface>::ImplMapProxy impl_map_proxy_type;
395 
396  //
397  stream << (boost::format("implementations of interface %1%:\n")
398  % runtime::typeName(typeid(Interface)));
399 
400  //
401  const impl_map_proxy_type& impls = factory.impls();
402 
403  for (typename impl_map_proxy_type::const_iterator it = impls.begin(); it
404  != impls.end(); ++it) {
405  stream << (boost::format("* %1%\n") % it->first);
406  }
407 
408  // Don't forget to return the stream.
409  return stream;
410 }
411 
412 }
413 }
ImplMapProxy(ImplMap &container)
Definition: Factory.h:83
virtual type_and_storage createBase(const Key &key, const runtime::Properties &properties_=runtime::Properties())=0
Create and return an instance of the implementation designated by key.
base::KeyType KeyType
Definition: Factory.h:133
ImplMapBaseProxy impl_map_base_proxy_
Definition: Factory.h:225
virtual void register_(const Key &key, const CreateFunction &create_function_)
Definition: Factory.h:308
A factory of which at most one instance exists at any time.
Definition: Factory.h:246
Objects of this class manage a family of named implementations of a particular interface.
Definition: Factory.h:129
boost::function1< InterfaceType *, const runtime::Properties & > CreateFunction
Definition: Factory.h:137
std::string typeName(const std::type_info &type)
Returns a (demangled) string representation of type.
pair< _T1, _T2 > make_pair(_T1 __x, _T2 __y)
A convenience wrapper for creating a pair from two objects.
std::map< Key, CreateFunction > ImplMap
Definition: Factory.h:139
Factory< Key, Interface > & owner
Definition: Factory.h:169
virtual void unregister(const Key &key)
Definition: Factory.h:322
boost::function1< void *, const runtime::Properties & > CreateFunction
Definition: Factory.h:71
An interface-independent factory interface, mainly used as a base class for more specific factories...
Definition: Factory.h:68
ImplMapBase impl_map_base_
Definition: Factory.h:224
ImplMapProxy & impls()
Return a container-like object holding all registered implementations.
Definition: Factory.h:297
Interface * createInst(const Key &key, const runtime::Properties &properties_=runtime::Properties())
Create and return an instance of the implementation designated by key.
Definition: Factory.h:350
void register_(const KeyType &key, const CreateFunction &create_function_)
Definition: Factory.h:262
This template class implements the singleton pattern.
Definition: Singleton.h:51
base::ImplMap ImplMapBase
Definition: Factory.h:141
virtual const ImplMapProxy & implsBase() const =0
Return a container-like object holding all registered implementations.
FactoryBase< Key > base
Definition: Factory.h:131
ImplMapProxy(Factory< Key, Interface > &owner)
Definition: Factory.h:256
ImplMapProxy impl_map_proxy_
Definition: Factory.h:228
Interface InterfaceType
Definition: Factory.h:134
base::ImplMapProxy ImplMapBaseProxy
Definition: Factory.h:142
AssociativeProxy< ImplMap > base_type
Definition: Factory.h:167
virtual const std::type_info & GetInterfaceType() const =0
Return the type information of the interface type of the factory.
std::string typeString(const std::string &known_type_string, const std::string &unknown_type_string, const T &value)
Returns one of two to strings depending on whether type T is known to be able to support stream outpu...
virtual ~Factory()
Definition: Factory.h:280
FactoryBase< Key >::type_and_storage createBase(const Key &key, const runtime::Properties &properties_=runtime::Properties())
Definition: Factory.h:341
std::map< Key, CreateFunction > ImplMap
Definition: Factory.h:74
AssociativeProxy< ImplMap > base
Definition: Factory.h:81
Properties objects are basically glorified map<string, boost::any> objects.
Definition: Properties.h:57
std::pair< const std::type_info *, void * > type_and_storage
Definition: Factory.h:72
This object presents the registered implementations in a form very similar to a STL container...
Definition: Factory.h:153
const std::type_info & GetInterfaceType() const
Return the type information of the interface type of the factory.
Definition: Factory.h:285
void unregister(const KeyType &key)
Definition: Factory.h:268
const ImplMapBaseProxy & implsBase() const
Return a container-like object holding all registered implementations.
Definition: Factory.h:291