From 05d68a0eab0e4442dd30b843cdbfaef02350b2b0 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 13 Jun 2023 11:50:28 +0200 Subject: [PATCH] Consider KeysetScrollPosition direction in WindowIterator. We now consider the scroll direction in the iterator to properly continue Keyset backward scrolling. Closes #2851 --- .../data/support/WindowIterator.java | 14 +++++++++- .../data/domain/WindowIteratorUnitTests.java | 27 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/data/support/WindowIterator.java b/src/main/java/org/springframework/data/support/WindowIterator.java index 210bc4bcb..9e80bccd8 100644 --- a/src/main/java/org/springframework/data/support/WindowIterator.java +++ b/src/main/java/org/springframework/data/support/WindowIterator.java @@ -19,6 +19,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.function.Function; +import org.springframework.data.domain.KeysetScrollPosition; import org.springframework.data.domain.ScrollPosition; import org.springframework.data.domain.Window; import org.springframework.lang.Nullable; @@ -92,7 +93,7 @@ public class WindowIterator implements Iterator { if (currentWindow != null && currentWindow.hasNext()) { - currentPosition = currentWindow.positionAt(currentWindow.size() - 1); + currentPosition = getNextPosition(currentPosition, currentWindow); currentIterator = null; currentWindow = null; continue; @@ -113,6 +114,17 @@ public class WindowIterator implements Iterator { return currentIterator.next(); } + private static ScrollPosition getNextPosition(ScrollPosition currentPosition, Window window) { + + if (currentPosition instanceof KeysetScrollPosition ksp) { + if (ksp.scrollsBackward()) { + return window.positionAt(0); + } + } + + return window.positionAt(window.size() - 1); + } + /** * Builder API to construct a {@link WindowIterator}. * diff --git a/src/test/java/org/springframework/data/domain/WindowIteratorUnitTests.java b/src/test/java/org/springframework/data/domain/WindowIteratorUnitTests.java index 1d0dff970..3f97ce84e 100644 --- a/src/test/java/org/springframework/data/domain/WindowIteratorUnitTests.java +++ b/src/test/java/org/springframework/data/domain/WindowIteratorUnitTests.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.function.Function; @@ -30,7 +31,9 @@ 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.domain.ScrollPosition.Direction; import org.springframework.data.support.WindowIterator; +import org.springframework.data.util.Streamable; /** * Unit tests for {@link WindowIterator}. @@ -127,4 +130,28 @@ class WindowIteratorUnitTests { assertThat(capturedResult).containsExactly("a", "b", "c", "d"); } + + @Test // GH-2151 + void considersBackwardKeysetScrolling() { + + Window initial = Window.from(List.of("c", "d"), + value -> KeysetScrollPosition.of(Map.of("k", 10 + value), Direction.BACKWARD), true); + Window terminal = Window.from(List.of("a", "b"), + value -> KeysetScrollPosition.of(Map.of("k", value), Direction.BACKWARD)); + + WindowIterator iterator = WindowIterator.of(it -> { + + if (it instanceof KeysetScrollPosition ksp) { + if (Integer.valueOf(10).equals(ksp.getKeys().get("k"))) { + return terminal; + } + } + + return initial; + + }).startingAt(ScrollPosition.keyset().backward()); + + List items = Streamable.of(() -> iterator).toList(); + assertThat(items).containsExactly("c", "d", "a", "b"); + } }