This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 14ec290b041dafaf7d5eb847fdcd9a9fbffb792c
Author: Rene Cordier <[email protected]>
AuthorDate: Thu Nov 27 16:31:46 2025 +0700

    JAMES-3340 Minor refactorings
---
 .../projections/CassandraEmailQueryView.java       |  42 +---
 .../projections/PostgresEmailQueryViewDAO.java     |  50 ++---
 .../jmap/api/projections/EmailQueryViewUtils.java  |  19 ++
 .../contract/EmailQueryMethodContract.scala        | 248 ++++-----------------
 4 files changed, 85 insertions(+), 274 deletions(-)

diff --git 
a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/projections/CassandraEmailQueryView.java
 
b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/projections/CassandraEmailQueryView.java
index 4ddb6f69ab..f75b39f3f0 100644
--- 
a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/projections/CassandraEmailQueryView.java
+++ 
b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/projections/CassandraEmailQueryView.java
@@ -25,7 +25,7 @@ import static 
com.datastax.oss.driver.api.querybuilder.QueryBuilder.deleteFrom;
 import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.insertInto;
 import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.selectFrom;
 import static 
org.apache.james.jmap.api.projections.EmailQueryViewUtils.backendLimitFetch;
-import static 
org.apache.james.jmap.api.projections.EmailQueryViewUtils.messagesWithCollapseThreads;
+import static 
org.apache.james.jmap.api.projections.EmailQueryViewUtils.messagesWithMaybeCollapseThreads;
 import static 
org.apache.james.jmap.cassandra.projections.table.CassandraEmailQueryViewTable.DATE_LOOKUP_TABLE;
 import static 
org.apache.james.jmap.cassandra.projections.table.CassandraEmailQueryViewTable.MAILBOX_ID;
 import static 
org.apache.james.jmap.cassandra.projections.table.CassandraEmailQueryViewTable.MESSAGE_ID;
@@ -199,12 +199,8 @@ public class CassandraEmailQueryView implements 
EmailQueryView {
             .setInt(LIMIT_MARKER, backendFetchLimit.getLimit().get()))
             .map(asEmailEntry(SENT_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentSortedBySentAtWithBackendLimit(mailboxId, limit, 
collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentSortedBySentAtWithBackendLimit(mailboxId, limit, 
collapseThreads, newLimit));
     }
 
     @Override
@@ -221,12 +217,8 @@ public class CassandraEmailQueryView implements 
EmailQueryView {
                 .setInt(LIMIT_MARKER, backendFetchLimit.getLimit().get()))
             .map(asEmailEntry(RECEIVED_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentSortedByReceivedAtWithBackendLimit(mailboxId, limit, 
collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentSortedByReceivedAtWithBackendLimit(mailboxId, limit, 
collapseThreads, newLimit));
     }
 
     @Override
@@ -268,12 +260,8 @@ public class CassandraEmailQueryView implements 
EmailQueryView {
                 .setInt(LIMIT_MARKER, backendFetchLimit.getLimit().get()))
             .map(asEmailEntry(SENT_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentSinceAfterSortedByReceivedAtWithBackendLimit(mailboxId, 
since, limit, collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentSinceAfterSortedByReceivedAtWithBackendLimit(mailboxId, 
since, limit, collapseThreads, newLimit));
     }
 
     @Override
@@ -291,12 +279,8 @@ public class CassandraEmailQueryView implements 
EmailQueryView {
                 .setInt(LIMIT_MARKER, backendFetchLimit.getLimit().get()))
             .map(asEmailEntry(SENT_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentBeforeSortedByReceivedAtWithBackendLimit(mailboxId, since, 
limit, collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentBeforeSortedByReceivedAtWithBackendLimit(mailboxId, since, 
limit, collapseThreads, newLimit));
     }
 
     @Override
@@ -314,12 +298,8 @@ public class CassandraEmailQueryView implements 
EmailQueryView {
                 .setInt(LIMIT_MARKER, backendFetchLimit.getLimit().get()))
             .map(asEmailEntry(SENT_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentSinceSentAtWithBackendLimit(mailboxId, since, limit, 
collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentSinceSentAtWithBackendLimit(mailboxId, since, limit, 
collapseThreads, newLimit));
     }
 
     private Function<Row, EmailEntry> asEmailEntry(CqlIdentifier dateField) {
diff --git 
a/server/data/data-jmap-postgres/src/main/java/org/apache/james/jmap/postgres/projections/PostgresEmailQueryViewDAO.java
 
b/server/data/data-jmap-postgres/src/main/java/org/apache/james/jmap/postgres/projections/PostgresEmailQueryViewDAO.java
index a8c0296c12..ce2f235b81 100644
--- 
a/server/data/data-jmap-postgres/src/main/java/org/apache/james/jmap/postgres/projections/PostgresEmailQueryViewDAO.java
+++ 
b/server/data/data-jmap-postgres/src/main/java/org/apache/james/jmap/postgres/projections/PostgresEmailQueryViewDAO.java
@@ -20,7 +20,7 @@
 package org.apache.james.jmap.postgres.projections;
 
 import static 
org.apache.james.jmap.api.projections.EmailQueryViewUtils.backendLimitFetch;
-import static 
org.apache.james.jmap.api.projections.EmailQueryViewUtils.messagesWithCollapseThreads;
+import static 
org.apache.james.jmap.api.projections.EmailQueryViewUtils.messagesWithMaybeCollapseThreads;
 import static 
org.apache.james.jmap.postgres.projections.PostgresEmailQueryViewDataDefinition.PostgresEmailQueryViewTable.MAILBOX_ID;
 import static 
org.apache.james.jmap.postgres.projections.PostgresEmailQueryViewDataDefinition.PostgresEmailQueryViewTable.MESSAGE_ID;
 import static 
org.apache.james.jmap.postgres.projections.PostgresEmailQueryViewDataDefinition.PostgresEmailQueryViewTable.PK_CONSTRAINT_NAME;
@@ -77,12 +77,8 @@ public class PostgresEmailQueryViewDAO {
                 .limit(backendFetchLimit.getLimit().get())))
             .map(asEmailEntry(SENT_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentSortedBySentAtWithBackendLimit(mailboxId, limit, 
collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentSortedBySentAtWithBackendLimit(mailboxId, limit, 
collapseThreads, newLimit));
     }
 
     public Flux<MessageId> 
listMailboxContentSortedByReceivedAt(PostgresMailboxId mailboxId, Limit limit, 
boolean collapseThreads) {
@@ -101,12 +97,8 @@ public class PostgresEmailQueryViewDAO {
                 .limit(backendFetchLimit.getLimit().get())))
             .map(asEmailEntry(RECEIVED_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentSortedByReceivedAtWithBackendLimit(mailboxId, limit, 
collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentSortedByReceivedAtWithBackendLimit(mailboxId, limit, 
collapseThreads, newLimit));
     }
 
     public Flux<MessageId> 
listMailboxContentSinceAfterSortedBySentAt(PostgresMailboxId mailboxId, 
ZonedDateTime since, Limit limit, boolean collapseThreads) {
@@ -126,12 +118,8 @@ public class PostgresEmailQueryViewDAO {
                 .limit(backendFetchLimit.getLimit().get())))
             .map(asEmailEntry(SENT_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentSinceAfterSortedBySentAtWithBackendLimit(mailboxId, since, 
limit, collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentSinceAfterSortedBySentAtWithBackendLimit(mailboxId, since, 
limit, collapseThreads, newLimit));
     }
 
     public Flux<MessageId> 
listMailboxContentSinceAfterSortedByReceivedAt(PostgresMailboxId mailboxId, 
ZonedDateTime since, Limit limit, boolean collapseThreads) {
@@ -151,12 +139,8 @@ public class PostgresEmailQueryViewDAO {
                 .limit(backendFetchLimit.getLimit().get())))
             .map(asEmailEntry(RECEIVED_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentSinceAfterSortedByReceivedAtWithBackendLimit(mailboxId, 
since, limit, collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentSinceAfterSortedByReceivedAtWithBackendLimit(mailboxId, 
since, limit, collapseThreads, newLimit));
     }
 
     public Flux<MessageId> 
listMailboxContentBeforeSortedByReceivedAt(PostgresMailboxId mailboxId, 
ZonedDateTime since, Limit limit, boolean collapseThreads) {
@@ -176,12 +160,8 @@ public class PostgresEmailQueryViewDAO {
                 .limit(backendFetchLimit.getLimit().get())))
             .map(asEmailEntry(RECEIVED_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentBeforeSortedByReceivedAtWithBackendLimit(mailboxId, since, 
limit, collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentBeforeSortedByReceivedAtWithBackendLimit(mailboxId, since, 
limit, collapseThreads, newLimit));
     }
 
     public Flux<MessageId> listMailboxContentSinceSentAt(PostgresMailboxId 
mailboxId, ZonedDateTime since, Limit limit, boolean collapseThreads) {
@@ -201,12 +181,8 @@ public class PostgresEmailQueryViewDAO {
                 .limit(backendFetchLimit.getLimit().get())))
             .map(asEmailEntry(SENT_AT));
 
-        if (collapseThreads) {
-            return messagesWithCollapseThreads(limit, backendFetchLimit, 
baseEntries,
-                newLimit -> 
listMailboxContentSinceSentAtWithBackendLimit(mailboxId, since, limit, 
collapseThreads, newLimit));
-        }
-
-        return baseEntries.map(EmailEntry::getMessageId);
+        return messagesWithMaybeCollapseThreads(limit, backendFetchLimit, 
baseEntries, collapseThreads,
+            newLimit -> 
listMailboxContentSinceSentAtWithBackendLimit(mailboxId, since, limit, 
collapseThreads, newLimit));
     }
 
     private Function<Record, EmailEntry> asEmailEntry(Field<OffsetDateTime> 
dateField) {
diff --git 
a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/projections/EmailQueryViewUtils.java
 
b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/projections/EmailQueryViewUtils.java
index 42f8ee454f..f604ce68f5 100644
--- 
a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/projections/EmailQueryViewUtils.java
+++ 
b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/projections/EmailQueryViewUtils.java
@@ -100,6 +100,25 @@ public class EmailQueryViewUtils {
             });
     }
 
+    public static Flux<MessageId> messagesWithMaybeCollapseThreads(Limit 
limit, Limit backendFetchLimit, Flux<EmailEntry> baseEntries, boolean 
collapseThreads, Function<Limit, Flux<MessageId>> listMessagesCallbackFunction) 
{
+        if (collapseThreads) {
+            return baseEntries.collectList()
+                .flatMapMany(results -> {
+                    List<EmailEntry> distinctByThreadId = 
distinctByThreadId(results);
+                    boolean hasEnoughResults = distinctByThreadId.size() >= 
limit.getLimit().get();
+                    boolean isExhaustive = results.size() < 
backendFetchLimit.getLimit().get();
+                    if (hasEnoughResults || isExhaustive) {
+                        return Flux.fromIterable(distinctByThreadId)
+                            .take(limit.getLimit().get())
+                            .map(EmailEntry::getMessageId);
+                    }
+                    Limit newBackendFetchLimit = 
Limit.from(backendFetchLimit.getLimit().get() * 
COLLAPSE_THREADS_LIMIT_MULTIPLIER);
+                    return 
listMessagesCallbackFunction.apply(newBackendFetchLimit);
+                });
+        }
+        return baseEntries.map(EmailEntry::getMessageId);
+    }
+
     private static List<EmailEntry> distinctByThreadId(List<EmailEntry> 
emailEntries) {
         ImmutableList.Builder<EmailEntry> list = ImmutableList.builder();
         HashSet<ThreadId> threadIdHashSet = new HashSet<>();
diff --git 
a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala
 
b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala
index f90c310660..8ebaa69b5f 100644
--- 
a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala
+++ 
b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala
@@ -7472,26 +7472,9 @@ trait EmailQueryMethodContract {
 
   @Test
   def inMailboxAfterSortedByReceivedAtShouldCollapseThreads(server: 
GuiceJamesServer): Unit = {
-    val message1: Message = Message.Builder
-      .of
-      .setSubject("test")
-      .setMessageId("Message-ID")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
-
-    val message2: Message = Message.Builder
-      .of
-      .setSubject("BTW")
-      .setMessageId("Message-ID-2")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
-
-    val message3: Message = Message.Builder
-      .of
-      .setSubject("Hello again")
-      .setMessageId("Message-ID-3")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
+    val message1: Message = buildTestThreadMessage("test", "Message-ID")
+    val message2: Message = buildTestThreadMessage("BTW", "Message-ID-2")
+    val message3: Message = buildTestThreadMessage("Hello again", 
"Message-ID-3")
 
     val beforeRequestDate1 = 
Date.from(ZonedDateTime.now().minusDays(3).toInstant)
     val requestDate = ZonedDateTime.now().minusDays(1)
@@ -7500,31 +7483,11 @@ trait EmailQueryMethodContract {
     val afterRequestDate3 = 
Date.from(ZonedDateTime.now().plusDays(2).toInstant)
     val mailboxProbe = server.getProbe(classOf[MailboxProbeImpl])
     val mailboxId = mailboxProbe.createMailbox(MailboxPath.inbox(BOB))
-    val messageId1: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(beforeRequestDate1)
-          .build(message1))
-      .getMessageId
 
-    val messageId2: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(afterRequestDate1)
-        .build(message2))
-      .getMessageId
-
-    val messageId3: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(afterRequestDate2)
-          .build(message3))
-      .getMessageId
-
-    val messageId4: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(afterRequestDate3)
-        .build(message3))
-      .getMessageId
+    val messageId1: MessageId = sendMessageToBobInbox(server, message1, 
beforeRequestDate1)
+    val messageId2: MessageId = sendMessageToBobInbox(server, message2, 
afterRequestDate1)
+    val messageId3: MessageId = sendMessageToBobInbox(server, message3, 
afterRequestDate2)
+    val messageId4: MessageId = sendMessageToBobInbox(server, message3, 
afterRequestDate3)
 
     val request =
       s"""{
@@ -7582,19 +7545,8 @@ trait EmailQueryMethodContract {
 
   @Test
   def inMailboxSortedByReceivedAtShouldCollapseThreads(server: 
GuiceJamesServer): Unit = {
-    val message1: Message = Message.Builder
-      .of
-      .setSubject("test")
-      .setMessageId("Message-ID")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
-
-    val message2: Message = Message.Builder
-      .of
-      .setSubject("BTW")
-      .setMessageId("Message-ID-2")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
+    val message1: Message = buildTestThreadMessage("test", "Message-ID")
+    val message2: Message = buildTestThreadMessage("BTW", "Message-ID-2")
 
     val beforeRequestDate1 = 
Date.from(ZonedDateTime.now().minusDays(3).toInstant)
     val beforeRequestDate2 = 
Date.from(ZonedDateTime.now().minusDays(2).toInstant)
@@ -7602,31 +7554,11 @@ trait EmailQueryMethodContract {
     val afterRequestDate2 = 
Date.from(ZonedDateTime.now().plusDays(1).toInstant)
     val mailboxProbe = server.getProbe(classOf[MailboxProbeImpl])
     val mailboxId = mailboxProbe.createMailbox(MailboxPath.inbox(BOB))
-    val messageId1: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(beforeRequestDate1)
-          .build(message1))
-      .getMessageId
-
-    val messageId2: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(beforeRequestDate2)
-        .build(message1))
-      .getMessageId
 
-    val messageId3: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(afterRequestDate1)
-          .build(message2))
-      .getMessageId
-
-    val messageId4: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(afterRequestDate2)
-        .build(message2))
-      .getMessageId
+    val messageId1: MessageId = sendMessageToBobInbox(server, message1, 
beforeRequestDate1)
+    val messageId2: MessageId = sendMessageToBobInbox(server, message1, 
beforeRequestDate2)
+    val messageId3: MessageId = sendMessageToBobInbox(server, message2, 
afterRequestDate1)
+    val messageId4: MessageId = sendMessageToBobInbox(server, message2, 
afterRequestDate2)
 
     val request =
       s"""{
@@ -7683,26 +7615,9 @@ trait EmailQueryMethodContract {
 
   @Test
   def inMailboxAfterSortedBySentAtShouldCollapseThreads(server: 
GuiceJamesServer): Unit = {
-    val message1: Message = Message.Builder
-      .of
-      .setSubject("test")
-      .setMessageId("Message-ID")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
-
-    val message2: Message = Message.Builder
-      .of
-      .setSubject("BTW")
-      .setMessageId("Message-ID-2")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
-
-    val message3: Message = Message.Builder
-      .of
-      .setSubject("Hello again")
-      .setMessageId("Message-ID-3")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
+    val message1: Message = buildTestThreadMessage("test", "Message-ID")
+    val message2: Message = buildTestThreadMessage("BTW", "Message-ID-2")
+    val message3: Message = buildTestThreadMessage("Hello again", 
"Message-ID-3")
 
     val beforeRequestDate1 = 
Date.from(ZonedDateTime.now().minusDays(3).toInstant)
     val requestDate = ZonedDateTime.now().minusDays(1)
@@ -7711,31 +7626,11 @@ trait EmailQueryMethodContract {
     val afterRequestDate3 = 
Date.from(ZonedDateTime.now().plusDays(2).toInstant)
     val mailboxProbe = server.getProbe(classOf[MailboxProbeImpl])
     val mailboxId = mailboxProbe.createMailbox(MailboxPath.inbox(BOB))
-    val messageId1: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(beforeRequestDate1)
-          .build(message1))
-      .getMessageId
 
-    val messageId2: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(afterRequestDate1)
-        .build(message2))
-      .getMessageId
-
-    val messageId3: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(afterRequestDate2)
-          .build(message3))
-      .getMessageId
-
-    val messageId4: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(afterRequestDate3)
-        .build(message3))
-      .getMessageId
+    val messageId1: MessageId = sendMessageToBobInbox(server, message1, 
beforeRequestDate1)
+    val messageId2: MessageId = sendMessageToBobInbox(server, message2, 
afterRequestDate1)
+    val messageId3: MessageId = sendMessageToBobInbox(server, message3, 
afterRequestDate2)
+    val messageId4: MessageId = sendMessageToBobInbox(server, message3, 
afterRequestDate3)
 
     val request =
       s"""{
@@ -7793,19 +7688,8 @@ trait EmailQueryMethodContract {
 
   @Test
   def inMailboxSortedBySentAtShouldCollapseThreads(server: GuiceJamesServer): 
Unit = {
-    val message1: Message = Message.Builder
-      .of
-      .setSubject("test")
-      .setMessageId("Message-ID")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
-
-    val message2: Message = Message.Builder
-      .of
-      .setSubject("BTW")
-      .setMessageId("Message-ID-2")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
+    val message1: Message = buildTestThreadMessage("test", "Message-ID")
+    val message2: Message = buildTestThreadMessage("BTW", "Message-ID-2")
 
     val beforeRequestDate1 = 
Date.from(ZonedDateTime.now().minusDays(3).toInstant)
     val beforeRequestDate2 = 
Date.from(ZonedDateTime.now().minusDays(2).toInstant)
@@ -7813,31 +7697,11 @@ trait EmailQueryMethodContract {
     val afterRequestDate2 = 
Date.from(ZonedDateTime.now().plusDays(1).toInstant)
     val mailboxProbe = server.getProbe(classOf[MailboxProbeImpl])
     val mailboxId = mailboxProbe.createMailbox(MailboxPath.inbox(BOB))
-    val messageId1: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(beforeRequestDate1)
-          .build(message1))
-      .getMessageId
-
-    val messageId2: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(beforeRequestDate2)
-        .build(message1))
-      .getMessageId
 
-    val messageId3: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(afterRequestDate1)
-          .build(message2))
-      .getMessageId
-
-    val messageId4: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(afterRequestDate2)
-        .build(message2))
-      .getMessageId
+    val messageId1: MessageId = sendMessageToBobInbox(server, message1, 
beforeRequestDate1)
+    val messageId2: MessageId = sendMessageToBobInbox(server, message1, 
beforeRequestDate2)
+    val messageId3: MessageId = sendMessageToBobInbox(server, message2, 
afterRequestDate1)
+    val messageId4: MessageId = sendMessageToBobInbox(server, message2, 
afterRequestDate2)
 
     val request =
       s"""{
@@ -7894,26 +7758,9 @@ trait EmailQueryMethodContract {
 
   @Test
   def inMailboxBeforeSortedByReceivedAtShouldCollapseThreads(server: 
GuiceJamesServer): Unit = {
-    val message1: Message = Message.Builder
-      .of
-      .setSubject("test")
-      .setMessageId("Message-ID")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
-
-    val message2: Message = Message.Builder
-      .of
-      .setSubject("BTW")
-      .setMessageId("Message-ID-2")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
-
-    val message3: Message = Message.Builder
-      .of
-      .setSubject("Hello again")
-      .setMessageId("Message-ID-3")
-      .setBody("testmail", StandardCharsets.UTF_8)
-      .build
+    val message1: Message = buildTestThreadMessage("test", "Message-ID")
+    val message2: Message = buildTestThreadMessage("BTW", "Message-ID-2")
+    val message3: Message = buildTestThreadMessage("Hello again", 
"Message-ID-3")
 
     val beforeRequestDate1 = 
Date.from(ZonedDateTime.now().minusDays(3).toInstant)
     val beforeRequestDate2 = 
Date.from(ZonedDateTime.now().minusDays(2).toInstant)
@@ -7922,31 +7769,11 @@ trait EmailQueryMethodContract {
     val afterRequestDate1 = 
Date.from(ZonedDateTime.now().plusDays(1).toInstant)
     val mailboxProbe = server.getProbe(classOf[MailboxProbeImpl])
     val mailboxId = mailboxProbe.createMailbox(MailboxPath.inbox(BOB))
-    val messageId1: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(beforeRequestDate1)
-          .build(message1))
-      .getMessageId
-
-    val messageId2: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(beforeRequestDate2)
-        .build(message2))
-      .getMessageId
-
-    val messageId3: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
-        AppendCommand.builder()
-          .withInternalDate(beforeRequestDate3)
-          .build(message2))
-      .getMessageId
 
-    val messageId4: MessageId = mailboxProbe
-      .appendMessage(BOB.asString, MailboxPath.inbox(BOB), 
AppendCommand.builder()
-        .withInternalDate(afterRequestDate1)
-        .build(message3))
-      .getMessageId
+    val messageId1: MessageId = sendMessageToBobInbox(server, message1, 
beforeRequestDate1)
+    val messageId2: MessageId = sendMessageToBobInbox(server, message2, 
beforeRequestDate2)
+    val messageId3: MessageId = sendMessageToBobInbox(server, message2, 
beforeRequestDate3)
+    val messageId4: MessageId = sendMessageToBobInbox(server, message3, 
afterRequestDate1)
 
     val request =
       s"""{
@@ -8009,6 +7836,15 @@ trait EmailQueryMethodContract {
       .getMessageId
   }
 
+  private def buildTestThreadMessage(subject: String, mimeMessageId: String) = 
{
+    Message.Builder
+      .of
+      .setMessageId(mimeMessageId)
+      .setSubject(subject)
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+  }
+
   private def generateQueryState(messages: MessageId*): String =
     Hashing.murmur3_32_fixed()
       .hashUnencodedChars(messages.toList.map(_.serialize).mkString(" "))


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

Reply via email to