From eee7f09e9068794af6e4ff1d55e1b222ce7e1063 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Thu, 26 Oct 2023 12:28:02 +0100 Subject: [PATCH] Refine hasPrevious/hasNext for keyset scrolling Closes gh-843 --- .../data/query/WindowConnectionAdapter.java | 24 ++++++++++++++++-- .../query/WindowConnectionAdapterTests.java | 25 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/query/WindowConnectionAdapter.java b/spring-graphql/src/main/java/org/springframework/graphql/data/query/WindowConnectionAdapter.java index 8d8edf82..44534947 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/query/WindowConnectionAdapter.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/query/WindowConnectionAdapter.java @@ -18,6 +18,7 @@ package org.springframework.graphql.data.query; import java.util.Collection; +import org.springframework.data.domain.KeysetScrollPosition; import org.springframework.data.domain.ScrollPosition; import org.springframework.data.domain.Window; import org.springframework.graphql.data.pagination.ConnectionAdapter; @@ -53,12 +54,31 @@ public final class WindowConnectionAdapter @Override public boolean hasPrevious(Object container) { Window window = window(container); - return (window.size() > 0 && !window.positionAt(0).isInitial()); + if (!window.isEmpty()) { + ScrollPosition position = window.positionAt(0); + if (position instanceof KeysetScrollPosition keysetPosition) { + return (keysetPosition.scrollsBackward() && window.hasNext()); + } + else { + return !position.isInitial(); + } + } + return false; } @Override public boolean hasNext(Object container) { - return window(container).hasNext(); + Window window = window(container); + if (!window.isEmpty()) { + ScrollPosition pos = window.positionAt(0); + if (pos instanceof KeysetScrollPosition keysetPos) { + return (keysetPos.scrollsForward() && window.hasNext()); + } + else { + return window.hasNext(); + } + } + return false; } @Override diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/WindowConnectionAdapterTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/WindowConnectionAdapterTests.java index 8ee611cb..e8d8f65c 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/WindowConnectionAdapterTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/WindowConnectionAdapterTests.java @@ -16,6 +16,7 @@ package org.springframework.graphql.data.query; +import java.util.Collections; import java.util.List; import org.junit.jupiter.api.Test; @@ -60,4 +61,28 @@ public class WindowConnectionAdapterTests { assertThat(this.adapter.cursorAt(window, 3)).isEqualTo("O_3"); } + @Test + void hasNextPreviousWithKeysetScrollForward() { + + Window window = Window.from( + BookSource.books(), + index -> ScrollPosition.of(Collections.singletonMap("id", index), ScrollPosition.Direction.FORWARD), + true); + + assertThat(this.adapter.hasPrevious(window)).isFalse(); + assertThat(this.adapter.hasNext(window)).isEqualTo(true); + } + + @Test + void hasNextPreviousWithKeysetScrollBackward() { + + Window window = Window.from( + BookSource.books(), + index -> ScrollPosition.of(Collections.singletonMap("id", index), ScrollPosition.Direction.BACKWARD), + true); + + assertThat(this.adapter.hasPrevious(window)).isEqualTo(true); + assertThat(this.adapter.hasNext(window)).isFalse(); + } + }