diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-07-24 17:26:25 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-07-27 23:22:10 +0200 |
commit | 7ae8c8719497ec7556f532bab061d3758976f792 (patch) | |
tree | 8ace2300cebcf6926c7053e3f23a5f68c304ad98 /common/clientapi.h | |
parent | 4430eabdfeddf02c20424508a2a4207b6b4a764e (diff) | |
download | sink-7ae8c8719497ec7556f532bab061d3758976f792.tar.gz sink-7ae8c8719497ec7556f532bab061d3758976f792.zip |
Mode FacadeFactory to separate file, mutex protected it, and loaded
resource
The factory is potentially used from several queries simultaneously,
so it's now mutex protected.
Additionally we try to load the plugins directly in the factory.
Diffstat (limited to 'common/clientapi.h')
-rw-r--r-- | common/clientapi.h | 94 |
1 files changed, 1 insertions, 93 deletions
diff --git a/common/clientapi.h b/common/clientapi.h index 4644ae1..d860305 100644 --- a/common/clientapi.h +++ b/common/clientapi.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "resultprovider.h" | 35 | #include "resultprovider.h" |
36 | #include "domain/applicationdomaintype.h" | 36 | #include "domain/applicationdomaintype.h" |
37 | #include "resourceconfig.h" | 37 | #include "resourceconfig.h" |
38 | #include "facadefactory.h" | ||
38 | #include "log.h" | 39 | #include "log.h" |
39 | 40 | ||
40 | namespace async { | 41 | namespace async { |
@@ -82,98 +83,6 @@ public: | |||
82 | }; | 83 | }; |
83 | 84 | ||
84 | 85 | ||
85 | /** | ||
86 | * Interface for the store facade. | ||
87 | * | ||
88 | * All methods are synchronous. | ||
89 | * Facades are stateful (they hold connections to resources and database). | ||
90 | * | ||
91 | * TODO: would it make sense to split the write, read and notification parts? (we could potentially save some connections) | ||
92 | */ | ||
93 | template<class DomainType> | ||
94 | class StoreFacade { | ||
95 | public: | ||
96 | virtual ~StoreFacade(){}; | ||
97 | QByteArray type() const { return ApplicationDomain::getTypeName<DomainType>(); } | ||
98 | virtual KAsync::Job<void> create(const DomainType &domainObject) = 0; | ||
99 | virtual KAsync::Job<void> modify(const DomainType &domainObject) = 0; | ||
100 | virtual KAsync::Job<void> remove(const DomainType &domainObject) = 0; | ||
101 | virtual KAsync::Job<void> load(const Query &query, const QSharedPointer<ResultProvider<typename DomainType::Ptr> > &resultProvider) = 0; | ||
102 | }; | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Facade factory that returns a store facade implementation, by loading a plugin and providing the relevant implementation. | ||
107 | * | ||
108 | * If we were to provide default implementations for certain capabilities. Here would be the place to do so. | ||
109 | */ | ||
110 | |||
111 | class FacadeFactory { | ||
112 | public: | ||
113 | typedef std::function<std::shared_ptr<void>(const QByteArray &)> FactoryFunction; | ||
114 | |||
115 | void registerStaticFacades(); | ||
116 | |||
117 | //FIXME: proper singleton implementation | ||
118 | static FacadeFactory &instance() | ||
119 | { | ||
120 | static FacadeFactory factory; | ||
121 | return factory; | ||
122 | } | ||
123 | |||
124 | static QByteArray key(const QByteArray &resource, const QByteArray &type) | ||
125 | { | ||
126 | return resource + type; | ||
127 | } | ||
128 | |||
129 | template<class DomainType, class Facade> | ||
130 | void registerFacade(const QByteArray &resource) | ||
131 | { | ||
132 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); | ||
133 | mFacadeRegistry.insert(key(resource, typeName), [](const QByteArray &instanceIdentifier){ return std::make_shared<Facade>(instanceIdentifier); }); | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Allows the registrar to register a specific instance. | ||
138 | * | ||
139 | * Primarily for testing. | ||
140 | */ | ||
141 | template<class DomainType, class Facade> | ||
142 | void registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction) | ||
143 | { | ||
144 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); | ||
145 | mFacadeRegistry.insert(key(resource, typeName), customFactoryFunction); | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Can be used to clear the factory. | ||
150 | * | ||
151 | * Primarily for testing. | ||
152 | */ | ||
153 | void resetFactory() | ||
154 | { | ||
155 | mFacadeRegistry.clear(); | ||
156 | } | ||
157 | |||
158 | template<class DomainType> | ||
159 | std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier) | ||
160 | { | ||
161 | const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>(); | ||
162 | if (auto factoryFunction = mFacadeRegistry.value(key(resource, typeName))) { | ||
163 | return std::static_pointer_cast<StoreFacade<DomainType> >(factoryFunction(instanceIdentifier)); | ||
164 | } | ||
165 | qWarning() << "Failed to find facade for resource: " << resource << " and type: " << typeName; | ||
166 | return std::shared_ptr<StoreFacade<DomainType> >(); | ||
167 | } | ||
168 | |||
169 | private: | ||
170 | FacadeFactory() | ||
171 | { | ||
172 | registerStaticFacades(); | ||
173 | } | ||
174 | |||
175 | QHash<QByteArray, FactoryFunction> mFacadeRegistry; | ||
176 | }; | ||
177 | 86 | ||
178 | /** | 87 | /** |
179 | * Store interface used in the client API. | 88 | * Store interface used in the client API. |
@@ -231,7 +140,6 @@ public: | |||
231 | // Query all resources and aggregate results | 140 | // Query all resources and aggregate results |
232 | KAsync::iterate(getResources(query.resources)) | 141 | KAsync::iterate(getResources(query.resources)) |
233 | .template each<void, QByteArray>([query, resultSet](const QByteArray &resource, KAsync::Future<void> &future) { | 142 | .template each<void, QByteArray>([query, resultSet](const QByteArray &resource, KAsync::Future<void> &future) { |
234 | //TODO pass resource identifier to factory | ||
235 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); | 143 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); |
236 | if (facade) { | 144 | if (facade) { |
237 | facade->load(query, resultSet).template then<void>([&future](){future.setFinished();}).exec(); | 145 | facade->load(query, resultSet).template then<void>([&future](){future.setFinished();}).exec(); |