-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
4 changed files
with
470 additions
and
0 deletions.
There are no files selected for viewing
168 changes: 168 additions & 0 deletions
168
src/main/java/org/kiwiproject/spring/data/KiwiPage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package org.kiwiproject.spring.data; | ||
|
||
import static java.util.Objects.nonNull; | ||
import static org.kiwiproject.base.KiwiPreconditions.checkArgumentNotNull; | ||
import static org.kiwiproject.base.KiwiPreconditions.checkPositive; | ||
import static org.kiwiproject.base.KiwiPreconditions.checkPositiveOrZero; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
import lombok.ToString; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* Represents one page of an overall list of results. | ||
* <p> | ||
* By default, pagination assumes a start page index of 0 (i.e. the page offset). You can change this | ||
* by calling {@code setPagingStartsWith(int)} or {@code usingOneAsFirstPage()}. | ||
* <p> | ||
* You can also indicate whether a sort has been applied to the data by setting the {@link KiwiSort} via | ||
* the setter method or via {@link #addKiwiSort(KiwiSort)}. | ||
* | ||
* @param <T> the type of content this page contains | ||
*/ | ||
@Getter | ||
@Setter | ||
@ToString(exclude = "content") | ||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
public class KiwiPage<T> { | ||
|
||
/** | ||
* The content on this specific page. | ||
*/ | ||
private List<T> content; | ||
|
||
/** | ||
* The size limit of the pagination, for example each page can have up to 25 items. The last page will often | ||
* contain fewer items than this limit unless the total number of items is such that there is no remainder | ||
* when dividing the total by the page size. e.g. if the total number of items is 100 and the page size is 20, | ||
* then each of the 5 pages has exactly 20 items (the page size). | ||
*/ | ||
private long size; | ||
|
||
/** | ||
* The number of this page, e.g. page X of Y. | ||
*/ | ||
private long number; | ||
|
||
/** | ||
* The number of items/elements on this page. Only on the last page can this be different | ||
*/ | ||
private long numberOfElements; | ||
|
||
/** | ||
* The total number of pages, calculated from the page size and total number of elements. | ||
*/ | ||
private long totalPages; | ||
|
||
/** | ||
* The total number of items/elements in the overall result list. | ||
*/ | ||
private long totalElements; | ||
|
||
/** | ||
* Describes any sort that is active for the pagination. Default value is null. | ||
*/ | ||
private KiwiSort sort; | ||
|
||
/** | ||
* Allows adjustment for instances where pagination starts with one instead of zero. | ||
*/ | ||
private int pagingStartsWith = 0; | ||
|
||
/** | ||
* Create a new instance. | ||
* <p> | ||
* If you need to add a sort or change {@code pagingStartsWith}, you can chain the {@link #addKiwiSort(KiwiSort)} | ||
* and {@link #usingOneAsFirstPage()} in a fluent style. | ||
* | ||
* @param pageNum the number of this page, can be 0 or 1-based (0 is the default) | ||
* @param limit the page size limit | ||
* @param total the total number of elements in the overall result list | ||
* @param contentList the content on this page | ||
* @param <T> the type of elements on this page | ||
* @return a new instance | ||
* @throws IllegalStateException if any of the numeric arguments are negative or the limit is zero | ||
* @throws IllegalArgumentException if contentList is null | ||
*/ | ||
public static <T> KiwiPage<T> of(long pageNum, long limit, long total, List<T> contentList) { | ||
checkPositiveOrZero(pageNum); | ||
checkPositive(limit); | ||
checkPositiveOrZero(total); | ||
checkArgumentNotNull(contentList); | ||
|
||
var page = new KiwiPage<T>(); | ||
page.setContent(contentList); | ||
page.setSize(limit); // this page might have fewer elements in contentList than the page size limit | ||
page.setNumber(pageNum); | ||
page.setNumberOfElements(contentList.size()); | ||
page.setTotalElements(total); | ||
page.setTotalPages((long) Math.ceil((double) total / limit)); | ||
return page; | ||
} | ||
|
||
/** | ||
* Adds the given sort, returning this instance for method chaining. | ||
* | ||
* @param sort the sort to add | ||
* @return this instance | ||
*/ | ||
public KiwiPage<T> addKiwiSort(KiwiSort sort) { | ||
setSort(sort); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets {@code pagingStartsWith} to zero, so that pagination assumes zero-based page numbering. | ||
* <p> | ||
* This can also be done via the setter method, but it does not permit method chaining. | ||
* | ||
* @return this instance | ||
*/ | ||
public KiwiPage<T> usingZeroAsFirstPage() { | ||
setPagingStartsWith(0); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets {@code pagingStartsWith} to zero, so that pagination assumes one-based page numbering. | ||
* <p> | ||
* This can also be done via the setter method, but it does not permit method chaining. | ||
* | ||
* @return this instance | ||
*/ | ||
public KiwiPage<T> usingOneAsFirstPage() { | ||
setPagingStartsWith(1); | ||
return this; | ||
} | ||
|
||
/** | ||
* Determines if this is the first page when paginating a result list. | ||
* | ||
* @return true if this is the first page | ||
*/ | ||
public boolean isFirst() { | ||
return number == pagingStartsWith; | ||
} | ||
|
||
/** | ||
* Determines if this is the last page when paginating a result list. | ||
* | ||
* @return true if this is the last page | ||
*/ | ||
public boolean isLast() { | ||
var offset = 1 - pagingStartsWith; | ||
return number == (totalPages - offset); | ||
} | ||
|
||
/** | ||
* Does this page have a sort applied? | ||
* | ||
* @return true if this page has a sort applied | ||
*/ | ||
public boolean isSorted() { | ||
return nonNull(sort); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package org.kiwiproject.spring.data; | ||
|
||
import static org.kiwiproject.base.KiwiPreconditions.checkArgumentNotBlank; | ||
import static org.kiwiproject.base.KiwiPreconditions.checkArgumentNotNull; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
import lombok.ToString; | ||
|
||
/** | ||
* Describes a sort on a specific property that is applied to a result list. | ||
*/ | ||
@Getter | ||
@Setter | ||
@ToString | ||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
public class KiwiSort { | ||
|
||
/** | ||
* Sort direction. | ||
*/ | ||
public enum Direction { | ||
|
||
/** | ||
* An ascending sort. | ||
*/ | ||
ASC(true), | ||
|
||
/** | ||
* A descending sort. | ||
*/ | ||
DESC(false); | ||
|
||
/** | ||
* Accessible via a getter method as well as direct field access. | ||
*/ | ||
@Getter | ||
public final boolean ascending; | ||
|
||
Direction(boolean ascending) { | ||
this.ascending = ascending; | ||
} | ||
} | ||
|
||
private String direction; // this is intentionally a string, for JSON serialization purposes | ||
private String property; | ||
private boolean ignoreCase; | ||
private boolean ascending; | ||
|
||
/** | ||
* Create a new instance. | ||
* <p> | ||
* If you want to specify that the sort is not case-sensitive, you can immediately call the | ||
* {@link #ignoringCase()} in a fluent style. | ||
* | ||
* @param property the property the sort is applied to | ||
* @param direction the sort direction | ||
* @return a new instance | ||
* @throws IllegalArgumentException if property is blank or direction is null | ||
*/ | ||
public static KiwiSort of(String property, KiwiSort.Direction direction) { | ||
checkArgumentNotBlank(property); | ||
checkArgumentNotNull(direction); | ||
|
||
var sort = new KiwiSort(); | ||
sort.setProperty(property); | ||
sort.setDirection(direction.name()); | ||
sort.setAscending(direction.isAscending()); | ||
sort.setIgnoreCase(false); | ||
return sort; | ||
} | ||
|
||
/** | ||
* Specifies that the sort is <em>not</em> case sensitive, i.e. it ignores case. | ||
* | ||
* @return this instance, for method chaining | ||
*/ | ||
public KiwiSort ignoringCase() { | ||
setIgnoreCase(true); | ||
return this; | ||
} | ||
} |
Oops, something went wrong.