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 2019/07/26 08:13:14 UTC
[james-project] 06/12: JAMES-2813 convert Query to QueryDTO
This is an automated email from the ASF dual-hosted git repository.
rouazana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit c357bafff687374c8809e28ae5d1354aa3717711
Author: Rémi Kowalski <rk...@linagora.com>
AuthorDate: Thu Jul 18 17:23:07 2019 +0200
JAMES-2813 convert Query to QueryDTO
---
.../james/vault/dto/query/QueryTranslator.java | 60 +++++++-
.../org/apache/james/vault/search/Criterion.java | 8 ++
.../java/org/apache/james/vault/search/Query.java | 4 +
.../james/vault/dto/query/QueryTranslatorTest.java | 156 ++++++++++++++++++++-
4 files changed, 217 insertions(+), 11 deletions(-)
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryTranslator.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryTranslator.java
index 2bd22fc..d76f884 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryTranslator.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryTranslator.java
@@ -19,7 +19,6 @@
package org.apache.james.vault.dto.query;
-
import static org.apache.james.vault.dto.query.QueryTranslator.FieldValueParser.BOOLEAN_PARSER;
import static org.apache.james.vault.dto.query.QueryTranslator.FieldValueParser.MAIL_ADDRESS_PARSER;
import static org.apache.james.vault.dto.query.QueryTranslator.FieldValueParser.STRING_PARSER;
@@ -32,6 +31,7 @@ import static org.apache.james.vault.search.Operator.EQUALS;
import static org.apache.james.vault.search.Operator.EQUALS_IGNORE_CASE;
import java.time.ZonedDateTime;
+import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
@@ -123,6 +123,36 @@ public class QueryTranslator {
T parse(String input);
}
+ interface FieldValueSerializer<T> {
+
+ FieldValueSerializer<MailboxId> MAILBOX_ID_SERIALIZER = MailboxId::serialize;
+ FieldValueSerializer<ZonedDateTime> ZONED_DATE_TIME_SERIALIZER = ZonedDateTime::toString;
+ FieldValueSerializer<String> STRING_SERIALIZER = input -> input;
+ FieldValueSerializer<Boolean> BOOLEAN_SERIALIZER = input -> input.toString();
+ FieldValueSerializer<MailAddress> MAIL_ADDRESS_SERIALIZER = MailAddress::asString;
+
+ static Optional<FieldValueSerializer> getSerializerForValue(Object value) {
+ if (value instanceof MailboxId) {
+ return Optional.of(MAILBOX_ID_SERIALIZER);
+ }
+ if (value instanceof ZonedDateTime) {
+ return Optional.of(ZONED_DATE_TIME_SERIALIZER);
+ }
+ if (value instanceof String) {
+ return Optional.of(STRING_SERIALIZER);
+ }
+ if (value instanceof Boolean) {
+ return Optional.of(BOOLEAN_SERIALIZER);
+ }
+ if (value instanceof MailAddress) {
+ return Optional.of(MAIL_ADDRESS_SERIALIZER);
+ }
+ return Optional.empty();
+ }
+
+ String serialize(T input);
+ }
+
private final ImmutableTable<FieldName, Operator, Function<String, Criterion<?>>> criterionRegistry;
@Inject
@@ -139,7 +169,7 @@ public class QueryTranslator {
.build();
}
- private ImmutableTable.Builder<FieldName, Operator, Function<String, Criterion<?>>> defaultRegistryBuilder() {
+ private ImmutableTable.Builder<FieldName, Operator, Function<String, Criterion<?>>> defaultRegistryBuilder() {
return ImmutableTable.<FieldName, Operator, Function<String, Criterion<?>>>builder()
.put(FieldName.DELETION_DATE, BEFORE_OR_EQUALS, testedValue -> CriterionFactory.deletionDate().beforeOrEquals(ZONED_DATE_TIME_PARSER.parse(testedValue)))
.put(FieldName.DELETION_DATE, AFTER_OR_EQUALS, testedValue -> CriterionFactory.deletionDate().afterOrEquals(ZONED_DATE_TIME_PARSER.parse(testedValue)))
@@ -161,9 +191,11 @@ public class QueryTranslator {
}
private Function<String, Criterion<?>> getCriterionParser(CriterionDTO dto) {
- return criterionRegistry.get(
- getField(dto.getFieldName()),
- getOperator(dto.getOperator()));
+ return getCriterionParser(getField(dto.getFieldName()), getOperator(dto.getOperator()));
+ }
+
+ private Function<String, Criterion<?>> getCriterionParser(FieldName fieldName, Operator operator) {
+ return criterionRegistry.get(fieldName, operator);
}
public Query translate(QueryElement queryElement) throws QueryTranslatorException {
@@ -175,6 +207,24 @@ public class QueryTranslator {
throw new IllegalArgumentException("cannot resolve query type: " + queryElement.getClass().getName());
}
+ public QueryDTO toDTO(Query query) throws QueryTranslatorException {
+ List<QueryElement> queryElements = query.getCriteria().stream().map(criterion -> {
+ FieldName fieldName = criterion.getField().fieldName();
+ Operator operator = criterion.getValueMatcher().operator();
+ Object value = criterion.getValueMatcher().expectedValue();
+
+ FieldValueSerializer fieldValueSerializer = FieldValueSerializer.getSerializerForValue(value).orElseThrow(
+ () -> new IllegalArgumentException("Value of type " + value.getClass().getSimpleName()
+ + "' is not handled by the combinaison of operator : " + operator.name()
+ + " and field :" + fieldName.name())
+ );
+
+ return new CriterionDTO(fieldName.getValue(), operator.getValue(), fieldValueSerializer.serialize(value));
+ }).collect(Guavate.toImmutableList());
+
+ return new QueryDTO(Combinator.AND.value, queryElements);
+ }
+
Query translate(QueryDTO queryDTO) throws QueryTranslatorException {
Preconditions.checkArgument(combinatorIsValid(queryDTO.getCombinator()), "combinator '" + queryDTO.getCombinator() + "' is not yet handled");
Preconditions.checkArgument(queryDTO.getCriteria().stream().allMatch(this::isCriterion), "nested query structure is not yet handled");
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Criterion.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Criterion.java
index 770c596..734e407 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Criterion.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Criterion.java
@@ -75,4 +75,12 @@ public class Criterion<T> {
.map(valueMatcher::matches)
.orElse(DEFAULT_TO_NON_MATCHED_IF_NON_EXIST);
}
+
+ public DeletedMessageField<T> getField() {
+ return field;
+ }
+
+ public ValueMatcher<?, T> getValueMatcher() {
+ return valueMatcher;
+ }
}
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Query.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Query.java
index ecc9b6c..f73e067 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Query.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Query.java
@@ -50,4 +50,8 @@ public class Query {
.reduce(Predicate::and)
.orElse(MATCH_ALL);
}
+
+ public List<Criterion<?>> getCriteria() {
+ return criteria;
+ }
}
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryTranslatorTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryTranslatorTest.java
index 37986f7..7360bd8 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryTranslatorTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryTranslatorTest.java
@@ -19,12 +19,19 @@
package org.apache.james.vault.dto.query;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import java.time.ZonedDateTime;
+
+import org.apache.james.core.MailAddress;
import org.apache.james.mailbox.inmemory.InMemoryId;
+import org.apache.james.mailbox.model.TestId;
+import org.apache.james.vault.search.CriterionFactory;
import org.apache.james.vault.search.FieldName;
import org.apache.james.vault.search.Operator;
+import org.apache.james.vault.search.Query;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -56,8 +63,8 @@ class QueryTranslatorTest {
@Test
void translateShouldThrowWhenPassingNestedQuery() {
assertThatThrownBy(() -> queryTranslator.translate(QueryDTO.and(
- QueryDTO.and(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS.getValue(), "james"))
- )))
+ QueryDTO.and(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS.getValue(), "james"))
+ )))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("nested query structure is not yet handled");
}
@@ -65,10 +72,147 @@ class QueryTranslatorTest {
@Test
void translateShouldNotThrowWhenPassingFlattenQuery() {
assertThatCode(() -> queryTranslator.translate(QueryDTO.and(
- new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS.getValue(), "james"),
- new CriterionDTO(FieldName.SENDER.getValue(), Operator.EQUALS.getValue(), "user@james.org"),
- new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "true")
- )))
+ new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS.getValue(), "james"),
+ new CriterionDTO(FieldName.SENDER.getValue(), Operator.EQUALS.getValue(), "user@james.org"),
+ new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "true")
+ )))
.doesNotThrowAnyException();
}
+
+ @Test
+ void toDTOShouldConvertQueryWithDeletionDateBeforeOrEquals() throws Exception{
+ String serializedDate = "2007-12-03T10:15:30+01:00[Europe/Paris]";
+ Query query = Query.of(
+ CriterionFactory.deletionDate().beforeOrEquals(ZonedDateTime.parse(serializedDate))
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.DELETION_DATE.getValue(), Operator.BEFORE_OR_EQUALS.getValue(), serializedDate)
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithDeletionDateAfterOrEquals() throws Exception{
+ String serializedDate = "2007-12-03T10:15:30+01:00[Europe/Paris]";
+ Query query = Query.of(
+ CriterionFactory.deletionDate().afterOrEquals(ZonedDateTime.parse(serializedDate))
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.DELETION_DATE.getValue(), Operator.AFTER_OR_EQUALS.getValue(), serializedDate)
+ ));
+ }
+ @Test
+ void toDTOShouldConvertQueryWithDeliveryDateBeforeOrEquals() throws Exception{
+ String serializedDate = "2007-12-03T10:15:30+01:00[Europe/Paris]";
+ Query query = Query.of(
+ CriterionFactory.deliveryDate().beforeOrEquals(ZonedDateTime.parse(serializedDate))
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.DELIVERY_DATE.getValue(), Operator.BEFORE_OR_EQUALS.getValue(), serializedDate)
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithDeliveryDateAfterOrEquals() throws Exception{
+ String serializedDate = "2007-12-03T10:15:30+01:00[Europe/Paris]";
+ Query query = Query.of(
+ CriterionFactory.deliveryDate().afterOrEquals(ZonedDateTime.parse(serializedDate))
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.DELIVERY_DATE.getValue(), Operator.AFTER_OR_EQUALS.getValue(), serializedDate)
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithRecipientsContains() throws Exception{
+ Query query = Query.of(
+ CriterionFactory.containsRecipient(new MailAddress("user@james.org"))
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.RECIPIENTS.getValue(), Operator.CONTAINS.getValue(), "user@james.org")
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithSenderEquals() throws Exception{
+ Query query = Query.of(
+ CriterionFactory.hasSender(new MailAddress("user@james.org"))
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.SENDER.getValue(), Operator.EQUALS.getValue(), "user@james.org")
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithHasAttachement() {
+ Query query = Query.of(
+ CriterionFactory.hasAttachment(true)
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "true")
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithSubjectEquals() {
+ Query query = Query.of(
+ CriterionFactory.subject().equals("james")
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.EQUALS.getValue(), "james")
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithSubjectEqualsIgnoreCase() {
+ Query query = Query.of(
+ CriterionFactory.subject().equalsIgnoreCase("james")
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.EQUALS_IGNORE_CASE.getValue(), "james")
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithSubjectContains() {
+ Query query = Query.of(
+ CriterionFactory.subject().contains("james")
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS.getValue(), "james")
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithSubjectContainsIgnoreCase() {
+ Query query = Query.of(
+ CriterionFactory.subject().containsIgnoreCase("james")
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS_IGNORE_CASE.getValue(), "james")
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertQueryWithContainsOriginMailbox() {
+ Query query = Query.of(
+ CriterionFactory.containsOriginMailbox(TestId.of(1L))
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.ORIGIN_MAILBOXES.getValue(), Operator.CONTAINS.getValue(), "1")
+ ));
+ }
+
+ @Test
+ void toDTOShouldConvertFlattenQuery() throws Exception {
+ Query query = Query.of(
+ CriterionFactory.subject().contains("james"),
+ CriterionFactory.hasSender(new MailAddress("user@james.org")),
+ CriterionFactory.hasAttachment(true)
+ );
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(
+ new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS.getValue(), "james"),
+ new CriterionDTO(FieldName.SENDER.getValue(), Operator.EQUALS.getValue(), "user@james.org"),
+ new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "true")
+ ));
+ }
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org