package com.stackoverflow.q24889243;
import static org.junit.jupiter.api.Assertions.*;
import java.time.Duration;
import java.util.List;
import java.util.function.Function;
import com.google.common.collect.BoundType;
import com.google.common.collect.Range;
import org.joda.time.ReadableDuration;
import org.junit.jupiter.api.Test;
public class Answer {
public static final <T extends Comparable<T>, R extends Comparable<R>> Range<R> transform(Range<T> fromRange,
Function<? super T, ? extends R> transformer) {
var hasLowerBound = fromRange.hasLowerBound();
var hasUpperBound = fromRange.hasUpperBound();
if (hasLowerBound && hasUpperBound) {
var fromLowerEndpoint = fromRange.lowerEndpoint();
var toLowerEndpoint = transformer.apply(fromLowerEndpoint);
var fromUpperEndpoint = fromRange.upperEndpoint();
var toUpperEndpoint = transformer.apply(fromUpperEndpoint);
return Range.range(toLowerEndpoint, fromRange.lowerBoundType(), toUpperEndpoint,
fromRange.upperBoundType());
}
if (hasLowerBound) {
var fromLowerEndpoint = fromRange.lowerEndpoint();
var toLowerEndpoint = transformer.apply(fromLowerEndpoint);
return Range.downTo(toLowerEndpoint, fromRange.lowerBoundType());
}
if (hasUpperBound) {
var fromUpperEndpoint = fromRange.upperEndpoint();
var toUpperEndpoint = transformer.apply(fromUpperEndpoint);
return Range.upTo(toUpperEndpoint, fromRange.upperBoundType());
}
return Range.all();
}
@Test
void testDurations() {
assertRangeTransformer(Duration::toMillis, Duration.ofMillis(10), Duration.ofMillis(15));
assertRangeTransformer(ReadableDuration::getMillis, org.joda.time.Duration.millis(10),
org.joda.time.Duration.millis(15));
}
<T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformer(
Function<? super T, ? extends R> transformer, T fromLowerBound, T fromUpperBound) {
assertRangeTransformer(transformer, fromLowerBound, BoundType.CLOSED, fromUpperBound, BoundType.CLOSED);
assertRangeTransformer(transformer, fromLowerBound, BoundType.CLOSED, fromUpperBound, BoundType.OPEN);
assertRangeTransformer(transformer, fromLowerBound, BoundType.OPEN, fromUpperBound, BoundType.CLOSED);
assertRangeTransformer(transformer, fromLowerBound, BoundType.OPEN, fromUpperBound, BoundType.OPEN);
assertRangeTransformerLowerBoundOnly(transformer, fromLowerBound, BoundType.CLOSED);
assertRangeTransformerLowerBoundOnly(transformer, fromLowerBound, BoundType.OPEN);
assertRangeTransformerUpperBoundOnly(transformer, fromUpperBound, BoundType.CLOSED);
assertRangeTransformerUpperBoundOnly(transformer, fromUpperBound, BoundType.OPEN);
this.<T, R>assertRangeTransformerAll(transformer);
}
<T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformer(
Function<? super T, ? extends R> transformer, T fromLowerBound, BoundType lowerBoundType, T fromUpperBound,
BoundType upperBoundType) {
var toLowerBound = transformer.apply(fromLowerBound);
var toUpperBound = transformer.apply(fromUpperBound);
var fromRange = Range.range(fromLowerBound, lowerBoundType, fromUpperBound, upperBoundType);
var actualToRange = transform(fromRange, transformer);
assertEquals(toLowerBound, actualToRange.lowerEndpoint());
assertEquals(fromRange.lowerBoundType(), actualToRange.lowerBoundType());
assertEquals(toUpperBound, actualToRange.upperEndpoint());
assertEquals(fromRange.upperBoundType(), actualToRange.upperBoundType());
}
<T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformerLowerBoundOnly(
Function<? super T, ? extends R> transformer, T fromLowerBound, BoundType lowerBoundType) {
var toLowerBound = transformer.apply(fromLowerBound);
var fromRange = Range.downTo(fromLowerBound, lowerBoundType);
var actualToRange = transform(fromRange, transformer);
assertFalse(actualToRange.hasUpperBound());
assertEquals(toLowerBound, actualToRange.lowerEndpoint());
assertEquals(fromRange.lowerBoundType(), actualToRange.lowerBoundType());
}
<T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformerUpperBoundOnly(
Function<? super T, ? extends R> transformer, T fromUpperBound, BoundType upperBoundType) {
var toLowerBound = transformer.apply(fromUpperBound);
var fromRange = Range.upTo(fromUpperBound, upperBoundType);
var actualToRange = transform(fromRange, transformer);
assertFalse(actualToRange.hasLowerBound());
assertEquals(toLowerBound, actualToRange.upperEndpoint());
assertEquals(fromRange.upperBoundType(), actualToRange.upperBoundType());
}
<T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformerAll(
Function<? super T, ? extends R> transformer) {
var fromRange = Range.<T>all();
var actualToRange = transform(fromRange, transformer);
assertFalse(actualToRange.hasLowerBound());
assertFalse(actualToRange.hasUpperBound());
}
}