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 <[email protected]> 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(), "[email protected]"), - 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(), "[email protected]"), + 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("[email protected]")) + ); + assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and( + new CriterionDTO(FieldName.RECIPIENTS.getValue(), Operator.CONTAINS.getValue(), "[email protected]") + )); + } + + @Test + void toDTOShouldConvertQueryWithSenderEquals() throws Exception{ + Query query = Query.of( + CriterionFactory.hasSender(new MailAddress("[email protected]")) + ); + assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and( + new CriterionDTO(FieldName.SENDER.getValue(), Operator.EQUALS.getValue(), "[email protected]") + )); + } + + @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("[email protected]")), + 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(), "[email protected]"), + new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "true") + )); + } } \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
