Author: btellier Date: Mon Jun 29 08:30:14 2015 New Revision: 1688122 URL: http://svn.apache.org/r1688122 Log: MAILBOX-235 rework Collector so that everything is immutable - patch contributed by Matthieu Baechlor
Modified: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollector.java james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryRepresentation.java james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/QueryConverter.java james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollectorTest.java james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/QueryConverterTest.java Modified: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java?rev=1688122&r1=1688121&r2=1688122&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java (original) +++ james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java Mon Jun 29 08:30:14 2015 @@ -140,7 +140,7 @@ public class CriterionConverter { private FilteredQueryRepresentation convertConjunction(SearchQuery.ConjunctionCriterion criterion) { return criterion.getCriteria().stream() .map(this::convertCriterion) - .collect(new FilteredQueryCollector(criterion.getType())); + .collect(FilteredQueryCollector.collector(criterion.getType())); } private FilteredQueryRepresentation convertFlag(SearchQuery.FlagCriterion flagCriterion) { @@ -192,7 +192,7 @@ public class CriterionConverter { } return Arrays.stream(uidCriterion.getOperator().getRange()) .map(this::uidRangeFilter) - .collect(new FilteredQueryCollector(SearchQuery.Conjunction.OR)); + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.OR)); } private FilteredQueryRepresentation uidRangeFilter(SearchQuery.NumericRange numericRange) { Modified: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollector.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollector.java?rev=1688122&r1=1688121&r2=1688122&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollector.java (original) +++ james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollector.java Mon Jun 29 08:30:14 2015 @@ -19,105 +19,19 @@ package org.apache.james.mailbox.elasticsearch.query; -import static org.elasticsearch.index.query.QueryBuilders.boolQuery; -import static org.elasticsearch.index.query.FilterBuilders.boolFilter; - -import org.apache.james.mailbox.model.SearchQuery; -import org.elasticsearch.index.query.BoolFilterBuilder; -import org.elasticsearch.index.query.BoolQueryBuilder; - -import java.util.EnumSet; -import java.util.Optional; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Collector; +import java.util.stream.Collectors; -public class FilteredQueryCollector implements Collector<FilteredQueryRepresentation, FilteredQueryRepresentation, FilteredQueryRepresentation> { - - private final SearchQuery.Conjunction type; - - public FilteredQueryCollector(SearchQuery.Conjunction type) { - this.type = type; - } - - @Override - public Supplier<FilteredQueryRepresentation> supplier() { - return FilteredQueryRepresentation::empty; - } - - @Override - public BiConsumer<FilteredQueryRepresentation, FilteredQueryRepresentation> accumulator() { - return this::apply; - } - - @Override - public BinaryOperator<FilteredQueryRepresentation> combiner() { - return this::apply; - } - - @Override - public Function<FilteredQueryRepresentation, FilteredQueryRepresentation> finisher() { - return (accumulator)->accumulator; - } - - @Override - public Set<Characteristics> characteristics() { - return EnumSet.of(Characteristics.UNORDERED); - } - - private FilteredQueryRepresentation apply(FilteredQueryRepresentation accumulator, FilteredQueryRepresentation collected) { - initializeAccumulatorWhenNeeded(accumulator, collected); - switch (type) { - case OR: - return applyOr(accumulator, collected); - case AND: - return applyAnd(accumulator, collected); - case NOR: - return applyNor(accumulator, collected); - } - return accumulator; - } +import org.apache.james.mailbox.model.SearchQuery; - private void initializeAccumulatorWhenNeeded(FilteredQueryRepresentation accumulator, FilteredQueryRepresentation collected) { - // This method is compulsory because elasticSearch refuses to build empty BoolQuery and empty BoolFilter - if (!accumulator.getQuery().isPresent() && collected.getQuery().isPresent()) { - accumulator.setQuery(Optional.of(boolQuery())); - } - if (!accumulator.getFilter().isPresent() && collected.getFilter().isPresent()) { - accumulator.setFilter(Optional.of(boolFilter())); - } - } +public class FilteredQueryCollector { - private FilteredQueryRepresentation applyNor(FilteredQueryRepresentation accumulator, FilteredQueryRepresentation collected) { - if (collected.getQuery().isPresent()) { - ((BoolQueryBuilder) accumulator.getQuery().get()).mustNot(collected.getQuery().get()); - } - if (collected.getFilter().isPresent()) { - ((BoolFilterBuilder) accumulator.getFilter().get()).mustNot(collected.getFilter().get()); - } - return accumulator; + public static Collector<FilteredQueryRepresentation, ?, FilteredQueryRepresentation> + collector(SearchQuery.Conjunction type) { + + return Collectors.reducing( + FilteredQueryRepresentation.empty(), + (x, y) -> x.combine(type, y)); } - private FilteredQueryRepresentation applyAnd(FilteredQueryRepresentation accumulator, FilteredQueryRepresentation collected) { - if (collected.getQuery().isPresent()) { - ((BoolQueryBuilder) accumulator.getQuery().get()).must(collected.getQuery().get()); - } - if (collected.getFilter().isPresent()) { - ((BoolFilterBuilder) accumulator.getFilter().get()).must(collected.getFilter().get()); - } - return accumulator; - } - - private FilteredQueryRepresentation applyOr(FilteredQueryRepresentation accumulator, FilteredQueryRepresentation collected) { - if (collected.getQuery().isPresent()) { - ((BoolQueryBuilder) accumulator.getQuery().get()).should(collected.getQuery().get()); - } - if (collected.getFilter().isPresent()) { - ((BoolFilterBuilder) accumulator.getFilter().get()).should(collected.getFilter().get()); - } - return accumulator; - } } Modified: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryRepresentation.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryRepresentation.java?rev=1688122&r1=1688121&r2=1688122&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryRepresentation.java (original) +++ james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryRepresentation.java Mon Jun 29 08:30:14 2015 @@ -19,10 +19,17 @@ package org.apache.james.mailbox.elasticsearch.query; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Function; + +import org.apache.james.mailbox.model.SearchQuery; +import org.elasticsearch.index.query.BoolFilterBuilder; +import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.FilterBuilder; +import org.elasticsearch.index.query.FilterBuilders; import org.elasticsearch.index.query.QueryBuilder; - -import java.util.Optional; +import org.elasticsearch.index.query.QueryBuilders; public class FilteredQueryRepresentation { @@ -38,8 +45,8 @@ public class FilteredQueryRepresentatio return new FilteredQueryRepresentation(Optional.empty(), Optional.empty()); } - private Optional<FilterBuilder> filter; - private Optional<QueryBuilder> query; + private final Optional<FilterBuilder> filter; + private final Optional<QueryBuilder> query; private FilteredQueryRepresentation(Optional<QueryBuilder> query, Optional<FilterBuilder> filter) { this.query = query; @@ -54,11 +61,90 @@ public class FilteredQueryRepresentatio return query; } - public void setFilter(Optional<FilterBuilder> filter) { - this.filter = filter; + public FilteredQueryRepresentation combine(SearchQuery.Conjunction type, FilteredQueryRepresentation collected) { + switch (type) { + case OR: + return applyOr(collected); + case AND: + return applyAnd(collected); + case NOR: + return new FilteredQueryRepresentation( + applyNorOnQuery(collected), + applyNorOnFilter(collected)); + } + return this; + } + + private FilteredQueryRepresentation applyAnd(FilteredQueryRepresentation collected) { + return new FilteredQueryRepresentation( + applyOnQuery( + (x, y) -> x.must(y), + collected.getQuery(), + (x) -> QueryBuilders.boolQuery().must(x)), + applyOnFilter( + (x, y) -> x.must(y), + collected.getFilter(), + (x) -> FilterBuilders.boolFilter().must(x))); + } + + private FilteredQueryRepresentation applyOr(FilteredQueryRepresentation collected) { + return new FilteredQueryRepresentation( + applyOnQuery( + (x, y) -> x.should(y), + collected.getQuery(), + (x) -> QueryBuilders.boolQuery().should(x)), + applyOnFilter( + (x, y) -> x.should(y), + collected.getFilter(), + (x) -> FilterBuilders.boolFilter().should(x))); + } + + private Optional<QueryBuilder> applyOnQuery(BiFunction<BoolQueryBuilder, QueryBuilder, QueryBuilder> function, Optional<QueryBuilder> input, Function<QueryBuilder, BoolQueryBuilder> s) { + return genericApply(ensureBoolQuery(function, s), query, input); + } + + private BiFunction<QueryBuilder, QueryBuilder, QueryBuilder> + ensureBoolQuery(BiFunction<BoolQueryBuilder, QueryBuilder, QueryBuilder> f, Function<QueryBuilder, BoolQueryBuilder> s) { + return (x, y) -> f.apply(s.apply(x), y); + } + + private Optional<FilterBuilder> applyOnFilter(BiFunction<BoolFilterBuilder, FilterBuilder, FilterBuilder> function, Optional<FilterBuilder> input, Function<FilterBuilder, BoolFilterBuilder> s) { + return genericApply(ensureBoolFilter(function, s), filter, input); + } + + private BiFunction<FilterBuilder, FilterBuilder, FilterBuilder> + ensureBoolFilter(BiFunction<BoolFilterBuilder, FilterBuilder, FilterBuilder> f, Function<FilterBuilder, BoolFilterBuilder> s) { + return (x, y) -> f.apply(s.apply(x), y); + } + + private <T> Optional<T> genericApply(BiFunction<T, T, T> function, Optional<T> lhs, Optional<T> rhs) { + if (rhs.isPresent()) { + if (lhs.isPresent()) { + return Optional.of(function.apply(rhs.get(), lhs.get())); + } else { + return rhs; + } + } else { + return lhs; + } + } + + private Optional<FilterBuilder> applyNorOnFilter(FilteredQueryRepresentation collected) { + // The cast is necessary for determining types ( in other cases : Optional<BoolFilterBuilder> is incompatible with Optional<FilterBuilder> + return collected.getFilter().map( + (collectedFilter) -> filter.map( + (innerFilter) -> Optional.of((FilterBuilder) FilterBuilders.boolFilter().must(innerFilter).mustNot(collectedFilter))) + .orElse(Optional.of(FilterBuilders.boolFilter().mustNot(collectedFilter))) + ).orElse(filter); + } + + private Optional<QueryBuilder> applyNorOnQuery(FilteredQueryRepresentation collected) { + // The cast is necessary for determining types ( in other cases : Optional<BoolQueryBuilder> is incompatible with Optional<QueryBuilder> + return collected.getQuery().map( + (collectedQuery) -> query.map( + (innerQuery) -> Optional.of((QueryBuilder)QueryBuilders.boolQuery().must(innerQuery).mustNot(collected.getQuery().get()))) + .orElse(Optional.of(QueryBuilders.boolQuery().mustNot(collectedQuery))) + ).orElse(query); } - public void setQuery(Optional<QueryBuilder> query) { - this.query = query; - } } Modified: james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/QueryConverter.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/QueryConverter.java?rev=1688122&r1=1688121&r2=1688122&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/QueryConverter.java (original) +++ james/mailbox/trunk/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/QueryConverter.java Mon Jun 29 08:30:14 2015 @@ -67,7 +67,7 @@ public class QueryConverter implements F private FilteredQueryRepresentation addMailboxFilters(FilteredQueryRepresentation elasticsearchQueryRepresentation, String mailboxUUID) { return Stream.of(elasticsearchQueryRepresentation, FilteredQueryRepresentation.fromFilter(termFilter(JsonMessageConstants.MAILBOX_ID, mailboxUUID))) - .collect(new FilteredQueryCollector(SearchQuery.Conjunction.AND)); + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.AND)); } private QueryBuilder getFinalQuery(FilteredQueryRepresentation filteredQueryRepresentation) { Modified: james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollectorTest.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollectorTest.java?rev=1688122&r1=1688121&r2=1688122&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollectorTest.java (original) +++ james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/FilteredQueryCollectorTest.java Mon Jun 29 08:30:14 2015 @@ -40,7 +40,7 @@ public class FilteredQueryCollectorTest List<FilteredQueryRepresentation> emptyFilteredQueryRepresentationList = Lists.newArrayList(); FilteredQueryRepresentation collectionResult = emptyFilteredQueryRepresentationList .stream() - .collect(new FilteredQueryCollector(SearchQuery.Conjunction.AND)); + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.AND)); assertThat(collectionResult.getFilter()).isEmpty(); assertThat(collectionResult.getQuery()).isEmpty(); } @@ -48,21 +48,21 @@ public class FilteredQueryCollectorTest @Test public void queryAloneShouldBeWellCollected() throws Exception { FilteredQueryRepresentation collectionResult = Stream.of(FilteredQueryRepresentation.fromQuery(matchAllQuery())) - .collect(new FilteredQueryCollector(SearchQuery.Conjunction.AND)); + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.AND)); assertThat(collectionResult.getFilter()).isEmpty(); assertThat(collectionResult.getQuery()).isPresent(); assertThatJson(collectionResult.getQuery().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) - .isEqualTo("{\"bool\":{\"must\":{\"match_all\":{}}}}"); + .isEqualTo("{\"match_all\":{}}"); } @Test public void filterAloneShouldBeWellCollected() throws Exception { FilteredQueryRepresentation collectionResult = Stream.of(FilteredQueryRepresentation.fromFilter(termFilter("field", "value"))) - .collect(new FilteredQueryCollector(SearchQuery.Conjunction.AND)); + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.AND)); assertThat(collectionResult.getFilter()).isPresent(); assertThat(collectionResult.getQuery()).isEmpty(); assertThatJson(collectionResult.getFilter().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) - .isEqualTo("{\"bool\":{\"must\":{\"term\":{\"field\":\"value\"}}}}"); + .isEqualTo("{\"term\":{\"field\":\"value\"}}"); } @Test @@ -70,13 +70,13 @@ public class FilteredQueryCollectorTest FilteredQueryRepresentation collectionResult = Stream.of( FilteredQueryRepresentation.fromFilter(termFilter("field", "value")), FilteredQueryRepresentation.fromQuery(matchAllQuery())) - .collect(new FilteredQueryCollector(SearchQuery.Conjunction.AND)); + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.AND)); assertThat(collectionResult.getFilter()).isPresent(); assertThat(collectionResult.getQuery()).isPresent(); assertThatJson(collectionResult.getQuery().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) - .isEqualTo("{\"bool\":{\"must\":{\"match_all\":{}}}}"); + .isEqualTo("{\"match_all\":{}}"); assertThatJson(collectionResult.getFilter().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) - .isEqualTo("{\"bool\":{\"must\":{\"term\":{\"field\":\"value\"}}}}"); + .isEqualTo("{\"term\":{\"field\":\"value\"}}"); } @Test @@ -84,7 +84,7 @@ public class FilteredQueryCollectorTest FilteredQueryRepresentation collectionResult = Stream.of( FilteredQueryRepresentation.fromQuery(matchAllQuery()), FilteredQueryRepresentation.fromQuery(matchAllQuery())) - .collect(new FilteredQueryCollector(SearchQuery.Conjunction.AND)); + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.AND)); assertThat(collectionResult.getFilter()).isEmpty(); assertThat(collectionResult.getQuery()).isPresent(); assertThatJson(collectionResult.getQuery().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) @@ -96,11 +96,148 @@ public class FilteredQueryCollectorTest FilteredQueryRepresentation collectionResult = Stream.of( FilteredQueryRepresentation.fromFilter(termFilter("field", "value")), FilteredQueryRepresentation.fromFilter(termFilter("field", "value"))) - .collect(new FilteredQueryCollector(SearchQuery.Conjunction.AND)); + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.AND)); assertThat(collectionResult.getFilter()).isPresent(); assertThat(collectionResult.getQuery()).isEmpty(); assertThatJson(collectionResult.getFilter().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) .isEqualTo("{\"bool\":{\"must\":[{\"term\":{\"field\":\"value\"}},{\"term\":{\"field\":\"value\"}}]}}"); } + @Test + public void emptyStreamShouldBeCollectedAsEmptyFilteredQueryRepresentationOnNor() throws Exception { + List<FilteredQueryRepresentation> emptyFilteredQueryRepresentationList = Lists.newArrayList(); + FilteredQueryRepresentation collectionResult = emptyFilteredQueryRepresentationList + .stream() + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.NOR)); + assertThat(collectionResult.getFilter()).isEmpty(); + assertThat(collectionResult.getQuery()).isEmpty(); + } + + @Test + public void queryAloneShouldBeWellCollectedOnNor() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of(FilteredQueryRepresentation.fromQuery(matchAllQuery())) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.NOR)); + assertThat(collectionResult.getFilter()).isEmpty(); + assertThat(collectionResult.getQuery()).isPresent(); + assertThatJson(collectionResult.getQuery().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"bool\":{\"must_not\":{\"match_all\":{}}}}"); + } + + @Test + public void filterAloneShouldBeWellCollectedOnNor() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of(FilteredQueryRepresentation.fromFilter(termFilter("field", "value"))) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.NOR)); + assertThat(collectionResult.getFilter()).isPresent(); + assertThat(collectionResult.getQuery()).isEmpty(); + assertThatJson(collectionResult.getFilter().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"bool\":{\"must_not\":{\"term\":{\"field\":\"value\"}}}}"); + } + + @Test + public void aggregationBetweenQueryAndFilterShouldWorkOnNor() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of( + FilteredQueryRepresentation.fromFilter(termFilter("field", "value")), + FilteredQueryRepresentation.fromQuery(matchAllQuery())) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.NOR)); + assertThat(collectionResult.getFilter()).isPresent(); + assertThat(collectionResult.getQuery()).isPresent(); + assertThatJson(collectionResult.getQuery().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"bool\":{\"must_not\":{\"match_all\":{}}}}"); + assertThatJson(collectionResult.getFilter().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"bool\":{\"must_not\":{\"term\":{\"field\":\"value\"}}}}"); + } + + @Test + public void queryAggregationShouldWorkOnNor() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of( + FilteredQueryRepresentation.fromQuery(matchAllQuery()), + FilteredQueryRepresentation.fromQuery(matchAllQuery())) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.NOR)); + assertThat(collectionResult.getFilter()).isEmpty(); + assertThat(collectionResult.getQuery()).isPresent(); + assertThatJson(collectionResult.getQuery().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"bool\":{\"must\":{\"bool\":{\"must_not\":{\"match_all\":{}}}},\"must_not\":{\"match_all\":{}}}}"); + } + + @Test + public void filterAggregationShouldWorkOnNor() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of( + FilteredQueryRepresentation.fromFilter(termFilter("field", "value")), + FilteredQueryRepresentation.fromFilter(termFilter("field", "value"))) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.NOR)); + assertThat(collectionResult.getFilter()).isPresent(); + assertThat(collectionResult.getQuery()).isEmpty(); + assertThatJson(collectionResult.getFilter().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo( + "{\"bool\":{\"must\":{\"bool\":{\"must_not\":{\"term\":{\"field\":\"value\"}}}},\"must_not\":{\"term\":{\"field\":\"value\"}}}}"); + } + + @Test + public void emptyStreamShouldBeCollectedAsEmptyFilteredQueryRepresentationOnOr() throws Exception { + List<FilteredQueryRepresentation> emptyFilteredQueryRepresentationList = Lists.newArrayList(); + FilteredQueryRepresentation collectionResult = emptyFilteredQueryRepresentationList + .stream() + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.OR)); + assertThat(collectionResult.getFilter()).isEmpty(); + assertThat(collectionResult.getQuery()).isEmpty(); + } + + @Test + public void queryAloneShouldBeWellCollectedOnOr() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of(FilteredQueryRepresentation.fromQuery(matchAllQuery())) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.OR)); + assertThat(collectionResult.getFilter()).isEmpty(); + assertThat(collectionResult.getQuery()).isPresent(); + assertThatJson(collectionResult.getQuery().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"match_all\":{}}"); + } + + @Test + public void filterAloneShouldBeWellCollectedOnOr() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of(FilteredQueryRepresentation.fromFilter(termFilter("field", "value"))) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.OR)); + assertThat(collectionResult.getFilter()).isPresent(); + assertThat(collectionResult.getQuery()).isEmpty(); + assertThatJson(collectionResult.getFilter().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"term\":{\"field\":\"value\"}}"); + } + + @Test + public void aggregationBetweenQueryAndFilterShouldWorkOnOr() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of( + FilteredQueryRepresentation.fromFilter(termFilter("field", "value")), + FilteredQueryRepresentation.fromQuery(matchAllQuery())) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.OR)); + assertThat(collectionResult.getFilter()).isPresent(); + assertThat(collectionResult.getQuery()).isPresent(); + assertThatJson(collectionResult.getQuery().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"match_all\":{}}"); + assertThatJson(collectionResult.getFilter().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"term\":{\"field\":\"value\"}}"); + } + + @Test + public void queryAggregationShouldWorkOnOr() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of( + FilteredQueryRepresentation.fromQuery(matchAllQuery()), + FilteredQueryRepresentation.fromQuery(matchAllQuery())) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.OR)); + assertThat(collectionResult.getFilter()).isEmpty(); + assertThat(collectionResult.getQuery()).isPresent(); + assertThatJson(collectionResult.getQuery().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"bool\":{\"should\":[{\"match_all\":{}},{\"match_all\":{}}]}}"); + } + + @Test + public void filterAggregationShouldWorkOnOr() throws Exception { + FilteredQueryRepresentation collectionResult = Stream.of( + FilteredQueryRepresentation.fromFilter(termFilter("field", "value")), + FilteredQueryRepresentation.fromFilter(termFilter("field", "value"))) + .collect(FilteredQueryCollector.collector(SearchQuery.Conjunction.OR)); + assertThat(collectionResult.getFilter()).isPresent(); + assertThat(collectionResult.getQuery()).isEmpty(); + assertThatJson(collectionResult.getFilter().get().toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .isEqualTo("{\"bool\":{\"should\":[{\"term\":{\"field\":\"value\"}},{\"term\":{\"field\":\"value\"}}]}}"); + } + } Modified: james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/QueryConverterTest.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/QueryConverterTest.java?rev=1688122&r1=1688121&r2=1688122&view=diff ============================================================================== --- james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/QueryConverterTest.java (original) +++ james/mailbox/trunk/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/query/QueryConverterTest.java Mon Jun 29 08:30:14 2015 @@ -48,27 +48,19 @@ public class QueryConverterTest { SearchQuery searchQuery = new SearchQuery(); searchQuery.andCriteria(SearchQuery.all()); assertThatJson(queryConverter.from(searchQuery, MAILBOX_UUID).toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .when(IGNORING_ARRAY_ORDER) .isEqualTo("{" + " \"filtered\": {" + " \"query\": {" + - " \"bool\": {" + - " \"must\": {" + " \"match_all\": {}" + - " }" + - " }" + " }," + " \"filter\": {" + - " \"bool\": {" + - " \"must\": {" + " \"term\": {" + " \"mailboxId\": \"12345\"" + " }" + - " }" + - " }" + " }" + " }" + - "}") - .when(IGNORING_ARRAY_ORDER); + "}"); } @Test @@ -76,32 +68,24 @@ public class QueryConverterTest { SearchQuery searchQuery = new SearchQuery(); searchQuery.andCriteria(SearchQuery.bodyContains("awesome Linagora team")); assertThatJson(queryConverter.from(searchQuery, MAILBOX_UUID).toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .when(IGNORING_ARRAY_ORDER) .isEqualTo("{" + " \"filtered\": {" + " \"query\": {" + - " \"bool\": {" + - " \"must\": {" + " \"match\": {" + " \"textBody\": {" + " \"query\": \"awesome Linagora team\"," + " \"type\": \"boolean\"" + " }" + - " }" + - " }" + " }" + " }," + " \"filter\": {" + - " \"bool\": {" + - " \"must\": {" + " \"term\": {" + " \"mailboxId\": \"12345\"" + " }" + - " }" + - " }" + " }" + " }" + - "}") - .when(IGNORING_ARRAY_ORDER); + "}"); } @Test @@ -109,6 +93,7 @@ public class QueryConverterTest { SearchQuery searchQuery = new SearchQuery(); searchQuery.andCriteria(SearchQuery.modSeqGreaterThan(42L)); assertThatJson(queryConverter.from(searchQuery, MAILBOX_UUID).toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .when(IGNORING_ARRAY_ORDER) .isEqualTo("{" + " \"filtered\" : {" + " \"query\" : {" + @@ -133,8 +118,7 @@ public class QueryConverterTest { " }" + " }" + " }" + - "}") - .when(IGNORING_ARRAY_ORDER); + "}"); } @Test @@ -143,11 +127,10 @@ public class QueryConverterTest { searchQuery.andCriteria(SearchQuery.bodyContains("awesome Linagora team")); searchQuery.andCriteria(SearchQuery.bodyContains("Gold fish")); assertThatJson(queryConverter.from(searchQuery, MAILBOX_UUID).toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .when(IGNORING_ARRAY_ORDER) .isEqualTo("{" + " \"filtered\": {" + " \"query\": {" + - " \"bool\": {" + - " \"must\": {" + " \"bool\": {" + " \"must\": [" + " {" + @@ -167,22 +150,15 @@ public class QueryConverterTest { " }" + " }" + " ]" + - " }" + - " }" + " }" + " }," + " \"filter\": {" + - " \"bool\": {" + - " \"must\": {" + " \"term\": {" + " \"mailboxId\": \"12345\"" + " }" + - " }" + - " }" + " }" + " }" + - "}") - .when(IGNORING_ARRAY_ORDER); + "}"); } @Test @@ -190,6 +166,7 @@ public class QueryConverterTest { SearchQuery searchQuery = new SearchQuery(); searchQuery.andCriteria(SearchQuery.modSeqGreaterThan(42L)); assertThatJson(queryConverter.from(searchQuery, MAILBOX_UUID + "\"},{\"exist\":\"id\"},{\"match\":\"well done").toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .when(IGNORING_ARRAY_ORDER) .isEqualTo("{" + " \"filtered\" : {" + " \"query\" : {" + @@ -214,8 +191,7 @@ public class QueryConverterTest { " }" + " }" + " }" + - "}") - .when(IGNORING_ARRAY_ORDER); + "}"); } @Test @@ -223,48 +199,40 @@ public class QueryConverterTest { SearchQuery searchQuery = new SearchQuery(); searchQuery.andCriteria(SearchQuery.address(SearchQuery.AddressType.Bcc, "Benoit Tellier<btell...@free.fr>")); assertThatJson(queryConverter.from(searchQuery, MAILBOX_UUID).toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .when(IGNORING_ARRAY_ORDER) .isEqualTo("{" + " \"filtered\" : {" + " \"query\" : {" + - " \"bool\" : {" + - " \"must\" : {" + - " \"nested\" : {" + - " \"query\" : {" + - " \"bool\" : {" + - " \"should\" : [ {" + - " \"match\" : {" + - " \"bcc.name\" : {" + - " \"query\" : \"Benoit Tellier<btell...@free.fr>\"," + - " \"type\" : \"boolean\"" + - " }" + - " }" + - " }, {" + - " \"match\" : {" + - " \"bcc.address\" : {" + - " \"query\" : \"Benoit Tellier<btell...@free.fr>\"," + - " \"type\" : \"boolean\"" + - " }" + - " }" + - " } ]" + + " \"nested\" : {" + + " \"query\" : {" + + " \"bool\" : {" + + " \"should\" : [ {" + + " \"match\" : {" + + " \"bcc.name\" : {" + + " \"query\" : \"Benoit Tellier<btell...@free.fr>\"," + + " \"type\" : \"boolean\"" + + " }" + + " }" + + " }, {" + + " \"match\" : {" + + " \"bcc.address\" : {" + + " \"query\" : \"Benoit Tellier<btell...@free.fr>\"," + + " \"type\" : \"boolean\"" + + " }" + " }" + - " }," + - " \"path\" : \"bcc\"" + + " } ]" + " }" + - " }" + + " }," + + " \"path\" : \"bcc\"" + " }" + " }," + " \"filter\" : {" + - " \"bool\" : {" + - " \"must\" : {" + - " \"term\" : {" + - " \"mailboxId\" : \"12345\"" + - " }" + - " }" + + " \"term\" : {" + + " \"mailboxId\" : \"12345\"" + " }" + " }" + " }" + - "}") - .when(IGNORING_ARRAY_ORDER); + "}"); } @Test @@ -275,6 +243,8 @@ public class QueryConverterTest { new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2015-02-25 21:54:38"), SearchQuery.DateResolution.Hour)); assertThatJson(queryConverter.from(searchQuery, MAILBOX_UUID).toXContent(jsonBuilder(), QueryBuilder.EMPTY_PARAMS).string()) + .when(IGNORING_VALUES) + .when(IGNORING_ARRAY_ORDER) .isEqualTo("{" + " \"filtered\": {" + " \"query\": {" + @@ -302,9 +272,7 @@ public class QueryConverterTest { " }" + " }" + " }" + - "}") - .when(IGNORING_VALUES) - .when(IGNORING_ARRAY_ORDER); + "}"); // We just test structure as time Zone used by Date is different, depending on computer configuration } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org