summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}