Skip to content

Commit 21e4fd5

Browse files
committed
Allow using Range with Comparator.
Remove Comparable requirement for general Range usage. Comparable is only required for the contains(…) check. Alternatively, accept a Comparator. Closes #2571
1 parent 0e5e869 commit 21e4fd5

File tree

2 files changed

+110
-33
lines changed

2 files changed

+110
-33
lines changed

src/main/java/org/springframework/data/domain/Range.java

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.domain;
1717

18+
import java.util.Comparator;
1819
import java.util.Optional;
1920

2021
import org.springframework.util.Assert;
@@ -27,7 +28,7 @@
2728
* @author Mark Paluch
2829
* @since 1.10
2930
*/
30-
public final class Range<T extends Comparable<T>> {
31+
public final class Range<T> {
3132

3233
private final static Range<?> UNBOUNDED = Range.of(Bound.unbounded(), Bound.UNBOUNDED);
3334

@@ -57,7 +58,7 @@ private Range(Bound<T> lowerBound, Bound<T> upperBound) {
5758
* @since 2.0
5859
*/
5960
@SuppressWarnings("unchecked")
60-
public static <T extends Comparable<T>> Range<T> unbounded() {
61+
public static <T> Range<T> unbounded() {
6162
return (Range<T>) UNBOUNDED;
6263
}
6364

@@ -70,7 +71,7 @@ public static <T extends Comparable<T>> Range<T> unbounded() {
7071
* @return
7172
* @since 2.2
7273
*/
73-
public static <T extends Comparable<T>> Range<T> closed(T from, T to) {
74+
public static <T> Range<T> closed(T from, T to) {
7475
return new Range<>(Bound.inclusive(from), Bound.inclusive(to));
7576
}
7677

@@ -83,7 +84,7 @@ public static <T extends Comparable<T>> Range<T> closed(T from, T to) {
8384
* @return
8485
* @since 2.2
8586
*/
86-
public static <T extends Comparable<T>> Range<T> open(T from, T to) {
87+
public static <T> Range<T> open(T from, T to) {
8788
return new Range<>(Bound.exclusive(from), Bound.exclusive(to));
8889
}
8990

@@ -96,7 +97,7 @@ public static <T extends Comparable<T>> Range<T> open(T from, T to) {
9697
* @return
9798
* @since 2.2
9899
*/
99-
public static <T extends Comparable<T>> Range<T> leftOpen(T from, T to) {
100+
public static <T> Range<T> leftOpen(T from, T to) {
100101
return new Range<>(Bound.exclusive(from), Bound.inclusive(to));
101102
}
102103

@@ -109,7 +110,7 @@ public static <T extends Comparable<T>> Range<T> leftOpen(T from, T to) {
109110
* @return
110111
* @since 2.2
111112
*/
112-
public static <T extends Comparable<T>> Range<T> rightOpen(T from, T to) {
113+
public static <T> Range<T> rightOpen(T from, T to) {
113114
return new Range<>(Bound.inclusive(from), Bound.exclusive(to));
114115
}
115116

@@ -122,7 +123,7 @@ public static <T extends Comparable<T>> Range<T> rightOpen(T from, T to) {
122123
* @return
123124
* @since 2.2
124125
*/
125-
public static <T extends Comparable<T>> Range<T> leftUnbounded(Bound<T> to) {
126+
public static <T> Range<T> leftUnbounded(Bound<T> to) {
126127
return new Range<>(Bound.unbounded(), to);
127128
}
128129

@@ -135,7 +136,7 @@ public static <T extends Comparable<T>> Range<T> leftUnbounded(Bound<T> to) {
135136
* @return
136137
* @since 2.2
137138
*/
138-
public static <T extends Comparable<T>> Range<T> rightUnbounded(Bound<T> from) {
139+
public static <T> Range<T> rightUnbounded(Bound<T> from) {
139140
return new Range<>(from, Bound.unbounded());
140141
}
141142

@@ -146,7 +147,7 @@ public static <T extends Comparable<T>> Range<T> rightUnbounded(Bound<T> from) {
146147
* @return
147148
* @since 2.0
148149
*/
149-
public static <T extends Comparable<T>> RangeBuilder<T> from(Bound<T> lower) {
150+
public static <T> RangeBuilder<T> from(Bound<T> lower) {
150151

151152
Assert.notNull(lower, "Lower bound must not be null!");
152153
return new RangeBuilder<>(lower);
@@ -161,7 +162,7 @@ public static <T extends Comparable<T>> RangeBuilder<T> from(Bound<T> lower) {
161162
* @since 2.0
162163
* @see #from(Bound)
163164
*/
164-
public static <T extends Comparable<T>> Range<T> of(Bound<T> lowerBound, Bound<T> upperBound) {
165+
public static <T> Range<T> of(Bound<T> lowerBound, Bound<T> upperBound) {
165166
return new Range<>(lowerBound, upperBound);
166167
}
167168

@@ -171,9 +172,9 @@ public static <T extends Comparable<T>> Range<T> of(Bound<T> lowerBound, Bound<T
171172
* @param <T>
172173
* @param value must not be {@literal null}.
173174
* @return
174-
* @see Range#closed(Comparable, Comparable)
175+
* @see Range#closed(Object, Object)
175176
*/
176-
public static <T extends Comparable<T>> Range<T> just(T value) {
177+
public static <T> Range<T> just(T value) {
177178
return Range.closed(value, value);
178179
}
179180

@@ -183,16 +184,34 @@ public static <T extends Comparable<T>> Range<T> just(T value) {
183184
* @param value must not be {@literal null}.
184185
* @return
185186
*/
186-
public boolean contains(T value) {
187+
@SuppressWarnings({ "unchecked" })
188+
public boolean contains(Comparable<T> value) {
189+
190+
return contains((T) value, (o1, o2) -> {
191+
192+
Assert.isInstanceOf(Comparable.class, o1,
193+
"Range value must be an instance of Comparable to use contains(Comparable<T>)");
194+
return ((Comparable<T>) o1).compareTo(o2);
195+
});
196+
}
197+
198+
/**
199+
* Returns whether the {@link Range} contains the given value.
200+
*
201+
* @param value must not be {@literal null}.
202+
* @return
203+
* @since 3.0
204+
*/
205+
public boolean contains(T value, Comparator<T> comparator) {
187206

188207
Assert.notNull(value, "Reference value must not be null!");
189208

190209
boolean greaterThanLowerBound = lowerBound.getValue() //
191-
.map(it -> lowerBound.isInclusive() ? it.compareTo(value) <= 0 : it.compareTo(value) < 0) //
210+
.map(it -> lowerBound.isInclusive() ? comparator.compare(it, value) <= 0 : comparator.compare(it, value) < 0) //
192211
.orElse(true);
193212

194213
boolean lessThanUpperBound = upperBound.getValue() //
195-
.map(it -> upperBound.isInclusive() ? it.compareTo(value) >= 0 : it.compareTo(value) > 0) //
214+
.map(it -> upperBound.isInclusive() ? comparator.compare(it, value) >= 0 : comparator.compare(it, value) > 0) //
196215
.orElse(true);
197216

198217
return greaterThanLowerBound && lessThanUpperBound;
@@ -238,13 +257,13 @@ public int hashCode() {
238257

239258
/**
240259
* Value object representing a boundary. A boundary can either be {@link #unbounded() unbounded},
241-
* {@link #inclusive(Comparable) including its value} or {@link #exclusive(Comparable) its value}.
260+
* {@link #inclusive(Object) including its value} or {@link #exclusive(Object) its value}.
242261
*
243262
* @author Mark Paluch
244263
* @since 2.0
245264
* @soundtrack Mohamed Ragab - Excelsior Sessions (March 2017)
246265
*/
247-
public static final class Bound<T extends Comparable<T>> {
266+
public static final class Bound<T> {
248267

249268
@SuppressWarnings({ "rawtypes", "unchecked" }) //
250269
private static final Bound<?> UNBOUNDED = new Bound(Optional.empty(), true);
@@ -261,7 +280,7 @@ private Bound(Optional<T> value, boolean inclusive) {
261280
* Creates an unbounded {@link Bound}.
262281
*/
263282
@SuppressWarnings("unchecked")
264-
public static <T extends Comparable<T>> Bound<T> unbounded() {
283+
public static <T> Bound<T> unbounded() {
265284
return (Bound<T>) UNBOUNDED;
266285
}
267286

@@ -280,7 +299,7 @@ public boolean isBounded() {
280299
* @param value must not be {@literal null}.
281300
* @return
282301
*/
283-
public static <T extends Comparable<T>> Bound<T> inclusive(T value) {
302+
public static <T> Bound<T> inclusive(T value) {
284303

285304
Assert.notNull(value, "Value must not be null!");
286305
return new Bound<>(Optional.of(value), true);
@@ -332,7 +351,7 @@ public static Bound<Double> inclusive(double value) {
332351
* @param value must not be {@literal null}.
333352
* @return
334353
*/
335-
public static <T extends Comparable<T>> Bound<T> exclusive(T value) {
354+
public static <T> Bound<T> exclusive(T value) {
336355

337356
Assert.notNull(value, "Value must not be null!");
338357
return new Bound<>(Optional.of(value), false);
@@ -439,7 +458,7 @@ public int hashCode() {
439458
* @since 2.0
440459
* @soundtrack Aly and Fila - Future Sound Of Egypt 493
441460
*/
442-
public static class RangeBuilder<T extends Comparable<T>> {
461+
public static class RangeBuilder<T> {
443462

444463
private final Bound<T> lower;
445464

0 commit comments

Comments
 (0)