You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2023/03/28 02:15:56 UTC
[james-project] branch master updated: JAMES-2080 Add a dedicated Subject search criterion (#1503)
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
The following commit(s) were added to refs/heads/master by this push:
new c7bf7ad6f0 JAMES-2080 Add a dedicated Subject search criterion (#1503)
c7bf7ad6f0 is described below
commit c7bf7ad6f0c2d394f608fd73c1239d98eea71f47
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Tue Mar 28 04:15:48 2023 +0200
JAMES-2080 Add a dedicated Subject search criterion (#1503)
---
.../apache/james/mailbox/model/SearchQuery.java | 42 ++++++++++++++++++++++
.../lucene/search/LuceneMessageSearchIndex.java | 3 ++
.../opensearch/query/CriterionConverter.java | 9 +++++
.../mail/SearchThreadIdGuessingAlgorithm.java | 2 +-
.../mailbox/store/search/MessageSearches.java | 3 ++
.../store/search/SimpleMessageSearchIndex.java | 3 +-
.../james/imap/processor/SearchProcessor.java | 2 +-
.../james/imap/processor/SearchProcessorTest.java | 5 ++-
.../james/jmap/draft/utils/FilterToCriteria.java | 4 +--
.../jmap/draft/utils/FilterToCriteriaTest.java | 10 +++---
.../james/jmap/utils/search/MailboxFilter.scala | 4 +--
11 files changed, 72 insertions(+), 15 deletions(-)
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/SearchQuery.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/SearchQuery.java
index fb9a1f1ac0..5e84e32913 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/SearchQuery.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/SearchQuery.java
@@ -750,6 +750,10 @@ public class SearchQuery {
return new MimeMessageIDCriterion(messageId);
}
+ public static Criterion subject(String subject) {
+ return new SubjectCriterion(subject);
+ }
+
public static Criterion threadId(ThreadId threadId) {
return new ThreadIdCriterion(threadId);
}
@@ -1156,6 +1160,44 @@ public class SearchQuery {
}
}
+ public static class SubjectCriterion extends Criterion {
+ private final String subject;
+
+ public SubjectCriterion(String subject) {
+ this.subject = subject;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public HeaderCriterion asHeaderCriterion() {
+ return new HeaderCriterion("Subject", new ContainsOperator(subject));
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (o instanceof SubjectCriterion) {
+ SubjectCriterion that = (SubjectCriterion) o;
+
+ return java.util.Objects.equals(this.subject, that.subject);
+ }
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ return java.util.Objects.hash(subject);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("subject", subject)
+ .toString();
+ }
+ }
+
/**
* Filters on the threadId of the messages.
*/
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 2bf8f7c9f2..c71e17ce5e 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
@@ -1245,6 +1245,9 @@ public class LuceneMessageSearchIndex extends ListeningMessageSearchIndex {
} else if (criterion instanceof SearchQuery.MimeMessageIDCriterion) {
SearchQuery.MimeMessageIDCriterion mimeMessageIDCriterion = (SearchQuery.MimeMessageIDCriterion) criterion;
return createHeaderQuery(mimeMessageIDCriterion.asHeaderCriterion());
+ } else if (criterion instanceof SearchQuery.SubjectCriterion) {
+ SearchQuery.SubjectCriterion subjectCriterion = (SearchQuery.SubjectCriterion) criterion;
+ return createHeaderQuery(subjectCriterion.asHeaderCriterion());
} else if (criterion instanceof SearchQuery.ThreadIdCriterion) {
SearchQuery.ThreadIdCriterion threadIdCriterion = (SearchQuery.ThreadIdCriterion) criterion;
return createTermQuery(THREAD_ID_FIELD, threadIdCriterion.getThreadId().serialize());
diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/CriterionConverter.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/CriterionConverter.java
index 9efe66925a..5b76063a77 100644
--- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/CriterionConverter.java
+++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/CriterionConverter.java
@@ -67,6 +67,7 @@ public class CriterionConverter {
registerCriterionConverter(SearchQuery.MessageIdCriterion.class, this::convertMessageId);
registerCriterionConverter(SearchQuery.ConjunctionCriterion.class, this::convertConjunction);
registerCriterionConverter(SearchQuery.HeaderCriterion.class, this::convertHeader);
+ registerCriterionConverter(SearchQuery.SubjectCriterion.class, this::convertSubject);
registerCriterionConverter(SearchQuery.TextCriterion.class, this::convertTextCriterion);
registerCriterionConverter(SearchQuery.CustomFlagCriterion.class, this::convertCustomFlagCriterion);
@@ -424,6 +425,14 @@ public class CriterionConverter {
headerCriterion.getOperator());
}
+ private Query convertSubject(SearchQuery.SubjectCriterion headerCriterion) {
+ return new MatchQuery.Builder()
+ .field(JsonMessageConstants.SUBJECT)
+ .query(new FieldValue.Builder().stringValue(headerCriterion.getSubject()).build())
+ .build()
+ ._toQuery();
+ }
+
private Query manageAddressFields(String headerName, String value) {
return new BoolQuery.Builder()
.should(new MatchQuery.Builder()
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/SearchThreadIdGuessingAlgorithm.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/SearchThreadIdGuessingAlgorithm.java
index 551e737b93..99c00f5a81 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/SearchThreadIdGuessingAlgorithm.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/SearchThreadIdGuessingAlgorithm.java
@@ -93,7 +93,7 @@ public class SearchThreadIdGuessingAlgorithm implements ThreadIdGuessingAlgorith
});
SearchQuery.Criterion mimeMessageIdCriterion = SearchQuery.or(mimeMessageIdCriteriaBuilder.build());
- SearchQuery.Criterion finalCriterion = subject.map(value -> SearchQuery.and(mimeMessageIdCriterion, SearchQuery.headerContains("Subject", SearchUtil.getBaseSubject(value.getValue()))))
+ SearchQuery.Criterion finalCriterion = subject.map(value -> SearchQuery.and(mimeMessageIdCriterion, SearchQuery.subject(SearchUtil.getBaseSubject(value.getValue()))))
.orElse(mimeMessageIdCriterion);
return MultimailboxesSearchQuery
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/MessageSearches.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/MessageSearches.java
index c1189aaff4..435be54147 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/MessageSearches.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/MessageSearches.java
@@ -188,6 +188,9 @@ public class MessageSearches implements Iterable<SimpleMessageSearchIndex.Search
} else if (criterion instanceof SearchQuery.MimeMessageIDCriterion) {
SearchQuery.MimeMessageIDCriterion mimeMessageIDCriterion = (SearchQuery.MimeMessageIDCriterion) criterion;
return isMatch(mimeMessageIDCriterion.asHeaderCriterion(), message, recentMessageUids);
+ } else if (criterion instanceof SearchQuery.SubjectCriterion) {
+ SearchQuery.SubjectCriterion subjectCriterion = (SearchQuery.SubjectCriterion) criterion;
+ return isMatch(subjectCriterion.asHeaderCriterion(), message, recentMessageUids);
} else if (criterion instanceof SearchQuery.ThreadIdCriterion) {
SearchQuery.ThreadIdCriterion threadIdCriterion = (SearchQuery.ThreadIdCriterion) criterion;
return matches(threadIdCriterion, message);
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java
index 1858d16b78..af1651e05b 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java
@@ -133,7 +133,8 @@ public class SimpleMessageSearchIndex implements MessageSearchIndex {
if (crit instanceof SearchQuery.AllCriterion || crit instanceof SearchQuery.TextCriterion) {
return FetchType.FULL;
}
- if (crit instanceof SearchQuery.HeaderCriterion || crit instanceof SearchQuery.MimeMessageIDCriterion) {
+ if (crit instanceof SearchQuery.HeaderCriterion || crit instanceof SearchQuery.MimeMessageIDCriterion
+ || crit instanceof SearchQuery.SubjectCriterion) {
return FetchType.HEADERS;
}
return FetchType.METADATA;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
index 3ab4073b44..6d506900c3 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
@@ -347,7 +347,7 @@ public class SearchProcessor extends AbstractMailboxProcessor<SearchRequest> imp
case TYPE_SMALLER:
return SearchQuery.sizeLessThan(key.getSize());
case TYPE_SUBJECT:
- return SearchQuery.headerContains(ImapConstants.RFC822_SUBJECT, key.getValue());
+ return SearchQuery.subject(key.getValue());
case TYPE_TEXT:
return SearchQuery.mailContains(key.getValue());
case TYPE_TO:
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/SearchProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/SearchProcessorTest.java
index 8658605fde..43389a778e 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/SearchProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/SearchProcessorTest.java
@@ -77,7 +77,7 @@ import it.unimi.dsi.fastutil.longs.LongList;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
-public class SearchProcessorTest {
+class SearchProcessorTest {
private static final int DAY = 6;
private static final int MONTH = 6;
@@ -424,8 +424,7 @@ public class SearchProcessorTest {
@Test
void testSUBJECT() throws Exception {
expectsGetSelectedMailbox();
- check(SearchKey.buildSubject(SUBJECT), SearchQuery.headerContains(
- ImapConstants.RFC822_SUBJECT, SUBJECT));
+ check(SearchKey.buildSubject(SUBJECT), SearchQuery.subject(SUBJECT));
}
@Test
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/utils/FilterToCriteria.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/utils/FilterToCriteria.java
index 5c9edd4829..c25b01da75 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/utils/FilterToCriteria.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/utils/FilterToCriteria.java
@@ -56,7 +56,7 @@ public class FilterToCriteria {
SearchQuery.address(AddressType.To, text),
SearchQuery.address(AddressType.Cc, text),
SearchQuery.address(AddressType.Bcc, text),
- SearchQuery.headerContains("Subject", text),
+ SearchQuery.subject(text),
SearchQuery.attachmentContains(text),
SearchQuery.bodyContains(text),
SearchQuery.attachmentFileName(text)))
@@ -65,7 +65,7 @@ public class FilterToCriteria {
filter.getTo().ifPresent(to -> builder.add(SearchQuery.address(AddressType.To, to)));
filter.getCc().ifPresent(cc -> builder.add(SearchQuery.address(AddressType.Cc, cc)));
filter.getBcc().ifPresent(bcc -> builder.add(SearchQuery.address(AddressType.Bcc, bcc)));
- filter.getSubject().ifPresent(subject -> builder.add(SearchQuery.headerContains("Subject", subject)));
+ filter.getSubject().ifPresent(subject -> builder.add(SearchQuery.subject(subject)));
filter.getAttachments().ifPresent(attachments -> builder.add(SearchQuery.attachmentContains(attachments)));
filter.getBody().ifPresent(body -> builder.add(SearchQuery.bodyContains(body)));
filter.getAfter().ifPresent(after -> builder.add(SearchQuery.sentDateAfter(Date.from(after.toInstant()), DateResolution.Second)));
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/utils/FilterToCriteriaTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/utils/FilterToCriteriaTest.java
index c03cbac7e8..eae8725850 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/utils/FilterToCriteriaTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/utils/FilterToCriteriaTest.java
@@ -123,7 +123,7 @@ public class FilterToCriteriaTest {
.subject(subject)
.build());
- assertThat(criteria).containsExactly(SearchQuery.headerContains("Subject", subject));
+ assertThat(criteria).containsExactly(SearchQuery.subject(subject));
}
@Test
@@ -158,7 +158,7 @@ public class FilterToCriteriaTest {
SearchQuery.address(AddressType.To, text),
SearchQuery.address(AddressType.Cc, text),
SearchQuery.address(AddressType.Bcc, text),
- SearchQuery.headerContains("Subject", text),
+ SearchQuery.subject(text),
SearchQuery.bodyContains(text),
SearchQuery.attachmentContains(text),
SearchQuery.attachmentFileName(text))));
@@ -336,7 +336,7 @@ public class FilterToCriteriaTest {
assertThat(criteria).containsExactly(SearchQuery.and(ImmutableList.of(
SearchQuery.address(AddressType.From, from),
SearchQuery.address(AddressType.To, to),
- SearchQuery.headerContains("Subject", subject))));
+ SearchQuery.subject(subject))));
}
@Test
@@ -357,7 +357,7 @@ public class FilterToCriteriaTest {
assertThat(criteria).containsExactly(SearchQuery.or(ImmutableList.of(
SearchQuery.address(AddressType.From, from),
SearchQuery.address(AddressType.To, to),
- SearchQuery.headerContains("Subject", subject))));
+ SearchQuery.subject(subject))));
}
@Test
@@ -378,7 +378,7 @@ public class FilterToCriteriaTest {
assertThat(criteria).containsExactly(SearchQuery.not(ImmutableList.of(
SearchQuery.address(AddressType.From, from),
SearchQuery.address(AddressType.To, to),
- SearchQuery.headerContains("Subject", subject))));
+ SearchQuery.subject(subject))));
}
@Test
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/search/MailboxFilter.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/search/MailboxFilter.scala
index 43e7fa523a..7ac016aafd 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/search/MailboxFilter.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/search/MailboxFilter.scala
@@ -249,7 +249,7 @@ object MailboxFilter {
SearchQuery.address(AddressType.Cc, text.value),
SearchQuery.address(AddressType.Bcc, text.value),
SearchQuery.address(AddressType.From, text.value),
- SearchQuery.headerContains("Subject", text.value),
+ SearchQuery.subject(text.value),
SearchQuery.bodyContains(text.value))
.asJava)))
case None => Right(Nil)
@@ -287,7 +287,7 @@ object MailboxFilter {
case object Subject extends ConditionFilter {
override def toQuery(filterCondition: FilterCondition): Either[UnsupportedFilterException, List[Criterion]] =
filterCondition.subject match {
- case Some(subject) => Right(List(SearchQuery.headerContains("Subject", subject.value)))
+ case Some(subject) => Right(List(SearchQuery.subject(subject.value)))
case None => Right(Nil)
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org