1//
2// DynamicFactory.h
3//
4// Library: Foundation
5// Package: Core
6// Module: DynamicFactory
7//
8// Definition of the DynamicFactory class.
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_DynamicFactory_INCLUDED
18#define Foundation_DynamicFactory_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/Instantiator.h"
23#include "Poco/AutoPtr.h"
24#include "Poco/Exception.h"
25#include "Poco/Mutex.h"
26#include <map>
27#include <memory>
28
29
30namespace Poco {
31
32
33template <class BaseT, class PtrT = AutoPtr<BaseT> >
34class DynamicFactory
35 /// A factory that creates objects by class name.
36{
37public:
38 typedef AbstractInstantiator<BaseT> AbstractFactory;
39 typedef PtrT Ptr;
40
41 DynamicFactory()
42 /// Creates the DynamicFactory.
43 {
44 }
45
46 ~DynamicFactory()
47 /// Destroys the DynamicFactory and deletes the instantiators for
48 /// all registered classes.
49 {
50 for (typename FactoryMap::iterator it = _map.begin(); it != _map.end(); ++it)
51 {
52 delete it->second;
53 }
54 }
55
56 Ptr createInstance(const std::string& className) const
57 /// Creates a new instance of the class with the given name.
58 /// The class must have been registered with registerClass.
59 /// If the class name is unknown, a NotFoundException is thrown.
60 {
61 FastMutex::ScopedLock lock(_mutex);
62
63 typename FactoryMap::const_iterator it = _map.find(className);
64 if (it != _map.end())
65 return it->second->createInstance();
66 else
67 throw NotFoundException(className);
68 }
69
70 template <class C>
71 void registerClass(const std::string& className)
72 /// Registers the instantiator for the given class with the DynamicFactory.
73 /// The DynamicFactory takes ownership of the instantiator and deletes
74 /// it when it's no longer used.
75 /// If the class has already been registered, an ExistsException is thrown
76 /// and the instantiator is deleted.
77 {
78 registerClass(className, new Instantiator<C, BaseT>);
79 }
80
81 void registerClass(const std::string& className, AbstractFactory* pAbstractFactory)
82 /// Registers the instantiator for the given class with the DynamicFactory.
83 /// The DynamicFactory takes ownership of the instantiator and deletes
84 /// it when it's no longer used.
85 /// If the class has already been registered, an ExistsException is thrown
86 /// and the instantiator is deleted.
87 {
88 poco_check_ptr (pAbstractFactory);
89
90 FastMutex::ScopedLock lock(_mutex);
91
92 std::unique_ptr<AbstractFactory> ptr(pAbstractFactory);
93 typename FactoryMap::iterator it = _map.find(className);
94 if (it == _map.end())
95 _map[className] = ptr.release();
96 else
97 throw ExistsException(className);
98 }
99
100 void unregisterClass(const std::string& className)
101 /// Unregisters the given class and deletes the instantiator
102 /// for the class.
103 /// Throws a NotFoundException if the class has not been registered.
104 {
105 FastMutex::ScopedLock lock(_mutex);
106
107 typename FactoryMap::iterator it = _map.find(className);
108 if (it != _map.end())
109 {
110 delete it->second;
111 _map.erase(it);
112 }
113 else throw NotFoundException(className);
114 }
115
116 bool isClass(const std::string& className) const
117 /// Returns true iff the given class has been registered.
118 {
119 FastMutex::ScopedLock lock(_mutex);
120
121 return _map.find(className) != _map.end();
122 }
123
124private:
125 DynamicFactory(const DynamicFactory&);
126 DynamicFactory& operator = (const DynamicFactory&);
127
128 typedef std::map<std::string, AbstractFactory*> FactoryMap;
129
130 FactoryMap _map;
131 mutable FastMutex _mutex;
132};
133
134
135} // namespace Poco
136
137
138#endif // Foundation_DynamicFactory_INCLUDED
139