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 cc8848f9ed3ad006f050d701e3ebb4c96482c24e Author: Rene Cordier <[email protected]> AuthorDate: Thu Jun 11 11:03:06 2020 +0700 JAMES-3202 implement `retrieveIndexedFlags` in ElasticSearchListeningMessageSearchIndex --- .../org/apache/james/mailbox/FlagsBuilder.java | 42 +++++++++ .../ElasticSearchListeningMessageSearchIndex.java | 47 +++++++++- ...asticSearchListeningMessageSearchIndexTest.java | 101 +++++++++++++++++++++ 3 files changed, 187 insertions(+), 3 deletions(-) diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/FlagsBuilder.java b/mailbox/api/src/main/java/org/apache/james/mailbox/FlagsBuilder.java index 81f41fd..f891e5c 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/FlagsBuilder.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/FlagsBuilder.java @@ -62,6 +62,48 @@ public class FlagsBuilder { return this; } + public FlagsBuilder isAnswered(boolean isAnswered) { + if (isAnswered) { + internalFlags.add(Flags.Flag.ANSWERED); + } + return this; + } + + public FlagsBuilder isDraft(boolean isDraft) { + if (isDraft) { + internalFlags.add(Flags.Flag.DRAFT); + } + return this; + } + + public FlagsBuilder isDeleted(boolean isDeleted) { + if (isDeleted) { + internalFlags.add(Flags.Flag.DELETED); + } + return this; + } + + public FlagsBuilder isFlagged(boolean isFlagged) { + if (isFlagged) { + internalFlags.add(Flags.Flag.FLAGGED); + } + return this; + } + + public FlagsBuilder isRecent(boolean isRecent) { + if (isRecent) { + internalFlags.add(Flags.Flag.RECENT); + } + return this; + } + + public FlagsBuilder isSeen(boolean isSeen) { + if (isSeen) { + internalFlags.add(Flags.Flag.SEEN); + } + return this; + } + public Flags build() { return new Flags(internalFlags); } diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java index 20caacb..e23882c 100644 --- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java +++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java @@ -18,12 +18,20 @@ ****************************************************************/ package org.apache.james.mailbox.elasticsearch.events; +import static org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants.IS_ANSWERED; +import static org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants.IS_DELETED; +import static org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants.IS_DRAFT; +import static org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants.IS_FLAGGED; +import static org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants.IS_RECENT; +import static org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants.IS_UNREAD; +import static org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants.MAILBOX_ID; import static org.apache.james.util.ReactorUtils.publishIfPresent; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import java.util.Collection; import java.util.EnumSet; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Stream; @@ -35,13 +43,13 @@ import org.apache.james.backends.es.DocumentId; import org.apache.james.backends.es.ElasticSearchIndexer; import org.apache.james.backends.es.RoutingKey; import org.apache.james.backends.es.UpdatedRepresentation; +import org.apache.james.mailbox.FlagsBuilder; import org.apache.james.mailbox.MailboxManager.MessageCapabilities; import org.apache.james.mailbox.MailboxManager.SearchCapabilities; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.SessionProvider; import org.apache.james.mailbox.elasticsearch.MailboxElasticSearchConstants; -import org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants; import org.apache.james.mailbox.elasticsearch.json.MessageToElasticSearchJson; import org.apache.james.mailbox.elasticsearch.search.ElasticSearchSearcher; import org.apache.james.mailbox.events.Group; @@ -53,6 +61,8 @@ import org.apache.james.mailbox.model.UpdatedFlags; import org.apache.james.mailbox.store.MailboxSessionMapperFactory; import org.apache.james.mailbox.store.mail.model.MailboxMessage; import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.query.TermQueryBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -178,7 +188,7 @@ public class ElasticSearchListeningMessageSearchIndex extends ListeningMessageSe @Override public Mono<Void> deleteAll(MailboxSession session, MailboxId mailboxId) { TermQueryBuilder queryBuilder = termQuery( - JsonMessageConstants.MAILBOX_ID, + MAILBOX_ID, mailboxId.serialize()); return elasticSearchIndexer @@ -217,6 +227,37 @@ public class ElasticSearchListeningMessageSearchIndex extends ListeningMessageSe @Override public Mono<Flags> retrieveIndexedFlags(Mailbox mailbox, MessageUid uid) { - return Mono.empty(); + RoutingKey routingKey = routingKeyFactory.from(mailbox.getMailboxId()); + + return elasticSearchIndexer.get(indexIdFor(mailbox, uid), routingKey) + .filter(GetResponse::isExists) + .map(GetResponse::getSourceAsMap) + .map(this::extractFlags) + .switchIfEmpty(Mono.error(new IndexNotFoundException( + String.format("Index for message %s in mailbox %s not found", uid.toString(), mailbox.getMailboxId().serialize())))); + } + + private Flags extractFlags(Map<String, Object> source) { + FlagsBuilder flagsBuilder = FlagsBuilder.builder() + .isAnswered(extractFlag(source, IS_ANSWERED)) + .isDeleted(extractFlag(source, IS_DELETED)) + .isDraft(extractFlag(source, IS_DRAFT)) + .isFlagged(extractFlag(source, IS_FLAGGED)) + .isRecent(extractFlag(source, IS_RECENT)) + .isSeen(!extractFlag(source, IS_UNREAD)); + + for (String userFlag : extractUserFlags(source)) { + flagsBuilder.add(userFlag); + } + + return flagsBuilder.build(); + } + + private boolean extractFlag(Map<String, Object> source, String flag) { + return (Boolean) source.get(flag); + } + + private List<String> extractUserFlags(Map<String, Object> source) { + return (List<String>) source.get("userFlags"); } } diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java index b5a5359..4f80bb0 100644 --- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java +++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java @@ -37,6 +37,7 @@ import org.apache.james.backends.es.ReactorElasticSearchClient; import org.apache.james.core.Username; import org.apache.james.mailbox.Authorizator; import org.apache.james.mailbox.DefaultMailboxes; +import org.apache.james.mailbox.FlagsBuilder; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.ModSeq; @@ -76,6 +77,7 @@ import org.apache.james.mailbox.store.extractor.DefaultTextExtractor; import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder; import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage; import org.awaitility.Duration; +import org.elasticsearch.index.IndexNotFoundException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -443,4 +445,103 @@ class ElasticSearchListeningMessageSearchIndexTest { assertThatCode(() -> testee.deleteAll(session, mailbox.getMailboxId()).block()) .doesNotThrowAnyException(); } + + @Test + void retrieveIndexedFlagsShouldRetrieveSystemFlags() { + Flags flags = FlagsBuilder.builder() + .add(Flags.Flag.RECENT) + .add(Flags.Flag.DRAFT) + .build(); + + SimpleMailboxMessage message = MESSAGE_BUILDER.messageId(MESSAGE_ID_4) + .uid(MESSAGE_UID_4) + .flags(flags) + .build(); + + testee.add(session, mailbox, message).block(); + + assertThat(testee.retrieveIndexedFlags(mailbox, MESSAGE_UID_4).block()) + .isEqualTo(flags); + } + + @Test + void retrieveIndexedFlagsShouldReturnEmptyFlagsWhenNoFlags() { + Flags flags = new Flags(); + + SimpleMailboxMessage message = MESSAGE_BUILDER.messageId(MESSAGE_ID_4) + .uid(MESSAGE_UID_4) + .flags(flags) + .build(); + + testee.add(session, mailbox, message).block(); + + assertThat(testee.retrieveIndexedFlags(mailbox, MESSAGE_UID_4).block()) + .isEqualTo(flags); + } + + @Test + void retrieveIndexedFlagsShouldReturnAllSystemFlagsWhenAllFlagsSet() { + Flags flags = FlagsBuilder.builder() + .add(Flags.Flag.ANSWERED) + .add(Flags.Flag.DELETED) + .add(Flags.Flag.RECENT) + .add(Flags.Flag.DRAFT) + .add(Flags.Flag.FLAGGED) + .add(Flags.Flag.SEEN) + .build(); + + SimpleMailboxMessage message = MESSAGE_BUILDER.messageId(MESSAGE_ID_4) + .uid(MESSAGE_UID_4) + .flags(flags) + .build(); + + testee.add(session, mailbox, message).block(); + + assertThat(testee.retrieveIndexedFlags(mailbox, MESSAGE_UID_4).block()) + .isEqualTo(flags); + } + + @Test + void retrieveIndexedFlagsShouldReturnUserFlags() { + Flags flags = FlagsBuilder.builder() + .add("flag1") + .add("flag2") + .build(); + + SimpleMailboxMessage message = MESSAGE_BUILDER.messageId(MESSAGE_ID_4) + .uid(MESSAGE_UID_4) + .flags(flags) + .build(); + + testee.add(session, mailbox, message).block(); + + assertThat(testee.retrieveIndexedFlags(mailbox, MESSAGE_UID_4).block()) + .isEqualTo(flags); + } + + @Test + void retrieveIndexedFlagsShouldReturnUserAndSystemFlags() { + Flags flags = FlagsBuilder.builder() + .add(Flags.Flag.ANSWERED) + .add(Flags.Flag.DELETED) + .add("flag1") + .add("flag2") + .build(); + + SimpleMailboxMessage message = MESSAGE_BUILDER.messageId(MESSAGE_ID_4) + .uid(MESSAGE_UID_4) + .flags(flags) + .build(); + + testee.add(session, mailbox, message).block(); + + assertThat(testee.retrieveIndexedFlags(mailbox, MESSAGE_UID_4).block()) + .isEqualTo(flags); + } + + @Test + void retrieveIndexedFlagsShouldPropagateExceptionWhenNotFound() { + assertThatThrownBy(() -> testee.retrieveIndexedFlags(mailbox, MESSAGE_UID_4).block()) + .isInstanceOf(IndexNotFoundException.class); + } } \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
