You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ro...@apache.org on 2016/07/20 10:37:54 UTC
[2/2] james-project git commit: JAMES-1801 Convert JMAP filter to
SearchQuery (all but inMailboxes, notInMailboxes & hasAttachment)
JAMES-1801 Convert JMAP filter to SearchQuery (all but inMailboxes, notInMailboxes & hasAttachment)
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/ce1fcea4
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/ce1fcea4
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/ce1fcea4
Branch: refs/heads/master
Commit: ce1fcea4f0604e869d4eba313faa78d181edbeb3
Parents: a17b49a
Author: Antoine Duprat <ad...@linagora.com>
Authored: Mon Jul 18 14:37:53 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Wed Jul 20 11:44:48 2016 +0200
----------------------------------------------------------------------
.../apache/james/mailbox/model/SearchQuery.java | 24 +-
.../integration/GetMessageListMethodTest.java | 37 +-
server/protocols/jmap/pom.xml | 5 +
.../james/jmap/model/FilterCondition.java | 88 ++--
.../org/apache/james/jmap/model/Header.java | 76 ++++
.../james/jmap/utils/FilterToSearchQuery.java | 105 +++++
.../james/jmap/model/FilterConditionTest.java | 127 ++----
.../org/apache/james/jmap/model/HeaderTest.java | 71 ++++
.../jmap/utils/FilterToSearchQueryTest.java | 415 +++++++++++++++++++
9 files changed, 815 insertions(+), 133 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/ce1fcea4/mailbox/api/src/main/java/org/apache/james/mailbox/model/SearchQuery.java
----------------------------------------------------------------------
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 b0efb1a..d815d9d 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
@@ -471,6 +471,17 @@ public class SearchQuery implements Serializable {
}
/**
+ * Creates a filter composing the listed criteria.
+ *
+ * @param criteria
+ * <code>List</code> of {@link Criterion}
+ * @return <code>Criterion</code>, not null
+ */
+ public static final Criterion or(List<Criterion> criteria) {
+ return new ConjunctionCriterion(Conjunction.OR, criteria);
+ }
+
+ /**
* Creates a filter composing the two different criteria.
*
* @param one
@@ -511,6 +522,17 @@ public class SearchQuery implements Serializable {
}
/**
+ * Creates a filter composing the listed criteria.
+ *
+ * @param criteria
+ * <code>List</code> of {@link Criterion}
+ * @return <code>Criterion</code>, not null
+ */
+ public static final Criterion not(List<Criterion> criteria) {
+ return new ConjunctionCriterion(Conjunction.NOR, criteria);
+ }
+
+ /**
* Creates a filter on the given flag.
*
* @param flag
@@ -611,7 +633,7 @@ public class SearchQuery implements Serializable {
private final List<Criterion> criterias = new ArrayList<Criterion>();
- private List<Sort> sorts = new ArrayList<SearchQuery.Sort>(Arrays.asList(new Sort(Sort.SortClause.Uid, false)));
+ private List<Sort> sorts = new ArrayList<Sort>(Arrays.asList(new Sort(Sort.SortClause.Uid, false)));
public void andCriteria(Criterion crit) {
criterias.add(crit);
http://git-wip-us.apache.org/repos/asf/james-project/blob/ce1fcea4/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
index 161010f..60408ab 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
@@ -69,11 +69,11 @@ public abstract class GetMessageListMethodTest {
jmapServer = createJmapServer();
jmapServer.start();
RestAssured.requestSpecification = new RequestSpecBuilder()
- .setContentType(ContentType.JSON)
- .setAccept(ContentType.JSON)
- .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)))
- .setPort(jmapServer.getJmapPort())
- .build();
+ .setContentType(ContentType.JSON)
+ .setAccept(ContentType.JSON)
+ .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)))
+ .setPort(jmapServer.getJmapPort())
+ .build();
this.domain = "domain.tld";
this.username = "username@" + domain;
@@ -89,7 +89,7 @@ public abstract class GetMessageListMethodTest {
}
@Test
- public void getMessageListShouldErrorInvalidArgumentsWhenRequestIsInvalid() throws Exception {
+ public void getMessageListShouldReturnErrorInvalidArgumentsWhenRequestIsInvalid() throws Exception {
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMessageList\", {\"filter\": true}, \"#0\"]]")
@@ -102,6 +102,31 @@ public abstract class GetMessageListMethodTest {
}
@Test
+ public void getMessageListShouldReturnErrorInvalidArgumentsWhenHeaderIsInvalid() throws Exception {
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessageList\", {\"filter\":{\"header\":[\"132\", \"456\", \"789\"]}}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("error"))
+ .body(ARGUMENTS + ".type", equalTo("invalidArguments"));
+ }
+
+ @Test
+ public void getMessageListShouldNotFailWhenHeaderIsValid() throws Exception {
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessageList\", {\"filter\":{\"header\":[\"132\", \"456\"]}}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messageList"));
+ }
+
+ @Test
public void getMessageListShouldReturnAllMessagesWhenSingleMailboxNoParameters() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
http://git-wip-us.apache.org/repos/asf/james-project/blob/ce1fcea4/server/protocols/jmap/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/pom.xml b/server/protocols/jmap/pom.xml
index 39a0e85..3e73bac 100644
--- a/server/protocols/jmap/pom.xml
+++ b/server/protocols/jmap/pom.xml
@@ -254,6 +254,11 @@
<artifactId>throwing-lambdas</artifactId>
</dependency>
<dependency>
+ <groupId>com.github.steveash.guavate</groupId>
+ <artifactId>guavate</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
<groupId>com.googlecode.thread-weaver</groupId>
<artifactId>threadweaver</artifactId>
<version>0.2</version>
http://git-wip-us.apache.org/repos/asf/james-project/blob/ce1fcea4/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/FilterCondition.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/FilterCondition.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/FilterCondition.java
index de5ea81..63663c5 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/FilterCondition.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/FilterCondition.java
@@ -19,13 +19,11 @@
package org.apache.james.jmap.model;
-import java.util.Date;
+import java.time.ZonedDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
-import org.apache.commons.lang.NotImplementedException;
-
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.common.annotations.VisibleForTesting;
@@ -45,8 +43,8 @@ public class FilterCondition implements Filter {
private Optional<List<String>> inMailboxes;
private Optional<List<String>> notInMailboxes;
- private Date before;
- private Date after;
+ private ZonedDateTime before;
+ private ZonedDateTime after;
private Integer minSize;
private Integer maxSize;
private Boolean isFlagged;
@@ -61,12 +59,11 @@ public class FilterCondition implements Filter {
private String bcc;
private String subject;
private String body;
- private Optional<List<String>> header;
+ private Header header;
private Builder() {
inMailboxes = Optional.empty();
notInMailboxes = Optional.empty();
- header = Optional.empty();
}
public Builder inMailboxes(String... inMailboxes) {
@@ -91,85 +88,102 @@ public class FilterCondition implements Filter {
return this;
}
- public Builder before(Date before) {
- throw new NotImplementedException();
+ public Builder before(ZonedDateTime before) {
+ this.before = before;
+ return this;
}
- public Builder after(Date after) {
- throw new NotImplementedException();
+ public Builder after(ZonedDateTime after) {
+ this.after = after;
+ return this;
}
public Builder minSize(int minSize) {
- throw new NotImplementedException();
+ this.minSize = minSize;
+ return this;
}
public Builder maxSize(int maxSize) {
- throw new NotImplementedException();
+ this.maxSize = maxSize;
+ return this;
}
- public Builder isFlagged(boolean isFlagger) {
- throw new NotImplementedException();
+ public Builder isFlagged(boolean isFlagged) {
+ this.isFlagged = isFlagged;
+ return this;
}
public Builder isUnread(boolean isUnread) {
- throw new NotImplementedException();
+ this.isUnread = isUnread;
+ return this;
}
public Builder isAnswered(boolean isAnswered) {
- throw new NotImplementedException();
+ this.isAnswered = isAnswered;
+ return this;
}
public Builder isDraft(boolean isDraft) {
- throw new NotImplementedException();
+ this.isDraft = isDraft;
+ return this;
}
public Builder hasAttachment(boolean hasAttachment) {
- throw new NotImplementedException();
+ this.hasAttachment = hasAttachment;
+ return this;
}
public Builder text(String text) {
- throw new NotImplementedException();
+ this.text = text;
+ return this;
}
public Builder from(String from) {
- throw new NotImplementedException();
+ this.from = from;
+ return this;
}
public Builder to(String to) {
- throw new NotImplementedException();
+ this.to = to;
+ return this;
}
public Builder cc(String cc) {
- throw new NotImplementedException();
+ this.cc = cc;
+ return this;
}
public Builder bcc(String bcc) {
- throw new NotImplementedException();
+ this.bcc = bcc;
+ return this;
}
public Builder subject(String subject) {
- throw new NotImplementedException();
+ this.subject = subject;
+ return this;
}
public Builder body(String body) {
- throw new NotImplementedException();
+ this.body = body;
+ return this;
}
- public Builder header(List<String> body) {
- throw new NotImplementedException();
+ public Builder header(Header header) {
+ this.header = header;
+ return this;
}
public FilterCondition build() {
return new FilterCondition(inMailboxes, notInMailboxes, Optional.ofNullable(before), Optional.ofNullable(after), Optional.ofNullable(minSize), Optional.ofNullable(maxSize),
Optional.ofNullable(isFlagged), Optional.ofNullable(isUnread), Optional.ofNullable(isAnswered), Optional.ofNullable(isDraft), Optional.ofNullable(hasAttachment),
- Optional.ofNullable(text), Optional.ofNullable(from), Optional.ofNullable(to), Optional.ofNullable(cc), Optional.ofNullable(bcc), Optional.ofNullable(subject), Optional.ofNullable(body), header);
+ Optional.ofNullable(text), Optional.ofNullable(from), Optional.ofNullable(to), Optional.ofNullable(cc), Optional.ofNullable(bcc), Optional.ofNullable(subject), Optional.ofNullable(body), Optional.ofNullable(header));
}
}
private final Optional<List<String>> inMailboxes;
private final Optional<List<String>> notInMailboxes;
- private final Optional<Date> before;
- private final Optional<Date> after;
+ private final Optional<ZonedDateTime> before;
+ private final Optional<ZonedDateTime> after;
private final Optional<Integer> minSize;
private final Optional<Integer> maxSize;
private final Optional<Boolean> isFlagged;
@@ -184,11 +198,11 @@ public class FilterCondition implements Filter {
private final Optional<String> bcc;
private final Optional<String> subject;
private final Optional<String> body;
- private final Optional<List<String>> header;
+ private final Optional<Header> header;
- @VisibleForTesting FilterCondition(Optional<List<String>> inMailboxes, Optional<List<String>> notInMailboxes, Optional<Date> before, Optional<Date> after, Optional<Integer> minSize, Optional<Integer> maxSize,
+ @VisibleForTesting FilterCondition(Optional<List<String>> inMailboxes, Optional<List<String>> notInMailboxes, Optional<ZonedDateTime> before, Optional<ZonedDateTime> after, Optional<Integer> minSize, Optional<Integer> maxSize,
Optional<Boolean> isFlagged, Optional<Boolean> isUnread, Optional<Boolean> isAnswered, Optional<Boolean> isDraft, Optional<Boolean> hasAttachment,
- Optional<String> text, Optional<String> from, Optional<String> to, Optional<String> cc, Optional<String> bcc, Optional<String> subject, Optional<String> body, Optional<List<String>> header) {
+ Optional<String> text, Optional<String> from, Optional<String> to, Optional<String> cc, Optional<String> bcc, Optional<String> subject, Optional<String> body, Optional<Header> header) {
this.inMailboxes = inMailboxes;
this.notInMailboxes = notInMailboxes;
@@ -219,11 +233,11 @@ public class FilterCondition implements Filter {
return notInMailboxes;
}
- public Optional<Date> getBefore() {
+ public Optional<ZonedDateTime> getBefore() {
return before;
}
- public Optional<Date> getAfter() {
+ public Optional<ZonedDateTime> getAfter() {
return after;
}
@@ -283,7 +297,7 @@ public class FilterCondition implements Filter {
return body;
}
- public Optional<List<String>> getHeader() {
+ public Optional<Header> getHeader() {
return header;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/ce1fcea4/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Header.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Header.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Header.java
new file mode 100644
index 0000000..2d2608c
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Header.java
@@ -0,0 +1,76 @@
+/****************************************************************
+ * 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.model;
+
+import java.util.List;
+import java.util.Optional;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+
+public class Header {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @JsonCreator
+ public static Header from(List<String> header) {
+ return builder().header(header).build();
+ }
+
+ public static class Builder {
+
+ private String name;
+ private Optional<String> value;
+
+ public Builder header(List<String> header) {
+ Preconditions.checkNotNull(header);
+ Preconditions.checkArgument(header.size() > 0, "'header' should contains at least one element");
+ Preconditions.checkArgument(header.size() < 3, "'header' should contains lesser than three elements");
+ this.name = header.get(0);
+ this.value = Optional.ofNullable(Iterables.get(header, 1, null));
+ return this;
+ }
+
+ public Header build() {
+ Preconditions.checkState(!Strings.isNullOrEmpty(name), "'name' is mandatory");
+ return new Header(name, value);
+ }
+ }
+
+ private final String name;
+ private final Optional<String> value;
+
+ private Header(String name, Optional<String> value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Optional<String> getValue() {
+ return value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/ce1fcea4/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/FilterToSearchQuery.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/FilterToSearchQuery.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/FilterToSearchQuery.java
new file mode 100644
index 0000000..db7b485
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/FilterToSearchQuery.java
@@ -0,0 +1,105 @@
+/****************************************************************
+ * 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.utils;
+
+import java.util.Date;
+
+import javax.mail.Flags.Flag;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.jmap.model.Filter;
+import org.apache.james.jmap.model.FilterCondition;
+import org.apache.james.jmap.model.FilterOperator;
+import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.model.SearchQuery.AddressType;
+import org.apache.james.mailbox.model.SearchQuery.Criterion;
+import org.apache.james.mailbox.model.SearchQuery.DateResolution;
+
+import com.github.fge.lambdas.Throwing;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableList;
+
+public class FilterToSearchQuery {
+
+ public SearchQuery convert(Filter filter) {
+ if (filter instanceof FilterCondition) {
+ return convertCondition((FilterCondition) filter);
+ }
+ if (filter instanceof FilterOperator) {
+ SearchQuery searchQuery = new SearchQuery();
+ searchQuery.andCriteria(convertOperator((FilterOperator) filter));
+ return searchQuery;
+ }
+ throw new RuntimeException("Unknown filter: " + filter.getClass());
+ }
+
+ private SearchQuery convertCondition(FilterCondition filter) {
+ SearchQuery searchQuery = new SearchQuery();
+ filter.getText().ifPresent(text -> {
+ searchQuery.andCriteria(
+ SearchQuery.or(ImmutableList.of(
+ SearchQuery.address(AddressType.From, text),
+ SearchQuery.address(AddressType.To, text),
+ SearchQuery.address(AddressType.Cc, text),
+ SearchQuery.address(AddressType.Bcc, text),
+ SearchQuery.headerContains("Subject", text),
+ SearchQuery.bodyContains(text)))
+ );
+ });
+ filter.getFrom().ifPresent(from -> searchQuery.andCriteria(SearchQuery.address(AddressType.From, from)));
+ filter.getTo().ifPresent(to -> searchQuery.andCriteria(SearchQuery.address(AddressType.To, to)));
+ filter.getCc().ifPresent(cc -> searchQuery.andCriteria(SearchQuery.address(AddressType.Cc, cc)));
+ filter.getBcc().ifPresent(bcc -> searchQuery.andCriteria(SearchQuery.address(AddressType.Bcc, bcc)));
+ filter.getSubject().ifPresent(subject -> searchQuery.andCriteria(SearchQuery.headerContains("Subject", subject)));
+ filter.getBody().ifPresent(body -> searchQuery.andCriteria(SearchQuery.bodyContains(body)));
+ filter.getAfter().ifPresent(after -> searchQuery.andCriteria(SearchQuery.internalDateAfter(Date.from(after.toInstant()), DateResolution.Second)));
+ filter.getBefore().ifPresent(before -> searchQuery.andCriteria(SearchQuery.internalDateBefore(Date.from(before.toInstant()), DateResolution.Second)));
+ filter.getHasAttachment().ifPresent(Throwing.consumer(hasAttachment -> { throw new NotImplementedException(); } ));
+ filter.getHeader().ifPresent(header -> searchQuery.andCriteria(SearchQuery.headerContains(header.getName(), header.getValue().orElse(null))));
+ filter.getIsAnswered().ifPresent(isAnswered -> searchQuery.andCriteria(SearchQuery.flagIsSet(Flag.ANSWERED)));
+ filter.getIsDraft().ifPresent(isDraft -> searchQuery.andCriteria(SearchQuery.flagIsSet(Flag.DRAFT)));
+ filter.getIsFlagged().ifPresent(isFlagged -> searchQuery.andCriteria(SearchQuery.flagIsSet(Flag.FLAGGED)));
+ filter.getIsUnread().ifPresent(isUnread -> searchQuery.andCriteria(SearchQuery.flagIsUnSet(Flag.SEEN)));
+ filter.getMaxSize().ifPresent(maxSize -> searchQuery.andCriteria(SearchQuery.sizeLessThan(maxSize)));
+ filter.getMinSize().ifPresent(minSize -> searchQuery.andCriteria(SearchQuery.sizeGreaterThan(minSize)));
+ return searchQuery;
+ }
+
+ private Criterion convertOperator(FilterOperator filter) {
+ switch (filter.getOperator()) {
+ case AND:
+ return SearchQuery.and(convertCriterias(filter));
+
+ case OR:
+ return SearchQuery.or(convertCriterias(filter));
+
+ case NOT:
+ return SearchQuery.not(convertCriterias(filter));
+ }
+ throw new RuntimeException("Unknown operator");
+ }
+
+ private ImmutableList<Criterion> convertCriterias(FilterOperator filter) {
+ return filter.getConditions().stream()
+ .map(this::convert)
+ .flatMap(sq -> sq.getCriterias().stream())
+ .collect(Guavate.toImmutableList());
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/ce1fcea4/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/FilterConditionTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/FilterConditionTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/FilterConditionTest.java
index a4707e5..5a518f0 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/FilterConditionTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/FilterConditionTest.java
@@ -21,9 +21,9 @@ package org.apache.james.jmap.model;
import static org.assertj.core.api.Assertions.assertThat;
+import java.time.ZonedDateTime;
import java.util.Optional;
-import org.apache.commons.lang.NotImplementedException;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
@@ -69,101 +69,50 @@ public class FilterConditionTest {
.build();
assertThat(filterCondition.getNotInMailboxes()).contains(ImmutableList.of("1", "2"));
}
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenBefore() {
- FilterCondition.builder().before(null);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenAfter() {
- FilterCondition.builder().after(null);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenMinSize() {
- FilterCondition.builder().minSize(0);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenMaxSize() {
- FilterCondition.builder().maxSize(0);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenIsFlagged() {
- FilterCondition.builder().isFlagged(false);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenIsUnread() {
- FilterCondition.builder().isUnread(false);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenIsAnswered() {
- FilterCondition.builder().isAnswered(false);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenIsDraft() {
- FilterCondition.builder().isDraft(false);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenHasAttachment() {
- FilterCondition.builder().hasAttachment(false);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenText() {
- FilterCondition.builder().text(null);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenFrom() {
- FilterCondition.builder().from(null);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenTo() {
- FilterCondition.builder().to(null);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenCc() {
- FilterCondition.builder().cc(null);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenBcc() {
- FilterCondition.builder().bcc(null);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenSubject() {
- FilterCondition.builder().subject(null);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenBody() {
- FilterCondition.builder().body(null);
- }
-
- @Test(expected=NotImplementedException.class)
- public void builderShouldThrowWhenHeader() {
- FilterCondition.builder().header(ImmutableList.of());
- }
@Test
public void buildShouldWork() {
- FilterCondition expectedFilterCondition = new FilterCondition(Optional.of(ImmutableList.of("1")), Optional.of(ImmutableList.of("2")), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(),
- Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(),
- Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty());
+ ZonedDateTime before = ZonedDateTime.parse("2016-07-19T14:30:00Z");
+ ZonedDateTime after = ZonedDateTime.parse("2016-07-19T14:31:00Z");
+ int minSize = 4;
+ int maxSize = 123;
+ boolean isFlagged = true;
+ boolean isUnread = true;
+ boolean isAnswered = true;
+ boolean isDraft = true;
+ boolean hasAttachment = true;
+ String text = "text";
+ String from = "sender@james.org";
+ String to = "recipient@james.org";
+ String cc = "copy@james.org";
+ String bcc = "blindcopy@james.org";
+ String subject = "subject";
+ String body = "body";
+ Header header = Header.from(ImmutableList.of("name", "value"));
+ FilterCondition expectedFilterCondition = new FilterCondition(Optional.of(ImmutableList.of("1")), Optional.of(ImmutableList.of("2")), Optional.of(before), Optional.of(after), Optional.of(minSize), Optional.of(maxSize),
+ Optional.of(isFlagged), Optional.of(isUnread), Optional.of(isAnswered), Optional.of(isDraft), Optional.of(hasAttachment), Optional.of(text), Optional.of(from),
+ Optional.of(to), Optional.of(cc), Optional.of(bcc), Optional.of(subject), Optional.of(body), Optional.of(header));
FilterCondition filterCondition = FilterCondition.builder()
.inMailboxes(Optional.of(ImmutableList.of("1")))
.notInMailboxes("2")
+ .before(before)
+ .after(after)
+ .minSize(minSize)
+ .maxSize(maxSize)
+ .isFlagged(isFlagged)
+ .isUnread(isUnread)
+ .isAnswered(isAnswered)
+ .isDraft(isDraft)
+ .hasAttachment(hasAttachment)
+ .text(text)
+ .from(from)
+ .to(to)
+ .cc(cc)
+ .bcc(bcc)
+ .subject(subject)
+ .body(body)
+ .header(header)
.build();
assertThat(filterCondition).isEqualToComparingFieldByField(expectedFilterCondition);
http://git-wip-us.apache.org/repos/asf/james-project/blob/ce1fcea4/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/HeaderTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/HeaderTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/HeaderTest.java
new file mode 100644
index 0000000..9d5d09b
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/HeaderTest.java
@@ -0,0 +1,71 @@
+/****************************************************************
+ * 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.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.Optional;
+
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class HeaderTest {
+
+ @Test
+ public void builderShouldThrowWhenHeaderIsNull() {
+ assertThatThrownBy(() -> Header.builder().header(null)).isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ public void builderShouldThrowWhenHeaderIsEmpty() {
+ assertThatThrownBy(() -> Header.builder().header(ImmutableList.of())).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void builderShouldThrowWhenHeaderHasMoreThanTwoElements() {
+ assertThatThrownBy(() -> Header.builder().header(ImmutableList.of("1", "2", "3"))).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void buildShouldThrowWhenNameIsNotGiven() {
+ assertThatThrownBy(() -> Header.builder().build()).isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ public void buildShouldSetNameWhenGiven() {
+ String expectedName = "name";
+ Header header = Header.builder().header(ImmutableList.of(expectedName)).build();
+
+ assertThat(header.getName()).isEqualTo(expectedName);
+ assertThat(header.getValue()).isEmpty();
+ }
+
+ @Test
+ public void buildShouldSetValueWhenGiven() {
+ String expectedName = "name";
+ String expectedValue = "value";
+ Header header = Header.builder().header(ImmutableList.of(expectedName, expectedValue)).build();
+
+ assertThat(header.getName()).isEqualTo(expectedName);
+ assertThat(header.getValue()).isEqualTo(Optional.of(expectedValue));
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/ce1fcea4/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/FilterToSearchQueryTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/FilterToSearchQueryTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/FilterToSearchQueryTest.java
new file mode 100644
index 0000000..41cfb39
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/FilterToSearchQueryTest.java
@@ -0,0 +1,415 @@
+/****************************************************************
+ * 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.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.time.ZonedDateTime;
+import java.util.Date;
+
+import javax.mail.Flags.Flag;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.jmap.model.Filter;
+import org.apache.james.jmap.model.FilterCondition;
+import org.apache.james.jmap.model.FilterOperator;
+import org.apache.james.jmap.model.Header;
+import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.model.SearchQuery.AddressType;
+import org.apache.james.mailbox.model.SearchQuery.DateResolution;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class FilterToSearchQueryTest {
+
+ @Test
+ public void filterConditionShouldThrowWhenUnknownFilter() {
+ Filter myFilter = (indentation -> null);
+ assertThatThrownBy(() -> new FilterToSearchQuery().convert(myFilter))
+ .isInstanceOf(RuntimeException.class)
+ .hasMessage("Unknown filter: " + myFilter.getClass());
+ }
+
+ @Test
+ public void filterConditionShouldMapEmptyWhenEmptyFilter() {
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .build());
+
+ assertThat(searchQuery).isEqualTo(new SearchQuery());
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenFrom() {
+ String from = "sender@james.org";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.address(AddressType.From, from));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .from(from)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenTo() {
+ String to = "recipient@james.org";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.address(AddressType.To, to));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .to(to)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenCc() {
+ String cc = "copy@james.org";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.address(AddressType.Cc, cc));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .cc(cc)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenBcc() {
+ String bcc = "blindcopy@james.org";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.address(AddressType.Bcc, bcc));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .bcc(bcc)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenSubject() {
+ String subject = "subject";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.headerContains("Subject", subject));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .subject(subject)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenBody() {
+ String body = "body";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.bodyContains(body));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .body(body)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenText() {
+ String text = "text";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.or(ImmutableList.of(
+ SearchQuery.address(AddressType.From, text),
+ SearchQuery.address(AddressType.To, text),
+ SearchQuery.address(AddressType.Cc, text),
+ SearchQuery.address(AddressType.Bcc, text),
+ SearchQuery.headerContains("Subject", text),
+ SearchQuery.bodyContains(text))));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .text(text)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenAfter() {
+ ZonedDateTime after = ZonedDateTime.now();
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.internalDateAfter(Date.from(after.toInstant()), DateResolution.Second));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .after(after)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenBefore() {
+ ZonedDateTime before = ZonedDateTime.now();
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.internalDateBefore(Date.from(before.toInstant()), DateResolution.Second));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .before(before)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldThrowWhenHasAttachment() {
+ assertThatThrownBy(() -> new FilterToSearchQuery().convert(FilterCondition.builder()
+ .hasAttachment(true)
+ .build()))
+ .isInstanceOf(NotImplementedException.class);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenIsAnswered() {
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.flagIsSet(Flag.ANSWERED));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .isAnswered(true)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenIsDraft() {
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.flagIsSet(Flag.DRAFT));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .isDraft(true)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenIsFlagged() {
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.flagIsSet(Flag.FLAGGED));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .isFlagged(true)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenIsUnread() {
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.flagIsUnSet(Flag.SEEN));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .isUnread(true)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenMaxSize() {
+ int maxSize = 123;
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.sizeLessThan(maxSize));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .maxSize(maxSize)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenMinSize() {
+ int minSize = 4;
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.sizeGreaterThan(minSize));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .minSize(minSize)
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenHeaderWithOneElement() {
+ String headerName = "name";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.headerExists(headerName));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .header(Header.from(ImmutableList.of(headerName)))
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenHeaderWithTwoElements() {
+ String headerName = "name";
+ String headerValue = "value";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.headerContains(headerName, headerValue));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(FilterCondition.builder()
+ .header(Header.from(ImmutableList.of(headerName, headerValue)))
+ .build());
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapTwoConditions() {
+ String from = "sender@james.org";
+ String to = "recipient@james.org";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.and(ImmutableList.of(
+ SearchQuery.address(AddressType.From, from),
+ SearchQuery.address(AddressType.To, to))));
+
+ Filter filter = FilterOperator.and(
+ FilterCondition.builder()
+ .from(from)
+ .build(),
+ FilterCondition.builder()
+ .to(to)
+ .build());
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(filter);
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenAndOperator() {
+ String from = "sender@james.org";
+ String to = "recipient@james.org";
+ String subject = "subject";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.and(ImmutableList.of(
+ SearchQuery.address(AddressType.From, from),
+ SearchQuery.address(AddressType.To, to),
+ SearchQuery.headerContains("Subject", subject))));
+
+ Filter complexFilter = FilterOperator.and(
+ FilterCondition.builder()
+ .from(from)
+ .to(to)
+ .subject(subject)
+ .build());
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(complexFilter);
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenOrOperator() {
+ String from = "sender@james.org";
+ String to = "recipient@james.org";
+ String subject = "subject";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.or(ImmutableList.of(
+ SearchQuery.address(AddressType.From, from),
+ SearchQuery.address(AddressType.To, to),
+ SearchQuery.headerContains("Subject", subject))));
+
+ Filter complexFilter = FilterOperator.or(
+ FilterCondition.builder()
+ .from(from)
+ .to(to)
+ .subject(subject)
+ .build());
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(complexFilter);
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenNotOperator() {
+ String from = "sender@james.org";
+ String to = "recipient@james.org";
+ String subject = "subject";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.not(ImmutableList.of(
+ SearchQuery.address(AddressType.From, from),
+ SearchQuery.address(AddressType.To, to),
+ SearchQuery.headerContains("Subject", subject))));
+
+ Filter complexFilter = FilterOperator.not(
+ FilterCondition.builder()
+ .from(from)
+ .to(to)
+ .subject(subject)
+ .build());
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(complexFilter);
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+
+ @Test
+ public void filterConditionShouldMapWhenComplexFilterTree() {
+ String from = "sender@james.org";
+ String to = "recipient@james.org";
+ String cc = "copy@james.org";
+ SearchQuery expectedSearchQuery = new SearchQuery();
+ expectedSearchQuery.andCriteria(SearchQuery.and(ImmutableList.of(
+ SearchQuery.address(AddressType.From, from),
+ SearchQuery.or(ImmutableList.of(
+ SearchQuery.not(SearchQuery.address(AddressType.To, to)),
+ SearchQuery.address(AddressType.Cc, cc))
+ )
+ )));
+
+ Filter complexFilter = FilterOperator.and(
+ FilterCondition.builder()
+ .from(from)
+ .build(),
+ FilterOperator.or(
+ FilterOperator.not(
+ FilterCondition.builder()
+ .to(to)
+ .build()),
+ FilterCondition.builder()
+ .cc(cc)
+ .build()
+ ));
+
+ SearchQuery searchQuery = new FilterToSearchQuery().convert(complexFilter);
+
+ assertThat(searchQuery).isEqualTo(expectedSearchQuery);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org