Mantid
Loading...
Searching...
No Matches
DynamicFactory.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2007 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#pragma once
8
9//----------------------------------------------------------------------
10// Includes
11//----------------------------------------------------------------------
13#include "MantidKernel/DllConfig.h"
17
18// Poco
19#include <Poco/Notification.h>
20#include <Poco/NotificationCenter.h>
21
22// std
23#include <functional>
24#include <iterator>
25#include <memory>
26#include <vector>
27
28namespace Mantid {
29namespace Kernel {
30
31//----------------------------------------------------------------------------
32// Forward declarations
33//----------------------------------------------------------------------------
34class Logger;
35
36using CaseSensitiveStringComparator = std::less<std::string>;
37
47template <class Base, class Comparator = CaseInsensitiveStringComparator> class DynamicFactory {
48
49public:
54 DynamicFactory(const DynamicFactory &) = delete;
56
60 class DynamicFactoryNotification : public Poco::Notification {};
66
71
76
81 virtual ~DynamicFactory() = default;
82
89 virtual std::shared_ptr<Base> create(const std::string &className) const {
90 auto it = _map.find(className);
91 if (it != _map.end())
92 return it->second->createInstance();
93 else
94 throw Exception::NotFoundError("DynamicFactory: " + className + " is not registered.\n", className);
95 }
96
106 virtual Base *createUnwrapped(const std::string &className) const {
107 auto it = _map.find(className);
108 if (it != _map.end())
109 return it->second->createUnwrappedInstance();
110 else
111 throw Exception::NotFoundError("DynamicFactory: " + className + " is not registered.\n", className);
112 }
113
120 template <class C> void subscribe(const std::string &className) {
121 subscribe(className, std::make_unique<Instantiator<C, Base>>());
122 }
123
135 void subscribe(const std::string &className, std::unique_ptr<AbstractFactory> pAbstractFactory,
136 SubscribeAction replace = ErrorIfExists) {
137 if (className.empty()) {
138 throw std::invalid_argument("Cannot register empty class name");
139 }
140
141 auto it = _map.find(className);
142 if (it == _map.end() || replace == OverwriteCurrent) {
143 _map[className] = std::move(pAbstractFactory);
145 } else {
146 throw std::runtime_error(className + " is already registered.\n");
147 }
148 }
149
154 void unsubscribe(const std::string &className) {
155 auto it = _map.find(className);
156 if (!className.empty() && it != _map.end()) {
157 _map.erase(it);
159 } else {
160 throw Exception::NotFoundError("DynamicFactory:" + className + " is not registered.\n", className);
161 }
162 }
163
167 bool exists(const std::string &className) const { return _map.find(className) != _map.end(); }
168
171 virtual const std::vector<std::string> getKeys() const {
172 std::vector<std::string> names;
173 names.reserve(_map.size());
174 std::transform(
175 _map.cbegin(), _map.cend(), std::back_inserter(names),
176 [](const std::pair<const std::string, std::unique_ptr<AbstractFactory>> &mapPair) { return mapPair.first; });
177 return names;
178 }
179
184 Poco::NotificationCenter notificationCenter;
185
186protected:
189
190private:
193 if (m_notifyStatus == Enabled)
195 }
198
200 using FactoryMap = std::map<std::string, std::unique_ptr<AbstractFactory>, Comparator>;
205};
206
207} // namespace Kernel
208} // namespace Mantid
Base class for dynamic factory notifications.
A notification that the factory has been updated.
The dynamic factory is a base dynamic factory for serving up objects in response to requests from oth...
FactoryMap _map
The map holding the registered class names and their instantiators.
virtual Base * createUnwrapped(const std::string &className) const
Creates a new instance of the class with the given name, which is not wrapped in a boost shared_ptr.
std::map< std::string, std::unique_ptr< AbstractFactory >, Comparator > FactoryMap
A typedef for the map of registered classes.
DynamicFactory(const DynamicFactory &)=delete
void subscribe(const std::string &className)
Registers the instantiator for the given class with the DynamicFactory.
DynamicFactory & operator=(const DynamicFactory &)=delete
void unsubscribe(const std::string &className)
Unregisters the given class and deletes the instantiator for the class.
virtual std::shared_ptr< Base > create(const std::string &className) const
Creates a new instance of the class with the given name.
DynamicFactory()
Protected constructor for base class.
virtual const std::vector< std::string > getKeys() const
Returns the keys in the map.
void sendUpdateNotificationIfEnabled()
Send an update notification if they are enabled.
NotificationStatus
Defines the whether notifications are dispatched.
virtual ~DynamicFactory()=default
Destroys the DynamicFactory and deletes the instantiators for all registered classes.
NotificationStatus m_notifyStatus
Flag marking whether we should dispatch notifications.
SubscribeAction
Defines replacement behaviour.
void sendUpdateNotification()
Send an update notification.
bool exists(const std::string &className) const
Returns true if the given class is currently registered.
void subscribe(const std::string &className, std::unique_ptr< AbstractFactory > pAbstractFactory, SubscribeAction replace=ErrorIfExists)
Registers the instantiator for the given class with the DynamicFactory.
void enableNotifications()
Enable notifications.
Poco::NotificationCenter notificationCenter
Sends notifications to observers.
void disableNotifications()
Disable notifications.
Exception for when an item is not found in a collection.
Definition: Exception.h:145
The instantiator is a generic class for creating objects of the template type.
Definition: Instantiator.h:54
std::less< std::string > CaseSensitiveStringComparator
Helper class which provides the Collimation Length for SANS instruments.