Skip to content
Snippets Groups Projects
FunctionFactory.h 6.64 KiB
Newer Older
#ifndef MANTID_API_FUNCTIONFACTORY_H_
#define MANTID_API_FUNCTIONFACTORY_H_

//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include <vector>
#include "MantidKernel/DynamicFactory.h"
#include "MantidKernel/SingletonHolder.h"
namespace Mantid {
namespace API {

//----------------------------------------------------------------------
// More forward declarations
//----------------------------------------------------------------------
class IFunction;
class CompositeFunction;
class Expression;

/** @class FunctionFactoryImpl

    The FunctionFactory class is in charge of the creation of concrete
    instances of fitting functions. It inherits most of its implementation from
    the Dynamic Factory base class.
    It is implemented as a singleton class.
    @author Roman Tolchenov, Tessella Support Services plc
    @date 27/10/2009

    Copyright &copy; 2007 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge
   National Laboratory & European Spallation Source

    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>
class MANTID_API_DLL FunctionFactoryImpl final
    : public Kernel::DynamicFactory<IFunction> {
public:
  FunctionFactoryImpl(const FunctionFactoryImpl &) = delete;
  FunctionFactoryImpl &operator=(const FunctionFactoryImpl &) = delete;
  /**Creates an instance of a function
   * @param type :: The function's type
   * @return A pointer to the created function
  boost::shared_ptr<IFunction> createFunction(const std::string &type) const;

  /// Creates an instance of a function
  boost::shared_ptr<IFunction>
  createInitialized(const std::string &input) const;

  /// Query available functions based on the template type
  template <typename FunctionType>
  const std::vector<std::string> &getFunctionNames() const;
  // Unhide the base class version (to satisfy the intel compiler)
  using Kernel::DynamicFactory<IFunction>::subscribe;
  void subscribe(const std::string &className,
                 AbstractFactory *pAbstractFactory,
                 Kernel::DynamicFactory<IFunction>::SubscribeAction replace =
                     ErrorIfExists);

  void unsubscribe(const std::string &className);

private:
  friend struct Mantid::Kernel::CreateUsingNew<FunctionFactoryImpl>;

  /// Private Constructor for singleton class
  FunctionFactoryImpl();
  /// Private Destructor
  ~FunctionFactoryImpl() override = default;
  /// These methods shouldn't be used to create functions
  using Kernel::DynamicFactory<IFunction>::create;
  using Kernel::DynamicFactory<IFunction>::createUnwrapped;

  /// Create a simple function
  boost::shared_ptr<IFunction>
  createSimple(const Expression &expr,
               std::map<std::string, std::string> &parentAttributes) const;
  /// Create a composite function
  boost::shared_ptr<CompositeFunction>
  createComposite(const Expression &expr,
                  std::map<std::string, std::string> &parentAttributes) const;

  /// Throw an exception
  void inputError(const std::string &str = "") const;
  /// Add constraints to the created function
  void addConstraints(boost::shared_ptr<IFunction> fun,
                      const Expression &expr) const;
  /// Add a single constraint to the created function
  void addConstraint(boost::shared_ptr<IFunction> fun,
                     const Expression &expr) const;
  /// Add ties to the created function
  void addTies(boost::shared_ptr<IFunction> fun, const Expression &expr) const;
  /// Add a tie to the created function
  void addTie(boost::shared_ptr<IFunction> fun, const Expression &expr) const;

  mutable std::map<std::string, std::vector<std::string>> m_cachedFunctionNames;
  mutable std::mutex m_mutex;
};

/**
 * Query available functions based on the template type
 * @tparam FunctionType :: The type of the functions to list
 * @returns A vector of the names of the functions matching the template type
 */
template <typename FunctionType>
const std::vector<std::string> &FunctionFactoryImpl::getFunctionNames() const {
  std::lock_guard<std::mutex> _lock(m_mutex);

  const std::string soughtType(typeid(FunctionType).name());
  if (m_cachedFunctionNames.find(soughtType) != m_cachedFunctionNames.end()) {
    return m_cachedFunctionNames[soughtType];
  }
  // Create the entry in the cache and work with it directly
  std::vector<std::string> &typeNames = m_cachedFunctionNames[soughtType];
  const std::vector<std::string> names = this->getKeys();
  std::copy_if(names.cbegin(), names.cend(), std::back_inserter(typeNames),
               [this](const std::string &name) {
                 boost::shared_ptr<IFunction> func = this->createFunction(name);
                 return boost::dynamic_pointer_cast<FunctionType>(func);
               });
  return typeNames;
}
typedef Mantid::Kernel::SingletonHolder<FunctionFactoryImpl> FunctionFactory;

/// Convenient typedef for an UpdateNotification
typedef FunctionFactoryImpl::UpdateNotification
    FunctionFactoryUpdateNotification;
/// Convenient typedef for an UpdateNotification AutoPtr
typedef const Poco::AutoPtr<FunctionFactoryUpdateNotification> &
    FunctionFactoryUpdateNotification_ptr;
namespace Mantid {
namespace Kernel {
EXTERN_MANTID_API template class MANTID_API_DLL
    Mantid::Kernel::SingletonHolder<Mantid::API::FunctionFactoryImpl>;
 * Macro for declaring a new type of function to be used with the
 * FunctionFactory
#define DECLARE_FUNCTION(classname)                                            \
  namespace {                                                                  \
  Mantid::Kernel::RegistrationHelper                                           \
      register_function_##classname(((Mantid::API::FunctionFactory::Instance() \
                                          .subscribe<classname>(#classname)),  \
                                     0));                                      \
  }