MAILBOX-337 mailbox should allow mass message deletion by messageId

Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/5bfbc370
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/5bfbc370
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/5bfbc370

Branch: refs/heads/master
Commit: 5bfbc37045ea2a73ce3d4b09ca3a5a55918cb9ee
Parents: 75f1d70
Author: benwa <[email protected]>
Authored: Thu May 24 16:11:57 2018 +0700
Committer: Matthieu Baechler <[email protected]>
Committed: Fri May 25 11:07:39 2018 +0200

----------------------------------------------------------------------
 .../apache/james/mailbox/MessageIdManager.java  |  12 +-
 .../james/mailbox/model/DeleteResult.java       | 112 +++++++++++++++++++
 .../mail/CassandraMessageIdMapper.java          |  19 +++-
 .../mailbox/store/StoreMessageIdManager.java    |  51 ++++++++-
 .../mailbox/store/mail/MessageIdMapper.java     |   7 ++
 .../AbstractMessageIdManagerSideEffectTest.java |  33 +++++-
 .../AbstractMessageIdManagerStorageTest.java    |  34 +++++-
 .../store/mail/model/MessageIdMapperTest.java   |  76 +++++++++++++
 8 files changed, 332 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/5bfbc370/mailbox/api/src/main/java/org/apache/james/mailbox/MessageIdManager.java
----------------------------------------------------------------------
diff --git 
a/mailbox/api/src/main/java/org/apache/james/mailbox/MessageIdManager.java 
b/mailbox/api/src/main/java/org/apache/james/mailbox/MessageIdManager.java
index 4eaa41b..c61581d 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/MessageIdManager.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/MessageIdManager.java
@@ -27,11 +27,14 @@ import javax.mail.Flags;
 
 import org.apache.james.mailbox.MessageManager.FlagsUpdateMode;
 import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.DeleteResult;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.MessageResult;
 import org.apache.james.mailbox.model.MessageResult.FetchGroup;
 
+import com.google.common.collect.ImmutableList;
+
 public interface MessageIdManager {
 
     Set<MessageId> accessibleMessages(Collection<MessageId> messageIds, final 
MailboxSession mailboxSession) throws MailboxException;
@@ -40,7 +43,14 @@ public interface MessageIdManager {
 
     List<MessageResult> getMessages(List<MessageId> messageId, FetchGroup 
minimal, MailboxSession mailboxSession) throws MailboxException;
 
-    void delete(MessageId messageId, List<MailboxId> mailboxIds, 
MailboxSession mailboxSession) throws MailboxException;
+    DeleteResult delete(MessageId messageId, List<MailboxId> mailboxIds, 
MailboxSession mailboxSession) throws MailboxException;
+
+    DeleteResult delete(List<MessageId> messageId, MailboxSession 
mailboxSession) throws MailboxException;
 
     void setInMailboxes(MessageId messageId, Collection<MailboxId> mailboxIds, 
MailboxSession mailboxSession) throws MailboxException;
+
+    default DeleteResult delete(MessageId messageId, MailboxSession 
mailboxSession) throws MailboxException {
+        return delete(ImmutableList.of(messageId), mailboxSession);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/5bfbc370/mailbox/api/src/main/java/org/apache/james/mailbox/model/DeleteResult.java
----------------------------------------------------------------------
diff --git 
a/mailbox/api/src/main/java/org/apache/james/mailbox/model/DeleteResult.java 
b/mailbox/api/src/main/java/org/apache/james/mailbox/model/DeleteResult.java
new file mode 100644
index 0000000..7bb4351
--- /dev/null
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/DeleteResult.java
@@ -0,0 +1,112 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.model;
+
+import java.util.Collection;
+import java.util.Objects;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+
+public class DeleteResult {
+    public static class Builder {
+        private final ImmutableSet.Builder<MessageId> destroyed;
+        private final ImmutableSet.Builder<MessageId> notFound;
+
+        public Builder() {
+            destroyed = ImmutableSet.builder();
+            notFound = ImmutableSet.builder();
+        }
+
+        public Builder addDestroyed(Collection<MessageId> messageIds) {
+            destroyed.addAll(messageIds);
+            return this;
+        }
+
+        public Builder addNotFound(Collection<MessageId> messageIds) {
+            notFound.addAll(messageIds);
+            return this;
+        }
+
+        public Builder addDestroyed(MessageId messageId) {
+            destroyed.add(messageId);
+            return this;
+        }
+
+        public Builder addNotFound(MessageId messageId) {
+            notFound.add(messageId);
+            return this;
+        }
+
+        public DeleteResult build() {
+            return new DeleteResult(
+                destroyed.build(),
+                notFound.build());
+        }
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static DeleteResult destroyed(MessageId messageId) {
+        return new Builder()
+            .addDestroyed(messageId)
+            .build();
+    }
+
+    public static DeleteResult notFound(MessageId messageId) {
+        return new Builder()
+            .addNotFound(messageId)
+            .build();
+    }
+
+    private final Set<MessageId> destroyed;
+    private final Set<MessageId> notFound;
+
+    public DeleteResult(Set<MessageId> destroyed, Set<MessageId> notFound) {
+        this.destroyed = destroyed;
+        this.notFound = notFound;
+    }
+
+    public Set<MessageId> getDestroyed() {
+        return destroyed;
+    }
+
+    public Set<MessageId> getNotFound() {
+        return notFound;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof DeleteResult) {
+            DeleteResult result = (DeleteResult) o;
+
+            return Objects.equals(this.destroyed, result.destroyed)
+                && Objects.equals(this.notFound, result.notFound);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(destroyed, notFound);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/5bfbc370/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
----------------------------------------------------------------------
diff --git 
a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
 
b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
index 4db9185..52ab41f 100644
--- 
a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
+++ 
b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
@@ -57,6 +57,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.steveash.guavate.Guavate;
 import com.google.common.base.Throwables;
+import com.google.common.collect.Multimap;
 
 public class CassandraMessageIdMapper implements MessageIdMapper {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(CassandraMessageIdMapper.class);
@@ -180,14 +181,26 @@ public class CassandraMessageIdMapper implements 
MessageIdMapper {
 
     @Override
     public void delete(MessageId messageId, Collection<MailboxId> mailboxIds) {
+        deleteAsFuture(messageId, mailboxIds).join();
+    }
+
+    public CompletableFuture<Void> deleteAsFuture(MessageId messageId, 
Collection<MailboxId> mailboxIds) {
         CassandraMessageId cassandraMessageId = (CassandraMessageId) messageId;
-        mailboxIds.stream()
+        return mailboxIds.stream()
             .map(mailboxId -> retrieveAndDeleteIndices(cassandraMessageId, 
Optional.of((CassandraId) mailboxId)))
             .reduce((f1, f2) -> CompletableFuture.allOf(f1, f2))
-            .orElse(CompletableFuture.completedFuture(null))
-            .join();
+            .orElse(CompletableFuture.completedFuture(null));
     }
 
+    @Override
+    public void delete(Multimap<MessageId, MailboxId> ids) {
+        FluentFutureStream.of(
+            ids.asMap()
+                .entrySet()
+                .stream()
+                .map(entry -> deleteAsFuture(entry.getKey(), 
entry.getValue())))
+            .join();
+    }
 
     private CompletableFuture<Void> 
retrieveAndDeleteIndices(CassandraMessageId messageId, Optional<CassandraId> 
mailboxId) {
         return imapUidDAO.retrieve(messageId, mailboxId)

http://git-wip-us.apache.org/repos/asf/james-project/blob/5bfbc370/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java
index bcda820..1a5f789 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java
@@ -39,6 +39,7 @@ import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
+import org.apache.james.mailbox.model.DeleteResult;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MessageAttachment;
@@ -58,6 +59,7 @@ import org.apache.james.mailbox.store.mail.model.FlagsFactory;
 import org.apache.james.mailbox.store.mail.model.FlagsFilter;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.Message;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
 import org.apache.james.mailbox.store.quota.QuotaChecker;
@@ -70,6 +72,7 @@ import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 
 public class StoreMessageIdManager implements MessageIdManager {
 
@@ -162,23 +165,61 @@ public class StoreMessageIdManager implements 
MessageIdManager {
     }
 
     @Override
-    public void delete(MessageId messageId, List<MailboxId> mailboxIds, 
MailboxSession mailboxSession) throws MailboxException {
+    public DeleteResult delete(MessageId messageId, List<MailboxId> 
mailboxIds, MailboxSession mailboxSession) throws MailboxException {
         MessageIdMapper messageIdMapper = 
mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession);
-        MailboxMapper mailboxMapper = 
mailboxSessionMapperFactory.getMailboxMapper(mailboxSession);
 
         assertRightsOnMailboxes(mailboxIds, mailboxSession, 
Right.DeleteMessages);
 
-        ImmutableList<MetadataWithMailboxId> metadataWithMailbox = 
messageIdMapper
+        List<MailboxMessage> messageList = messageIdMapper
             .find(ImmutableList.of(messageId), 
MessageMapper.FetchType.Metadata)
             .stream()
             .filter(inMailboxes(mailboxIds))
+            .collect(Guavate.toImmutableList());
+
+        if (!messageList.isEmpty()) {
+            delete(messageIdMapper, messageList, mailboxSession);
+            return DeleteResult.destroyed(messageId);
+        }
+        return DeleteResult.notFound(messageId);
+    }
+
+    @Override
+    public DeleteResult delete(List<MessageId> messageIds, MailboxSession 
mailboxSession) throws MailboxException {
+        MessageIdMapper messageIdMapper = 
mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession);
+
+        List<MailboxMessage> messageList = messageIdMapper.find(messageIds, 
MessageMapper.FetchType.Metadata);
+        ImmutableSet<MailboxId> allowedMailboxIds = 
getAllowedMailboxIds(mailboxSession, messageList, Right.DeleteMessages);
+
+        ImmutableSet<MessageId> accessibleMessages = messageList.stream()
+            .filter(message -> 
allowedMailboxIds.contains(message.getMailboxId()))
+            .map(MailboxMessage::getMessageId)
+            .distinct()
+            .collect(Guavate.toImmutableSet());
+        Sets.SetView<MessageId> nonAccessibleMessages = 
Sets.difference(ImmutableSet.copyOf(messageIds), accessibleMessages);
+
+        delete(messageIdMapper, messageList, mailboxSession);
+
+        return DeleteResult.builder()
+            .addDestroyed(accessibleMessages)
+            .addNotFound(nonAccessibleMessages)
+            .build();
+    }
+
+    private void delete(MessageIdMapper messageIdMapper, List<MailboxMessage> 
messageList, MailboxSession mailboxSession) throws MailboxException {
+        ImmutableList<MetadataWithMailboxId> metadataWithMailbox = 
messageList.stream()
             .map(StoreMessageIdManager::toMetadataWithMailboxId)
             .collect(Guavate.toImmutableList());
 
-        messageIdMapper.delete(messageId, mailboxIds);
+        messageIdMapper.delete(
+            messageList.stream()
+                .collect(Guavate.toImmutableListMultimap(
+                    Message::getMessageId,
+                    MailboxMessage::getMailboxId)));
 
+        MailboxMapper mailboxMapper = 
mailboxSessionMapperFactory.getMailboxMapper(mailboxSession);
         for (MetadataWithMailboxId metadataWithMailboxId : 
metadataWithMailbox) {
-            dispatcher.expunged(mailboxSession, 
metadataWithMailboxId.messageMetaData, 
mailboxMapper.findMailboxById(metadataWithMailboxId.mailboxId));
+            dispatcher.expunged(mailboxSession, 
metadataWithMailboxId.messageMetaData,
+                
mailboxMapper.findMailboxById(metadataWithMailboxId.mailboxId));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/5bfbc370/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MessageIdMapper.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MessageIdMapper.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MessageIdMapper.java
index 9d5d4d9..2f9457f 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MessageIdMapper.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MessageIdMapper.java
@@ -33,6 +33,8 @@ import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 
+import com.google.common.collect.Multimap;
+
 public interface MessageIdMapper {
 
     List<MailboxMessage> find(Collection<MessageId> messageIds, FetchType 
fetchType);
@@ -47,5 +49,10 @@ public interface MessageIdMapper {
 
     void delete(MessageId messageId, Collection<MailboxId> mailboxIds);
 
+    default void delete(Multimap<MessageId, MailboxId> ids) {
+        ids.asMap()
+            .forEach(this::delete);
+    }
+
     Map<MailboxId, UpdatedFlags> setFlags(MessageId messageId, List<MailboxId> 
mailboxIds, Flags newState, MessageManager.FlagsUpdateMode updateMode) throws 
MailboxException;
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/5bfbc370/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
index 3f38a6f..9f81ac0 100644
--- 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
+++ 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
@@ -68,6 +68,7 @@ public abstract class AbstractMessageIdManagerSideEffectTest {
         .computedLimit(QuotaCount.count(100))
         .build();
     private static final MessageUid messageUid1 = MessageUid.of(111);
+    private static final MessageUid messageUid2 = MessageUid.of(113);
 
     public static final Flags FLAGS = new Flags();
 
@@ -98,7 +99,6 @@ public abstract class AbstractMessageIdManagerSideEffectTest {
         mailbox3 = testingData.createMailbox(MailboxFixture.SENT_ALICE, 
session);
     }
 
-
     @Test
     public void deleteShouldCallEventDispatcher() throws Exception {
         givenUnlimitedQuota();
@@ -115,6 +115,25 @@ public abstract class 
AbstractMessageIdManagerSideEffectTest {
     }
 
     @Test
+    public void deletesShouldCallEventDispatcher() throws Exception {
+        givenUnlimitedQuota();
+        MessageId messageId1 = testingData.persist(mailbox1.getMailboxId(), 
messageUid1, FLAGS, session);
+        MessageId messageId2 = testingData.persist(mailbox1.getMailboxId(), 
messageUid2, FLAGS, session);
+        reset(dispatcher);
+
+        MessageResult messageResult1 = 
messageIdManager.getMessages(ImmutableList.of(messageId1), 
FetchGroupImpl.MINIMAL, session).get(0);
+        SimpleMessageMetaData simpleMessageMetaData1 = 
fromMessageResult(messageId1, messageResult1);
+        MessageResult messageResult2 = 
messageIdManager.getMessages(ImmutableList.of(messageId2), 
FetchGroupImpl.MINIMAL, session).get(0);
+        SimpleMessageMetaData simpleMessageMetaData2 = 
fromMessageResult(messageId2, messageResult2);
+
+        messageIdManager.delete(ImmutableList.of(messageId1, messageId2), 
session);
+
+        verify(dispatcher).expunged(session, simpleMessageMetaData1, mailbox1);
+        verify(dispatcher).expunged(session, simpleMessageMetaData2, mailbox1);
+        verifyNoMoreInteractions(dispatcher);
+    }
+
+    @Test
     public void 
deleteShouldNotCallEventDispatcherWhenMessageIsInWrongMailbox() throws 
Exception {
         givenUnlimitedQuota();
         MessageId messageId = testingData.persist(mailbox2.getMailboxId(), 
messageUid1, FLAGS, session);
@@ -298,6 +317,18 @@ public abstract class 
AbstractMessageIdManagerSideEffectTest {
     }
 
     @Test
+    public void deletesShouldNotDispatchEventWhenMessageDoesNotExist() throws 
Exception {
+        givenUnlimitedQuota();
+        MessageId messageId = testingData.createNotUsedMessageId();
+
+        reset(dispatcher);
+
+        messageIdManager.delete(ImmutableList.of(messageId), session);
+
+        verifyNoMoreInteractions(dispatcher);
+    }
+
+    @Test
     public void setFlagsShouldNotDispatchEventWhenMessageDoesNotExist() throws 
Exception {
         givenUnlimitedQuota();
         MessageId messageId = testingData.createNotUsedMessageId();

http://git-wip-us.apache.org/repos/asf/james-project/blob/5bfbc370/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java
 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java
index 1e64270..e60c0ff 100644
--- 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java
+++ 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java
@@ -33,9 +33,11 @@ import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageIdManager;
 import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.fixture.MailboxFixture;
 import org.apache.james.mailbox.mock.MockMailboxSession;
+import org.apache.james.mailbox.model.DeleteResult;
 import org.apache.james.mailbox.model.FetchGroupImpl;
 import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.Rfc4314Rights;
@@ -101,10 +103,11 @@ public abstract class AbstractMessageIdManagerStorageTest 
{
     }
 
     @Test
-    public void deleteMessageShouldNotFailWhenMessageDoesNotExist() throws 
Exception {
+    public void deleteMessageShouldReturnNotFoundWhenMessageDoesNotExist() 
throws MailboxException {
         MessageId messageId = testingData.createNotUsedMessageId();
 
-        messageIdManager.delete(messageId, 
ImmutableList.of(aliceMailbox1.getMailboxId()), aliceSession);
+        assertThat(messageIdManager.delete(messageId, bobSession))
+            .isEqualTo(DeleteResult.notFound(messageId));
     }
 
     @Test
@@ -279,6 +282,15 @@ public abstract class AbstractMessageIdManagerStorageTest {
     }
 
     @Test
+    public void deleteAllMessageShouldRemoveMessageFromMailbox() throws 
Exception {
+        MessageId messageId = 
testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, 
aliceSession);
+
+        messageIdManager.delete(messageId, aliceSession);
+
+        assertThat(messageIdManager.getMessages(ImmutableList.of(messageId), 
FetchGroupImpl.MINIMAL, aliceSession)).isEmpty();
+    }
+
+    @Test
     public void deleteMessageShouldRemoveMessageOnlyFromMailbox() throws 
Exception {
         MessageId messageId = 
testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, 
aliceSession);
         messageIdManager.setInMailboxes(messageId, 
ImmutableList.of(aliceMailbox1.getMailboxId(), aliceMailbox2.getMailboxId()), 
aliceSession);
@@ -291,6 +303,16 @@ public abstract class AbstractMessageIdManagerStorageTest {
     }
 
     @Test
+    public void deleteAllShouldRemoveMessageFromAllMailbox() throws Exception {
+        MessageId messageId = 
testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, 
aliceSession);
+        messageIdManager.setInMailboxes(messageId, 
ImmutableList.of(aliceMailbox1.getMailboxId(), aliceMailbox2.getMailboxId()), 
aliceSession);
+
+        messageIdManager.delete(messageId, aliceSession);
+
+        assertThat(messageIdManager.getMessages(ImmutableList.of(messageId), 
FetchGroupImpl.MINIMAL, aliceSession)).isEmpty();
+    }
+
+    @Test
     public void deleteMessageShouldNotRemoveMessageOnAnotherMailbox() throws 
Exception {
         MessageId messageId = 
testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, 
aliceSession);
 
@@ -311,6 +333,14 @@ public abstract class AbstractMessageIdManagerStorageTest {
     }
 
     @Test
+    public void deleteAllShouldReturnNotFoundWhenDeletingOnOtherSession() 
throws Exception {
+        MessageId messageId = 
testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, 
aliceSession);
+
+        assertThat(messageIdManager.delete(messageId, bobSession))
+            .isEqualTo(DeleteResult.notFound(messageId));
+    }
+
+    @Test
     public void deleteMessageShouldThrowExceptionWhenDeletingOnSystemSession() 
throws Exception {
         expectedException.expect(MailboxNotFoundException.class);
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/5bfbc370/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
index 054c44a..badf740 100644
--- 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
+++ 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
@@ -30,6 +30,7 @@ import javax.mail.Flags;
 import javax.mail.Flags.Flag;
 import javax.mail.util.SharedByteArrayInputStream;
 
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.mailbox.FlagsBuilder;
 import org.apache.james.mailbox.MessageManager.FlagsUpdateMode;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -52,7 +53,9 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
+import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMultimap;
 
 public abstract class MessageIdMapperTest {
 
@@ -880,6 +883,79 @@ public abstract class MessageIdMapperTest {
         
assertThat(messageMapper.countUnseenMessagesInMailbox(benwaInboxMailbox)).isEqualTo(1);
     }
 
+    @Test
+    public void deletesShouldOnlyRemoveConcernedMessages() throws Exception {
+        saveMessages();
+
+        SimpleMailboxMessage copiedMessage = 
SimpleMailboxMessage.copy(benwaWorkMailbox.getMailboxId(), message1);
+        copiedMessage.setUid(mapperProvider.generateMessageUid());
+        
copiedMessage.setModSeq(mapperProvider.generateModSeq(benwaWorkMailbox));
+        sut.copyInMailbox(copiedMessage);
+
+        sut.delete(
+            ImmutableMultimap.<MessageId, MailboxId>builder()
+                .put(message1.getMessageId(), benwaWorkMailbox.getMailboxId())
+                .put(message2.getMessageId(), benwaInboxMailbox.getMailboxId())
+                .build());
+
+        ImmutableList<Pair<MessageId, MailboxId>> storedMessages =
+            sut.find(ImmutableList.of(message1.getMessageId(), 
message2.getMessageId()), FetchType.Metadata)
+                .stream()
+                .map(message -> Pair.of(message.getMessageId(), 
message.getMailboxId()))
+                .collect(Guavate.toImmutableList());
+
+        assertThat(storedMessages)
+            .containsOnly(Pair.of(message1.getMessageId(), 
benwaInboxMailbox.getMailboxId()));
+    }
+
+    @Test
+    public void deletesShouldUpdateMessageCount() throws Exception {
+        saveMessages();
+
+        SimpleMailboxMessage copiedMessage = 
SimpleMailboxMessage.copy(benwaWorkMailbox.getMailboxId(), message1);
+        copiedMessage.setUid(mapperProvider.generateMessageUid());
+        
copiedMessage.setModSeq(mapperProvider.generateModSeq(benwaWorkMailbox));
+        sut.copyInMailbox(copiedMessage);
+
+        sut.delete(
+            ImmutableMultimap.<MessageId, MailboxId>builder()
+                .put(message1.getMessageId(), benwaWorkMailbox.getMailboxId())
+                .put(message2.getMessageId(), benwaInboxMailbox.getMailboxId())
+                .build());
+
+        assertThat(messageMapper.countMessagesInMailbox(benwaInboxMailbox))
+            .isEqualTo(2);
+    }
+
+    @Test
+    public void deletesShouldUpdateUnreadCount() throws Exception {
+        message1.setUid(mapperProvider.generateMessageUid());
+        message1.setModSeq(mapperProvider.generateModSeq(benwaInboxMailbox));
+        message1.setFlags(new Flags(Flag.SEEN));
+        sut.save(message1);
+
+        message2.setUid(mapperProvider.generateMessageUid());
+        message2.setModSeq(mapperProvider.generateModSeq(benwaInboxMailbox));
+        sut.save(message2);
+
+        sut.delete(
+            ImmutableMultimap.<MessageId, MailboxId>builder()
+                .put(message1.getMessageId(), benwaInboxMailbox.getMailboxId())
+                .put(message2.getMessageId(), benwaInboxMailbox.getMailboxId())
+                .build());
+
+        
assertThat(messageMapper.countUnseenMessagesInMailbox(benwaInboxMailbox))
+            .isEqualTo(0);
+    }
+
+    @Test
+    public void deletesShouldNotFailUponMissingMessage() {
+        sut.delete(
+            ImmutableMultimap.<MessageId, MailboxId>builder()
+                .put(message1.getMessageId(), benwaWorkMailbox.getMailboxId())
+                .build());
+    }
+
     private SimpleMailbox createMailbox(MailboxPath mailboxPath) throws 
MailboxException {
         SimpleMailbox mailbox = new SimpleMailbox(mailboxPath, UID_VALIDITY);
         mailbox.setMailboxId(mapperProvider.generateId());


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to