Skip to content

Commit 9fae107

Browse files
committed
DATACMNS-286 - Extended Page/Pageable APIs.
Pageable and Page interfaces now expose API to easily access Pageables pointing to the previous and next Page instance if available.
1 parent 7df1cb7 commit 9fae107

File tree

7 files changed

+198
-50
lines changed

7 files changed

+198
-50
lines changed

src/main/java/org/springframework/data/domain/Page.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,24 @@ public interface Page<T> extends Iterable<T> {
9090
*/
9191
boolean isLastPage();
9292

93+
/**
94+
* Returns the {@link Pageable} to request the next {@link Page}. Can be {@literal null} in case the current
95+
* {@link Page} is already the last one. Clients should check {@link #hasNextPage()} before calling this method to
96+
* make sure they receive a non-{@literal null} value.
97+
*
98+
* @return
99+
*/
100+
Pageable nextPageable();
101+
102+
/**
103+
* Returns the {@link Pageable} to request the previous page. Can be {@literal null} in case the current {@link Page}
104+
* is already the first one. Clients should check {@link #hasPreviousPage()} before calling this method make sure
105+
* receive a non-{@literal null} value.
106+
*
107+
* @return
108+
*/
109+
Pageable previousPageable();
110+
93111
/*
94112
* (non-Javadoc)
95113
* @see java.lang.Iterable#iterator()

src/main/java/org/springframework/data/domain/PageImpl.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,27 @@ public boolean isLastPage() {
135135
return !hasNextPage();
136136
}
137137

138+
/*
139+
* (non-Javadoc)
140+
* @see org.springframework.data.domain.Page#nextPageable()
141+
*/
142+
public Pageable nextPageable() {
143+
return hasNextPage() ? pageable.next() : null;
144+
}
145+
146+
/*
147+
* (non-Javadoc)
148+
* @see org.springframework.data.domain.Page#previousOrFirstPageable()
149+
*/
150+
public Pageable previousPageable() {
151+
152+
if (hasPreviousPage()) {
153+
return pageable.previousOrFirst();
154+
}
155+
156+
return null;
157+
}
158+
138159
/*
139160
* (non-Javadoc)
140161
* @see org.springframework.data.domain.Page#iterator()

src/main/java/org/springframework/data/domain/PageRequest.java

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2012 the original author or authors.
2+
* Copyright 2008-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -40,7 +40,6 @@ public class PageRequest implements Pageable, Serializable {
4040
* @param page
4141
*/
4242
public PageRequest(int page, int size) {
43-
4443
this(page, size, null);
4544
}
4645

@@ -53,7 +52,6 @@ public PageRequest(int page, int size) {
5352
* @param properties
5453
*/
5554
public PageRequest(int page, int size, Direction direction, String... properties) {
56-
5755
this(page, size, new Sort(direction, properties));
5856
}
5957

@@ -62,16 +60,16 @@ public PageRequest(int page, int size, Direction direction, String... properties
6260
*
6361
* @param page
6462
* @param size
65-
* @param sort
63+
* @param sort can be {@literal null}.
6664
*/
6765
public PageRequest(int page, int size, Sort sort) {
6866

69-
if (0 > page) {
67+
if (page < 0) {
7068
throw new IllegalArgumentException("Page index must not be less than zero!");
7169
}
7270

73-
if (0 >= size) {
74-
throw new IllegalArgumentException("Page size must not be less than or equal to zero!");
71+
if (size < 0) {
72+
throw new IllegalArgumentException("Page size must not be less than zero!");
7573
}
7674

7775
this.page = page;
@@ -80,50 +78,74 @@ public PageRequest(int page, int size, Sort sort) {
8078
}
8179

8280
/*
83-
* (non-Javadoc)
84-
*
85-
* @see org.springframework.data.domain.Pageable#getPageSize()
86-
*/
81+
* (non-Javadoc)
82+
* @see org.springframework.data.domain.Pageable#getPageSize()
83+
*/
8784
public int getPageSize() {
8885

8986
return size;
9087
}
9188

9289
/*
93-
* (non-Javadoc)
94-
*
95-
* @see org.springframework.data.domain.Pageable#getPageNumber()
96-
*/
90+
* (non-Javadoc)
91+
* @see org.springframework.data.domain.Pageable#getPageNumber()
92+
*/
9793
public int getPageNumber() {
98-
9994
return page;
10095
}
10196

10297
/*
103-
* (non-Javadoc)
104-
*
105-
* @see org.springframework.data.domain.Pageable#getFirstItem()
106-
*/
98+
* (non-Javadoc)
99+
* @see org.springframework.data.domain.Pageable#getOffset()
100+
*/
107101
public int getOffset() {
108-
109102
return page * size;
110103
}
111104

112105
/*
113-
* (non-Javadoc)
114-
*
115-
* @see org.springframework.data.domain.Pageable#getSort()
116-
*/
106+
* (non-Javadoc)
107+
* @see org.springframework.data.domain.Pageable#getSort()
108+
*/
117109
public Sort getSort() {
118-
119110
return sort;
120111
}
121112

113+
/*
114+
* (non-Javadoc)
115+
* @see org.springframework.data.domain.Pageable#hasPrevious()
116+
*/
117+
public boolean hasPrevious() {
118+
return page > 0;
119+
}
120+
121+
/*
122+
* (non-Javadoc)
123+
* @see org.springframework.data.domain.Pageable#next()
124+
*/
125+
public Pageable next() {
126+
return new PageRequest(page + 1, size, sort);
127+
}
128+
129+
/*
130+
* (non-Javadoc)
131+
* @see org.springframework.data.domain.Pageable#previousOrFirst()
132+
*/
133+
public Pageable previousOrFirst() {
134+
return hasPrevious() ? new PageRequest(page - 1, size, sort) : this;
135+
}
136+
137+
/*
138+
* (non-Javadoc)
139+
* @see org.springframework.data.domain.Pageable#first()
140+
*/
141+
public Pageable first() {
142+
return new PageRequest(0, size, sort);
143+
}
144+
122145
/*
123-
* (non-Javadoc)
124-
*
125-
* @see java.lang.Object#equals(java.lang.Object)
126-
*/
146+
* (non-Javadoc)
147+
* @see java.lang.Object#equals(java.lang.Object)
148+
*/
127149
@Override
128150
public boolean equals(final Object obj) {
129151

@@ -146,10 +168,9 @@ public boolean equals(final Object obj) {
146168
}
147169

148170
/*
149-
* (non-Javadoc)
150-
*
151-
* @see java.lang.Object#hashCode()
152-
*/
171+
* (non-Javadoc)
172+
* @see java.lang.Object#hashCode()
173+
*/
153174
@Override
154175
public int hashCode() {
155176

@@ -161,4 +182,14 @@ public int hashCode() {
161182

162183
return result;
163184
}
185+
186+
/*
187+
* (non-Javadoc)
188+
* @see java.lang.Object#toString()
189+
*/
190+
@Override
191+
public String toString() {
192+
return String.format("Page request [number: %d, size %d, sort: %s]", page, size,
193+
sort == null ? null : sort.toString());
194+
}
164195
}

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

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2010 the original author or authors.
2+
* Copyright 2008-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -49,4 +49,33 @@ public interface Pageable {
4949
* @return
5050
*/
5151
Sort getSort();
52+
53+
/**
54+
* Returns the {@link Pageable} requesting the next {@link Page}.
55+
*
56+
* @return
57+
*/
58+
Pageable next();
59+
60+
/**
61+
* Returns the previous {@link Pageable} or the first {@link Pageable} if the current one already is the first one.
62+
*
63+
* @return
64+
*/
65+
Pageable previousOrFirst();
66+
67+
/**
68+
* Returns the {@link Pageable} requesting the first page.
69+
*
70+
* @return
71+
*/
72+
Pageable first();
73+
74+
/**
75+
* Returns whether there's a previous {@link Pageable} we can access from the current one. Will return
76+
* {@literal false} in case the current {@link Pageable} already refers to the first page.
77+
*
78+
* @return
79+
*/
80+
boolean hasPrevious();
5281
}

src/main/java/org/springframework/data/domain/Sort.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ public static enum Direction {
199199
* Returns the {@link Direction} enum for the given {@link String} value.
200200
*
201201
* @param value
202+
* @throws IllegalArgumentException in case the given value cannot be parsed into an enum value.
202203
* @return
203204
*/
204205
public static Direction fromString(String value) {
@@ -210,6 +211,22 @@ public static Direction fromString(String value) {
210211
"Invalid value '%s' for orders given! Has to be either 'desc' or 'asc' (case insensitive).", value), e);
211212
}
212213
}
214+
215+
/**
216+
* Returns the {@link Direction} enum for the given {@link String} or null if it cannot be parsed into an enum
217+
* value.
218+
*
219+
* @param value
220+
* @return
221+
*/
222+
public static Direction fromStringOrNull(String value) {
223+
224+
try {
225+
return fromString(value);
226+
} catch (IllegalArgumentException e) {
227+
return null;
228+
}
229+
}
213230
}
214231

215232
/**

src/test/java/org/springframework/data/domain/PageImplUnitTests.java

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2010 the original author or authors.
2+
* Copyright 2008-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
55
* use this file except in compliance with the License. You may obtain a copy of
@@ -13,7 +13,6 @@
1313
* License for the specific language governing permissions and limitations under
1414
* the License.
1515
*/
16-
1716
package org.springframework.data.domain;
1817

1918
import static org.hamcrest.CoreMatchers.*;
@@ -51,32 +50,56 @@ public void assertEqualsForComplexSetup() throws Exception {
5150
PageImpl<String> page = new PageImpl<String>(content, pageable, 100);
5251

5352
assertEqualsAndHashcode(page, page);
54-
5553
assertEqualsAndHashcode(page, new PageImpl<String>(content, pageable, 100));
56-
5754
assertNotEqualsAndHashcode(page, new PageImpl<String>(content, pageable, 90));
58-
5955
assertNotEqualsAndHashcode(page, new PageImpl<String>(content, new PageRequest(1, 10), 100));
60-
6156
assertNotEqualsAndHashcode(page, new PageImpl<String>(content, new PageRequest(0, 15), 100));
6257
}
6358

6459
@Test(expected = IllegalArgumentException.class)
6560
public void preventsNullContentForSimpleSetup() throws Exception {
66-
6761
new PageImpl<Object>(null);
6862
}
6963

7064
@Test(expected = IllegalArgumentException.class)
7165
public void preventsNullContentForAdvancedSetup() throws Exception {
72-
7366
new PageImpl<Object>(null, null, 0);
7467
}
7568

69+
@Test
70+
public void returnsNextPageable() {
71+
72+
Page<Object> page = new PageImpl<Object>(Arrays.asList(new Object()), new PageRequest(0, 1), 10);
73+
74+
assertThat(page.isFirstPage(), is(true));
75+
assertThat(page.hasPreviousPage(), is(false));
76+
assertThat(page.previousPageable(), is(nullValue()));
77+
78+
assertThat(page.isLastPage(), is(false));
79+
assertThat(page.hasNextPage(), is(true));
80+
assertThat(page.nextPageable(), is((Pageable) new PageRequest(1, 1)));
81+
}
82+
83+
@Test
84+
public void returnsPreviousPageable() {
85+
86+
Page<Object> page = new PageImpl<Object>(Arrays.asList(new Object()), new PageRequest(1, 1), 2);
87+
88+
assertThat(page.isFirstPage(), is(false));
89+
assertThat(page.hasPreviousPage(), is(true));
90+
assertThat(page.previousPageable(), is((Pageable) new PageRequest(0, 1)));
91+
92+
assertThat(page.isLastPage(), is(true));
93+
assertThat(page.hasNextPage(), is(false));
94+
assertThat(page.nextPageable(), is(nullValue()));
95+
}
96+
7697
@Test
7798
public void createsPageForEmptyContentCorrectly() {
99+
78100
List<String> list = Collections.emptyList();
79101
Page<String> page = new PageImpl<String>(list);
102+
80103
assertThat(page.getContent(), is(list));
81104
assertThat(page.getNumber(), is(0));
82105
assertThat(page.getNumberOfElements(), is(0));

0 commit comments

Comments
 (0)