IMAP-370 Factorize code between copies and moves

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

Branch: refs/heads/master
Commit: b06992f18a09ca351d64880e37cc9ef7f13433d0
Parents: ea9d77d
Author: Benoit Tellier <[email protected]>
Authored: Wed Feb 24 12:09:53 2016 +0700
Committer: Benoit Tellier <[email protected]>
Committed: Fri Mar 4 19:33:23 2016 +0700

----------------------------------------------------------------------
 .../james/mailbox/store/MessageBatcher.java     | 57 ++++++++++++++++
 .../mailbox/store/StoreMailboxManager.java      | 57 +++++++---------
 .../mailbox/store/StoreMessageManager.java      | 39 ++++-------
 .../james/mailbox/store/MessageBatcherTest.java | 71 ++++++++++++++++++++
 4 files changed, 168 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/b06992f1/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageBatcher.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageBatcher.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageBatcher.java
new file mode 100644
index 0000000..0631f02
--- /dev/null
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageBatcher.java
@@ -0,0 +1,57 @@
+/****************************************************************
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.store.mail.model.MailboxId;
+import org.msgpack.core.Preconditions;
+
+public class MessageBatcher {
+
+    public static final int NO_BATCH_SIZE = 0;
+
+    public interface BatchedOperation {
+        List<MessageRange> execute(MessageRange messageRange) throws 
MailboxException;
+    }
+
+    private final int moveBatchSize;
+
+    public MessageBatcher(int moveBatchSize) {
+        Preconditions.checkArgument(moveBatchSize >= NO_BATCH_SIZE);
+        this.moveBatchSize = moveBatchSize;
+    }
+
+    public List<MessageRange> batchMessages(MessageRange set, BatchedOperation 
batchedOperation) throws MailboxException {
+        if (moveBatchSize > 0) {
+            List<MessageRange> movedRanges = new ArrayList<MessageRange>();
+            for (MessageRange messageRange : set.split(moveBatchSize)) {
+                movedRanges.addAll(batchedOperation.execute(messageRange));
+            }
+            return movedRanges;
+        } else {
+            return batchedOperation.execute(set);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/b06992f1/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
index 7a2fda2..9262a87 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
@@ -21,7 +21,6 @@ package org.apache.james.mailbox.store;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Random;
@@ -99,9 +98,9 @@ public class StoreMailboxManager<Id extends MailboxId> 
implements MailboxManager
 
     private final static Random RANDOM = new Random();
 
-    private int copyBatchSize = 0;
+    private MessageBatcher copyBatcher;
 
-    private int moveBatchSize = 0;
+    private MessageBatcher moveBatcher;
 
     private final MailboxPathLocker locker;
 
@@ -148,11 +147,11 @@ public class StoreMailboxManager<Id extends MailboxId> 
implements MailboxManager
     }
 
     public void setCopyBatchSize(int copyBatchSize) {
-        this.copyBatchSize = copyBatchSize;
+        this.copyBatcher = new MessageBatcher(copyBatchSize);
     }
 
     public void setMoveBatchSize(int moveBatchSize) {
-        this.moveBatchSize = moveBatchSize;
+        this.moveBatcher = new MessageBatcher(moveBatchSize);
     }
 
     public void setFetchBatchSize(int fetchBatchSize) {
@@ -189,6 +188,12 @@ public class StoreMailboxManager<Id extends MailboxId> 
implements MailboxManager
         if (quotaUpdater != null && quotaUpdater instanceof MailboxListener) {
             this.addGlobalListener((MailboxListener) quotaUpdater, null);
         }
+        if (copyBatcher == null) {
+            copyBatcher = new MessageBatcher(MessageBatcher.NO_BATCH_SIZE);
+        }
+        if (moveBatcher == null) {
+            moveBatcher = new MessageBatcher(MessageBatcher.NO_BATCH_SIZE);
+        }
     }
 
     /**
@@ -505,38 +510,28 @@ public class StoreMailboxManager<Id extends MailboxId> 
implements MailboxManager
 
     @Override
     @SuppressWarnings("unchecked")
-    public List<MessageRange> copyMessages(MessageRange set, MailboxPath from, 
MailboxPath to, MailboxSession session) throws MailboxException {
-        StoreMessageManager<Id> toMailbox = (StoreMessageManager<Id>) 
getMailbox(to, session);
-        StoreMessageManager<Id> fromMailbox = (StoreMessageManager<Id>) 
getMailbox(from, session);
-
-        if (copyBatchSize > 0) {
-            List<MessageRange> copiedRanges = new ArrayList<MessageRange>();
-            Iterator<MessageRange> ranges = 
set.split(copyBatchSize).iterator();
-            while (ranges.hasNext()) {
-                copiedRanges.addAll(fromMailbox.copyTo(ranges.next(), 
toMailbox, session));
+    public List<MessageRange> copyMessages(MessageRange set, MailboxPath from, 
MailboxPath to, final MailboxSession session) throws MailboxException {
+        final StoreMessageManager<Id> toMailbox = (StoreMessageManager<Id>) 
getMailbox(to, session);
+        final StoreMessageManager<Id> fromMailbox = (StoreMessageManager<Id>) 
getMailbox(from, session);
+
+        return copyBatcher.batchMessages(set, new 
MessageBatcher.BatchedOperation() {
+            public List<MessageRange> execute(MessageRange messageRange) 
throws MailboxException {
+                return fromMailbox.copyTo(messageRange, toMailbox, session);
             }
-            return copiedRanges;
-        } else {
-            return fromMailbox.copyTo(set, toMailbox, session);
-        }
+        });
     }
 
     @Override
     @SuppressWarnings("unchecked")
-    public List<MessageRange> moveMessages(MessageRange set, MailboxPath from, 
MailboxPath to, MailboxSession session) throws MailboxException {
-        StoreMessageManager<Id> toMailbox = (StoreMessageManager<Id>) 
getMailbox(to, session);
-        StoreMessageManager<Id> fromMailbox = (StoreMessageManager<Id>) 
getMailbox(from, session);
-
-        if (moveBatchSize > 0) {
-            List<MessageRange> movedRanges = new ArrayList<MessageRange>();
-            Iterator<MessageRange> ranges = 
set.split(moveBatchSize).iterator();
-            while (ranges.hasNext()) {
-                movedRanges.addAll(fromMailbox.moveTo(ranges.next(), 
toMailbox, session));
+    public List<MessageRange> moveMessages(MessageRange set, MailboxPath from, 
MailboxPath to, final MailboxSession session) throws MailboxException {
+        final StoreMessageManager<Id> toMailbox = (StoreMessageManager<Id>) 
getMailbox(to, session);
+        final StoreMessageManager<Id> fromMailbox = (StoreMessageManager<Id>) 
getMailbox(from, session);
+
+        return moveBatcher.batchMessages(set, new 
MessageBatcher.BatchedOperation() {
+            public List<MessageRange> execute(MessageRange messageRange) 
throws MailboxException {
+                return fromMailbox.moveTo(messageRange, toMailbox, session);
             }
-            return movedRanges;
-        } else {
-            return fromMailbox.moveTo(set, toMailbox, session);
-        }
+        });
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/b06992f1/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
index 9005d89..f0098c3 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
@@ -51,6 +51,7 @@ import org.apache.james.mailbox.exception.ReadOnlyException;
 import org.apache.james.mailbox.exception.UnsupportedRightException;
 import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.MailboxACLRights;
+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.model.MessageResult.FetchGroup;
@@ -735,41 +736,29 @@ public class StoreMessageManager<Id extends MailboxId> 
implements org.apache.jam
        }
 
 
-    /**
-     * @see 
org.apache.james.mailbox.store.AbstractStoreMessageManager#copy(org.apache.james.mailbox.model.MessageRange,
-     *      org.apache.james.mailbox.store.AbstractStoreMessageManager,
-     *      org.apache.james.mailbox.MailboxSession)
-     */
     private SortedMap<Long, MessageMetaData> copy(MessageRange set, 
StoreMessageManager<Id> to, MailboxSession session) throws MailboxException {
+        Iterator<MailboxMessage<Id>> originalRows = retrieveOriginalRows(set, 
session);
+        return collectMetadata(to.copy(originalRows, session));
+    }
+
+    private SortedMap<Long, MessageMetaData> move(MessageRange set, 
StoreMessageManager<Id> to, MailboxSession session) throws MailboxException {
+        Iterator<MailboxMessage<Id>> originalRows = retrieveOriginalRows(set, 
session);
+        return collectMetadata(to.move(originalRows, session));
+    }
+
+    private Iterator<MailboxMessage<Id>> retrieveOriginalRows(MessageRange 
set, MailboxSession session) throws MailboxException {
         MessageMapper<Id> messageMapper = 
mapperFactory.getMessageMapper(session);
+        return messageMapper.findInMailbox(mailbox, set, FetchType.Full, -1);
+    }
 
+    private SortedMap<Long, MessageMetaData> 
collectMetadata(Iterator<MessageMetaData> ids) {
         final SortedMap<Long, MessageMetaData> copiedMessages = new 
TreeMap<Long, MessageMetaData>();
-        Iterator<MailboxMessage<Id>> originalRows = 
messageMapper.findInMailbox(mailbox, set, FetchType.Full, -1);
-        Iterator<MessageMetaData> ids = to.copy(originalRows, session);
         while (ids.hasNext()) {
             MessageMetaData data = ids.next();
             copiedMessages.put(data.getUid(), data);
         }
-
         return copiedMessages;
     }
-
-    private SortedMap<Long, MessageMetaData> move(MessageRange set,
-                       final StoreMessageManager<Id> to, MailboxSession 
session) throws MailboxException {
-        MessageMapper<Id> messageMapper = 
mapperFactory.getMessageMapper(session);
-
-        final SortedMap<Long, MessageMetaData> movedMessages = new 
TreeMap<Long, MessageMetaData>();
-        Iterator<MailboxMessage<Id>> originalRows = 
messageMapper.findInMailbox(mailbox, set, FetchType.Full, -1);
-        Iterator<MessageMetaData> ids = to.move(originalRows, session);
-        while (ids.hasNext()) {
-            MessageMetaData data = ids.next();
-            movedMessages.put(data.getUid(), data);
-        }
-
-        return movedMessages;
-       }
-
-
     /**
      * Return the count of unseen messages
      * 

http://git-wip-us.apache.org/repos/asf/james-project/blob/b06992f1/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBatcherTest.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBatcherTest.java
 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBatcherTest.java
new file mode 100644
index 0000000..7de44ee
--- /dev/null
+++ 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBatcherTest.java
@@ -0,0 +1,71 @@
+/****************************************************************
+ * 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;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MessageRange;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class MessageBatcherTest {
+
+    private MessageBatcher.BatchedOperation incrementBatcher = new 
MessageBatcher.BatchedOperation() {
+        @Override
+        public List<MessageRange> execute(MessageRange messageRange) throws 
MailboxException {
+            return 
Lists.<MessageRange>newArrayList(MessageRange.range(messageRange.getUidFrom() + 
1, messageRange.getUidTo() + 1));
+        }
+    };
+
+    @Test
+    public void batchMessagesShouldWorkOnSingleRangeMode() throws Exception {
+        MessageBatcher messageBatcher = new MessageBatcher(0);
+        
+        assertThat(messageBatcher.batchMessages(MessageRange.range(1, 10), 
incrementBatcher)).containsOnly(MessageRange.range(2, 11));
+    }
+
+    @Test
+    public void batchMessagesShouldWorkWithNonZeroBatchedSize() throws 
Exception {
+        MessageBatcher messageBatcher = new MessageBatcher(5);
+
+        assertThat(messageBatcher.batchMessages(MessageRange.range(1, 10), 
incrementBatcher)).containsOnly(MessageRange.range(2, 6), MessageRange.range(7, 
11));
+    }
+
+    @Test(expected = MailboxException.class)
+    public void batchMessagesShouldPropagateExceptions() throws Exception {
+        MessageBatcher messageBatcher = new MessageBatcher(0);
+
+        messageBatcher.batchMessages(MessageRange.range(1, 10), new 
MessageBatcher.BatchedOperation() {
+            public List<MessageRange> execute(MessageRange messageRange) 
throws MailboxException {
+                throw new MailboxException();
+            }
+        });
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void messageBatcherShouldThrowOnNegativeBatchSize() throws 
Exception {
+        MessageBatcher messageBatcher = new MessageBatcher(-1);
+    }
+
+}


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

Reply via email to