diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-07-08 09:19:43 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-07-08 09:19:43 +0200 |
commit | 228a3380328535f30fcb187cae7db2415ec2d314 (patch) | |
tree | c5aff9f889ac41aa5f79bd5d144f2c94a8298edc | |
parent | 12a87e1d6d5c0e4b5a5aacbfa880678629321c1d (diff) | |
download | sink-228a3380328535f30fcb187cae7db2415ec2d314.tar.gz sink-228a3380328535f30fcb187cae7db2415ec2d314.zip |
We can add resources.
-rw-r--r-- | common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | common/clientapi.cpp | 6 | ||||
-rw-r--r-- | common/clientapi.h | 19 | ||||
-rw-r--r-- | common/resourcefacade.cpp | 94 | ||||
-rw-r--r-- | common/resourcefacade.h | 34 | ||||
-rw-r--r-- | tests/clientapitest.cpp | 18 |
6 files changed, 168 insertions, 4 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 9e30752..58c7ea0 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt | |||
@@ -26,6 +26,7 @@ set(command_SRCS | |||
26 | threadboundary.cpp | 26 | threadboundary.cpp |
27 | messagequeue.cpp | 27 | messagequeue.cpp |
28 | index.cpp | 28 | index.cpp |
29 | resourcefacade.cpp | ||
29 | domain/applicationdomaintype.cpp | 30 | domain/applicationdomaintype.cpp |
30 | domain/event.cpp | 31 | domain/event.cpp |
31 | ${storage_SRCS}) | 32 | ${storage_SRCS}) |
diff --git a/common/clientapi.cpp b/common/clientapi.cpp index 2f8763f..88349db 100644 --- a/common/clientapi.cpp +++ b/common/clientapi.cpp | |||
@@ -2,6 +2,7 @@ | |||
2 | #include "clientapi.h" | 2 | #include "clientapi.h" |
3 | #include "resourceaccess.h" | 3 | #include "resourceaccess.h" |
4 | #include "commands.h" | 4 | #include "commands.h" |
5 | #include "resourcefacade.h" | ||
5 | #include "log.h" | 6 | #include "log.h" |
6 | #include <QtConcurrent/QtConcurrentRun> | 7 | #include <QtConcurrent/QtConcurrentRun> |
7 | 8 | ||
@@ -16,6 +17,11 @@ namespace async | |||
16 | namespace Akonadi2 | 17 | namespace Akonadi2 |
17 | { | 18 | { |
18 | 19 | ||
20 | void FacadeFactory::registerStaticFacades() | ||
21 | { | ||
22 | FacadeFactory::instance().registerFacade<Akonadi2::ApplicationDomain::AkonadiResource, ResourceFacade>("resourceconfig"); | ||
23 | } | ||
24 | |||
19 | void Store::shutdown(const QByteArray &identifier) | 25 | void Store::shutdown(const QByteArray &identifier) |
20 | { | 26 | { |
21 | Trace() << "shutdown"; | 27 | Trace() << "shutdown"; |
diff --git a/common/clientapi.h b/common/clientapi.h index 2d926fd..d658003 100644 --- a/common/clientapi.h +++ b/common/clientapi.h | |||
@@ -110,6 +110,8 @@ class FacadeFactory { | |||
110 | public: | 110 | public: |
111 | typedef std::function<std::shared_ptr<void>(const QByteArray &)> FactoryFunction; | 111 | typedef std::function<std::shared_ptr<void>(const QByteArray &)> FactoryFunction; |
112 | 112 | ||
113 | static void registerStaticFacades(); | ||
114 | |||
113 | //FIXME: proper singleton implementation | 115 | //FIXME: proper singleton implementation |
114 | static FacadeFactory &instance() | 116 | static FacadeFactory &instance() |
115 | { | 117 | { |
@@ -179,6 +181,9 @@ public: | |||
179 | static QByteArray resourceName(const QByteArray &instanceIdentifier) | 181 | static QByteArray resourceName(const QByteArray &instanceIdentifier) |
180 | { | 182 | { |
181 | auto split = instanceIdentifier.split('.'); | 183 | auto split = instanceIdentifier.split('.'); |
184 | if (split.size() <= 1) { | ||
185 | return instanceIdentifier; | ||
186 | } | ||
182 | split.removeLast(); | 187 | split.removeLast(); |
183 | return split.join('.'); | 188 | return split.join('.'); |
184 | } | 189 | } |
@@ -195,6 +200,7 @@ public: | |||
195 | //We must guarantee that the emitter is returned before the first result is emitted. | 200 | //We must guarantee that the emitter is returned before the first result is emitted. |
196 | //The result provider must be threadsafe. | 201 | //The result provider must be threadsafe. |
197 | async::run([query, resultSet](){ | 202 | async::run([query, resultSet](){ |
203 | //TODO if query.resources is empty, search for all resource that provide the type we're looking for | ||
198 | // Query all resources and aggregate results | 204 | // Query all resources and aggregate results |
199 | KAsync::iterate(query.resources) | 205 | KAsync::iterate(query.resources) |
200 | .template each<void, QByteArray>([query, resultSet](const QByteArray &resource, KAsync::Future<void> &future) { | 206 | .template each<void, QByteArray>([query, resultSet](const QByteArray &resource, KAsync::Future<void> &future) { |
@@ -205,7 +211,6 @@ public: | |||
205 | //Keep the facade alive for the lifetime of the resultSet. | 211 | //Keep the facade alive for the lifetime of the resultSet. |
206 | resultSet->setFacade(facade); | 212 | resultSet->setFacade(facade); |
207 | } else { | 213 | } else { |
208 | qWarning() << "Could not find facade for resource " << resource; | ||
209 | //Ignore the error and carry on | 214 | //Ignore the error and carry on |
210 | future.setFinished(); | 215 | future.setFinished(); |
211 | } | 216 | } |
@@ -245,7 +250,9 @@ public: | |||
245 | static void create(const DomainType &domainObject, const QByteArray &resourceIdentifier) { | 250 | static void create(const DomainType &domainObject, const QByteArray &resourceIdentifier) { |
246 | //Potentially move to separate thread as well | 251 | //Potentially move to separate thread as well |
247 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceIdentifier), resourceIdentifier); | 252 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceIdentifier), resourceIdentifier); |
248 | facade->create(domainObject).exec().waitForFinished(); | 253 | if (facade) { |
254 | facade->create(domainObject).exec().waitForFinished(); | ||
255 | } | ||
249 | //TODO return job? | 256 | //TODO return job? |
250 | } | 257 | } |
251 | 258 | ||
@@ -258,7 +265,9 @@ public: | |||
258 | static void modify(const DomainType &domainObject, const QByteArray &resourceIdentifier) { | 265 | static void modify(const DomainType &domainObject, const QByteArray &resourceIdentifier) { |
259 | //Potentially move to separate thread as well | 266 | //Potentially move to separate thread as well |
260 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceIdentifier), resourceIdentifier); | 267 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceIdentifier), resourceIdentifier); |
261 | facade->modify(domainObject).exec().waitForFinished(); | 268 | if (facade) { |
269 | facade->modify(domainObject).exec().waitForFinished(); | ||
270 | } | ||
262 | //TODO return job? | 271 | //TODO return job? |
263 | } | 272 | } |
264 | 273 | ||
@@ -269,7 +278,9 @@ public: | |||
269 | static void remove(const DomainType &domainObject, const QByteArray &resourceIdentifier) { | 278 | static void remove(const DomainType &domainObject, const QByteArray &resourceIdentifier) { |
270 | //Potentially move to separate thread as well | 279 | //Potentially move to separate thread as well |
271 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceIdentifier), resourceIdentifier); | 280 | auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceIdentifier), resourceIdentifier); |
272 | facade->remove(domainObject).exec().waitForFinished(); | 281 | if (facade) { |
282 | facade->remove(domainObject).exec().waitForFinished(); | ||
283 | } | ||
273 | //TODO return job? | 284 | //TODO return job? |
274 | } | 285 | } |
275 | 286 | ||
diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp new file mode 100644 index 0000000..2c6eabc --- /dev/null +++ b/common/resourcefacade.cpp | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | #include "resourcefacade.h" | ||
20 | |||
21 | #include <QSettings> | ||
22 | #include <QStandardPaths> | ||
23 | |||
24 | ResourceFacade::ResourceFacade(const QByteArray &) | ||
25 | : Akonadi2::StoreFacade<Akonadi2::ApplicationDomain::AkonadiResource>() | ||
26 | { | ||
27 | |||
28 | } | ||
29 | |||
30 | ResourceFacade::~ResourceFacade() | ||
31 | { | ||
32 | |||
33 | } | ||
34 | |||
35 | static QSharedPointer<QSettings> getSettings() | ||
36 | { | ||
37 | return QSharedPointer<QSettings>::create(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/akonadi2/resources.ini", QSettings::IniFormat); | ||
38 | } | ||
39 | |||
40 | KAsync::Job<void> ResourceFacade::create(const Akonadi2::ApplicationDomain::AkonadiResource &resource) | ||
41 | { | ||
42 | return KAsync::start<void>([resource, this]() { | ||
43 | auto settings = getSettings(); | ||
44 | const QByteArray identifier = resource.getProperty("identifier").toByteArray(); | ||
45 | const QByteArray type = resource.getProperty("type").toByteArray(); | ||
46 | |||
47 | settings->beginGroup("resources"); | ||
48 | settings->setValue(identifier, type); | ||
49 | settings->endGroup(); | ||
50 | settings->beginGroup(identifier); | ||
51 | //Add some settings? | ||
52 | settings->endGroup(); | ||
53 | settings->sync(); | ||
54 | }); | ||
55 | } | ||
56 | |||
57 | KAsync::Job<void> ResourceFacade::modify(const Akonadi2::ApplicationDomain::AkonadiResource &resource) | ||
58 | { | ||
59 | return KAsync::null<void>(); | ||
60 | } | ||
61 | |||
62 | KAsync::Job<void> ResourceFacade::remove(const Akonadi2::ApplicationDomain::AkonadiResource &resource) | ||
63 | { | ||
64 | return KAsync::start<void>([resource, this]() { | ||
65 | auto settings = getSettings(); | ||
66 | const QByteArray identifier = resource.getProperty("identifier").toByteArray(); | ||
67 | |||
68 | settings->beginGroup("resources"); | ||
69 | settings->remove(identifier); | ||
70 | settings->endGroup(); | ||
71 | settings->sync(); | ||
72 | }); | ||
73 | } | ||
74 | |||
75 | KAsync::Job<void> ResourceFacade::load(const Akonadi2::Query &query, const QSharedPointer<Akonadi2::ResultProvider<typename Akonadi2::ApplicationDomain::AkonadiResource::Ptr> > &resultProvider) | ||
76 | { | ||
77 | return KAsync::start<void>([query, resultProvider]() { | ||
78 | auto settings = getSettings(); | ||
79 | settings->beginGroup("resources"); | ||
80 | for (const auto &identifier : settings->childKeys()) { | ||
81 | const auto type = settings->value(identifier).toByteArray(); | ||
82 | auto resource = Akonadi2::ApplicationDomain::AkonadiResource::Ptr::create(); | ||
83 | resource->setProperty("identifier", identifier); | ||
84 | resource->setProperty("type", type); | ||
85 | resultProvider->add(resource); | ||
86 | } | ||
87 | settings->endGroup(); | ||
88 | |||
89 | //TODO initialResultSetComplete should be implicit | ||
90 | resultProvider->initialResultSetComplete(); | ||
91 | resultProvider->complete(); | ||
92 | }); | ||
93 | } | ||
94 | |||
diff --git a/common/resourcefacade.h b/common/resourcefacade.h new file mode 100644 index 0000000..2b36f21 --- /dev/null +++ b/common/resourcefacade.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | #pragma once | ||
21 | |||
22 | #include "common/clientapi.h" | ||
23 | #include "common/resultprovider.h" | ||
24 | |||
25 | class ResourceFacade : public Akonadi2::StoreFacade<Akonadi2::ApplicationDomain::AkonadiResource> | ||
26 | { | ||
27 | public: | ||
28 | ResourceFacade(const QByteArray &instanceIdentifier); | ||
29 | virtual ~ResourceFacade(); | ||
30 | KAsync::Job<void> create(const Akonadi2::ApplicationDomain::AkonadiResource &resource) Q_DECL_OVERRIDE; | ||
31 | KAsync::Job<void> modify(const Akonadi2::ApplicationDomain::AkonadiResource &resource) Q_DECL_OVERRIDE; | ||
32 | KAsync::Job<void> remove(const Akonadi2::ApplicationDomain::AkonadiResource &resource) Q_DECL_OVERRIDE; | ||
33 | KAsync::Job<void> load(const Akonadi2::Query &query, const QSharedPointer<Akonadi2::ResultProvider<typename Akonadi2::ApplicationDomain::AkonadiResource::Ptr> > &resultProvider) Q_DECL_OVERRIDE; | ||
34 | }; | ||
diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp index a874dd7..e7db0d0 100644 --- a/tests/clientapitest.cpp +++ b/tests/clientapitest.cpp | |||
@@ -174,6 +174,24 @@ private Q_SLOTS: | |||
174 | QTRY_VERIFY(!facade->capturedResultProvider); | 174 | QTRY_VERIFY(!facade->capturedResultProvider); |
175 | } | 175 | } |
176 | 176 | ||
177 | void resourceManagement() | ||
178 | { | ||
179 | Akonadi2::FacadeFactory::registerStaticFacades(); | ||
180 | Akonadi2::ApplicationDomain::AkonadiResource res; | ||
181 | res.setProperty("identifier", "identifier1"); | ||
182 | res.setProperty("type", "dummyresource"); | ||
183 | |||
184 | Akonadi2::Store::create(res, "resourceconfig"); | ||
185 | |||
186 | { | ||
187 | Akonadi2::Query query; | ||
188 | query.resources << "resourceconfig"; | ||
189 | async::SyncListResult<Akonadi2::ApplicationDomain::AkonadiResource::Ptr> result(Akonadi2::Store::load<Akonadi2::ApplicationDomain::AkonadiResource>(query)); | ||
190 | result.exec(); | ||
191 | QCOMPARE(result.size(), 1); | ||
192 | } | ||
193 | } | ||
194 | |||
177 | }; | 195 | }; |
178 | 196 | ||
179 | QTEST_MAIN(ClientAPITest) | 197 | QTEST_MAIN(ClientAPITest) |