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 bt...@apache.org on 2019/08/27 07:41:53 UTC
[james-project] 05/17: JAMES-2866 JSON serialization for Condition
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 5a192d585c9a3ee26bdff2dc4a7501dbc87a77b5
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Aug 21 15:04:20 2019 +0700
JAMES-2866 JSON serialization for Condition
---
server/mailet/mock-smtp-server/pom.xml | 5 +
.../apache/james/mock/smtp/server/Condition.java | 111 ++++++++++++++++-----
.../apache/james/mock/smtp/server/Operator.java | 60 ++++++++++-
.../james/mock/smtp/server/ConditionTest.java | 95 +++++++++++++++---
4 files changed, 232 insertions(+), 39 deletions(-)
diff --git a/server/mailet/mock-smtp-server/pom.xml b/server/mailet/mock-smtp-server/pom.xml
index 8db2a69..bdcbea7 100644
--- a/server/mailet/mock-smtp-server/pom.xml
+++ b/server/mailet/mock-smtp-server/pom.xml
@@ -50,6 +50,11 @@
<artifactId>guava</artifactId>
</dependency>
<dependency>
+ <groupId>net.javacrumbs.json-unit</groupId>
+ <artifactId>json-unit-assertj</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId>
<scope>test</scope>
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/Condition.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/Condition.java
index 422eea7..523794b 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/Condition.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/Condition.java
@@ -20,43 +20,106 @@
package org.apache.james.mock.smtp.server;
import java.util.Objects;
+import java.util.Optional;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.common.base.Preconditions;
-class Condition {
+@JsonDeserialize(builder = Condition.Builder.class)
+interface Condition {
+ @JsonPOJOBuilder(withPrefix = "")
+ class Builder {
+ private Operator.OperatorName operator;
+ private Optional<String> matchingValue;
- static final Condition MATCH_ALL = new Condition(Operator.MATCH_ALL, "any");
+ public Builder() {
+ this.matchingValue = Optional.empty();
+ }
- private final Operator operator;
- private final String matchingValue;
+ public Builder operator(Operator.OperatorName operator) {
+ this.operator = operator;
+ return this;
+ }
- Condition(Operator operator, String matchingValue) {
- Preconditions.checkNotNull(operator);
- Preconditions.checkNotNull(matchingValue);
+ public Builder matchingValue(String matchingValue) {
+ this.matchingValue = Optional.of(matchingValue);
+ return this;
+ }
- this.operator = operator;
- this.matchingValue = matchingValue;
- }
+ public Condition build() {
+ Preconditions.checkState(operator != null, "You need to specify an operator");
- boolean matches(String line) {
- return operator.actual(line)
- .expected(matchingValue)
- .matches();
+ return operator.getConditionFactory().apply(matchingValue);
+ }
}
- @Override
- public final boolean equals(Object o) {
- if (o instanceof Condition) {
- Condition condition = (Condition) o;
+ class MatchAllCondition implements Condition {
+ public Operator.OperatorName getOperator() {
+ return Operator.OperatorName.MATCH_ALL;
+ }
- return Objects.equals(this.operator, condition.operator)
- && Objects.equals(this.matchingValue, condition.matchingValue);
+ @Override
+ public boolean matches(String line) {
+ return true;
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ return o instanceof MatchAllCondition;
+ }
+
+ @Override
+ public final int hashCode() {
+ return Objects.hash(MatchAllCondition.class);
}
- return false;
}
- @Override
- public final int hashCode() {
- return Objects.hash(operator, matchingValue);
+ class OperatorCondition implements Condition {
+ private final Operator operator;
+ private final String matchingValue;
+
+ OperatorCondition(Operator operator, String matchingValue) {
+ Preconditions.checkNotNull(operator);
+ Preconditions.checkNotNull(matchingValue);
+
+ this.operator = operator;
+ this.matchingValue = matchingValue;
+ }
+
+ public Operator.OperatorName getOperator() {
+ return operator.getOperatorName();
+ }
+
+ public String getMatchingValue() {
+ return matchingValue;
+ }
+
+ @Override
+ public boolean matches(String line) {
+ return operator.actual(line)
+ .expected(matchingValue)
+ .matches();
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (o instanceof OperatorCondition) {
+ OperatorCondition condition = (OperatorCondition) o;
+
+ return Objects.equals(this.operator, condition.operator)
+ && Objects.equals(this.matchingValue, condition.matchingValue);
+ }
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ return Objects.hash(operator, matchingValue);
+ }
}
+
+ Condition MATCH_ALL = new MatchAllCondition();
+
+ boolean matches(String line);
}
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/Operator.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/Operator.java
index 26947c0..d56e04c 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/Operator.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/Operator.java
@@ -19,7 +19,52 @@
package org.apache.james.mock.smtp.server;
+import java.util.Arrays;
+import java.util.Optional;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+
public interface Operator {
+ enum OperatorName {
+ CONTAINS("contains", maybeMatchingValue -> {
+ Preconditions.checkState(maybeMatchingValue.isPresent(), "You need to specify a matchingValue with the contains operator");
+
+ return new Condition.OperatorCondition(Operator.CONTAINS, maybeMatchingValue.get());
+ }),
+ MATCH_ALL("matchAll", maybeMatchingValue -> {
+ Preconditions.checkState(!maybeMatchingValue.isPresent(), "You should not specify a matchingValue with the matchAll operator");
+
+ return new Condition.MatchAllCondition();
+ });
+
+ private final String name;
+ private final Function<Optional<String>, Condition> conditionFactory;
+
+ @JsonCreator
+ public static OperatorName from(String name) {
+ return Arrays.stream(values())
+ .filter(value -> value.name.equals(name))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException("Unsuported " + name + " operator"));
+ }
+
+ OperatorName(String name, Function<Optional<String>, Condition> conditionFactory) {
+ this.name = name;
+ this.conditionFactory = conditionFactory;
+ }
+
+ @JsonValue
+ public String getName() {
+ return name;
+ }
+
+ public Function<Optional<String>, Condition> getConditionFactory() {
+ return conditionFactory;
+ }
+ }
@FunctionalInterface
interface Expected {
@@ -31,8 +76,19 @@ public interface Operator {
boolean matches();
}
- Operator CONTAINS = actual -> expected -> () -> actual.contains(expected);
- Operator MATCH_ALL = actual -> expected -> () -> true;
+ Operator CONTAINS = new Operator() {
+ @Override
+ public Expected actual(String actual) {
+ return expected -> () -> actual.contains(expected);
+ }
+
+ @Override
+ public OperatorName getOperatorName() {
+ return OperatorName.CONTAINS;
+ }
+ };
Expected actual(String actual);
+
+ OperatorName getOperatorName();
}
diff --git a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConditionTest.java b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConditionTest.java
index e5fe70a..eefbe1c 100644
--- a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConditionTest.java
+++ b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConditionTest.java
@@ -19,35 +19,54 @@
package org.apache.james.mock.smtp.server;
+import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
+
import nl.jqno.equalsverifier.EqualsVerifier;
class ConditionTest {
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+ @Test
+ void operatorConditionShouldMatchBeanContract() {
+ EqualsVerifier.forClass(Condition.OperatorCondition.class)
+ .verify();
+ }
+
@Test
- void shouldMatchBeanContract() {
- EqualsVerifier.forClass(Condition.class)
+ void matchAllShouldMatchBeanContract() {
+ EqualsVerifier.forClass(Condition.MatchAllCondition.class)
.verify();
}
@Test
+ void differentConditionTypesShouldNotBeEqual() {
+ assertThat(Condition.MATCH_ALL)
+ .isNotEqualTo(new Condition.OperatorCondition(Operator.CONTAINS, "any"));
+ }
+
+ @Test
void constructorShouldThrowWhenNullOperator() {
- assertThatThrownBy(() -> new Condition(null, "matchingValue"))
+ assertThatThrownBy(() -> new Condition.OperatorCondition(null, "matchingValue"))
.isInstanceOf(NullPointerException.class);
}
@Test
void constructorShouldThrowWhenNullMatchingValue() {
- assertThatThrownBy(() -> new Condition(Operator.CONTAINS, null))
+ assertThatThrownBy(() -> new Condition.OperatorCondition(Operator.CONTAINS, null))
.isInstanceOf(NullPointerException.class);
}
@Test
void matchesShouldReturnTrueWhenOperatorMatches() {
- Condition condition = new Condition(Operator.CONTAINS, "match me");
+ Condition condition = new Condition.OperatorCondition(Operator.CONTAINS, "match me");
assertThat(condition.matches("this contains match me string"))
.isTrue();
@@ -55,7 +74,7 @@ class ConditionTest {
@Test
void matchesShouldReturnFalseWhenOperatorDoesNotMatch() {
- Condition condition = new Condition(Operator.CONTAINS, "match me");
+ Condition condition = new Condition.OperatorCondition(Operator.CONTAINS, "match me");
assertThat(condition.matches("this contains another string"))
.isFalse();
@@ -63,7 +82,7 @@ class ConditionTest {
@Test
void matchesShouldThrowWhenNullLine() {
- Condition condition = new Condition(Operator.CONTAINS, "match me");
+ Condition condition = new Condition.OperatorCondition(Operator.CONTAINS, "match me");
assertThatThrownBy(() -> condition.matches(null))
.isInstanceOf(NullPointerException.class);
@@ -71,22 +90,72 @@ class ConditionTest {
@Test
void matchAllShouldReturnTrue() {
- assertThat(Condition.MATCH_ALL
- .matches("this contains another string"))
+ assertThat(Condition.MATCH_ALL.matches("this contains another string"))
.isTrue();
}
@Test
void matchAllShouldReturnTrueEvenWhenLineIsNull() {
- assertThat(Condition.MATCH_ALL
- .matches(null))
+ assertThat(Condition.MATCH_ALL.matches(null))
.isTrue();
}
@Test
void matchAllShouldReturnTrueEvenWhenLineIsEmpty() {
- assertThat(Condition.MATCH_ALL
- .matches(""))
+ assertThat(Condition.MATCH_ALL.matches(""))
.isTrue();
}
+
+ @Nested
+ class JSONTest {
+ @Test
+ void jacksonShouldDeserializeCondition() throws Exception {
+ Condition condition = OBJECT_MAPPER.readValue(
+ "{\"operator\":\"contains\", \"matchingValue\":\"matchme\"}",
+ Condition.class);
+
+ assertThat(condition).isEqualTo(new Condition.OperatorCondition(Operator.CONTAINS, "matchme"));
+ }
+
+ @Test
+ void jacksonShouldDeserializeMatchAllCondition() throws Exception {
+ Condition condition = OBJECT_MAPPER.readValue(
+ "{\"operator\":\"matchAll\"}",
+ Condition.class);
+
+ assertThat(condition).isEqualTo(Condition.MATCH_ALL);
+ }
+
+ @Test
+ void jacksonShouldSerializeCondition() throws Exception {
+ String json = OBJECT_MAPPER.writeValueAsString(new Condition.OperatorCondition(Operator.CONTAINS, "matchme"));
+
+ assertThatJson(json).isEqualTo("{\"operator\":\"contains\", \"matchingValue\":\"matchme\"}");
+ }
+
+ @Test
+ void jacksonShouldSerializeMatchAllCondition() throws Exception {
+ String json = OBJECT_MAPPER.writeValueAsString(Condition.MATCH_ALL);
+
+ assertThatJson(json).isEqualTo("{\"operator\":\"matchAll\"}");
+ }
+
+ @Test
+ void jacksonShouldThrowWhenDeserializeMatchAllConditionWithMatchingValue(){
+ String json = "{\"operator\":\"matchAll\", \"matchingValue\":\"matchme\"}";
+
+ assertThatThrownBy(() -> OBJECT_MAPPER.readValue(json, Condition.class))
+ .isInstanceOf(InvalidDefinitionException.class)
+ .hasMessageContaining("You should not specify a matchingValue with the matchAll operator");
+ }
+
+ @Test
+ void jacksonShouldThrowWhenDeserializeContainsConditionWithoutMatchingValue(){
+ String json = "{\"operator\":\"contains\"}";
+
+ assertThatThrownBy(() -> OBJECT_MAPPER.readValue(json, Condition.class))
+ .isInstanceOf(InvalidDefinitionException.class)
+ .hasMessageContaining("You need to specify a matchingValue with the contains operator");
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org