library of assembled shared sources

http://lass.cocamware.com

clone_factory.h

Go to the documentation of this file.
00001 /*
00002  * *** ATTENTION!  DO NOT MODIFY THIS FILE DIRECTLY! ***
00003  * 
00004  * It has automatically been generated from clone_factory.tmpl.h
00005  * by param_expander.py on Sun Nov 09 16:55:52 2008.
00006  */
00007 
00008 /** @file
00009  *  @author Bram de Greve (bramz@users.sourceforge.net)
00010  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00011  *
00012  *  *** BEGIN LICENSE INFORMATION ***
00013  *  
00014  *  The contents of this file are subject to the Common Public Attribution License 
00015  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00016  *  the License. You may obtain a copy of the License at 
00017  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00018  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00019  *  use of software over a computer network and provide for limited attribution for 
00020  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00021  *  with Exhibit B.
00022  *  
00023  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00024  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00025  *  language governing rights and limitations under the License.
00026  *  
00027  *  The Original Code is LASS - Library of Assembled Shared Sources.
00028  *  
00029  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00030  *  The Original Developer is the Initial Developer.
00031  *  
00032  *  All portions of the code written by the Initial Developer are:
00033  *  Copyright (C) 2004-2007 the Initial Developer.
00034  *  All Rights Reserved.
00035  *  
00036  *  Contributor(s):
00037  *
00038  *  Alternatively, the contents of this file may be used under the terms of the 
00039  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00040  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00041  *  of your version of this file only under the terms of the GPL and not to allow 
00042  *  others to use your version of this file under the CPAL, indicate your decision by 
00043  *  deleting the provisions above and replace them with the notice and other 
00044  *  provisions required by the GPL License. If you do not delete the provisions above,
00045  *  a recipient may use your version of this file under either the CPAL or the GPL.
00046  *  
00047  *  *** END LICENSE INFORMATION ***
00048  */
00049 
00050 
00051 
00052 /** @class lass::util::CloneFactory
00053  *  @brief object creation by cloning prototypes
00054  *  @author Bram de Greve [Bramz]
00055  *
00056  *  A clone factory is much like an object factory (lass::util::ObjectFactory), except that it will
00057  *  clone existings object rather than creating new ones from the ground up using maker functions.
00058  *
00059  *  A clone factory creates objects of the same hierarchy, i.e. objects that have a common base
00060  *  class.  The base class is an @e abstract product and the derived classes are @e concrete
00061  *  products.  The factory let you decide what concrete product to create at @e runtime by
00062  *  using a specific @e identifier.  These identifiers can be integers or strings or any
00063  *  type you can use in a std::map.
00064  *
00065  *  Before you can create any products, you must @e subscribe @e prototypes and @e cloner methods
00066  *  to the factory.  A @e prototype is an object instance that will be cloned by the @e cloner
00067  *  function.  Together, a pair of a @e prototype and a @e cloner function provides the
00068  *  functionality of one @e maker function in the ObjectFactory.
00069  *
00070  *  Again, all this @a cloners must have the same signature and should return a pointer to the
00071  *  abstract product.  Their first argument will be a reference to the prototype being cloned.
00072  *  The following arguments will be filled by the @a iP1, @a iP2, @a iP3, ... that are provided to
00073  *  the make() method of the clone factory.
00074  *
00075  *  @code
00076  *  class Base
00077  *  {
00078  *  public:
00079  *      Base(const std::string& iName): name_(iName) {}
00080  *      virtual std::string who() const { return std::string("Base ") + name_; }
00081  *      virtual Base* clone() const { return new Base(*this); }
00082  *  protected:
00083  *      std::string name_;
00084  *  };
00085  *
00086  *  class Foo: public Base
00087  *  {
00088  *  public:
00089  *      Foo(const std::string& iName): Base(iName) {}
00090  *      virtual std::string who() const { return std::string("Foo ") + name_; }
00091  *      virtual Base* clone() const { return new Foo(*this); }
00092  *  };
00093  *
00094  *  class Bar: public Base
00095  *  {
00096  *  public:
00097  *      Bar(const std::string& iName): Base(iName) {}
00098  *      virtual std::string who() const { return std::string("Bar ") + name_; }
00099  *      virtual Base* clone() const { return new Bar(*this); }
00100  *  };
00101  *
00102  *  Base* clone(const Base& iPrototype) { return iPrototype.clone(); }
00103  *
00104   * typedef util::CloneFactory<Base, std::string> TFactory;
00105  *  typedef std::auto_ptr<Base> TBasePtr;
00106  *
00107  *  TFactory factory(clone);
00108  *  factory.subscribe("Joe", TBasePtr(new Base("Joe")));
00109  *  factory.subscribe("Moe", TBasePtr(new Foo("Moe")));
00110  *  factory.subscribe("Doe", TBasePtr(new Bar("Doe")));
00111  *
00112  *  TBasePtr a(factory.make("Joe"));
00113  *  LASS_COUT << a->who() << "\n"; // Base Joe
00114  *  TBasePtr b(factory.make("Moe"));
00115  *  LASS_COUT << b->who() << "\n"; // Foo Moe
00116  *  TBasePtr c(factory.make("Doe"));
00117  *  LASS_COUT << c->who() << "\n"; // Bar Doe
00118  *  @endcode
00119  */
00120 
00121 #ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_CLONE_FACTORY_H
00122 #define LASS_GUARDIAN_OF_INCLUSION_UTIL_CLONE_FACTORY_H
00123 
00124 #include "util_common.h"
00125 #include "shared_ptr.h"
00126 
00127 namespace lass
00128 {
00129 namespace util
00130 {
00131 
00132 template
00133 <
00134     class AbstractProduct,
00135     class IdentifierType,
00136     class ProductCloner = AbstractProduct*(*)(const AbstractProduct&)
00137 >
00138 class CloneFactory
00139 {
00140 public:
00141 
00142     typedef AbstractProduct TAbstractProduct;
00143     typedef IdentifierType TIdentifier;
00144     typedef ProductCloner TProductCloner;
00145 
00146     /** create a clone factory by specifying its cloner function @a iCloner.
00147      */
00148     CloneFactory(typename CallTraits<ProductCloner>::TParam iCloner):
00149         cloner_(iCloner)
00150     {
00151     }
00152 
00153     /** register a concrete product to the CloneFactory by a @a iIdentifier that will identify
00154      *  the product, and an @a iPrototype that will be cloned.
00155      */
00156     bool subscribe(typename CallTraits<IdentifierType>::TParam iIdentifier,
00157                    std::auto_ptr<AbstractProduct> iPrototype)
00158     {
00159         return prototypes_.insert(typename TPrototypes::value_type(iIdentifier, iPrototype)).second;
00160     }
00161 
00162     /** unregister a concrete product by its @a iIdentifier
00163      */
00164     bool unsubscribe(typename CallTraits<IdentifierType>::TParam iIdentifier)
00165     {
00166         return prototypes_.erase(iIdentifier) == 1;
00167     }
00168 
00169     /** Create a new concrete product by cloning the prototype
00170      *  only to be used if maker don't want any parameters.
00171      */
00172     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier) const
00173     {
00174         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00175         if (i == prototypes_.end())
00176         {
00177             LASS_THROW("Unknown Product identifier '" << iIdentifier
00178                 << "' passed to CloneFactory.");
00179         }
00180         return cloner_(*i->second);
00181     }
00182     
00183     /** create a new concrete product by cloning the prototype with 1 additional parameter(s).
00184      *  only to be used if it can be mapped on @a iCloner function.
00185      */
00186     template <typename P1>
00187     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00188                           P1& iP1) const
00189     {
00190         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00191         if (i == prototypes_.end())
00192         {
00193             LASS_THROW("Unknown Product identifier '" << iIdentifier
00194                 << "' passed to CloneFactory.");
00195         }
00196         return cloner_(*i->second, iP1);
00197     }
00198     
00199     /** create a new concrete product by cloning the prototype with 2 additional parameter(s).
00200      *  only to be used if it can be mapped on @a iCloner function.
00201      */
00202     template <typename P1, typename P2>
00203     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00204                           P1& iP1, P2& iP2) const
00205     {
00206         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00207         if (i == prototypes_.end())
00208         {
00209             LASS_THROW("Unknown Product identifier '" << iIdentifier
00210                 << "' passed to CloneFactory.");
00211         }
00212         return cloner_(*i->second, iP1, iP2);
00213     }
00214     
00215     /** create a new concrete product by cloning the prototype with 3 additional parameter(s).
00216      *  only to be used if it can be mapped on @a iCloner function.
00217      */
00218     template <typename P1, typename P2, typename P3>
00219     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00220                           P1& iP1, P2& iP2, P3& iP3) const
00221     {
00222         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00223         if (i == prototypes_.end())
00224         {
00225             LASS_THROW("Unknown Product identifier '" << iIdentifier
00226                 << "' passed to CloneFactory.");
00227         }
00228         return cloner_(*i->second, iP1, iP2, iP3);
00229     }
00230     
00231     /** create a new concrete product by cloning the prototype with 4 additional parameter(s).
00232      *  only to be used if it can be mapped on @a iCloner function.
00233      */
00234     template <typename P1, typename P2, typename P3, typename P4>
00235     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00236                           P1& iP1, P2& iP2, P3& iP3, P4& iP4) const
00237     {
00238         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00239         if (i == prototypes_.end())
00240         {
00241             LASS_THROW("Unknown Product identifier '" << iIdentifier
00242                 << "' passed to CloneFactory.");
00243         }
00244         return cloner_(*i->second, iP1, iP2, iP3, iP4);
00245     }
00246     
00247     /** create a new concrete product by cloning the prototype with 5 additional parameter(s).
00248      *  only to be used if it can be mapped on @a iCloner function.
00249      */
00250     template <typename P1, typename P2, typename P3, typename P4, typename P5>
00251     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00252                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5) const
00253     {
00254         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00255         if (i == prototypes_.end())
00256         {
00257             LASS_THROW("Unknown Product identifier '" << iIdentifier
00258                 << "' passed to CloneFactory.");
00259         }
00260         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5);
00261     }
00262     
00263     /** create a new concrete product by cloning the prototype with 6 additional parameter(s).
00264      *  only to be used if it can be mapped on @a iCloner function.
00265      */
00266     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
00267     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00268                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6) const
00269     {
00270         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00271         if (i == prototypes_.end())
00272         {
00273             LASS_THROW("Unknown Product identifier '" << iIdentifier
00274                 << "' passed to CloneFactory.");
00275         }
00276         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6);
00277     }
00278     
00279     /** create a new concrete product by cloning the prototype with 7 additional parameter(s).
00280      *  only to be used if it can be mapped on @a iCloner function.
00281      */
00282     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
00283     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00284                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6, P7& iP7) const
00285     {
00286         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00287         if (i == prototypes_.end())
00288         {
00289             LASS_THROW("Unknown Product identifier '" << iIdentifier
00290                 << "' passed to CloneFactory.");
00291         }
00292         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6, iP7);
00293     }
00294     
00295     /** create a new concrete product by cloning the prototype with 8 additional parameter(s).
00296      *  only to be used if it can be mapped on @a iCloner function.
00297      */
00298     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
00299     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00300                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6, P7& iP7, P8& iP8) const
00301     {
00302         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00303         if (i == prototypes_.end())
00304         {
00305             LASS_THROW("Unknown Product identifier '" << iIdentifier
00306                 << "' passed to CloneFactory.");
00307         }
00308         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6, iP7, iP8);
00309     }
00310     
00311     /** create a new concrete product by cloning the prototype with 9 additional parameter(s).
00312      *  only to be used if it can be mapped on @a iCloner function.
00313      */
00314     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
00315     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00316                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6, P7& iP7, P8& iP8, P9& iP9) const
00317     {
00318         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00319         if (i == prototypes_.end())
00320         {
00321             LASS_THROW("Unknown Product identifier '" << iIdentifier
00322                 << "' passed to CloneFactory.");
00323         }
00324         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6, iP7, iP8, iP9);
00325     }
00326     
00327     /** create a new concrete product by cloning the prototype with 10 additional parameter(s).
00328      *  only to be used if it can be mapped on @a iCloner function.
00329      */
00330     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
00331     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00332                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6, P7& iP7, P8& iP8, P9& iP9, P10& iP10) const
00333     {
00334         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00335         if (i == prototypes_.end())
00336         {
00337             LASS_THROW("Unknown Product identifier '" << iIdentifier
00338                 << "' passed to CloneFactory.");
00339         }
00340         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6, iP7, iP8, iP9, iP10);
00341     }
00342     
00343     /** create a new concrete product by cloning the prototype with 11 additional parameter(s).
00344      *  only to be used if it can be mapped on @a iCloner function.
00345      */
00346     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11>
00347     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00348                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6, P7& iP7, P8& iP8, P9& iP9, P10& iP10, P11& iP11) const
00349     {
00350         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00351         if (i == prototypes_.end())
00352         {
00353             LASS_THROW("Unknown Product identifier '" << iIdentifier
00354                 << "' passed to CloneFactory.");
00355         }
00356         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6, iP7, iP8, iP9, iP10, iP11);
00357     }
00358     
00359     /** create a new concrete product by cloning the prototype with 12 additional parameter(s).
00360      *  only to be used if it can be mapped on @a iCloner function.
00361      */
00362     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12>
00363     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00364                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6, P7& iP7, P8& iP8, P9& iP9, P10& iP10, P11& iP11, P12& iP12) const
00365     {
00366         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00367         if (i == prototypes_.end())
00368         {
00369             LASS_THROW("Unknown Product identifier '" << iIdentifier
00370                 << "' passed to CloneFactory.");
00371         }
00372         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6, iP7, iP8, iP9, iP10, iP11, iP12);
00373     }
00374     
00375     /** create a new concrete product by cloning the prototype with 13 additional parameter(s).
00376      *  only to be used if it can be mapped on @a iCloner function.
00377      */
00378     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12, typename P13>
00379     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00380                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6, P7& iP7, P8& iP8, P9& iP9, P10& iP10, P11& iP11, P12& iP12, P13& iP13) const
00381     {
00382         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00383         if (i == prototypes_.end())
00384         {
00385             LASS_THROW("Unknown Product identifier '" << iIdentifier
00386                 << "' passed to CloneFactory.");
00387         }
00388         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6, iP7, iP8, iP9, iP10, iP11, iP12, iP13);
00389     }
00390     
00391     /** create a new concrete product by cloning the prototype with 14 additional parameter(s).
00392      *  only to be used if it can be mapped on @a iCloner function.
00393      */
00394     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12, typename P13, typename P14>
00395     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00396                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6, P7& iP7, P8& iP8, P9& iP9, P10& iP10, P11& iP11, P12& iP12, P13& iP13, P14& iP14) const
00397     {
00398         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00399         if (i == prototypes_.end())
00400         {
00401             LASS_THROW("Unknown Product identifier '" << iIdentifier
00402                 << "' passed to CloneFactory.");
00403         }
00404         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6, iP7, iP8, iP9, iP10, iP11, iP12, iP13, iP14);
00405     }
00406     
00407     /** create a new concrete product by cloning the prototype with 15 additional parameter(s).
00408      *  only to be used if it can be mapped on @a iCloner function.
00409      */
00410     template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12, typename P13, typename P14, typename P15>
00411     AbstractProduct* make(typename CallTraits<IdentifierType>::TParam iIdentifier,
00412                           P1& iP1, P2& iP2, P3& iP3, P4& iP4, P5& iP5, P6& iP6, P7& iP7, P8& iP8, P9& iP9, P10& iP10, P11& iP11, P12& iP12, P13& iP13, P14& iP14, P15& iP15) const
00413     {
00414         typename TPrototypes::const_iterator i = prototypes_.find(iIdentifier);
00415         if (i == prototypes_.end())
00416         {
00417             LASS_THROW("Unknown Product identifier '" << iIdentifier
00418                 << "' passed to CloneFactory.");
00419         }
00420         return cloner_(*i->second, iP1, iP2, iP3, iP4, iP5, iP6, iP7, iP8, iP9, iP10, iP11, iP12, iP13, iP14, iP15);
00421     }
00422     
00423 
00424 private:
00425 
00426     typedef SharedPtr<AbstractProduct> TPrototypePtr;
00427     typedef std::map<IdentifierType, TPrototypePtr> TPrototypes;
00428 
00429     TPrototypes prototypes_;
00430     TProductCloner cloner_;
00431 };
00432 
00433 
00434 
00435 }
00436 
00437 }
00438 
00439 #endif
00440 
00441 // EOF

Generated on Mon Nov 10 14:20:01 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo