Akonadi

collectioncreatehandler.cpp
1/***************************************************************************
2 * SPDX-FileCopyrightText: 2006 Ingo Kloecker <kloecker@kde.org> *
3 * *
4 * SPDX-License-Identifier: LGPL-2.0-or-later *
5 ***************************************************************************/
6#include "collectioncreatehandler.h"
7
8#include "connection.h"
9#include "handlerhelper.h"
10#include "shared/akranges.h"
11#include "storage/datastore.h"
12#include "storage/selectquerybuilder.h"
13#include "storage/transaction.h"
14
15#include "private/scope_p.h"
16
17using namespace Akonadi;
18using namespace Akonadi::Server;
19using namespace AkRanges;
20
21namespace
22{
23
24[[nodiscard]] bool isTopLevelCollection(const Scope &scope)
25{
26 return scope.scope() == Scope::Uid && scope.uidSet().size() == 1 && scope.uid() == 0;
27}
28
29} // namespace
30
31CollectionCreateHandler::CollectionCreateHandler(AkonadiServer &akonadi)
32 : Handler(akonadi)
33{
34}
35
36bool CollectionCreateHandler::parseStream()
37{
38 const auto &cmd = Protocol::cmdCast<Protocol::CreateCollectionCommand>(m_command);
39
40 if (cmd.name().isEmpty()) {
41 return failureResponse(QStringLiteral("Invalid collection name"));
42 }
43
44 Collection parent;
45 qint64 resourceId = 0;
46 bool forceVirtual = false;
47 MimeType::List parentContentTypes;
48
49 // Invalid or empty scope means we refer to root collection
50 if (!isTopLevelCollection(cmd.parent())) {
51 parent = HandlerHelper::collectionFromScope(cmd.parent(), connection()->context());
52 if (!parent.isValid()) {
53 return failureResponse(QStringLiteral("Invalid parent collection"));
54 }
55
56 // check if parent can contain a sub-folder
57 parentContentTypes = parent.mimeTypes();
58 const auto hasMimeType = [](const QString &mimeType) {
59 return [mimeType](const MimeType &mt) {
60 return mt.name() == mimeType;
61 };
62 };
63 const bool canContainCollections = parentContentTypes | Actions::any(hasMimeType(CollectionMimeType));
64 const bool canContainVirtualCollections = parentContentTypes | Actions::any(hasMimeType(VirtualCollectionMimeType));
65
66 if (!canContainCollections && !canContainVirtualCollections) {
67 return failureResponse(QStringLiteral("Parent collection can not contain sub-collections"));
68 }
69
70 // If only virtual collections are supported, force every new collection to
71 // be virtual. Otherwise depend on VIRTUAL attribute in the command
72 if (canContainVirtualCollections && !canContainCollections) {
73 forceVirtual = true;
74 }
75
76 // inherit resource
77 resourceId = parent.resourceId();
78 } else {
79 const QString sessionId = QString::fromUtf8(connection()->sessionId());
80 Resource res = Resource::retrieveByName(sessionId);
81 if (!res.isValid()) {
82 return failureResponse(QStringLiteral("Cannot create top-level collection"));
83 }
84 resourceId = res.id();
85 }
86
87 Collection collection;
88 if (parent.isValid()) {
89 collection.setParentId(parent.id());
90 }
91 collection.setName(cmd.name());
92 collection.setResourceId(resourceId);
93 collection.setRemoteId(cmd.remoteId());
94 collection.setRemoteRevision(cmd.remoteRevision());
95 collection.setIsVirtual(cmd.isVirtual() || forceVirtual);
96 collection.setEnabled(cmd.enabled());
97 collection.setSyncPref(static_cast<Collection::Tristate>(cmd.syncPref()));
98 collection.setDisplayPref(static_cast<Collection::Tristate>(cmd.displayPref()));
99 collection.setIndexPref(static_cast<Collection::Tristate>(cmd.indexPref()));
100 const Protocol::CachePolicy &cp = cmd.cachePolicy();
101 collection.setCachePolicyCacheTimeout(cp.cacheTimeout());
102 collection.setCachePolicyCheckInterval(cp.checkInterval());
103 collection.setCachePolicyInherit(cp.inherit());
104 collection.setCachePolicyLocalParts(cp.localParts().join(QLatin1Char(' ')));
105 collection.setCachePolicySyncOnDemand(cp.syncOnDemand());
106
107 DataStore *db = connection()->storageBackend();
108 Transaction transaction(db, QStringLiteral("CREATE"));
109
110 QStringList effectiveMimeTypes = cmd.mimeTypes();
111 if (effectiveMimeTypes.isEmpty()) {
112 effectiveMimeTypes = parentContentTypes | Views::transform(&MimeType::name) | Actions::toQList;
113 }
114
115 if (!db->appendCollection(collection, effectiveMimeTypes, cmd.attributes())) {
116 return failureResponse(QStringLiteral("Could not create collection %1, resourceId %2").arg(cmd.name()).arg(resourceId));
117 }
118
119 if (!transaction.commit()) {
120 return failureResponse(QStringLiteral("Unable to commit transaction."));
121 }
122
123 db->activeCachePolicy(collection);
124
125 sendResponse<Protocol::FetchCollectionsResponse>(HandlerHelper::fetchCollectionsResponse(akonadi(), collection));
126
127 return successResponse<Protocol::CreateCollectionResponse>();
128}
Represents a collection of PIM items.
Definition collection.h:62
void setName(const QString &name)
Sets the i18n'ed name of the collection.
CachePolicy cachePolicy() const
Returns the cache policy of the collection.
void setRemoteId(const QString &id)
Sets the remote id of the collection.
void setEnabled(bool enabled)
Sets the collection's enabled state.
void setRemoteRevision(const QString &revision)
Sets the remote revision of the collection.
This class handles all the database access.
Definition datastore.h:95
virtual void activeCachePolicy(Collection &col)
Determines the active cache policy for this Collection.
static Protocol::FetchCollectionsResponse fetchCollectionsResponse(AkonadiServer &akonadi, const Collection &col)
Returns the protocol representation of the given collection.
The handler interfaces describes an entity capable of handling an AkonadiIMAP command.
Definition handler.h:32
Helper class for DataStore transaction handling.
Definition transaction.h:23
Helper integration between Akonadi and Qt.
KCALUTILS_EXPORT QString mimeType()
bool isEmpty() const const
T qobject_cast(QObject *object)
QString fromUtf8(QByteArrayView str)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:38 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.