Pagination
This example uses plain refinements and refinement aliases to describe common pagination rules. The aliases keep the contracts readable while still relating results to the input values.
import liquidjava.specification.*;
@RefinementAlias("Page(int p) { p >= 1 }")
@RefinementAlias("PageSize(int s) { 1 <= s && s <= 100 }")
@RefinementAlias("PageCount(int p) { p >= 0 }")
@RefinementAlias("ItemCount(int n) { n >= 0 }")
public class Pagination {
@Refinement("ItemCount(_) && _ == (page - 1) * size")
public static int offset(
@Refinement("Page(_)") int page,
@Refinement("PageSize(_)") int size
) {
return (page - 1) * size;
}
@Refinement("Page(_) && _ == page + 1")
public static int nextPage(@Refinement("Page(_)") int page) {
return page + 1;
}
@Refinement("PageCount(_) && _ == (items + size - 1) / size")
public static int totalPages(
@Refinement("ItemCount(_)") int items,
@Refinement("PageSize(_)") int size
) {
return (items + size - 1) / size;
}
}
int size = 20;
int page = 3;
int offset = Pagination.offset(page, size);
int next = Pagination.nextPage(page);
int total = Pagination.totalPages(50, size);
Pagination.offset(0, 20); // Refinement Error
Pagination.totalPages(50, 200); // Refinement Error
The aliases capture the key domain concepts for pagination:
Pagesays page numbers start at1PageSizeconstrains the accepted page size rangePageCountprevents negative page countsItemCountprevents negative item counts