File indexing completed on 2024-06-23 05:07:03
0001 /* 0002 SPDX-FileCopyrightText: 2014 Daniel Vrátil <dvratil@redhat.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "tagcreatehandler.h" 0008 0009 #include "connection.h" 0010 #include "storage/countquerybuilder.h" 0011 #include "storage/datastore.h" 0012 #include "storage/querybuilder.h" 0013 #include "storage/transaction.h" 0014 #include "tagfetchhelper.h" 0015 0016 #include "private/imapset_p.h" 0017 #include "private/scope_p.h" 0018 0019 using namespace Akonadi; 0020 using namespace Akonadi::Server; 0021 0022 TagCreateHandler::TagCreateHandler(AkonadiServer &akonadi) 0023 : Handler(akonadi) 0024 { 0025 } 0026 0027 bool TagCreateHandler::parseStream() 0028 { 0029 const auto &cmd = Protocol::cmdCast<Protocol::CreateTagCommand>(m_command); 0030 0031 if (!cmd.remoteId().isEmpty() && !connection()->context().resource().isValid()) { 0032 return failureResponse(QStringLiteral("Only resources can create tags with remote ID")); 0033 } 0034 0035 Transaction trx(storageBackend(), QStringLiteral("TAGAPPEND")); 0036 0037 TagType tagType; 0038 if (!cmd.type().isEmpty()) { 0039 const QString typeName = QString::fromUtf8(cmd.type()); 0040 tagType = TagType::retrieveByNameOrCreate(typeName); 0041 if (!tagType.isValid()) { 0042 return failureResponse(QStringLiteral("Unable to create tagtype '") % typeName % QStringLiteral("'")); 0043 } 0044 } 0045 0046 qint64 tagId = -1; 0047 const QString gid = QString::fromUtf8(cmd.gid()); 0048 if (cmd.merge()) { 0049 QueryBuilder qb(Tag::tableName()); 0050 qb.addColumn(Tag::idColumn()); 0051 qb.addValueCondition(Tag::gidColumn(), Query::Equals, gid); 0052 if (!qb.exec()) { 0053 return failureResponse("Unable to list tags"); 0054 } 0055 if (qb.query().next()) { 0056 tagId = qb.query().value(0).toLongLong(); 0057 } 0058 qb.query().finish(); 0059 } 0060 if (tagId < 0) { 0061 Tag insertedTag; 0062 insertedTag.setGid(gid); 0063 if (cmd.parentId() >= 0) { 0064 insertedTag.setParentId(cmd.parentId()); 0065 } 0066 if (tagType.isValid()) { 0067 insertedTag.setTypeId(tagType.id()); 0068 } 0069 if (!insertedTag.insert(&tagId)) { 0070 return failureResponse("Failed to store tag"); 0071 } 0072 0073 const Protocol::Attributes attrs = cmd.attributes(); 0074 for (auto iter = attrs.cbegin(), end = attrs.cend(); iter != end; ++iter) { 0075 TagAttribute attribute; 0076 attribute.setTagId(tagId); 0077 attribute.setType(iter.key()); 0078 attribute.setValue(iter.value()); 0079 if (!attribute.insert()) { 0080 return failureResponse("Failed to store tag attribute"); 0081 } 0082 } 0083 0084 storageBackend()->notificationCollector()->tagAdded(insertedTag); 0085 } 0086 0087 if (!cmd.remoteId().isEmpty()) { 0088 const qint64 resourceId = connection()->context().resource().id(); 0089 0090 CountQueryBuilder qb(TagRemoteIdResourceRelation::tableName()); 0091 qb.addValueCondition(TagRemoteIdResourceRelation::tagIdColumn(), Query::Equals, tagId); 0092 qb.addValueCondition(TagRemoteIdResourceRelation::resourceIdColumn(), Query::Equals, resourceId); 0093 if (!qb.exec()) { 0094 return failureResponse("Failed to query for existing TagRemoteIdResourceRelation entries"); 0095 } 0096 const bool exists = (qb.result() > 0); 0097 0098 // If the relation is already existing simply update it (can happen if a resource simply creates the tag again while enabling merge) 0099 bool ret = false; 0100 if (exists) { 0101 // Simply using update() doesn't work since TagRemoteIdResourceRelation only takes the tagId for identification of the column 0102 QueryBuilder qb(TagRemoteIdResourceRelation::tableName(), QueryBuilder::Update); 0103 qb.addValueCondition(TagRemoteIdResourceRelation::tagIdColumn(), Query::Equals, tagId); 0104 qb.addValueCondition(TagRemoteIdResourceRelation::resourceIdColumn(), Query::Equals, resourceId); 0105 qb.setColumnValue(TagRemoteIdResourceRelation::remoteIdColumn(), QString::fromUtf8(cmd.remoteId())); 0106 ret = qb.exec(); 0107 } else { 0108 TagRemoteIdResourceRelation rel; 0109 rel.setTagId(tagId); 0110 rel.setResourceId(resourceId); 0111 rel.setRemoteId(QString::fromUtf8(cmd.remoteId())); 0112 ret = rel.insert(); 0113 } 0114 if (!ret) { 0115 return failureResponse("Failed to store tag remote ID"); 0116 } 0117 } 0118 0119 trx.commit(); 0120 0121 Scope scope; 0122 ImapSet set; 0123 set.add(QList<qint64>() << tagId); 0124 scope.setUidSet(set); 0125 0126 Protocol::TagFetchScope fetchScope; 0127 fetchScope.setFetchRemoteID(true); 0128 fetchScope.setFetchAllAttributes(true); 0129 0130 TagFetchHelper helper(connection(), scope, fetchScope); 0131 if (!helper.fetchTags()) { 0132 return failureResponse("Failed to fetch the new tag"); 0133 } 0134 0135 return successResponse<Protocol::CreateTagResponse>(); 0136 }