Browse Source

Polishing Window scrolling API.

Moved general-purpose factory methods to the common ScrollPosition interface. Introduced a couple of domain specific methods to conveniently work with both Keyset- (to e.g. change direction) and OffsetScrollPosition (to e.g. advance the offset). Consolidated unit tests accordingly.

Moved WindowIterator to ….data.support package. Fixed case of Direction enum values.

Fixes #2824.
pull/2825/head
Oliver Drotbohm 3 years ago
parent
commit
cac1c211ef
No known key found for this signature in database
GPG Key ID: C25FBFA0DA493A1D
  1. 2
      src/main/asciidoc/repositories-paging-sorting.adoc
  2. 140
      src/main/java/org/springframework/data/domain/KeysetScrollPosition.java
  3. 78
      src/main/java/org/springframework/data/domain/OffsetScrollPosition.java
  4. 3
      src/main/java/org/springframework/data/domain/Pageable.java
  5. 81
      src/main/java/org/springframework/data/domain/ScrollPosition.java
  6. 6
      src/main/java/org/springframework/data/support/WindowIterator.java
  7. 43
      src/test/java/org/springframework/data/domain/KeysetScrollPositionUnitTests.java
  8. 50
      src/test/java/org/springframework/data/domain/OffsetScrollPositionUnitTests.java
  9. 2
      src/test/java/org/springframework/data/domain/PageRequestUnitTests.java
  10. 140
      src/test/java/org/springframework/data/domain/ScrollPositionUnitTests.java
  11. 29
      src/test/java/org/springframework/data/domain/WindowIteratorUnitTests.java
  12. 8
      src/test/java/org/springframework/data/domain/WindowUnitTests.java
  13. 3
      src/test/java/org/springframework/data/repository/query/ParametersParameterAccessorUnitTests.java
  14. 12
      src/test/java/org/springframework/data/repository/query/SimpleParameterAccessorUnitTests.java

2
src/main/asciidoc/repositories-paging-sorting.adoc

@ -14,7 +14,7 @@ Page<User> findByLastname(String lastname, Pageable pageable); @@ -14,7 +14,7 @@ Page<User> findByLastname(String lastname, Pageable pageable);
Slice<User> findByLastname(String lastname, Pageable pageable);
Scroll<User> findTop10ByLastname(String lastname, ScrollPosition position, Sort sort);
Window<User> findTop10ByLastname(String lastname, ScrollPosition position, Sort sort);
List<User> findByLastname(String lastname, Sort sort);

140
src/main/java/org/springframework/data/domain/KeysetScrollPosition.java

@ -18,27 +18,33 @@ package org.springframework.data.domain; @@ -18,27 +18,33 @@ package org.springframework.data.domain;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* A {@link ScrollPosition} based on the last seen keyset. Keyset scrolling must be associated with a {@link Sort
* well-defined sort} to be able to extract the keyset when resuming scrolling within the sorted result set.
* A {@link ScrollPosition} based on the last seen key set. Keyset scrolling must be associated with a {@link Sort
* well-defined sort} to be able to extract the key set when resuming scrolling within the sorted result set.
*
* @author Mark Paluch
* @author Oliver Drotbohm
* @since 3.1
*/
public final class KeysetScrollPosition implements ScrollPosition {
private static final KeysetScrollPosition initial = new KeysetScrollPosition(Collections.emptyMap(),
Direction.Forward);
private static final KeysetScrollPosition INITIAL = new KeysetScrollPosition(Collections.emptyMap(),
Direction.FORWARD);
private final Map<String, Object> keys;
private final Direction direction;
private KeysetScrollPosition(Map<String, Object> keys, Direction direction) {
Assert.notNull(keys, "Keys must not be null");
Assert.notNull(direction, "Direction must not be null");
this.keys = keys;
this.direction = direction;
}
@ -46,44 +52,27 @@ public final class KeysetScrollPosition implements ScrollPosition { @@ -46,44 +52,27 @@ public final class KeysetScrollPosition implements ScrollPosition {
/**
* Creates a new initial {@link KeysetScrollPosition} to start scrolling using keyset-queries.
*
* @return a new initial {@link KeysetScrollPosition} to start scrolling using keyset-queries.
*/
public static KeysetScrollPosition initial() {
return initial;
}
/**
* Creates a new {@link KeysetScrollPosition} from a keyset.
*
* @param keys must not be {@literal null}.
* @return a new {@link KeysetScrollPosition} for the given keyset.
* @return will never be {@literal null}.
*/
public static KeysetScrollPosition of(Map<String, ?> keys) {
return of(keys, Direction.Forward);
static KeysetScrollPosition initial() {
return INITIAL;
}
/**
* Creates a new {@link KeysetScrollPosition} from a keyset and {@link Direction}.
* Creates a new {@link KeysetScrollPosition} from a key set and {@link Direction}.
*
* @param keys must not be {@literal null}.
* @param direction must not be {@literal null}.
* @return a new {@link KeysetScrollPosition} for the given keyset and {@link Direction}.
* @return will never be {@literal null}.
*/
public static KeysetScrollPosition of(Map<String, ?> keys, Direction direction) {
static KeysetScrollPosition of(Map<String, ?> keys, Direction direction) {
Assert.notNull(keys, "Keys must not be null");
Assert.notNull(direction, "Direction must not be null");
if (keys.isEmpty()) {
return initial();
}
return new KeysetScrollPosition(Collections.unmodifiableMap(new LinkedHashMap<>(keys)), direction);
}
@Override
public boolean isInitial() {
return keys.isEmpty();
return keys.isEmpty()
? initial()
: new KeysetScrollPosition(Collections.unmodifiableMap(new LinkedHashMap<>(keys)), direction);
}
/**
@ -100,45 +89,78 @@ public final class KeysetScrollPosition implements ScrollPosition { @@ -100,45 +89,78 @@ public final class KeysetScrollPosition implements ScrollPosition {
return direction;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
KeysetScrollPosition that = (KeysetScrollPosition) o;
return ObjectUtils.nullSafeEquals(keys, that.keys) && direction == that.direction;
/**
* Returns whether the current {@link KeysetScrollPosition} scrolls forward.
*
* @return whether the current {@link KeysetScrollPosition} scrolls forward.
*/
public boolean scrollsForward() {
return direction == Direction.FORWARD;
}
@Override
public int hashCode() {
/**
* Returns whether the current {@link KeysetScrollPosition} scrolls backward.
*
* @return whether the current {@link KeysetScrollPosition} scrolls backward.
*/
public boolean scrollsBackward() {
return direction == Direction.BACKWARD;
}
int result = 17;
/**
* Returns a {@link KeysetScrollPosition} based on the same keyset and scrolling forward.
*
* @return will never be {@literal null}.
*/
public KeysetScrollPosition forward() {
return direction == Direction.FORWARD ? this : new KeysetScrollPosition(keys, Direction.FORWARD);
}
result += 31 * ObjectUtils.nullSafeHashCode(keys);
result += 31 * ObjectUtils.nullSafeHashCode(direction);
/**
* Returns a {@link KeysetScrollPosition} based on the same keyset and scrolling backward.
*
* @return will never be {@literal null}.
*/
public KeysetScrollPosition backward() {
return direction == Direction.BACKWARD ? this : new KeysetScrollPosition(keys, Direction.BACKWARD);
}
return result;
/**
* Returns a new {@link KeysetScrollPosition} with the direction reversed.
*
* @return will never be {@literal null}.
*/
public KeysetScrollPosition reverse() {
return new KeysetScrollPosition(keys, direction.reverse());
}
@Override
public String toString() {
return String.format("KeysetScrollPosition [%s, %s]", direction, keys);
public boolean isInitial() {
return keys.isEmpty();
}
/**
* Keyset scrolling direction.
*/
public enum Direction {
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
/**
* Forward (default) direction to scroll from the beginning of the results to their end.
*/
Forward,
if (!(o instanceof KeysetScrollPosition that)) {
return false;
}
return ObjectUtils.nullSafeEquals(keys, that.keys) //
&& direction == that.direction;
}
/**
* Backward direction to scroll from the end of the results to their beginning.
*/
Backward;
@Override
public int hashCode() {
return Objects.hash(keys, direction);
}
@Override
public String toString() {
return String.format("KeysetScrollPosition [%s, %s]", direction, keys);
}
}

78
src/main/java/org/springframework/data/domain/OffsetScrollPosition.java

@ -15,49 +15,54 @@ @@ -15,49 +15,54 @@
*/
package org.springframework.data.domain;
import java.util.Objects;
import java.util.function.IntFunction;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* A {@link ScrollPosition} based on the offsets within query results.
*
* @author Mark Paluch
* @author Oliver Drotbohm
* @since 3.1
*/
public final class OffsetScrollPosition implements ScrollPosition {
private static final OffsetScrollPosition initial = new OffsetScrollPosition(0);
private static final OffsetScrollPosition INITIAL = new OffsetScrollPosition(0);
private final long offset;
/**
* Creates a new {@link OffsetScrollPosition} for the given non-negative offset.
*
* @param offset must be greater or equal to zero.
*/
private OffsetScrollPosition(long offset) {
Assert.isTrue(offset >= 0, "Offset must not be negative");
this.offset = offset;
}
/**
* Creates a new initial {@link OffsetScrollPosition} to start scrolling using offset/limit.
*
* @return a new initial {@link OffsetScrollPosition} to start scrolling using offset/limit.
* @return will never be {@literal null}.
*/
public static OffsetScrollPosition initial() {
return initial;
static OffsetScrollPosition initial() {
return INITIAL;
}
/**
* Creates a new {@link OffsetScrollPosition} from an {@code offset}.
*
* @param offset
* @return a new {@link OffsetScrollPosition} with the given {@code offset}.
* @param offset the non-negative offset to start at.
* @return will never be {@literal null}.
*/
public static OffsetScrollPosition of(long offset) {
if (offset == 0) {
return initial();
}
return new OffsetScrollPosition(offset);
static OffsetScrollPosition of(long offset) {
return offset == 0 ? initial() : new OffsetScrollPosition(offset);
}
/**
@ -73,36 +78,51 @@ public final class OffsetScrollPosition implements ScrollPosition { @@ -73,36 +78,51 @@ public final class OffsetScrollPosition implements ScrollPosition {
return startOffset == 0 ? OffsetPositionFunction.ZERO : new OffsetPositionFunction(startOffset);
}
@Override
public boolean isInitial() {
return offset == 0;
}
/**
* The zero or positive offset.
*
* @return the offset.
*/
public long getOffset() {
return offset;
}
/**
* Returns a new {@link OffsetScrollPosition} that has been advanced by the given value. Negative deltas will be
* constrained so that the new offset is at least zero.
*
* @param delta the value to advance the current offset by.
* @return will never be {@literal null}.
*/
public OffsetScrollPosition advanceBy(long delta) {
var value = offset + delta;
return new OffsetScrollPosition(value < 0 ? 0 : value);
}
@Override
public boolean isInitial() {
return offset == 0;
}
@Override
public boolean equals(Object o) {
if (this == o)
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
if (o == null || getClass() != o.getClass())
}
if (!(o instanceof OffsetScrollPosition that)) {
return false;
OffsetScrollPosition that = (OffsetScrollPosition) o;
}
return offset == that.offset;
}
@Override
public int hashCode() {
int result = 17;
result += 31 * ObjectUtils.nullSafeHashCode(offset);
return result;
return Objects.hash(offset);
}
@Override

3
src/main/java/org/springframework/data/domain/Pageable.java

@ -174,7 +174,6 @@ public interface Pageable { @@ -174,7 +174,6 @@ public interface Pageable {
throw new IllegalStateException("Cannot create OffsetScrollPosition from an unpaged instance");
}
return OffsetScrollPosition.of(getOffset());
return ScrollPosition.offset(getOffset());
}
}

81
src/main/java/org/springframework/data/domain/ScrollPosition.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.domain;
import java.util.Map;
/**
* Interface to specify a position within a total query result. Scroll positions are used to start scrolling from the
* beginning of a query result or to resume scrolling from a given position within the query result.
@ -30,4 +32,83 @@ public interface ScrollPosition { @@ -30,4 +32,83 @@ public interface ScrollPosition {
* @return
*/
boolean isInitial();
/**
* Creates a new initial {@link ScrollPosition} to start scrolling using keyset-queries.
*
* @return will never be {@literal null}.
*/
public static KeysetScrollPosition keyset() {
return KeysetScrollPosition.initial();
}
/**
* Creates a new initial {@link ScrollPosition} to start scrolling using offset / limit.
*
* @return will never be {@literal null}.
*/
public static OffsetScrollPosition offset() {
return OffsetScrollPosition.initial();
}
/**
* Creates a new {@link ScrollPosition} from an {@code offset}.
*
* @param offset
* @return a new {@link OffsetScrollPosition} with the given {@code offset}.
*/
public static OffsetScrollPosition offset(long offset) {
return OffsetScrollPosition.of(offset);
}
/**
* Creates a new {@link ScrollPosition} from a key set scrolling forward.
*
* @param keys must not be {@literal null}.
* @return will never be {@literal null}.
*/
public static KeysetScrollPosition forward(Map<String, ?> keys) {
return of(keys, Direction.FORWARD);
}
/**
* Creates a new {@link ScrollPosition} from a key set scrolling backward.
*
* @param keys must not be {@literal null}.
* @return will never be {@literal null}.
*/
public static KeysetScrollPosition backward(Map<String, ?> keys) {
return of(keys, Direction.BACKWARD);
}
/**
* Creates a new {@link ScrollPosition} from a key set and {@link Direction}.
*
* @param keys must not be {@literal null}.
* @param direction must not be {@literal null}.
* @return will never be {@literal null}.
*/
public static KeysetScrollPosition of(Map<String, ?> keys, Direction direction) {
return KeysetScrollPosition.of(keys, direction);
}
/**
* Keyset scrolling direction.
*/
public enum Direction {
/**
* Forward (default) direction to scroll from the beginning of the results to their end.
*/
FORWARD,
/**
* Backward direction to scroll from the end of the results to their beginning.
*/
BACKWARD;
Direction reverse() {
return this == FORWARD ? BACKWARD : FORWARD;
}
}
}

6
src/main/java/org/springframework/data/domain/WindowIterator.java → src/main/java/org/springframework/data/support/WindowIterator.java

@ -13,12 +13,14 @@ @@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain;
package org.springframework.data.support;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Function;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Window;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@ -28,7 +30,7 @@ import org.springframework.util.Assert; @@ -28,7 +30,7 @@ import org.springframework.util.Assert;
*
* <pre class="code">
* WindowIterator&lt;User&gt; users = WindowIterator.of(position -> repository.findFirst10By("spring", position))
* .startingAt(OffsetScrollPosition.initial());
* .startingAt(ScrollPosition.offset());
*
* while (users.hasNext()) {
* User u = users.next();

43
src/test/java/org/springframework/data/domain/KeysetScrollPositionUnitTests.java

@ -1,43 +0,0 @@ @@ -1,43 +0,0 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed 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
*
* https://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.springframework.data.domain;
import static org.assertj.core.api.Assertions.*;
import java.util.Collections;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.KeysetScrollPosition.Direction;
/**
* Unit tests for {@link KeysetScrollPosition}.
*
* @author Mark Paluch
*/
class KeysetScrollPositionUnitTests {
@Test // GH-2151
void equalsAndHashCode() {
KeysetScrollPosition foo1 = KeysetScrollPosition.of(Collections.singletonMap("k", "v"));
KeysetScrollPosition foo2 = KeysetScrollPosition.of(Collections.singletonMap("k", "v"));
KeysetScrollPosition bar = KeysetScrollPosition.of(Collections.singletonMap("k", "v"), Direction.Backward);
assertThat(foo1).isEqualTo(foo2).hasSameClassAs(foo2);
assertThat(foo1).isNotEqualTo(bar).doesNotHaveSameHashCodeAs(bar);
}
}

50
src/test/java/org/springframework/data/domain/OffsetScrollPositionUnitTests.java

@ -1,50 +0,0 @@ @@ -1,50 +0,0 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed 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
*
* https://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.springframework.data.domain;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.domain.OffsetScrollPosition.*;
import org.junit.jupiter.api.Test;
/**
* Unit tests for {@link OffsetScrollPosition}.
*
* @author Mark Paluch
*/
class OffsetScrollPositionUnitTests {
@Test // GH-2151
void equalsAndHashCode() {
OffsetScrollPosition foo1 = OffsetScrollPosition.of(1);
OffsetScrollPosition foo2 = OffsetScrollPosition.of(1);
OffsetScrollPosition bar = OffsetScrollPosition.of(2);
assertThat(foo1).isEqualTo(foo2).hasSameClassAs(foo2);
assertThat(foo1).isNotEqualTo(bar).doesNotHaveSameHashCodeAs(bar);
}
@Test // GH-2151
void shouldCreateCorrectIndexPosition() {
assertThat(positionFunction(0).apply(0)).isEqualTo(OffsetScrollPosition.of(1));
assertThat(positionFunction(0).apply(1)).isEqualTo(OffsetScrollPosition.of(2));
assertThat(positionFunction(100).apply(0)).isEqualTo(OffsetScrollPosition.of(101));
assertThat(positionFunction(100).apply(1)).isEqualTo(OffsetScrollPosition.of(102));
}
}

2
src/test/java/org/springframework/data/domain/PageRequestUnitTests.java

@ -72,6 +72,6 @@ class PageRequestUnitTests extends AbstractPageRequestUnitTests { @@ -72,6 +72,6 @@ class PageRequestUnitTests extends AbstractPageRequestUnitTests {
PageRequest request = PageRequest.of(1, 10);
assertThat(request.toScrollPosition()).isEqualTo(OffsetScrollPosition.of(10));
assertThat(request.toScrollPosition()).isEqualTo(ScrollPosition.offset(10));
}
}

140
src/test/java/org/springframework/data/domain/ScrollPositionUnitTests.java

@ -0,0 +1,140 @@ @@ -0,0 +1,140 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed 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
*
* https://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.springframework.data.domain;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.domain.OffsetScrollPosition.*;
import java.util.Collections;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.ScrollPosition.Direction;
/**
* Unit tests for {@link KeysetScrollPosition}.
*
* @author Mark Paluch
* @author Oliver Drotbohm
*/
class ScrollPositionUnitTests {
private static final Map<String, ?> KEYS = Collections.singletonMap("k", "v");
@Test // GH-2151
void equalsAndHashCodeForKeysets() {
ScrollPosition foo1 = ScrollPosition.forward(KEYS);
ScrollPosition foo2 = ScrollPosition.forward(KEYS);
ScrollPosition bar = ScrollPosition.backward(KEYS);
assertThat(foo1).isEqualTo(foo2).hasSameClassAs(foo2);
assertThat(foo1).isNotEqualTo(bar).doesNotHaveSameHashCodeAs(bar);
}
@Test // GH-2151
void equalsAndHashCodeForOffsets() {
ScrollPosition foo1 = ScrollPosition.offset(1);
ScrollPosition foo2 = ScrollPosition.offset(1);
ScrollPosition bar = ScrollPosition.offset(2);
assertThat(foo1).isEqualTo(foo2).hasSameClassAs(foo2);
assertThat(foo1).isNotEqualTo(bar).doesNotHaveSameHashCodeAs(bar);
}
@Test // GH-2151
void shouldCreateCorrectIndexPosition() {
assertThat(positionFunction(0).apply(0)).isEqualTo(ScrollPosition.offset(1));
assertThat(positionFunction(0).apply(1)).isEqualTo(ScrollPosition.offset(2));
assertThat(positionFunction(100).apply(0)).isEqualTo(ScrollPosition.offset(101));
assertThat(positionFunction(100).apply(1)).isEqualTo(ScrollPosition.offset(102));
}
@Test // GH-2151
void rejectsNegativeOffset() {
assertThatIllegalArgumentException().isThrownBy(() -> ScrollPosition.offset(-1));
}
@Test // GH-2151
void advanceOffsetBelowZeroCapsAtZero() {
OffsetScrollPosition offset = ScrollPosition.offset(5);
assertThat(offset.getOffset()).isEqualTo(5);
assertThat(offset.advanceBy(-10)).isEqualTo(ScrollPosition.offset(0));
}
@Test // GH-2824
void setsUpForwardScrolling() {
KeysetScrollPosition position = ScrollPosition.forward(KEYS);
assertThat(position.getKeys()).isEqualTo(KEYS);
assertThat(position.getDirection()).isEqualTo(Direction.FORWARD);
assertThat(position.scrollsForward()).isTrue();
assertThat(position.scrollsBackward()).isFalse();
KeysetScrollPosition backward = position.backward();
assertThat(backward.getKeys()).isEqualTo(KEYS);
assertThat(backward.getDirection()).isEqualTo(Direction.BACKWARD);
assertThat(backward.scrollsForward()).isFalse();
assertThat(backward.scrollsBackward()).isTrue();
assertThat(position.reverse()).isEqualTo(backward);
}
@Test // GH-2824
void setsUpBackwardScrolling() {
KeysetScrollPosition position = ScrollPosition.backward(KEYS);
assertThat(position.getKeys()).isEqualTo(KEYS);
assertThat(position.getDirection()).isEqualTo(Direction.BACKWARD);
assertThat(position.scrollsForward()).isFalse();
assertThat(position.scrollsBackward()).isTrue();
KeysetScrollPosition forward = position.forward();
assertThat(forward.getKeys()).isEqualTo(KEYS);
assertThat(forward.getDirection()).isEqualTo(Direction.FORWARD);
assertThat(forward.scrollsForward()).isTrue();
assertThat(forward.scrollsBackward()).isFalse();
assertThat(position.reverse()).isEqualTo(forward);
}
@Test // GH-2824
void initialOffsetPosition() {
OffsetScrollPosition position = ScrollPosition.offset();
assertThat(position.isInitial()).isTrue();
assertThat(position.getOffset()).isEqualTo(0);
}
@Test // GH-2824
void initialKeysetPosition() {
KeysetScrollPosition keyset = ScrollPosition.keyset();
assertThat(keyset.isInitial()).isTrue();
assertThat(keyset.scrollsForward()).isTrue();
}
}

29
src/test/java/org/springframework/data/domain/WindowIteratorUnitTests.java

@ -30,6 +30,7 @@ import org.junit.jupiter.api.extension.ExtendWith; @@ -30,6 +30,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.data.support.WindowIterator;
/**
* Unit tests for {@link WindowIterator}.
@ -45,20 +46,20 @@ class WindowIteratorUnitTests { @@ -45,20 +46,20 @@ class WindowIteratorUnitTests {
void loadsDataOnNext() {
Function<ScrollPosition, Window<String>> fkt = mock(Function.class);
WindowIterator<String> iterator = WindowIterator.of(fkt).startingAt(OffsetScrollPosition.initial());
WindowIterator<String> iterator = WindowIterator.of(fkt).startingAt(ScrollPosition.offset());
verifyNoInteractions(fkt);
when(fkt.apply(any())).thenReturn(Window.from(Collections.emptyList(), value -> OffsetScrollPosition.initial()));
when(fkt.apply(any())).thenReturn(Window.from(Collections.emptyList(), value -> ScrollPosition.offset()));
iterator.hasNext();
verify(fkt).apply(OffsetScrollPosition.initial());
verify(fkt).apply(ScrollPosition.offset());
}
@Test // GH-2151
void hasNextReturnsFalseIfNoDataAvailable() {
Window<Object> window = Window.from(Collections.emptyList(), value -> OffsetScrollPosition.initial());
WindowIterator<Object> iterator = WindowIterator.of(it -> window).startingAt(OffsetScrollPosition.initial());
Window<Object> window = Window.from(Collections.emptyList(), value -> ScrollPosition.offset());
WindowIterator<Object> iterator = WindowIterator.of(it -> window).startingAt(ScrollPosition.offset());
assertThat(iterator.hasNext()).isFalse();
}
@ -66,8 +67,8 @@ class WindowIteratorUnitTests { @@ -66,8 +67,8 @@ class WindowIteratorUnitTests {
@Test // GH-2151
void nextThrowsExceptionIfNoElementAvailable() {
Window<Object> window = Window.from(Collections.emptyList(), value -> OffsetScrollPosition.initial());
WindowIterator<Object> iterator = WindowIterator.of(it -> window).startingAt(OffsetScrollPosition.initial());
Window<Object> window = Window.from(Collections.emptyList(), value -> ScrollPosition.offset());
WindowIterator<Object> iterator = WindowIterator.of(it -> window).startingAt(ScrollPosition.offset());
assertThatExceptionOfType(NoSuchElementException.class).isThrownBy(iterator::next);
}
@ -75,8 +76,8 @@ class WindowIteratorUnitTests { @@ -75,8 +76,8 @@ class WindowIteratorUnitTests {
@Test // GH-2151
void hasNextReturnsTrueIfDataAvailableButOnlyOnePage() {
Window<String> window = Window.from(List.of("a", "b"), value -> OffsetScrollPosition.initial());
WindowIterator<String> iterator = WindowIterator.of(it -> window).startingAt(OffsetScrollPosition.initial());
Window<String> window = Window.from(List.of("a", "b"), value -> ScrollPosition.offset());
WindowIterator<String> iterator = WindowIterator.of(it -> window).startingAt(ScrollPosition.offset());
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("a");
@ -89,14 +90,14 @@ class WindowIteratorUnitTests { @@ -89,14 +90,14 @@ class WindowIteratorUnitTests {
@Test // GH-2151
void hasNextReturnsCorrectlyIfNextPageIsEmpty() {
Window<String> window = Window.from(List.of("a", "b"), value -> OffsetScrollPosition.initial());
Window<String> window = Window.from(List.of("a", "b"), value -> ScrollPosition.offset());
WindowIterator<String> iterator = WindowIterator.of(it -> {
if (it.isInitial()) {
return window;
}
return Window.from(Collections.emptyList(), OffsetScrollPosition::of, false);
}).startingAt(OffsetScrollPosition.initial());
}).startingAt(ScrollPosition.offset());
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("a");
@ -109,15 +110,15 @@ class WindowIteratorUnitTests { @@ -109,15 +110,15 @@ class WindowIteratorUnitTests {
@Test // GH-2151
void allowsToIterateAllWindows() {
Window<String> window1 = Window.from(List.of("a", "b"), OffsetScrollPosition::of, true);
Window<String> window2 = Window.from(List.of("c", "d"), value -> OffsetScrollPosition.of(2 + value));
Window<String> window1 = Window.from(List.of("a", "b"), ScrollPosition::offset, true);
Window<String> window2 = Window.from(List.of("c", "d"), value -> ScrollPosition.offset(2 + value));
WindowIterator<String> iterator = WindowIterator.of(it -> {
if (it.isInitial()) {
return window1;
}
return window2;
}).startingAt(OffsetScrollPosition.initial());
}).startingAt(ScrollPosition.offset());
List<String> capturedResult = new ArrayList<>(4);
while (iterator.hasNext()) {

8
src/test/java/org/springframework/data/domain/WindowUnitTests.java

@ -58,13 +58,13 @@ class WindowUnitTests { @@ -58,13 +58,13 @@ class WindowUnitTests {
Window<Integer> window = Window.from(List.of(1, 2, 3), OffsetScrollPosition.positionFunction(0));
assertThat(window.positionAt(0)).isEqualTo(OffsetScrollPosition.of(1));
assertThat(window.positionAt(window.size() - 1)).isEqualTo(OffsetScrollPosition.of(3));
assertThat(window.positionAt(0)).isEqualTo(ScrollPosition.offset(1));
assertThat(window.positionAt(window.size() - 1)).isEqualTo(ScrollPosition.offset(3));
// by index
assertThat(window.positionAt(1)).isEqualTo(OffsetScrollPosition.of(2));
assertThat(window.positionAt(1)).isEqualTo(ScrollPosition.offset(2));
// by object
assertThat(window.positionAt(Integer.valueOf(1))).isEqualTo(OffsetScrollPosition.of(1));
assertThat(window.positionAt(Integer.valueOf(1))).isEqualTo(ScrollPosition.offset(1));
}
}

3
src/test/java/org/springframework/data/repository/query/ParametersParameterAccessorUnitTests.java

@ -19,7 +19,6 @@ import static org.assertj.core.api.Assertions.*; @@ -19,7 +19,6 @@ import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
@ -84,7 +83,7 @@ class ParametersParameterAccessorUnitTests { @@ -84,7 +83,7 @@ class ParametersParameterAccessorUnitTests {
var method = Sample.class.getMethod("method", ScrollPosition.class, String.class);
var parameters = new DefaultParameters(method);
var accessor = new ParametersParameterAccessor(parameters, new Object[] { OffsetScrollPosition.of(1), "Foo" });
var accessor = new ParametersParameterAccessor(parameters, new Object[] { ScrollPosition.offset(1), "Foo" });
assertThat(accessor).hasSize(1);
assertThat(accessor.getBindableValue(0)).isEqualTo("Foo");

12
src/test/java/org/springframework/data/repository/query/SimpleParameterAccessorUnitTests.java

@ -19,7 +19,6 @@ import static org.assertj.core.api.Assertions.*; @@ -19,7 +19,6 @@ import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
@ -61,7 +60,8 @@ class SimpleParameterAccessorUnitTests { @@ -61,7 +60,8 @@ class SimpleParameterAccessorUnitTests {
@Test
void rejectsTooLittleNumberOfArguments() {
assertThatIllegalArgumentException().isThrownBy(() -> new ParametersParameterAccessor(parameters, new Object[0]));
assertThatIllegalArgumentException()
.isThrownBy(() -> new ParametersParameterAccessor(parameters, new Object[0]));
}
@Test
@ -82,7 +82,7 @@ class SimpleParameterAccessorUnitTests { @@ -82,7 +82,7 @@ class SimpleParameterAccessorUnitTests {
@Test // GH-2151
void returnsScrollPositionIfAvailable() {
var cursorRequest = OffsetScrollPosition.of(1);
var cursorRequest = ScrollPosition.offset(1);
ParameterAccessor accessor = new ParametersParameterAccessor(cursorRequestParameters,
new Object[] { cursorRequest });
@ -103,7 +103,8 @@ class SimpleParameterAccessorUnitTests { @@ -103,7 +103,8 @@ class SimpleParameterAccessorUnitTests {
void returnsPageableIfAvailable() {
Pageable pageable = PageRequest.of(0, 10);
ParameterAccessor accessor = new ParametersParameterAccessor(pageableParameters, new Object[] { "test", pageable });
ParameterAccessor accessor = new ParametersParameterAccessor(pageableParameters,
new Object[] { "test", pageable });
assertThat(accessor.getPageable()).isEqualTo(pageable);
assertThat(accessor.getSort().isSorted()).isFalse();
@ -114,7 +115,8 @@ class SimpleParameterAccessorUnitTests { @@ -114,7 +115,8 @@ class SimpleParameterAccessorUnitTests {
var sort = Sort.by("foo");
Pageable pageable = PageRequest.of(0, 10, sort);
ParameterAccessor accessor = new ParametersParameterAccessor(pageableParameters, new Object[] { "test", pageable });
ParameterAccessor accessor = new ParametersParameterAccessor(pageableParameters,
new Object[] { "test", pageable });
assertThat(accessor.getPageable()).isEqualTo(pageable);
assertThat(accessor.getSort()).isEqualTo(sort);

Loading…
Cancel
Save