Akonadi

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

KDE's Doxygen guidelines are available online.