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 1b5a9c75039dd236153e26e6c22fa1ef61d26a60 Author: Rene Cordier <[email protected]> AuthorDate: Wed Jun 10 17:43:28 2020 +0700 JAMES-3202 implement `retrieveIndexedFlags` in LuceneMailboxMessageSearchIndexTest --- .../lucene/search/LuceneMessageSearchIndex.java | 58 +++++++-- .../LuceneMailboxMessageSearchIndexTest.java | 137 +++++++++++++++++++++ 2 files changed, 186 insertions(+), 9 deletions(-) diff --git a/mailbox/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java b/mailbox/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java index 7337a4f..9a8e480 100644 --- a/mailbox/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java +++ b/mailbox/lucene/src/main/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndex.java @@ -1209,13 +1209,10 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { for (ScoreDoc sDoc : sDocs) { Document doc = searcher.doc(sDoc.doc); - if (doc.getFieldable(FLAGS_FIELD) == null) { - doc.removeFields(FLAGS_FIELD); - indexFlags(doc, f); + doc.removeFields(FLAGS_FIELD); + indexFlags(doc, f); - writer.updateDocument(new Term(ID_FIELD, doc.get(ID_FIELD)), doc); - - } + writer.updateDocument(new Term(ID_FIELD, doc.get(ID_FIELD)), doc); } } } @@ -1241,12 +1238,12 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { Flag[] flags = f.getSystemFlags(); for (Flag flag : flags) { fString.add(toString(flag)); - doc.add(new Field(FLAGS_FIELD, toString(flag), Store.NO, Index.NOT_ANALYZED)); + doc.add(new Field(FLAGS_FIELD, toString(flag), Store.YES, Index.NOT_ANALYZED)); } String[] userFlags = f.getUserFlags(); for (String userFlag : userFlags) { - doc.add(new Field(FLAGS_FIELD, userFlag, Store.NO, Index.NOT_ANALYZED)); + doc.add(new Field(FLAGS_FIELD, userFlag, Store.YES, Index.NOT_ANALYZED)); } // if no flags are there we just use a empty field @@ -1300,6 +1297,49 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { @Override public Mono<Flags> retrieveIndexedFlags(Mailbox mailbox, MessageUid uid) { - return Mono.empty(); + return Mono.fromCallable(() -> retrieveFlags(mailbox, uid)); + } + + private Flags retrieveFlags(Mailbox mailbox, MessageUid uid) throws IOException { + try (IndexSearcher searcher = new IndexSearcher(IndexReader.open(writer, true))) { + Flags retrievedFlags = new Flags(); + + BooleanQuery query = new BooleanQuery(); + query.add(new TermQuery(new Term(MAILBOX_ID_FIELD, mailbox.getMailboxId().serialize())), BooleanClause.Occur.MUST); + query.add(createQuery(MessageRange.one(uid)), BooleanClause.Occur.MUST); + query.add(new PrefixQuery(new Term(FLAGS_FIELD, "")), BooleanClause.Occur.MUST); + + TopDocs docs = searcher.search(query, 100000); + ScoreDoc[] sDocs = docs.scoreDocs; + for (ScoreDoc sDoc : sDocs) { + Document doc = searcher.doc(sDoc.doc); + + Stream.of(doc.getValues(FLAGS_FIELD)) + .forEach(flag -> fromString(flag).ifPresentOrElse(retrievedFlags::add, () -> retrievedFlags.add(flag))); + } + return retrievedFlags; + } + } + + /** + * Convert the given {@link Flag} to a String + */ + private Optional<Flag> fromString(String flag) { + switch (flag) { + case "\\ANSWERED": + return Optional.of(Flag.ANSWERED); + case "\\DELETED": + return Optional.of(Flag.DELETED); + case "\\DRAFT": + return Optional.of(Flag.DRAFT); + case "\\FLAGGED": + return Optional.of(Flag.FLAGGED); + case "\\RECENT": + return Optional.of(Flag.RECENT); + case "\\FLAG": + return Optional.of(Flag.SEEN); + default: + return Optional.empty(); + } } } \ No newline at end of file diff --git a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java index be30a35..15ac2a3 100644 --- a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java +++ b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java @@ -19,6 +19,7 @@ package org.apache.james.mailbox.lucene.search; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.james.mailbox.store.MessageIdManagerTestSystem.MOD_SEQ; import static org.assertj.core.api.Assertions.assertThat; import java.nio.charset.StandardCharsets; @@ -34,6 +35,7 @@ import javax.mail.Flags; import javax.mail.Flags.Flag; import org.apache.james.core.Username; +import org.apache.james.mailbox.FlagsBuilder; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MailboxSessionUtil; import org.apache.james.mailbox.MessageUid; @@ -49,12 +51,14 @@ import org.apache.james.mailbox.model.SearchQuery.Sort.SortClause; import org.apache.james.mailbox.model.TestId; import org.apache.james.mailbox.model.TestMessageId; import org.apache.james.mailbox.model.UidValidity; +import org.apache.james.mailbox.model.UpdatedFlags; import org.apache.james.mailbox.store.MessageBuilder; import org.apache.lucene.store.RAMDirectory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; class LuceneMailboxMessageSearchIndexTest { static final long LIMIT = 100L; @@ -614,4 +618,137 @@ class LuceneMailboxMessageSearchIndexTest { Stream<MessageUid> result = index.search(session, mailbox, query); assertThat(result).containsExactly(uid3, uid4); } + + @Test + void updateShouldUpdateFlags() throws Exception { + Flags newFlags = new Flags(Flags.Flag.DRAFT); + UpdatedFlags updatedFlags = UpdatedFlags.builder() + .uid(uid2) + .modSeq(MOD_SEQ) + .oldFlags(new Flags(Flag.ANSWERED)) + .newFlags(newFlags) + .build(); + + index.update(session, mailbox, Lists.newArrayList(updatedFlags)).block(); + + SearchQuery query = SearchQuery.of(SearchQuery.flagIsSet(Flags.Flag.DRAFT)); + assertThat(index.search(session, mailbox, query)) + .containsExactly(uid2); + } + + @Test + void updateShouldNotUpdateNorThrowOnUnknownMessageUid() throws Exception { + Flags newFlags = new Flags(Flags.Flag.DRAFT); + UpdatedFlags updatedFlags = UpdatedFlags.builder() + .uid(MessageUid.of(42)) + .modSeq(MOD_SEQ) + .oldFlags(new Flags()) + .newFlags(newFlags) + .build(); + + index.update(session, mailbox, Lists.newArrayList(updatedFlags)).block(); + + SearchQuery query = SearchQuery.of(SearchQuery.flagIsSet(Flags.Flag.DRAFT)); + assertThat(index.search(session, mailbox, query)) + .isEmpty(); + } + + @Test + void updateShouldBeIdempotent() throws Exception { + Flags newFlags = new Flags(Flags.Flag.DRAFT); + UpdatedFlags updatedFlags = UpdatedFlags.builder() + .uid(uid2) + .modSeq(MOD_SEQ) + .oldFlags(new Flags()) + .newFlags(newFlags) + .build(); + + index.update(session, mailbox, Lists.newArrayList(updatedFlags)).block(); + index.update(session, mailbox, Lists.newArrayList(updatedFlags)).block(); + + SearchQuery query = SearchQuery.of(SearchQuery.flagIsSet(Flags.Flag.DRAFT)); + assertThat(index.search(session, mailbox, query)) + .containsExactly(uid2); + } + + @Test + void retrieveIndexedFlagsShouldRetrieveSystemFlags() { + Flags expectedFlags = new Flags(Flag.ANSWERED); + + assertThat(index.retrieveIndexedFlags(mailbox, uid1).block()) + .isEqualTo(expectedFlags); + } + + @Test + void retrieveIndexedFlagsShouldReturnEmptyFlagsWhenNoFlags() { + Flags expectedFlags = new Flags(); + + assertThat(index.retrieveIndexedFlags(mailbox, uid5).block()) + .isEqualTo(expectedFlags); + } + + @Test + void retrieveIndexedFlagsShouldReturnAllSystemFlagsWhenAllFlagsSet() { + Flags newFlags = 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(); + + UpdatedFlags updatedFlags = UpdatedFlags.builder() + .uid(uid2) + .modSeq(MOD_SEQ) + .oldFlags(new Flags(Flag.ANSWERED)) + .newFlags(newFlags) + .build(); + + index.update(session, mailbox, Lists.newArrayList(updatedFlags)).block(); + + assertThat(index.retrieveIndexedFlags(mailbox, uid2).block()) + .isEqualTo(newFlags); + } + + @Test + void retrieveIndexedFlagsShouldReturnUserFlags() { + Flags newFlags = FlagsBuilder.builder() + .add("flag1") + .add("flag2") + .build(); + + UpdatedFlags updatedFlags = UpdatedFlags.builder() + .uid(uid2) + .modSeq(MOD_SEQ) + .oldFlags(new Flags(Flag.ANSWERED)) + .newFlags(newFlags) + .build(); + + index.update(session, mailbox, Lists.newArrayList(updatedFlags)).block(); + + assertThat(index.retrieveIndexedFlags(mailbox, uid2).block()) + .isEqualTo(newFlags); + } + + @Test + void retrieveIndexedFlagsShouldReturnUserAndSystemFlags() { + Flags newFlags = FlagsBuilder.builder() + .add("flag1") + .add("flag2") + .add(Flag.DRAFT) + .build(); + + UpdatedFlags updatedFlags = UpdatedFlags.builder() + .uid(uid2) + .modSeq(MOD_SEQ) + .oldFlags(new Flags(Flag.ANSWERED)) + .newFlags(newFlags) + .build(); + + index.update(session, mailbox, Lists.newArrayList(updatedFlags)).block(); + + assertThat(index.retrieveIndexedFlags(mailbox, uid2).block()) + .isEqualTo(newFlags); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
