7#include "tagmodifyhandler.h"
10#include "shared/akranges.h"
11#include "storage/datastore.h"
12#include "storage/querybuilder.h"
13#include "tagfetchhelper.h"
16using namespace Akonadi::Server;
17using namespace AkRanges;
19TagModifyHandler::TagModifyHandler(AkonadiServer &akonadi)
24bool TagModifyHandler::parseStream()
26 const auto &cmd = Protocol::cmdCast<Protocol::ModifyTagCommand>(m_command);
28 Tag changedTag = Tag::retrieveById(cmd.tagId());
29 if (!changedTag.isValid()) {
30 return failureResponse(
"No such tag");
33 QSet<QByteArray> changes;
36 const TagAttribute::List attributes = TagAttribute::retrieveFiltered(TagAttribute::tagIdFullColumnName(), cmd.tagId());
37 const auto attributesMap = attributes | Views::transform([](
const auto &attr) {
38 return std::make_pair(attr.type(), attr);
42 if (cmd.modifiedParts() & Protocol::ModifyTagCommand::ParentId) {
43 if (cmd.parentId() != changedTag.parentId()) {
44 changedTag.setParentId(cmd.parentId());
45 changes << AKONADI_PARAM_PARENT;
49 if (cmd.modifiedParts() & Protocol::ModifyTagCommand::Type) {
50 TagType
type = TagType::retrieveById(changedTag.typeId());
52 if (newTypeName !=
type.name()) {
53 const TagType newType = TagType::retrieveByNameOrCreate(newTypeName);
54 if (!newType.isValid()) {
55 return failureResponse(
"Failed to create new tag type");
57 changedTag.setTagType(newType);
58 changes << AKONADI_PARAM_MIMETYPE;
62 bool tagRemoved =
false;
63 if (cmd.modifiedParts() & Protocol::ModifyTagCommand::RemoteId) {
64 if (!connection()->context().resource().
isValid()) {
65 return failureResponse(
"Only resources can change tag remote ID");
69 QueryBuilder qb(TagRemoteIdResourceRelation::tableName(), QueryBuilder::Delete);
70 qb.addValueCondition(TagRemoteIdResourceRelation::tagIdColumn(), Query::Equals, cmd.tagId());
71 qb.addValueCondition(TagRemoteIdResourceRelation::resourceIdColumn(), Query::Equals, connection()->context().resource().
id());
74 if (!cmd.remoteId().isEmpty()) {
75 TagRemoteIdResourceRelation remoteIdRelation;
77 remoteIdRelation.setResourceId(connection()->context().resource().
id());
78 remoteIdRelation.setTag(changedTag);
79 if (!remoteIdRelation.insert()) {
80 return failureResponse(
"Failed to insert remotedid resource relation");
83 const int tagRidsCount = TagRemoteIdResourceRelation::count(TagRemoteIdResourceRelation::tagIdColumn(), changedTag.
id());
87 if (tagRidsCount == 0) {
88 if (!storageBackend()->removeTags(Tag::List() << changedTag)) {
89 return failureResponse(
"Failed to remove tag");
98 if (cmd.modifiedParts() & Protocol::ModifyTagCommand::RemovedAttributes) {
99 const auto attrNames = cmd.removedAttributes();
100 for (
const QByteArray &attrName : attrNames) {
101 TagAttribute attribute = attributesMap.value(attrName);
102 TagAttribute::remove(attribute.id());
107 if (cmd.modifiedParts() & Protocol::ModifyTagCommand::Attributes) {
108 const QMap<QByteArray, QByteArray> attrs = cmd.attributes();
109 for (
auto iter = attrs.
cbegin(), end = attrs.
cend(); iter != end; ++iter) {
110 if (attributesMap.contains(iter.key())) {
111 TagAttribute attribute = attributesMap.value(iter.key());
112 attribute.setValue(iter.value());
113 if (!attribute.update()) {
114 return failureResponse(
"Failed to update attribute");
117 TagAttribute attribute;
118 attribute.setTagId(cmd.tagId());
119 attribute.setType(iter.key());
120 attribute.setValue(iter.value());
121 if (!attribute.insert()) {
122 return failureResponse(
"Failed to insert attribute");
125 changes << iter.key();
130 if (!changedTag.update()) {
131 return failureResponse(
"Failed to store changes");
134 storageBackend()->notificationCollector()->tagChanged(changedTag);
137 Protocol::TagFetchScope fetchScope;
138 fetchScope.setFetchRemoteID(
true);
139 fetchScope.setFetchAllAttributes(
true);
141 TagFetchHelper helper(connection(),
Scope(cmd.tagId()), fetchScope);
142 if (!helper.fetchTags()) {
143 return failureResponse(
"Failed to fetch response");
146 successResponse<Protocol::DeleteTagResponse>();
149 return successResponse<Protocol::ModifyTagResponse>();
QList< Attribute * > List
Describes a list of attributes.
The handler interfaces describes an entity capable of handling an AkonadiIMAP command.
Id id() const
Returns the unique identifier of the tag.
Helper integration between Akonadi and Qt.
bool isValid(QStringView ifopt)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
const_iterator cbegin() const const
const_iterator cend() const const
bool isEmpty() const const
QString fromUtf8(QByteArrayView str)