This is an automated email from the ASF dual-hosted git repository. rcordier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 4221fdc120dce9d471f12c7f25b02fdc2ebd0d1f Author: TungTV <vtt...@linagora.com> AuthorDate: Mon Sep 30 14:27:22 2024 +0700 JAMES-4046 LuceneMessageSearchIndex - clean code --- .../lucene/search/LuceneMessageSearchIndex.java | 153 ++++++++------------- 1 file changed, 54 insertions(+), 99 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 0e65faed85..80758f25b6 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 @@ -33,7 +33,6 @@ import java.util.List; import java.util.Locale; import java.util.Optional; import java.util.Set; -import java.util.TimeZone; import java.util.stream.Stream; import jakarta.annotation.PreDestroy; @@ -41,6 +40,7 @@ import jakarta.inject.Inject; import jakarta.mail.Flags; import jakarta.mail.Flags.Flag; +import org.apache.commons.lang3.StringUtils; import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxManager.SearchCapabilities; import org.apache.james.mailbox.MailboxSession; @@ -54,7 +54,6 @@ import org.apache.james.mailbox.model.MessageAttachmentMetadata; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.model.SearchQuery; -import org.apache.james.mailbox.model.SearchQuery.AllCriterion; import org.apache.james.mailbox.model.SearchQuery.AttachmentCriterion; import org.apache.james.mailbox.model.SearchQuery.ContainsOperator; import org.apache.james.mailbox.model.SearchQuery.Criterion; @@ -63,7 +62,6 @@ import org.apache.james.mailbox.model.SearchQuery.DateOperator; import org.apache.james.mailbox.model.SearchQuery.DateResolution; import org.apache.james.mailbox.model.SearchQuery.FlagCriterion; import org.apache.james.mailbox.model.SearchQuery.HeaderCriterion; -import org.apache.james.mailbox.model.SearchQuery.HeaderOperator; import org.apache.james.mailbox.model.SearchQuery.NumericOperator; import org.apache.james.mailbox.model.SearchQuery.UidCriterion; import org.apache.james.mailbox.model.SearchQuery.UidRange; @@ -368,6 +366,8 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { private static final String MEDIA_TYPE_TEXT = "text"; private static final String MEDIA_TYPE_MESSAGE = "message"; private static final String DEFAULT_ENCODING = "US-ASCII"; + private static final boolean INCLUDE_LOWER = true; + private static final boolean INCLUDE_UPPER = true; private static final SortField UID_SORT = new SortField(UID_FIELD, SortField.Type.LONG); private static final SortField UID_SORT_REVERSE = new SortField(UID_FIELD, SortField.Type.LONG, true); @@ -472,7 +472,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { * If set to true this implementation will use {@link WildcardQuery} to match suffix and prefix. This is what RFC3501 expects but is often not what the user does. * It also slow things a lot if you have complex queries which use many "TEXT" arguments. If you want the implementation to behave strict like RFC3501 says, you should * set this to true. - * + * <p> * The default is false for performance reasons */ public void setEnableSuffixMatch(boolean suffixMatch) { @@ -498,6 +498,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { return Flux.fromIterable(searchMultimap(mailboxIds, searchQuery) .stream() + .filter(searchResult -> searchResult.getMessageId().isPresent()) .map(searchResult -> searchResult.getMessageId().get()) .filter(SearchUtil.distinct()) .limit(Long.valueOf(limit).intValue()) @@ -528,7 +529,8 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { Document doc = searcher.storedFields().document(sDoc.doc); MessageUid uid = MessageUid.of(doc.getField(UID_FIELD).numericValue().longValue()); MailboxId mailboxId = mailboxIdFactory.fromString(doc.get(MAILBOX_ID_FIELD)); - Optional<MessageId> messageId = toMessageId(Optional.ofNullable(doc.get(MESSAGE_ID_FIELD))); + Optional<MessageId> messageId = Optional.ofNullable(doc.get(MESSAGE_ID_FIELD)) + .map(messageIdFactory::fromString); results.add(new SearchResult(messageId, mailboxId, uid)); } } catch (IOException e) { @@ -537,10 +539,6 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { return results.build(); } - private Optional<MessageId> toMessageId(Optional<String> messageIdField) { - return messageIdField.map(messageIdFactory::fromString); - } - private Query buildQueryFromMailboxes(Collection<MailboxId> mailboxIds) { BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder(); for (MailboxId id: mailboxIds) { @@ -552,7 +550,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { /** * Create a new {@link Document} for the given {@link MailboxMessage}. This Document does not contain any flags data. The {@link Flags} are stored in a seperate Document. - * + * <p> * See {@link #createFlagsDocument(MailboxMessage)} */ private Document createMessageDocument(final MailboxSession session, final MailboxMessage membership) throws IOException, MimeException { @@ -574,8 +572,8 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { doc.add(new StringField(THREAD_ID_FIELD, serializedThreadId, Store.YES)); } - // create an unqiue key for the document which can be used later on updates to find the document - doc.add(new StringField(ID_FIELD, membership.getMailboxId().serialize().toUpperCase(Locale.US) + "-" + Long.toString(membership.getUid().asLong()), Store.YES)); + // create a unique key for the document which can be used later on updates to find the document + doc.add(new StringField(ID_FIELD, membership.getMailboxId().serialize().toUpperCase(Locale.US) + "-" + membership.getUid().asLong(), Store.YES)); doc.add(new StringField(INTERNAL_DATE_FIELD_YEAR_RESOLUTION, DateTools.dateToString(membership.getInternalDate(), DateTools.Resolution.YEAR), Store.NO)); doc.add(new StringField(INTERNAL_DATE_FIELD_MONTH_RESOLUTION, DateTools.dateToString(membership.getInternalDate(), DateTools.Resolution.MONTH), Store.NO)); @@ -633,7 +631,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { } - // Check if we can index the the address in the right manner + // Check if we can index the address in the right manner if (field != null) { // not sure if we really should reparse it. It maybe be better to check just for the right type. // But this impl was easier in the first place @@ -756,7 +754,6 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { // parse the message to index headers and body parser.parse(membership.getFullContent()); - return doc; } @@ -775,10 +772,6 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { }; } - private static Calendar getGMT() { - return Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.US); - } - private String toInteralDateField(DateResolution res) { return switch (res) { case Year -> INTERNAL_DATE_FIELD_YEAR_RESOLUTION; @@ -804,7 +797,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { /** * Return a {@link Query} which is build based on the given {@link SearchQuery.InternalDateCriterion} */ - private Query createInternalDateQuery(SearchQuery.InternalDateCriterion crit) throws UnsupportedSearchException { + private Query createInternalDateQuery(SearchQuery.InternalDateCriterion crit) { DateOperator dop = crit.getOperator(); DateResolution res = dop.getDateResultion(); String field = toInteralDateField(res); @@ -814,7 +807,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { /** * Return a {@link Query} which is build based on the given {@link SearchQuery.SaveDateCriterion} */ - private Query createSaveDateQuery(SearchQuery.SaveDateCriterion crit) throws UnsupportedSearchException { + private Query createSaveDateQuery(SearchQuery.SaveDateCriterion crit) { DateOperator dop = crit.getOperator(); DateResolution res = dop.getDateResultion(); String field = toSaveDateField(res); @@ -824,7 +817,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { /** * Return a {@link Query} which is build based on the given {@link SearchQuery.SizeCriterion} */ - private Query createSizeQuery(SearchQuery.SizeCriterion crit) throws UnsupportedSearchException { + private Query createSizeQuery(SearchQuery.SizeCriterion crit) { NumericOperator op = crit.getOperator(); return switch (op.getType()) { case EQUALS -> LongPoint.newExactQuery(SIZE_FIELD, op.getValue()); @@ -848,28 +841,19 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { * Return a {@link Query} which is build based on the given {@link SearchQuery.HeaderCriterion} */ private Query createHeaderQuery(SearchQuery.HeaderCriterion crit) throws UnsupportedSearchException { - HeaderOperator op = crit.getOperator(); + if (crit.getOperator() == null) { + throw new UnsupportedSearchException(); + } + String name = crit.getHeaderName().toUpperCase(Locale.US); String fieldName = PREFIX_HEADER_FIELD + name; - switch (op) { - case ContainsOperator cop -> { - return createTermQuery(fieldName, cop.getValue().toUpperCase(Locale.US)); - } - case SearchQuery.ExistsOperator existsOperator -> { - return new PrefixQuery(new Term(fieldName, "")); - } - case DateOperator dop -> { - String field = toSentDateField(dop.getDateResultion()); - return createQuery(field, dop); - } - case SearchQuery.AddressOperator addressOperator -> { - String field = name.toLowerCase(Locale.US); - return createTermQuery(field, addressOperator.getAddress().toUpperCase(Locale.US)); - } - case null, default -> - // Operator not supported - throw new UnsupportedSearchException(); - } + return switch (crit.getOperator()) { + case ContainsOperator cop -> createTermQuery(fieldName, cop.getValue().toUpperCase(Locale.US)); + case SearchQuery.ExistsOperator existsOperator -> new PrefixQuery(new Term(fieldName, StringUtils.EMPTY)); + case DateOperator dop -> createQuery(toSentDateField(dop.getDateResultion()), dop); + case SearchQuery.AddressOperator addressOperator -> createTermQuery(name.toLowerCase(Locale.US), addressOperator.getAddress().toUpperCase(Locale.US)); + default -> throw new UnsupportedSearchException(); + }; } @@ -880,10 +864,8 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { String value = DateTools.dateToString(date, dRes); return switch (dop.getType()) { case ON -> new TermQuery(new Term(field, value)); - case BEFORE -> - TermRangeQuery.newStringRange(field, DateTools.dateToString(MIN_DATE, dRes), value, true, false); - case AFTER -> - TermRangeQuery.newStringRange(field, value, DateTools.dateToString(MAX_DATE, dRes), false, true); + case BEFORE -> TermRangeQuery.newStringRange(field, DateTools.dateToString(MIN_DATE, dRes), value, INCLUDE_LOWER, !INCLUDE_UPPER); + case AFTER -> TermRangeQuery.newStringRange(field, value, DateTools.dateToString(MAX_DATE, dRes), !INCLUDE_LOWER, INCLUDE_UPPER); }; } @@ -1009,55 +991,31 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { } private SortField createSortField(SearchQuery.Sort s, boolean reverse) { + if (s.getSortClause() == null) { + return null; + } + if (reverse) { + return switch (s.getSortClause()) { + case Arrival -> ARRIVAL_MAILBOX_SORT_REVERSE; + case SentDate -> SENT_DATE_SORT_REVERSE; + case MailboxCc -> FIRST_CC_MAILBOX_SORT_REVERSE; + case MailboxFrom -> FIRST_FROM_MAILBOX_SORT_REVERSE; + case Size -> SIZE_SORT_REVERSE; + case BaseSubject -> BASE_SUBJECT_SORT_REVERSE; + case MailboxTo -> FIRST_TO_MAILBOX_SORT_REVERSE; + case Uid -> UID_SORT_REVERSE; + default -> null; + }; + } return switch (s.getSortClause()) { - case Arrival -> { - if (reverse) { - yield ARRIVAL_MAILBOX_SORT_REVERSE; - } - yield ARRIVAL_MAILBOX_SORT; - } - case SentDate -> { - if (reverse) { - yield SENT_DATE_SORT_REVERSE; - } - yield SENT_DATE_SORT; - } - case MailboxCc -> { - if (reverse) { - yield FIRST_CC_MAILBOX_SORT_REVERSE; - } - yield FIRST_CC_MAILBOX_SORT; - } - case MailboxFrom -> { - if (reverse) { - yield FIRST_FROM_MAILBOX_SORT_REVERSE; - } - yield FIRST_FROM_MAILBOX_SORT; - } - case Size -> { - if (reverse) { - yield SIZE_SORT_REVERSE; - } - yield SIZE_SORT; - } - case BaseSubject -> { - if (reverse) { - yield BASE_SUBJECT_SORT_REVERSE; - } - yield BASE_SUBJECT_SORT; - } - case MailboxTo -> { - if (reverse) { - yield FIRST_TO_MAILBOX_SORT_REVERSE; - } - yield FIRST_TO_MAILBOX_SORT; - } - case Uid -> { - if (reverse) { - yield UID_SORT_REVERSE; - } - yield UID_SORT; - } + case Arrival -> ARRIVAL_MAILBOX_SORT; + case SentDate -> SENT_DATE_SORT; + case MailboxCc -> FIRST_CC_MAILBOX_SORT; + case MailboxFrom -> FIRST_FROM_MAILBOX_SORT; + case Size -> SIZE_SORT; + case BaseSubject -> BASE_SUBJECT_SORT; + case MailboxTo -> FIRST_TO_MAILBOX_SORT; + case Uid -> UID_SORT; default -> null; }; } @@ -1104,7 +1062,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { /** * Return a {@link Query} which is build based on the given {@link SearchQuery.AllCriterion} */ - private Query createAllQuery(SearchQuery.AllCriterion crit) throws UnsupportedSearchException { + private Query createAllQuery() { BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder(); queryBuilder.add(createQuery(MessageRange.all()), BooleanClause.Occur.MUST); @@ -1116,7 +1074,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { /** * Return a {@link Query} which is build based on the given {@link SearchQuery.ConjunctionCriterion} */ - private Query createConjunctionQuery(SearchQuery.ConjunctionCriterion crit, Query inMailboxes, Collection<MessageUid> recentUids) throws UnsupportedSearchException, MailboxException { + private Query createConjunctionQuery(SearchQuery.ConjunctionCriterion crit, Query inMailboxes, Collection<MessageUid> recentUids) throws MailboxException { List<Criterion> crits = crit.getCriteria(); BooleanQuery.Builder conQuery = new BooleanQuery.Builder(); switch (crit.getType()) { @@ -1170,7 +1128,7 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { } else if (criterion instanceof SearchQuery.TextCriterion crit) { return createTextQuery(crit); } else if (criterion instanceof SearchQuery.AllCriterion) { - return createAllQuery((AllCriterion) criterion); + return createAllQuery(); } else if (criterion instanceof SearchQuery.ConjunctionCriterion crit) { return createConjunctionQuery(crit, inMailboxes, recentUids); } else if (criterion instanceof SearchQuery.ModSeqCriterion) { @@ -1244,10 +1202,8 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { * Add the given {@link Flags} to the {@link Document} */ private void indexFlags(Document doc, Flags f) { - List<String> fString = new ArrayList<>(); Flag[] flags = f.getSystemFlags(); for (Flag flag : flags) { - fString.add(toString(flag)); doc.add(new StringField(FLAGS_FIELD, toString(flag), Store.YES)); } @@ -1260,7 +1216,6 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex { if (flags.length == 0 && userFlags.length == 0) { doc.add(new StringField(FLAGS_FIELD, "",Store.NO)); } - } private Query createQuery(MessageRange range) { --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org