summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2015-07-24 17:26:25 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2015-07-27 23:22:10 +0200
commit7ae8c8719497ec7556f532bab061d3758976f792 (patch)
tree8ace2300cebcf6926c7053e3f23a5f68c304ad98
parent4430eabdfeddf02c20424508a2a4207b6b4a764e (diff)
downloadsink-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.
-rw-r--r--common/CMakeLists.txt1
-rw-r--r--common/clientapi.cpp6
-rw-r--r--common/clientapi.h94
-rw-r--r--common/facadefactory.cpp79
-rw-r--r--common/facadefactory.h91
-rw-r--r--common/facadeinterface.h51
6 files changed, 224 insertions, 98 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 56ae59b..a69c62c 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -14,6 +14,7 @@ set(command_SRCS
14 log.cpp 14 log.cpp
15 entitybuffer.cpp 15 entitybuffer.cpp
16 clientapi.cpp 16 clientapi.cpp
17 facadefactory.cpp
17 commands.cpp 18 commands.cpp
18 facade.cpp 19 facade.cpp
19 pipeline.cpp 20 pipeline.cpp
diff --git a/common/clientapi.cpp b/common/clientapi.cpp
index c19ea4f..a98340c 100644
--- a/common/clientapi.cpp
+++ b/common/clientapi.cpp
@@ -28,13 +28,9 @@ namespace async
28 }; 28 };
29} // namespace async 29} // namespace async
30 30
31namespace Akonadi2
32{
33 31
34void FacadeFactory::registerStaticFacades() 32namespace Akonadi2
35{ 33{
36 registerFacade<Akonadi2::ApplicationDomain::AkonadiResource, ResourceFacade>("resourceconfig");
37}
38 34
39void Store::shutdown(const QByteArray &identifier) 35void Store::shutdown(const QByteArray &identifier)
40{ 36{
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
40namespace async { 41namespace 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 */
93template<class DomainType>
94class StoreFacade {
95public:
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
111class FacadeFactory {
112public:
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
169private:
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();
diff --git a/common/facadefactory.cpp b/common/facadefactory.cpp
new file mode 100644
index 0000000..f833b06
--- /dev/null
+++ b/common/facadefactory.cpp
@@ -0,0 +1,79 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20#include "facadefactory.h"
21
22#include "resourcefacade.h"
23#include "resource.h"
24
25using namespace Akonadi2;
26
27QMutex FacadeFactory::sMutex;
28
29FacadeFactory::FacadeFactory()
30{
31 registerStaticFacades();
32}
33
34FacadeFactory &FacadeFactory::instance()
35{
36 QMutexLocker locker(&sMutex);
37 static FacadeFactory *instance = 0;
38 if (!instance) {
39 instance = new FacadeFactory;
40 }
41 return *instance;
42}
43
44QByteArray FacadeFactory::key(const QByteArray &resource, const QByteArray &type)
45{
46 return resource + type;
47}
48
49void FacadeFactory::resetFactory()
50{
51 QMutexLocker locker(&sMutex);
52 mFacadeRegistry.clear();
53}
54
55void FacadeFactory::registerStaticFacades()
56{
57 registerFacade<Akonadi2::ApplicationDomain::AkonadiResource, ResourceFacade>("resourceconfig");
58}
59
60std::shared_ptr<void> FacadeFactory::getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier, const QByteArray &typeName)
61{
62 QMutexLocker locker(&sMutex);
63
64 const QByteArray k = key(resource, typeName);
65 if (!mFacadeRegistry.contains(k)) {
66 Akonadi2::ResourceFactory::load(QString::fromLatin1(resource));
67 }
68
69 if (auto factoryFunction = mFacadeRegistry.value(k)) {
70 return factoryFunction(instanceIdentifier);
71 }
72 qWarning() << "Failed to find facade for resource: " << resource << " and type: " << typeName;
73 return std::shared_ptr<void>();
74}
75
76void FacadeFactory::registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction, const QByteArray typeName)
77{
78 mFacadeRegistry.insert(key(resource, typeName), customFactoryFunction);
79}
diff --git a/common/facadefactory.h b/common/facadefactory.h
new file mode 100644
index 0000000..4a6a698
--- /dev/null
+++ b/common/facadefactory.h
@@ -0,0 +1,91 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#pragma once
22
23#include <QByteArray>
24#include <QDebug>
25#include <QMutex>
26#include <functional>
27#include <memory>
28
29#include "facadeinterface.h"
30#include "domain/applicationdomaintype.h"
31#include "log.h"
32
33namespace Akonadi2 {
34
35/**
36 * Facade factory that returns a store facade implementation, by loading a plugin and providing the relevant implementation.
37 *
38 * If we were to provide default implementations for certain capabilities. Here would be the place to do so.
39 */
40class FacadeFactory {
41public:
42 typedef std::function<std::shared_ptr<void>(const QByteArray &)> FactoryFunction;
43
44 void registerStaticFacades();
45
46 static FacadeFactory &instance();
47
48 static QByteArray key(const QByteArray &resource, const QByteArray &type);
49
50 template<class DomainType, class Facade>
51 void registerFacade(const QByteArray &resource)
52 {
53 registerFacade(resource, [](const QByteArray &instanceIdentifier){ return std::make_shared<Facade>(instanceIdentifier); }, ApplicationDomain::getTypeName<DomainType>());
54 }
55
56 /*
57 * Allows the registrar to register a specific instance.
58 *
59 * Primarily for testing.
60 */
61 template<class DomainType, class Facade>
62 void registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction)
63 {
64 registerFacade(resource, customFactoryFunction, ApplicationDomain::getTypeName<DomainType>());
65 }
66
67 /*
68 * Can be used to clear the factory.
69 *
70 * Primarily for testing.
71 */
72 void resetFactory();
73
74 template<class DomainType>
75 std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier)
76 {
77 const QByteArray typeName = ApplicationDomain::getTypeName<DomainType>();
78 return std::static_pointer_cast<StoreFacade<DomainType> >(getFacade(resource, instanceIdentifier, typeName));
79 }
80
81private:
82 FacadeFactory();
83 std::shared_ptr<void> getFacade(const QByteArray &resource, const QByteArray &instanceIdentifier, const QByteArray &typeName);
84 void registerFacade(const QByteArray &resource, const FactoryFunction &customFactoryFunction, const QByteArray typeName);
85
86 QHash<QByteArray, FactoryFunction> mFacadeRegistry;
87 static QMutex sMutex;
88};
89
90}
91
diff --git a/common/facadeinterface.h b/common/facadeinterface.h
new file mode 100644
index 0000000..a88c104
--- /dev/null
+++ b/common/facadeinterface.h
@@ -0,0 +1,51 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#pragma once
22
23#include <Async/Async>
24#include <QByteArray>
25#include <QSharedPointer>
26#include "domain/applicationdomaintype.h"
27#include "resultprovider.h"
28
29namespace Akonadi2 {
30class Query;
31
32/**
33 * Interface for the store facade.
34 *
35 * All methods are synchronous.
36 * Facades are stateful (they hold connections to resources and database).
37 *
38 * TODO: would it make sense to split the write, read and notification parts? (we could potentially save some connections)
39 */
40template<class DomainType>
41class StoreFacade {
42public:
43 virtual ~StoreFacade(){};
44 QByteArray type() const { return ApplicationDomain::getTypeName<DomainType>(); }
45 virtual KAsync::Job<void> create(const DomainType &domainObject) = 0;
46 virtual KAsync::Job<void> modify(const DomainType &domainObject) = 0;
47 virtual KAsync::Job<void> remove(const DomainType &domainObject) = 0;
48 virtual KAsync::Job<void> load(const Query &query, const QSharedPointer<async::ResultProvider<typename DomainType::Ptr> > &resultProvider) = 0;
49};
50
51}