Newer
Older
Peterson, Peter
committed
#ifndef MANTID_API_ALGORITHMFACTORY_H_
#define MANTID_API_ALGORITHMFACTORY_H_
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include <vector>
#include <unordered_set>
#include <sstream>
Gigg, Martyn Anthony
committed
#include "MantidAPI/DllConfig.h"
Peterson, Peter
committed
#include "MantidKernel/DynamicFactory.h"
#include "MantidKernel/SingletonHolder.h"
namespace Mantid {
namespace API {
/// Structure uniquely describing an algorithm with its name, category and
/// version.
struct Algorithm_descriptor {
std::string name; ///< name
std::string alias; ///< alias
std::string category; ///< category
int version; ///< version
Peterson, Peter
committed
};
//----------------------------------------------------------------------
// Forward declarations
//----------------------------------------------------------------------
class IAlgorithm;
class Algorithm;
/** The AlgorithmFactory class is in charge of the creation of concrete
instances of Algorithms. It inherits most of its implementation from
the Dynamic Factory base class.
It is implemented as a singleton class.
Peterson, Peter
committed
@author Russell Taylor, Tessella Support Services plc
@date 21/09/2007
Copyright © 2007-2011 ISIS Rutherford Appleton Laboratory, NScD Oak
Ridge National Laboratory & European Spallation Source
Peterson, Peter
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://github.com/mantidproject/mantid>
Peterson, Peter
committed
*/
class MANTID_API_DLL AlgorithmFactoryImpl
: public Kernel::DynamicFactory<Algorithm> {
Peterson, Peter
committed
public:
Gigg, Martyn Anthony
committed
// Unhide the base class version (to satisfy the intel compiler)
using Kernel::DynamicFactory<Algorithm>::create;
/// Creates an instance of an algorithm
boost::shared_ptr<Algorithm> create(const std::string &, const int &) const;
/// algorithm factory specific function to subscribe algorithms, calls the
/// dynamic factory subscribe function internally
template <class C> std::pair<std::string, int> subscribe() {
Kernel::Instantiator<C, Algorithm> *newI =
new Kernel::Instantiator<C, Algorithm>;
return this->subscribe(newI);
Gigg, Martyn Anthony
committed
}
Peterson, Peter
committed
Gigg, Martyn Anthony
committed
/**
* Subscribes an algorithm using a custom instantiator. This
* object takes ownership of the instantiator
* @param instantiator - A pointer to a custom instantiator
* @param replaceExisting - Defines what happens if an algorithm of the same
* name/version already exists, see SubscribeAction
* @returns The classname that was registered
Gigg, Martyn Anthony
committed
*/
template <class T>
std::pair<std::string, int>
subscribe(Kernel::AbstractInstantiator<T> *instantiator,
const SubscribeAction replaceExisting = ErrorIfExists) {
boost::shared_ptr<IAlgorithm> tempAlg = instantiator->createInstance();
Peterson, Peter
committed
const int version = extractAlgVersion(tempAlg);
const std::string className = extractAlgName(tempAlg);
Gigg, Martyn Anthony
committed
typename VersionMap::const_iterator it = m_vmap.find(className);
if (!className.empty()) {
const std::string key = createName(className, version);
if (it == m_vmap.end()) {
m_vmap[className] = version;
} else {
if (version == it->second && replaceExisting == ErrorIfExists) {
std::ostringstream os;
os << "Cannot register algorithm " << className
<< " twice with the same version\n";
delete instantiator;
throw std::runtime_error(os.str());
Peterson, Peter
committed
}
if (version > it->second) {
m_vmap[className] = version;
}
Kernel::DynamicFactory<Algorithm>::subscribe(key, instantiator,
replaceExisting);
} else {
delete instantiator;
throw std::invalid_argument("Cannot register empty algorithm name");
return std::make_pair(className, version);
Peterson, Peter
committed
}
/// Unsubscribe the given algorithm
void unsubscribe(const std::string &algorithmName, const int version);
/// Does an algorithm of the given name and version exist
bool exists(const std::string &algorithmName, const int version = -1);
Peterson, Peter
committed
/// Get the algorithm names and version - mangled use decodeName to separate
const std::vector<std::string> getKeys() const override;
const std::vector<std::string> getKeys(bool includeHidden) const;
/// Returns the highest version of the algorithm currently registered
int highestVersion(const std::string &algorithmName) const;
/// Get the algorithm categories
const std::unordered_set<std::string>
getCategories(bool includeHidden = false) const;
/// Get the algorithm categories
const std::map<std::string, bool> getCategoriesWithState() const;
Peterson, Peter
committed
/// Returns algorithm descriptors.
std::vector<Algorithm_descriptor>
getDescriptors(bool includeHidden = false) const;
/// unmangles the names used as keys into the name and version
std::pair<std::string, int> decodeName(const std::string &mangledName) const;
Peterson, Peter
committed
Peterson, Peter
committed
friend struct Mantid::Kernel::CreateUsingNew<AlgorithmFactoryImpl>;
/// Extract the name of an algorithm
const std::string
extractAlgName(const boost::shared_ptr<IAlgorithm> alg) const;
Peterson, Peter
committed
/// Extract the version of an algorithm
Janik Zikovsky
committed
int extractAlgVersion(const boost::shared_ptr<IAlgorithm> alg) const;
Peterson, Peter
committed
/// Create an algorithm object with the specified name
boost::shared_ptr<Algorithm> createAlgorithm(const std::string &name,
const int version) const;
Peterson, Peter
committed
/// Private Constructor for singleton class
Peterson, Peter
committed
/// Private copy constructor - NO COPY ALLOWED
AlgorithmFactoryImpl(const AlgorithmFactoryImpl &);
Peterson, Peter
committed
/// Private assignment operator - NO ASSIGNMENT ALLOWED
AlgorithmFactoryImpl &operator=(const AlgorithmFactoryImpl &);
/// Private Destructor
~AlgorithmFactoryImpl() override;
Peterson, Peter
committed
/// creates an algorithm name convolved from an name and version
std::string createName(const std::string &, const int &) const;
void fillHiddenCategories(std::unordered_set<std::string> *categorySet) const;
Peterson, Peter
committed
/// A typedef for the map of algorithm versions
Gigg, Martyn Anthony
committed
typedef std::map<std::string, int> VersionMap;
Peterson, Peter
committed
/// The map holding the registered class names and their highest versions
Gigg, Martyn Anthony
committed
VersionMap m_vmap;
Peterson, Peter
committed
};
/// Forward declaration of a specialisation of SingletonHolder for
/// AlgorithmFactoryImpl (needed for dllexport/dllimport) and a typedef for it.
Peterson, Peter
committed
#ifdef _WIN32
// this breaks new namespace declaraion rules; need to find a better fix
template class MANTID_API_DLL
Mantid::Kernel::SingletonHolder<AlgorithmFactoryImpl>;
Peterson, Peter
committed
#endif /* _WIN32 */
typedef MANTID_API_DLL Mantid::Kernel::SingletonHolder<AlgorithmFactoryImpl>
AlgorithmFactory;
Peterson, Peter
committed
/// Convenient typedef for an UpdateNotification
typedef Mantid::Kernel::DynamicFactory<Algorithm>::UpdateNotification
AlgorithmFactoryUpdateNotification;
typedef const Poco::AutoPtr<Mantid::Kernel::DynamicFactory<
Algorithm>::UpdateNotification> &AlgorithmFactoryUpdateNotification_ptr;
Peterson, Peter
committed
} // namespace API
} // namespace Mantid
#endif /*MANTID_API_ALGORITHMFACTORY_H_*/