IMAP-370 Cassandra should implement move command

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

Branch: refs/heads/master
Commit: ea9d77dee363f4b197ff42eece6a731f64d63b17
Parents: 8a29217
Author: Benoit Tellier <btell...@linagora.com>
Authored: Tue Feb 23 16:11:15 2016 +0700
Committer: Benoit Tellier <btell...@linagora.com>
Committed: Fri Mar 4 19:32:49 2016 +0700

----------------------------------------------------------------------
 .../cassandra/mail/CassandraMessageMapper.java  |  48 +++---
 .../mail/CassandraMessageMoveTest.java          |  30 ++++
 .../mail/model/AbstractMessageMoveTest.java     | 145 +++++++++++++++++++
 3 files changed, 202 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ea9d77de/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
----------------------------------------------------------------------
diff --git 
a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
 
b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 1ec2348..c46447d 100644
--- 
a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ 
b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -151,14 +151,18 @@ public class CassandraMessageMapper implements 
MessageMapper<CassandraId> {
 
     @Override
     public void delete(Mailbox<CassandraId> mailbox, 
MailboxMessage<CassandraId> message) {
+        deleteUsingMailboxId(mailbox.getMailboxId(), message);
+    }
+
+    private void deleteUsingMailboxId(CassandraId mailboxId, 
MailboxMessage<CassandraId> message) {
         session.execute(
             QueryBuilder.delete()
                 .from(TABLE_NAME)
-                .where(eq(MAILBOX_ID, mailbox.getMailboxId().asUuid()))
+                .where(eq(MAILBOX_ID, mailboxId.asUuid()))
                 .and(eq(IMAP_UID, message.getUid())));
-        decrementCount(mailbox);
+        decrementCount(mailboxId);
         if (!message.isSeen()) {
-            decrementUnseen(mailbox);
+            decrementUnseen(mailboxId);
         }
     }
 
@@ -196,8 +200,10 @@ public class CassandraMessageMapper implements 
MessageMapper<CassandraId> {
     }
 
     @Override
-    public MessageMetaData move(Mailbox<CassandraId> mailbox, 
MailboxMessage<CassandraId> original) throws MailboxException {
-        throw new UnsupportedOperationException("Not implemented - see 
https://issues.apache.org/jira/browse/IMAP-370";);
+    public MessageMetaData move(Mailbox<CassandraId> destinationMailbox, 
MailboxMessage<CassandraId> original) throws MailboxException {
+        MessageMetaData messageMetaData = copy(destinationMailbox, original);
+        deleteUsingMailboxId(original.getMailboxId(), original);
+        return messageMetaData;
     }
 
     @Override
@@ -216,9 +222,9 @@ public class CassandraMessageMapper implements 
MessageMapper<CassandraId> {
         message.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
         MessageMetaData messageMetaData = save(mailbox, message);
         if (!message.isSeen()) {
-            incrementUnseen(mailbox);
+            incrementUnseen(mailbox.getMailboxId());
         }
-        incrementCount(mailbox);
+        incrementCount(mailbox.getMailboxId());
         return messageMetaData;
     }
 
@@ -243,9 +249,9 @@ public class CassandraMessageMapper implements 
MessageMapper<CassandraId> {
 
         original.setUid(uidProvider.nextUid(mailboxSession, mailbox));
         original.setModSeq(modSeqProvider.nextModSeq(mailboxSession, mailbox));
-        incrementCount(mailbox);
+        incrementCount(mailbox.getMailboxId());
         if(!original.isSeen()) {
-            incrementUnseen(mailbox);
+            incrementUnseen(mailbox.getMailboxId());
         }
         original.setFlags(new 
FlagsBuilder().add(original.createFlags()).add(Flag.RECENT).build());
         return save(mailbox, original);
@@ -256,24 +262,24 @@ public class CassandraMessageMapper implements 
MessageMapper<CassandraId> {
         return uidProvider.lastUid(mailboxSession, mailbox);
     }
 
-    private void decrementCount(Mailbox<CassandraId> mailbox) {
-        updateMailbox(mailbox, decr(CassandraMailboxCountersTable.COUNT));
+    private void decrementCount(CassandraId mailboxId) {
+        updateMailbox(mailboxId, decr(CassandraMailboxCountersTable.COUNT));
     }
 
-    private void incrementCount(Mailbox<CassandraId> mailbox) {
-        updateMailbox(mailbox, incr(CassandraMailboxCountersTable.COUNT));
+    private void incrementCount(CassandraId mailboxId) {
+        updateMailbox(mailboxId, incr(CassandraMailboxCountersTable.COUNT));
     }
 
-    private void decrementUnseen(Mailbox<CassandraId> mailbox) {
-        updateMailbox(mailbox, decr(CassandraMailboxCountersTable.UNSEEN));
+    private void decrementUnseen(CassandraId mailboxId) {
+        updateMailbox(mailboxId, decr(CassandraMailboxCountersTable.UNSEEN));
     }
 
-    private void incrementUnseen(Mailbox<CassandraId> mailbox) {
-        updateMailbox(mailbox, incr(CassandraMailboxCountersTable.UNSEEN));
+    private void incrementUnseen(CassandraId mailboxId) {
+        updateMailbox(mailboxId, incr(CassandraMailboxCountersTable.UNSEEN));
     }
 
-    private void updateMailbox(Mailbox<CassandraId> mailbox, Assignment 
operation) {
-        
session.execute(update(CassandraMailboxCountersTable.TABLE_NAME).with(operation).where(eq(CassandraMailboxCountersTable.MAILBOX_ID,
 mailbox.getMailboxId().asUuid())));
+    private void updateMailbox(CassandraId mailboxId, Assignment operation) {
+        
session.execute(update(CassandraMailboxCountersTable.TABLE_NAME).with(operation).where(eq(CassandraMailboxCountersTable.MAILBOX_ID,
 mailboxId.asUuid())));
     }
 
     private MailboxMessage<CassandraId> message(Row row) {
@@ -366,10 +372,10 @@ public class CassandraMessageMapper implements 
MessageMapper<CassandraId> {
 
     private void manageUnseenMessageCounts(Mailbox<CassandraId> mailbox, Flags 
oldFlags, Flags newFlags) {
         if (oldFlags.contains(Flag.SEEN) && !newFlags.contains(Flag.SEEN)) {
-            incrementUnseen(mailbox);
+            incrementUnseen(mailbox.getMailboxId());
         }
         if (!oldFlags.contains(Flag.SEEN) && newFlags.contains(Flag.SEEN)) {
-            decrementUnseen(mailbox);
+            decrementUnseen(mailbox.getMailboxId());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea9d77de/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMoveTest.java
----------------------------------------------------------------------
diff --git 
a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMoveTest.java
 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMoveTest.java
new file mode 100644
index 0000000..51bc8c3
--- /dev/null
+++ 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMoveTest.java
@@ -0,0 +1,30 @@
+/****************************************************************
+ * 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.cassandra.mail;
+
+import org.apache.james.mailbox.cassandra.CassandraId;
+import org.apache.james.mailbox.store.mail.model.AbstractMessageMoveTest;
+
+public class CassandraMessageMoveTest extends 
AbstractMessageMoveTest<CassandraId> {
+
+    public CassandraMessageMoveTest() {
+        super(new CassandraMapperProvider());
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ea9d77de/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AbstractMessageMoveTest.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AbstractMessageMoveTest.java
 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AbstractMessageMoveTest.java
new file mode 100644
index 0000000..ed38feb
--- /dev/null
+++ 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AbstractMessageMoveTest.java
@@ -0,0 +1,145 @@
+/****************************************************************
+ * 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.store.mail.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Date;
+
+import javax.mail.Flags;
+import javax.mail.util.SharedByteArrayInputStream;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MessageMetaData;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
+import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public abstract class AbstractMessageMoveTest<Id extends MailboxId> {
+
+    private final static char DELIMITER = ':';
+    private static final int LIMIT = 10;
+    private static final int BODY_START = 16;
+    public static final int UID_VALIDITY = 42;
+
+    private MapperProvider<Id> mapperProvider;
+    private MessageMapper<Id> messageMapper;
+
+    private SimpleMailbox<Id> benwaInboxMailbox;
+    private SimpleMailbox<Id> benwaWorkMailbox;
+
+    private SimpleMailboxMessage<Id> message1;
+
+    public AbstractMessageMoveTest(MapperProvider<Id> mapperProvider) {
+        this.mapperProvider = mapperProvider;
+    }
+
+    @Before
+    public void setUp() throws MailboxException {
+        mapperProvider.ensureMapperPrepared();
+        messageMapper = mapperProvider.createMessageMapper();
+        benwaInboxMailbox = createMailbox(new MailboxPath("#private", "benwa", 
"INBOX"));
+        benwaWorkMailbox = createMailbox( new MailboxPath("#private", "benwa", 
"INBOX"+DELIMITER+"work"));
+        message1 = createMessage(benwaInboxMailbox, "Subject: Test1 
\n\nBody1\n.\n", BODY_START, new PropertyBuilder());
+    }
+
+    @After
+    public void tearDown() throws MailboxException {
+        mapperProvider.clearMapper();
+    }
+
+    @Test
+    public void movingAMessageShouldWork() throws Exception {
+        messageMapper.add(benwaInboxMailbox, message1);
+        message1.setModSeq(messageMapper.getHighestModSeq(benwaInboxMailbox));
+
+        messageMapper.move(benwaWorkMailbox, message1);
+
+        assertThat(retrieveMessageFromStorage(benwaWorkMailbox, 
message1)).isEqualTo(message1);
+    }
+
+    @Test
+    public void movingAMessageShouldReturnCorrectMetadata() throws Exception {
+        messageMapper.add(benwaInboxMailbox, message1);
+        message1.setModSeq(messageMapper.getHighestModSeq(benwaInboxMailbox));
+
+        MessageMetaData messageMetaData = messageMapper.move(benwaWorkMailbox, 
message1);
+
+        
assertThat(messageMetaData.getFlags()).isEqualTo(message1.createFlags());
+        
assertThat(messageMetaData.getUid()).isEqualTo(messageMapper.getLastUid(benwaWorkMailbox));
+        
assertThat(messageMetaData.getModSeq()).isEqualTo(messageMapper.getHighestModSeq(benwaWorkMailbox));
+    }
+
+    @Test
+    public void movingAMessageShouldNotViolateMessageCount() throws Exception {
+        messageMapper.add(benwaInboxMailbox, message1);
+        message1.setModSeq(messageMapper.getHighestModSeq(benwaInboxMailbox));
+
+        messageMapper.move(benwaWorkMailbox, message1);
+
+        
assertThat(messageMapper.countMessagesInMailbox(benwaInboxMailbox)).isEqualTo(0);
+        
assertThat(messageMapper.countMessagesInMailbox(benwaWorkMailbox)).isEqualTo(1);
+    }
+
+    @Test
+    public void movingAMessageShouldNotViolateUnseenMessageCount() throws 
Exception {
+        messageMapper.add(benwaInboxMailbox, message1);
+        message1.setModSeq(messageMapper.getHighestModSeq(benwaInboxMailbox));
+
+        messageMapper.move(benwaWorkMailbox, message1);
+
+        
assertThat(messageMapper.countUnseenMessagesInMailbox(benwaInboxMailbox)).isEqualTo(0);
+        
assertThat(messageMapper.countUnseenMessagesInMailbox(benwaWorkMailbox)).isEqualTo(1);
+    }
+
+    @Test
+    public void movingASeenMessageShouldNotIncrementUnseenMessageCount() 
throws Exception {
+        message1.setFlags(new Flags(Flags.Flag.SEEN));
+        messageMapper.add(benwaInboxMailbox, message1);
+        message1.setModSeq(messageMapper.getHighestModSeq(benwaInboxMailbox));
+
+        messageMapper.move(benwaWorkMailbox, message1);
+
+        
assertThat(messageMapper.countUnseenMessagesInMailbox(benwaInboxMailbox)).isEqualTo(0);
+        
assertThat(messageMapper.countUnseenMessagesInMailbox(benwaWorkMailbox)).isEqualTo(0);
+    }
+
+    private SimpleMailbox<Id> createMailbox(MailboxPath mailboxPath) {
+        SimpleMailbox<Id> mailbox = new SimpleMailbox<Id>(mailboxPath, 
UID_VALIDITY);
+        Id id = mapperProvider.generateId();
+        mailbox.setMailboxId(id);
+        return mailbox;
+    }
+
+    private MailboxMessage<Id> retrieveMessageFromStorage(Mailbox<Id> mailbox, 
MailboxMessage<Id> message) throws MailboxException {
+        return messageMapper.findInMailbox(mailbox, 
MessageRange.one(message.getUid()), FetchType.Metadata, LIMIT).next();
+    }
+    
+    private SimpleMailboxMessage<Id> createMessage(Mailbox<Id> mailbox, String 
content, int bodyStart, PropertyBuilder propertyBuilder) {
+        return new SimpleMailboxMessage<Id>(new Date(), content.length(), 
bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), 
propertyBuilder, mailbox.getMailboxId());
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to