1818import java .util .Collections ;
1919import java .util .LinkedHashMap ;
2020import java .util .Map ;
21+ import java .util .Objects ;
2122
23+ import org .springframework .lang .Nullable ;
2224import org .springframework .util .Assert ;
2325import org .springframework .util .ObjectUtils ;
2426
2527/**
26- * A {@link ScrollPosition} based on the last seen keyset . Keyset scrolling must be associated with a {@link Sort
27- * well-defined sort} to be able to extract the keyset when resuming scrolling within the sorted result set.
28+ * A {@link ScrollPosition} based on the last seen key set . Keyset scrolling must be associated with a {@link Sort
29+ * well-defined sort} to be able to extract the key set when resuming scrolling within the sorted result set.
2830 *
2931 * @author Mark Paluch
32+ * @author Oliver Drotbohm
3033 * @since 3.1
3134 */
3235public final class KeysetScrollPosition implements ScrollPosition {
3336
34- private static final KeysetScrollPosition initial = new KeysetScrollPosition (Collections .emptyMap (),
35- Direction .Forward );
37+ private static final KeysetScrollPosition INITIAL = new KeysetScrollPosition (Collections .emptyMap (),
38+ Direction .FORWARD );
3639
3740 private final Map <String , Object > keys ;
38-
3941 private final Direction direction ;
4042
4143 private KeysetScrollPosition (Map <String , Object > keys , Direction direction ) {
44+
45+ Assert .notNull (keys , "Keys must not be null" );
46+ Assert .notNull (direction , "Direction must not be null" );
47+
4248 this .keys = keys ;
4349 this .direction = direction ;
4450 }
4551
4652 /**
4753 * Creates a new initial {@link KeysetScrollPosition} to start scrolling using keyset-queries.
4854 *
49- * @return a new initial {@link KeysetScrollPosition} to start scrolling using keyset-queries.
50- */
51- public static KeysetScrollPosition initial () {
52- return initial ;
53- }
54-
55- /**
56- * Creates a new {@link KeysetScrollPosition} from a keyset.
57- *
58- * @param keys must not be {@literal null}.
59- * @return a new {@link KeysetScrollPosition} for the given keyset.
55+ * @return will never be {@literal null}.
6056 */
61- public static KeysetScrollPosition of ( Map < String , ?> keys ) {
62- return of ( keys , Direction . Forward ) ;
57+ static KeysetScrollPosition initial ( ) {
58+ return INITIAL ;
6359 }
6460
6561 /**
66- * Creates a new {@link KeysetScrollPosition} from a keyset and {@link Direction}.
62+ * Creates a new {@link KeysetScrollPosition} from a key set and {@link Direction}.
6763 *
6864 * @param keys must not be {@literal null}.
6965 * @param direction must not be {@literal null}.
70- * @return a new {@link KeysetScrollPosition} for the given keyset and {@link Direction }.
66+ * @return will never be {@literal null }.
7167 */
72- public static KeysetScrollPosition of (Map <String , ?> keys , Direction direction ) {
68+ static KeysetScrollPosition of (Map <String , ?> keys , Direction direction ) {
7369
7470 Assert .notNull (keys , "Keys must not be null" );
7571 Assert .notNull (direction , "Direction must not be null" );
7672
77- if (keys .isEmpty ()) {
78- return initial ();
79- }
80-
81- return new KeysetScrollPosition (Collections .unmodifiableMap (new LinkedHashMap <>(keys )), direction );
82- }
83-
84- @ Override
85- public boolean isInitial () {
86- return keys .isEmpty ();
73+ return keys .isEmpty ()
74+ ? initial ()
75+ : new KeysetScrollPosition (Collections .unmodifiableMap (new LinkedHashMap <>(keys )), direction );
8776 }
8877
8978 /**
@@ -100,45 +89,78 @@ public Direction getDirection() {
10089 return direction ;
10190 }
10291
103- @ Override
104- public boolean equals (Object o ) {
105- if (this == o )
106- return true ;
107- if (o == null || getClass () != o .getClass ())
108- return false ;
109- KeysetScrollPosition that = (KeysetScrollPosition ) o ;
110- return ObjectUtils .nullSafeEquals (keys , that .keys ) && direction == that .direction ;
92+ /**
93+ * Returns whether the current {@link KeysetScrollPosition} scrolls forward.
94+ *
95+ * @return whether the current {@link KeysetScrollPosition} scrolls forward.
96+ */
97+ public boolean scrollsForward () {
98+ return direction == Direction .FORWARD ;
11199 }
112100
113- @ Override
114- public int hashCode () {
101+ /**
102+ * Returns whether the current {@link KeysetScrollPosition} scrolls backward.
103+ *
104+ * @return whether the current {@link KeysetScrollPosition} scrolls backward.
105+ */
106+ public boolean scrollsBackward () {
107+ return direction == Direction .BACKWARD ;
108+ }
115109
116- int result = 17 ;
110+ /**
111+ * Returns a {@link KeysetScrollPosition} based on the same keyset and scrolling forward.
112+ *
113+ * @return will never be {@literal null}.
114+ */
115+ public KeysetScrollPosition forward () {
116+ return direction == Direction .FORWARD ? this : new KeysetScrollPosition (keys , Direction .FORWARD );
117+ }
117118
118- result += 31 * ObjectUtils .nullSafeHashCode (keys );
119- result += 31 * ObjectUtils .nullSafeHashCode (direction );
119+ /**
120+ * Returns a {@link KeysetScrollPosition} based on the same keyset and scrolling backward.
121+ *
122+ * @return will never be {@literal null}.
123+ */
124+ public KeysetScrollPosition backward () {
125+ return direction == Direction .BACKWARD ? this : new KeysetScrollPosition (keys , Direction .BACKWARD );
126+ }
120127
121- return result ;
128+ /**
129+ * Returns a new {@link KeysetScrollPosition} with the direction reversed.
130+ *
131+ * @return will never be {@literal null}.
132+ */
133+ public KeysetScrollPosition reverse () {
134+ return new KeysetScrollPosition (keys , direction .reverse ());
122135 }
123136
124137 @ Override
125- public String toString () {
126- return String . format ( "KeysetScrollPosition [%s, %s]" , direction , keys );
138+ public boolean isInitial () {
139+ return keys . isEmpty ( );
127140 }
128141
129- /**
130- * Keyset scrolling direction.
131- */
132- public enum Direction {
142+ @ Override
143+ public boolean equals (@ Nullable Object o ) {
144+
145+ if (this == o ) {
146+ return true ;
147+ }
133148
134- /**
135- * Forward (default) direction to scroll from the beginning of the results to their end.
136- */
137- Forward ,
149+ if (!(o instanceof KeysetScrollPosition that )) {
150+ return false ;
151+ }
152+
153+ return ObjectUtils .nullSafeEquals (keys , that .keys ) //
154+ && direction == that .direction ;
155+ }
138156
139- /**
140- * Backward direction to scroll from the end of the results to their beginning.
141- */
142- Backward ;
157+ @ Override
158+ public int hashCode () {
159+ return Objects .hash (keys , direction );
160+ }
161+
162+ @ Override
163+ public String toString () {
164+ return String .format ("KeysetScrollPosition [%s, %s]" , direction , keys );
143165 }
144166}
0 commit comments