Newer
Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2007 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source
// & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
Peterson, Peter
committed
#ifndef MANTID_API_ALGORITHMFACTORY_H_
#define MANTID_API_ALGORITHMFACTORY_H_
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
Gigg, Martyn Anthony
committed
#include "MantidAPI/DllConfig.h"
Peterson, Peter
committed
#include "MantidKernel/DynamicFactory.h"
#include "MantidKernel/SingletonHolder.h"
#include <sstream>
#include <unordered_set>
#include <vector>
Peterson, Peter
committed
namespace Mantid {
namespace API {
/// Structure uniquely describing an algorithm with its name, category and
/// version.
struct AlgorithmDescriptor {
std::string name; ///< Algorithm Name
int version; ///< version
std::string category; ///< category
std::string alias; ///< alias
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
*/
class MANTID_API_DLL AlgorithmFactoryImpl final
: public Kernel::DynamicFactory<Algorithm> {
Peterson, Peter
committed
public:
AlgorithmFactoryImpl(const AlgorithmFactoryImpl &) = delete;
AlgorithmFactoryImpl &operator=(const AlgorithmFactoryImpl &) = delete;
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() {
std::unique_ptr<Kernel::AbstractInstantiator<Algorithm>> newI =
std::make_unique<Kernel::Instantiator<C, Algorithm>>();
return this->subscribe(std::move(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(std::unique_ptr<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";
throw std::runtime_error(os.str());
Peterson, Peter
committed
}
if (version > it->second) {
m_vmap[className] = version;
}
Kernel::DynamicFactory<Algorithm>::subscribe(key, std::move(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<AlgorithmDescriptor>
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
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
using VersionMap = std::map<std::string, int>;
Peterson, Peter
committed
/// The map holding the registered class names and their highest versions
Gigg, Martyn Anthony
committed
VersionMap m_vmap;
Peterson, Peter
committed
};
using AlgorithmFactory = Mantid::Kernel::SingletonHolder<AlgorithmFactoryImpl>;
Peterson, Peter
committed
/// Convenient typedef for an UpdateNotification
using AlgorithmFactoryUpdateNotification =
Mantid::Kernel::DynamicFactory<Algorithm>::UpdateNotification;
using AlgorithmFactoryUpdateNotification_ptr = const Poco::AutoPtr<
Mantid::Kernel::DynamicFactory<Algorithm>::UpdateNotification> &;
Peterson, Peter
committed
} // namespace API
} // namespace Mantid
namespace Mantid {
namespace Kernel {
EXTERN_MANTID_API template class MANTID_API_DLL
Mantid::Kernel::SingletonHolder<Mantid::API::AlgorithmFactoryImpl>;
Peterson, Peter
committed
#endif /*MANTID_API_ALGORITHMFACTORY_H_*/