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 673e909b50c01c8b70c9faaa738588140ff807ad
Author: Benoit Tellier <[email protected]>
AuthorDate: Mon Nov 16 14:19:43 2020 +0700

    JAMES-3440 JMAP RFC-8621 should use EmailQueryView when enabled
---
 .../apache/james/modules/TestJMAPServerModule.java |  1 +
 .../DistributedEmailQueryMethodNoViewTest.java     | 62 ++++++++++++++++
 .../src/test/resources/listeners.xml               |  4 +
 .../contract/EmailQueryMethodContract.scala        | 73 ++++++++++++++++++
 .../memory/MemoryEmailQueryMethodNoViewTest.java   | 58 +++++++++++++++
 .../src/test/resources/listeners.xml               |  4 +
 .../org/apache/james/jmap/mail/EmailQuery.scala    | 46 +++++++++++-
 .../james/jmap/method/EmailQueryMethod.scala       | 86 +++++++++++++++++++---
 8 files changed, 320 insertions(+), 14 deletions(-)

diff --git 
a/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
 
b/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
index d004632..83496ec 100644
--- 
a/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
+++ 
b/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
@@ -116,6 +116,7 @@ public class TestJMAPServerModule extends AbstractModule {
         return JMAPConfiguration.builder()
             .enable()
             .randomPort()
+            .enableEmailQueryView()
             .build();
     }
 
diff --git 
a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEmailQueryMethodNoViewTest.java
 
b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEmailQueryMethodNoViewTest.java
new file mode 100644
index 0000000..235118b
--- /dev/null
+++ 
b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEmailQueryMethodNoViewTest.java
@@ -0,0 +1,62 @@
+/****************************************************************
+ * 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.jmap.rfc8621.distributed;
+
+import org.apache.james.CassandraExtension;
+import org.apache.james.CassandraRabbitMQJamesConfiguration;
+import org.apache.james.CassandraRabbitMQJamesServerMain;
+import org.apache.james.DockerElasticSearchExtension;
+import org.apache.james.JamesServerBuilder;
+import org.apache.james.JamesServerExtension;
+import org.apache.james.jmap.JMAPConfiguration;
+import org.apache.james.jmap.rfc8621.contract.EmailQueryMethodContract;
+import org.apache.james.modules.AwsS3BlobStoreExtension;
+import org.apache.james.modules.RabbitMQExtension;
+import org.apache.james.modules.TestJMAPServerModule;
+import org.apache.james.modules.blobstore.BlobStoreConfiguration;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class DistributedEmailQueryMethodNoViewTest implements 
EmailQueryMethodContract {
+    public static final DockerElasticSearchExtension ELASTIC_SEARCH_EXTENSION 
= new DockerElasticSearchExtension();
+
+    @RegisterExtension
+    static JamesServerExtension testExtension = new 
JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir ->
+        CassandraRabbitMQJamesConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .blobStore(BlobStoreConfiguration.builder()
+                    .s3()
+                    .disableCache()
+                    .deduplication())
+            .build())
+        .extension(ELASTIC_SEARCH_EXTENSION)
+        .extension(new CassandraExtension())
+        .extension(new RabbitMQExtension())
+        .extension(new AwsS3BlobStoreExtension())
+        .server(configuration -> 
CassandraRabbitMQJamesServerMain.createServer(configuration)
+            .overrideWith(new TestJMAPServerModule())
+            .overrideWith(binder -> binder.bind(JMAPConfiguration.class)
+                .toInstance(JMAPConfiguration.builder()
+                    .enable()
+                    .randomPort()
+                    .disableEmailQueryView()
+                    .build())))
+        .build();
+}
diff --git 
a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
 
b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
index ff2e517..1ff4055 100644
--- 
a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
+++ 
b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
@@ -46,4 +46,8 @@
       <name>second</name>
     </configuration>
   </listener>
+  <listener>
+    <class>org.apache.james.jmap.event.PopulateEmailQueryViewListener</class>
+    <async>true</async>
+  </listener>
 </listeners>
\ No newline at end of file
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 9f9078a..ff8ec97 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
@@ -1629,6 +1629,78 @@ trait EmailQueryMethodContract {
   }
 
   @Test
+  def listMailsShouldBeSortedByDescendingOrderOfSentAtAndInMailbox(server: 
GuiceJamesServer): Unit = {
+    val mailboxId = 
server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB))
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+
+    val requestDateMessage1 = 
Date.from(ZonedDateTime.now().minusDays(1).toInstant)
+    val messageId1: MessageId = server.getProbe(classOf[MailboxProbeImpl])
+      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
+        AppendCommand.builder()
+          .withInternalDate(requestDateMessage1)
+          .build(message))
+      .getMessageId
+
+    val requestDateMessage2 = 
Date.from(ZonedDateTime.now().minusDays(2).toInstant)
+    val messageId2 = server.getProbe(classOf[MailboxProbeImpl])
+      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
+        AppendCommand.builder()
+          .withInternalDate(requestDateMessage2)
+          .build(message))
+      .getMessageId
+
+    val requestDateMessage3 = 
Date.from(ZonedDateTime.now().minusDays(3).toInstant)
+    val messageId3 = server.getProbe(classOf[MailboxProbeImpl])
+      .appendMessage(BOB.asString, MailboxPath.inbox(BOB),
+        AppendCommand.builder()
+          .withInternalDate(requestDateMessage3)
+          .build(message))
+      .getMessageId
+
+    val request =
+      s"""{
+         |  "using": [
+         |    "urn:ietf:params:jmap:core",
+         |    "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/query",
+         |    {
+         |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "filter": {
+         |        "inMailbox": "${mailboxId.serialize}"
+         |      },
+         |      "comparator": [{
+         |        "property":"sentAt",
+         |        "isAscending": false
+         |      }]
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+    assertThatJson(response)
+      .inPath("$.methodResponses[0][1].ids")
+      .isEqualTo(s"""["${messageId1.serialize}", "${messageId2.serialize}", 
"${messageId3.serialize}"]""")
+    }
+  }
+
+  @Test
   def listMailsShouldBeSortedByAscendingOrderOfSentAt(server: 
GuiceJamesServer): Unit = {
     
server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB))
     val otherMailboxPath = MailboxPath.forUser(BOB, "other")
@@ -2967,6 +3039,7 @@ trait EmailQueryMethodContract {
         .isEqualTo(s"""["${messageId1.serialize}"]""")
     }
   }
+
   @Test
   def shouldListMailsReceivedBeforeADateInclusively(server: GuiceJamesServer): 
Unit = {
     val message: Message = buildTestMessage
diff --git 
a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailQueryMethodNoViewTest.java
 
b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailQueryMethodNoViewTest.java
new file mode 100644
index 0000000..8cbe04a
--- /dev/null
+++ 
b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailQueryMethodNoViewTest.java
@@ -0,0 +1,58 @@
+/****************************************************************
+ * 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.jmap.rfc8621.memory;
+
+import static 
org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE;
+
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.JamesServerBuilder;
+import org.apache.james.JamesServerExtension;
+import org.apache.james.jmap.JMAPConfiguration;
+import org.apache.james.jmap.rfc8621.contract.EmailQueryMethodContract;
+import org.apache.james.modules.TestJMAPServerModule;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class MemoryEmailQueryMethodNoViewTest implements 
EmailQueryMethodContract {
+    @RegisterExtension
+    static JamesServerExtension testExtension = new 
JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        .server(configuration -> 
GuiceJamesServer.forConfiguration(configuration)
+            .combineWith(IN_MEMORY_SERVER_AGGREGATE_MODULE)
+            .overrideWith(new TestJMAPServerModule())
+            .overrideWith(binder -> binder.bind(JMAPConfiguration.class)
+                .toInstance(JMAPConfiguration.builder()
+                    .enable()
+                    .randomPort()
+                    .disableEmailQueryView()
+                    .build())))
+        .build();
+
+    @Test
+    @Override
+    @Disabled("JAMES-3377 Not supported for in-memory test")
+    public void 
emailQueryFilterByTextShouldIgnoreMarkupsInHtmlBody(GuiceJamesServer server) {}
+
+    @Test
+    @Override
+    @Disabled("JAMES-3377 Not supported for in-memory test" +
+        "In memory do not attempt message parsing a performs a full match on 
the raw message content")
+    public void 
emailQueryFilterByTextShouldIgnoreAttachmentContent(GuiceJamesServer server) {}
+}
diff --git 
a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
 
b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
index 59e3fec..a1a139d 100644
--- 
a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
+++ 
b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
@@ -43,4 +43,8 @@
       <name>second</name>
     </configuration>
   </listener>
+  <listener>
+    <class>org.apache.james.jmap.event.PopulateEmailQueryViewListener</class>
+    <async>true</async>
+  </listener>
 </listeners>
\ No newline at end of file
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailQuery.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailQuery.scala
index 7f154e1..462fff0 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailQuery.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailQuery.scala
@@ -35,7 +35,11 @@ case class UnsupportedFilterException(unsupportedFilter: 
String) extends Unsuppo
 case class UnsupportedNestingException(message: String) extends 
UnsupportedOperationException
 case class UnsupportedRequestParameterException(unsupportedParam: String) 
extends UnsupportedOperationException
 
-sealed trait FilterQuery
+sealed trait FilterQuery {
+  def inMailboxFilterOnly: Boolean
+
+  def inMailboxAndAfterFilterOnly: Boolean
+}
 
 sealed trait Operator
 case object And extends Operator
@@ -43,7 +47,11 @@ case object Or extends Operator
 case object Not extends Operator
 
 case class FilterOperator(operator: Operator,
-                          conditions: Seq[FilterQuery]) extends FilterQuery
+                          conditions: Seq[FilterQuery]) extends FilterQuery {
+  override val inMailboxFilterOnly: Boolean = false
+
+  override val inMailboxAndAfterFilterOnly: Boolean = false
+}
 
 case class Text(value: String) extends AnyVal
 case class From(value: String) extends AnyVal
@@ -81,7 +89,35 @@ case class FilterCondition(inMailbox: Option[MailboxId],
                            bcc: Option[Bcc],
                            subject: Option[Subject],
                            header: Option[Header],
-                           body: Option[Body]) extends FilterQuery
+                           body: Option[Body]) extends FilterQuery {
+  private val noOtherFiltersThanInMailboxAndAfter: Boolean = 
inMailboxOtherThan.isEmpty &&
+    before.isEmpty &&
+    hasKeyword.isEmpty &&
+    notKeyword.isEmpty &&
+    minSize.isEmpty &&
+    maxSize.isEmpty &&
+    hasAttachment.isEmpty &&
+    allInThreadHaveKeyword.isEmpty &&
+    someInThreadHaveKeyword.isEmpty &&
+    noneInThreadHaveKeyword.isEmpty &&
+    text.isEmpty &&
+    from.isEmpty &&
+    to.isEmpty &&
+    cc.isEmpty &&
+    bcc.isEmpty &&
+    subject.isEmpty &&
+    header.isEmpty &&
+    body.isEmpty
+
+  override val inMailboxFilterOnly: Boolean = inMailbox.nonEmpty &&
+    after.isEmpty &&
+    noOtherFiltersThanInMailboxAndAfter
+
+
+  override val inMailboxAndAfterFilterOnly: Boolean = inMailbox.nonEmpty &&
+    after.nonEmpty &&
+    noOtherFiltersThanInMailboxAndAfter
+}
 
 case class EmailQueryRequest(accountId: AccountId,
                              position: Option[PositionUnparsed],
@@ -163,6 +199,10 @@ case class IsAscending(sortByASC: Boolean) extends AnyVal {
 
 case class Collation(value: String) extends AnyVal
 
+object Comparator {
+  val SENT_AT_DESC: Comparator = Comparator(SentAtSortProperty, 
Some(IsAscending.DESCENDING), None)
+}
+
 case class Comparator(property: SortProperty,
                       isAscending: Option[IsAscending],
                       collation: Option[Collation]) {
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
index 6c32948..ae7d822 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
@@ -18,31 +18,40 @@
  ****************************************************************/
 package org.apache.james.jmap.method
 
+import java.time.ZonedDateTime
+
 import cats.implicits._
 import eu.timepit.refined.auto._
 import javax.inject.Inject
+import org.apache.james.jmap.JMAPConfiguration
+import org.apache.james.jmap.api.projections.EmailQueryView
 import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, 
JMAP_CORE, JMAP_MAIL}
 import org.apache.james.jmap.core.Invocation.{Arguments, MethodName}
 import org.apache.james.jmap.core.Limit.Limit
 import org.apache.james.jmap.core.Position.Position
 import org.apache.james.jmap.core.{CanCalculateChanges, Invocation, Limit, 
Position, QueryState}
 import org.apache.james.jmap.json.{EmailQuerySerializer, ResponseSerializer}
-import org.apache.james.jmap.mail.{Comparator, EmailQueryRequest, 
EmailQueryResponse, UnsupportedRequestParameterException}
+import org.apache.james.jmap.mail.{Comparator, EmailQueryRequest, 
EmailQueryResponse, FilterCondition, UnsupportedRequestParameterException}
 import org.apache.james.jmap.routes.SessionSupplier
 import org.apache.james.jmap.utils.search.MailboxFilter
 import org.apache.james.jmap.utils.search.MailboxFilter.QueryFilter
-import org.apache.james.mailbox.model.MultimailboxesSearchQuery
+import org.apache.james.mailbox.exception.MailboxNotFoundException
+import org.apache.james.mailbox.model.{MailboxId, MessageId, 
MultimailboxesSearchQuery}
 import org.apache.james.mailbox.{MailboxManager, MailboxSession}
 import org.apache.james.metrics.api.MetricFactory
+import org.apache.james.util.streams.{Limit => JavaLimit}
 import play.api.libs.json.{JsError, JsSuccess}
 import reactor.core.scala.publisher.{SFlux, SMono}
+import reactor.core.scheduler.Schedulers
 
 import scala.jdk.CollectionConverters._
 
 class EmailQueryMethod @Inject() (serializer: EmailQuerySerializer,
                                   mailboxManager: MailboxManager,
                                   val metricFactory: MetricFactory,
-                                  val sessionSupplier: SessionSupplier) 
extends MethodRequiringAccountId[EmailQueryRequest] {
+                                  val sessionSupplier: SessionSupplier,
+                                  val configuration: JMAPConfiguration,
+                                  val emailQueryView: EmailQueryView) extends 
MethodRequiringAccountId[EmailQueryRequest] {
   override val methodName: MethodName = MethodName("Email/query")
   override val requiredCapabilities: Set[CapabilityIdentifier] = 
Set(JMAP_CORE, JMAP_MAIL)
 
@@ -71,17 +80,72 @@ class EmailQueryMethod @Inject() (serializer: 
EmailQuerySerializer,
 
   override def getRequest(mailboxSession: MailboxSession, invocation: 
Invocation): SMono[EmailQueryRequest] = 
asEmailQueryRequest(invocation.arguments)
 
-  private def executeQuery(mailboxSession: MailboxSession, request: 
EmailQueryRequest, searchQuery: MultimailboxesSearchQuery, position: Position, 
limitToUse: Limit): SMono[EmailQueryResponse] = {
+  private def executeQuery(session: MailboxSession, request: 
EmailQueryRequest, searchQuery: MultimailboxesSearchQuery, position: Position, 
limit: Limit): SMono[EmailQueryResponse] = {
+    val ids: SMono[Seq[MessageId]] = request match {
+      case request: EmailQueryRequest if 
matchesInMailboxSortedBySentAt(request) =>
+        queryViewForListingSortedBySentAt(session, position, limit, request)
+      case request: EmailQueryRequest if 
matchesInMailboxAfterSortedBySentAt(request) =>
+        queryViewForContentAfterSortedBySentAt(session, position, limit, 
request)
+      case _ => executeQueryAgainstSearchIndex(session, searchQuery, position, 
limit)
+    }
+
+    ids.map(ids => toResponse(request, position, limit, ids))
+  }
+
+  private def queryViewForContentAfterSortedBySentAt(mailboxSession: 
MailboxSession, position: Position, limitToUse: Limit, request: 
EmailQueryRequest): SMono[Seq[MessageId]] = {
+    val condition: FilterCondition = 
request.filter.get.asInstanceOf[FilterCondition]
+    val mailboxId: MailboxId = condition.inMailbox.get
+    val after: ZonedDateTime = condition.after.get.asUTC
+    SMono.fromCallable(() => mailboxManager.getMailbox(mailboxId, 
mailboxSession))
+      .subscribeOn(Schedulers.elastic())
+      .`then`(SFlux.fromPublisher(
+        emailQueryView.listMailboxContentSinceReceivedAt(mailboxId, after, 
JavaLimit.from(limitToUse.value)))
+        .drop(position.value)
+        .take(limitToUse.value)
+        .collectSeq())
+      .onErrorResume({
+        case _: MailboxNotFoundException => SMono.just[Seq[MessageId]](Seq())
+        case e => SMono.raiseError[Seq[MessageId]](e)
+      })
+  }
+
+  private def queryViewForListingSortedBySentAt(mailboxSession: 
MailboxSession, position: Position, limitToUse: Limit, request: 
EmailQueryRequest): SMono[Seq[MessageId]] = {
+    val mailboxId: MailboxId = 
request.filter.get.asInstanceOf[FilterCondition].inMailbox.get
+    SMono.fromCallable(() => mailboxManager.getMailbox(mailboxId, 
mailboxSession))
+      .subscribeOn(Schedulers.elastic())
+      .`then`(SFlux.fromPublisher(
+        emailQueryView.listMailboxContent(mailboxId, 
JavaLimit.from(limitToUse.value)))
+        .drop(position.value)
+        .take(limitToUse.value)
+        .collectSeq())
+      .onErrorResume({
+        case _: MailboxNotFoundException => SMono.just[Seq[MessageId]](Seq())
+        case e => SMono.raiseError[Seq[MessageId]](e)
+      })
+  }
+
+  private def matchesInMailboxSortedBySentAt(request: EmailQueryRequest): 
Boolean =
+    configuration.isEmailQueryViewEnabled &&
+      request.filter.exists(_.inMailboxFilterOnly) &&
+      request.comparator.contains(Set(Comparator.SENT_AT_DESC))
+
+  private def matchesInMailboxAfterSortedBySentAt(request: EmailQueryRequest): 
Boolean =
+    configuration.isEmailQueryViewEnabled &&
+      request.filter.exists(_.inMailboxAndAfterFilterOnly) &&
+      request.comparator.contains(Set(Comparator.SENT_AT_DESC))
+
+  private def toResponse(request: EmailQueryRequest, position: Position, 
limitToUse: Limit, ids: Seq[MessageId]): EmailQueryResponse =
+    EmailQueryResponse(accountId = request.accountId,
+      queryState = QueryState.forIds(ids),
+      canCalculateChanges = CanCalculateChanges.CANNOT,
+      ids = ids,
+      position = position,
+      limit = Some(limitToUse).filterNot(used => 
request.limit.map(_.value).contains(used.value)))
+
+  private def executeQueryAgainstSearchIndex(mailboxSession: MailboxSession, 
searchQuery: MultimailboxesSearchQuery, position: Position, limitToUse: Limit): 
SMono[Seq[MessageId]] =
     SFlux.fromPublisher(mailboxManager.search(searchQuery, mailboxSession, 
position.value + limitToUse))
       .drop(position.value)
       .collectSeq()
-      .map(ids => EmailQueryResponse(accountId = request.accountId,
-        queryState = QueryState.forIds(ids),
-        canCalculateChanges = CanCalculateChanges.CANNOT,
-        ids = ids,
-        position = position,
-        limit = Some(limitToUse).filterNot(used => 
request.limit.map(_.value).contains(used.value))))
-  }
 
   private def searchQueryFromRequest(request: EmailQueryRequest, capabilities: 
Set[CapabilityIdentifier], session: MailboxSession): 
Either[UnsupportedOperationException, MultimailboxesSearchQuery] = {
     val comparators: List[Comparator] = 
request.comparator.getOrElse(Set()).toList


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

Reply via email to