JAMES-1894 Introduce a Sort converter that targets Search Queries
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/d42f234b Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/d42f234b Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/d42f234b Branch: refs/heads/master Commit: d42f234b945c681240951a3642a2e821f23748ab Parents: 678f55a Author: Benoit Tellier <btell...@linagora.com> Authored: Thu Dec 22 10:20:14 2016 +0700 Committer: Benoit Tellier <btell...@linagora.com> Committed: Mon Jan 9 21:58:32 2017 +0700 ---------------------------------------------------------------------- .../apache/james/mailbox/model/SearchQuery.java | 22 +++- .../elasticsearch/query/SortConverter.java | 2 +- .../apache/james/jmap/utils/SortConverter.java | 89 +++++++++++++++ .../james/jmap/utils/SortConverterTest.java | 114 +++++++++++++++++++ 4 files changed, 225 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/d42f234b/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 46a96a3..9faae8f 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 @@ -145,7 +145,12 @@ public class SearchQuery implements Serializable { /** * Uid of the message. This is the DEFAULT if no other is specified */ - Uid + Uid, + + /** + * Unique Id of the message. + */ + Id } private final boolean reverse; @@ -182,6 +187,21 @@ public class SearchQuery implements Serializable { public SortClause getSortClause() { return sortClause; } + + @Override + public boolean equals(Object o) { + if (o instanceof Sort) { + Sort that = (Sort) o; + return Objects.equal(this.sortClause, that.sortClause) + && Objects.equal(this.reverse, that.reverse); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(sortClause, reverse); + } } /** http://git-wip-us.apache.org/repos/asf/james-project/blob/d42f234b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java index 5644239..737827e 100644 --- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java +++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java @@ -70,7 +70,7 @@ public class SortConverter { } private static SortOrder getOrder(SearchQuery.Sort sort) { - if( sort.isReverse() ) { + if(sort.isReverse()) { return SortOrder.DESC; } else { return SortOrder.ASC; http://git-wip-us.apache.org/repos/asf/james-project/blob/d42f234b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SortConverter.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SortConverter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SortConverter.java new file mode 100644 index 0000000..74ad6a6 --- /dev/null +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SortConverter.java @@ -0,0 +1,89 @@ +/**************************************************************** + O * 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.List; +import java.util.Map; + +import org.apache.james.mailbox.model.SearchQuery; + +import com.github.steveash.guavate.Guavate; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableMap; + +public class SortConverter { + + private static final String SEPARATOR = " "; + private static final String DESC_ORDERING = "desc"; + private static final String ASC_ORDERING = "asc"; + + private static final Map<String, SearchQuery.Sort.SortClause> SORT_CLAUSE_MAP = ImmutableMap.of( + "date", SearchQuery.Sort.SortClause.Arrival, + "id", SearchQuery.Sort.SortClause.Id); + public static final boolean REVERSE = true; + public static final SearchQuery.Sort DEFAULT_SORT = new SearchQuery.Sort(SearchQuery.Sort.SortClause.Arrival, REVERSE); + + + public static List<SearchQuery.Sort> convertToSorts(List<String> jmapSorts) { + Preconditions.checkNotNull(jmapSorts); + ImmutableList<SearchQuery.Sort> result = jmapSorts.stream() + .map(SortConverter::toSort) + .collect(Guavate.toImmutableList()); + if (result.isEmpty()) { + return ImmutableList.of(DEFAULT_SORT); + } + return result; + } + + private static SearchQuery.Sort toSort(String jmapSort) { + Preconditions.checkNotNull(jmapSort); + List<String> splitToList = Splitter.on(SEPARATOR).splitToList(jmapSort); + checkField(splitToList); + return new SearchQuery.Sort(getSortClause(splitToList.get(0)), + isReverse(splitToList)); + } + + private static SearchQuery.Sort.SortClause getSortClause(String field) { + if (! SORT_CLAUSE_MAP.containsKey(field)) { + throw new IllegalArgumentException("Unknown sorting field: " + field + " should be one of " + SORT_CLAUSE_MAP.keySet()); + } + return SORT_CLAUSE_MAP.get(field); + } + + private static boolean isReverse(List<String> splitList) { + if (splitList.size() == 1) { + return true; + } + String order = splitList.get(1); + switch (order) { + case DESC_ORDERING: + return true; + case ASC_ORDERING: + return false; + } + throw new IllegalArgumentException("Unknown sorting order: " + order + " should be one of [asc, desc]"); + } + + private static void checkField(List<String> splitToList) { + Preconditions.checkArgument(splitToList.size() > 0 && splitToList.size() <=2, "Bad sort field definition. Must contains a field and an optional order separated by a space"); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/d42f234b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/SortConverterTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/SortConverterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/SortConverterTest.java new file mode 100644 index 0000000..bcd48ae --- /dev/null +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/SortConverterTest.java @@ -0,0 +1,114 @@ +/**************************************************************** + * 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 java.util.List; + +import org.apache.james.mailbox.model.SearchQuery; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +public class SortConverterTest { + + public static final boolean REVERSE = true; + public static final boolean NOT_REVERSE = !REVERSE; + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void convertToSortsShouldThrowOnNullValue() { + expectedException.expect(NullPointerException.class); + SortConverter.convertToSorts(null); + } + + @Test + public void convertToSortsShouldReturnDefaultSortOnEmptyEntry() { + assertThat(SortConverter.convertToSorts(ImmutableList.of())) + .containsOnly(new SearchQuery.Sort(SearchQuery.Sort.SortClause.Arrival, REVERSE)); + } + + @Test + public void convertToSortsShouldThrowOnNullJmapSort() { + List<String> jmapSorts = Lists.newArrayList((String) null); + expectedException.expect(NullPointerException.class); + SortConverter.convertToSorts(jmapSorts); + } + + @Test + public void convertToSortsShouldThrowOnEmptyJmapSort() { + expectedException.expect(IllegalArgumentException.class); + SortConverter.convertToSorts(ImmutableList.of("")); + } + + @Test + public void convertToSortsShouldThrowOnUnknownJmapSort() { + expectedException.expect(IllegalArgumentException.class); + SortConverter.convertToSorts(ImmutableList.of("unknown")); + } + + @Test + public void convertToSortsShouldSupportDate() { + assertThat(SortConverter.convertToSorts(ImmutableList.of("date desc"))) + .containsExactly(new SearchQuery.Sort(SearchQuery.Sort.SortClause.Arrival, REVERSE)); + } + + @Test + public void convertToSortsShouldSupportId() { + assertThat(SortConverter.convertToSorts(ImmutableList.of("id desc"))) + .containsExactly(new SearchQuery.Sort(SearchQuery.Sort.SortClause.Id, REVERSE)); + } + + @Test + public void convertToSortsShouldBeDescWhenNoOrderClause() { + assertThat(SortConverter.convertToSorts(ImmutableList.of("date"))) + .containsExactly(new SearchQuery.Sort(SearchQuery.Sort.SortClause.Arrival, REVERSE)); + } + + @Test + public void convertToSortsShouldThrowWhenOnUnknownOrderClause() { + expectedException.expect(IllegalArgumentException.class); + SortConverter.convertToSorts(ImmutableList.of("date unknown")); + } + + @Test + public void convertToSortsShouldSupportAscOrder() { + assertThat(SortConverter.convertToSorts(ImmutableList.of("date asc"))) + .containsExactly(new SearchQuery.Sort(SearchQuery.Sort.SortClause.Arrival, NOT_REVERSE)); + } + + @Test + public void convertToSortsShouldThrowWhenJmapSortIsTooLong() { + expectedException.expect(IllegalArgumentException.class); + SortConverter.convertToSorts(ImmutableList.of("date asc toomuch")); + } + + @Test + public void convertToSortsShouldSupportMultipleSorts() { + assertThat(SortConverter.convertToSorts(ImmutableList.of("date asc", "id desc"))) + .containsExactly(new SearchQuery.Sort(SearchQuery.Sort.SortClause.Arrival, NOT_REVERSE), + new SearchQuery.Sort(SearchQuery.Sort.SortClause.Id, REVERSE)); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org