Newer
Older
Russell Taylor
committed
#ifndef MANTID_KERNEL_DYNAMICFACTORY_H_
#define MANTID_KERNEL_DYNAMICFACTORY_H_
Russell Taylor
committed
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidKernel/System.h"
#include "MantidKernel/Instantiator.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/Exception.h"
Russell Taylor
committed
#include <map>
Russell Taylor
committed
namespace Mantid
{
Russell Taylor
committed
namespace Kernel
{
Russell Taylor
committed
/** @class DynamicFactory DynamicFactory.h Kernel/DynamicFactory.h
The dynamic factory is a base dynamic factory for serving up objects in response to requests from other classes.
@author Nick Draper, Tessella Support Services plc
@date 10/10/2007
Copyright © 2007 STFC Rutherford Appleton Laboratories
Russell Taylor
committed
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>.
Code Documentation is available at: <http://doxygen.mantidproject.org>
Russell Taylor
committed
*/
template <class Base>
Russell Taylor
committed
class DynamicFactory
Russell Taylor
committed
{
public:
/// A typedef for the instantiator
typedef AbstractInstantiator<Base> AbstractFactory;
/// Destroys the DynamicFactory and deletes the instantiators for
/// all registered classes.
Russell Taylor
committed
virtual ~DynamicFactory()
{
for (typename FactoryMap::iterator it = _map.begin(); it != _map.end(); ++it)
{
Russell Taylor
committed
}
}
Russell Taylor
committed
Russell Taylor
committed
/// Creates a new instance of the class with the given name.
Russell Taylor
committed
/// The class must have been registered with registerClass.
/// If the class name is unknown, a NotFoundException is thrown.
/// @param className the name of the class you wish to create
virtual boost::shared_ptr<Base> create(const std::string& className) const
Russell Taylor
committed
{
Russell Taylor
committed
typename FactoryMap::const_iterator it = _map.find(className);
if (it != _map.end())
return it->second->createInstance();
Russell Taylor
committed
else
throw Exception::NotFoundError("DynamicFactory:"+ className + " is not registered.\n", className);
Russell Taylor
committed
}
/// Registers the instantiator for the given class with the DynamicFactory.
/// The DynamicFactory takes ownership of the instantiator and deletes
/// it when it's no longer used.
/// If the class has already been registered, an ExistsException is thrown
/// and the instantiator is deleted.
/// @param className the name of the class you wish to subscribe
Russell Taylor
committed
template <class C>
void subscribe(const std::string& className)
{
Russell Taylor
committed
subscribe(className, new Instantiator<C, Base>);
Russell Taylor
committed
}
/// Registers the instantiator for the given class with the DynamicFactory.
/// The DynamicFactory takes ownership of the instantiator and deletes
/// it when it's no longer used.
/// If the class has already been registered, an ExistsException is thrown
/// and the instantiator is deleted.
/// @param className the name of the class you wish to subscribe
/// @param pAbstractFactory A pointer to an abstractFactory for this class
Russell Taylor
committed
void subscribe(const std::string& className, AbstractFactory* pAbstractFactory)
{
Russell Taylor
committed
// std::cout << "class: " << className << std::endl;
Russell Taylor
committed
typename FactoryMap::iterator it = _map.find(className);
if (!className.empty() && it == _map.end())
_map[className] = pAbstractFactory;
Russell Taylor
committed
else
Russell Taylor
committed
{
delete pAbstractFactory;
throw std::runtime_error(className + "is already registered.\n");
Russell Taylor
committed
}
Russell Taylor
committed
}
/// Unregisters the given class and deletes the instantiator
/// for the class.
/// Throws a NotFoundException if the class has not been registered.
/// @param className the name of the class you wish to unsubscribe
Russell Taylor
committed
void unsubscribe(const std::string& className)
{
typename FactoryMap::iterator it = _map.find(className);
Russell Taylor
committed
{
delete it->second;
_map.erase(it);
}
else
throw Exception::NotFoundError("DynamicFactory:"+ className + " is not registered.\n",className);
Russell Taylor
committed
}
/// Returns true if the given class is currently registered.
/// @param className the name of the class you wish to check
/// @returns true is the class is subscribed
Russell Taylor
committed
bool exists(const std::string& className) const
{
return _map.find(className) != _map.end();
}
protected:
/// Protected constructor for base class
DynamicFactory()
Russell Taylor
committed
{
}
Russell Taylor
committed
private:
/// Private copy constructor - NO COPY ALLOWED
DynamicFactory(const DynamicFactory&);
/// Private assignment operator - NO ASSIGNMENT ALLOWED
DynamicFactory& operator = (const DynamicFactory&);
/// A typedef for the map of registered classes
Russell Taylor
committed
typedef std::map<std::string, AbstractFactory*> FactoryMap;
/// The map holding the registered class names and their instantiators
FactoryMap _map;
};
Russell Taylor
committed
} // namespace Kernel
} // namespace Mantid
Russell Taylor
committed
Russell Taylor
committed
#endif /*MANTID_KERNEL_DYNAMICFACTORY_H_*/