All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.simter.data.Page Maven / Gradle / Ivy

There is a newer version: 1.1.0
Show newest version
package tech.simter.data;

import java.io.Serializable;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * A page is a sublist of a list of objects.
 * It allows gain information about the position of it in the containing entire list.
 * 

* The main interface methods just 4 of below, all other method can be calculate from them: *

    *
  • int getNumber() - The page number, it's one of the page conditions
  • *
  • int getCapacity() - The page capacity, it's the maximal size of each page, it's one of the page conditions
  • *
  • int getRows() - All real row data of this page, it's one of the page results
  • *
  • int getTotalCount() - The total amount of all data store in the repository, it's one of the page results
  • *
* * @param the type of the row data * @author RJ 2017-04-27 */ public interface Page extends Serializable, Iterable { /** * The default page capacity. */ int DEFAULT_CAPACITY = 25; /** * The number of this page. It's minimal value is 1. * * @return the number of this page */ int getNumber(); /** * The maximal size of each page. It's minimal value is 1. * * @return the maximal size of each page */ int getCapacity(); /** * All the row data of this page. * Returns {@link Collections#emptyList()} if this page has no data. Implementer should never return null. * * @return all the real row data of this page */ List getRows(); /** * The total amount of all rows in the store. * * @return zero if the repository has no data */ long getTotalCount(); /** * The number of total pages. It's minimal value is 0. * * @return zero if the repository has no data */ int getPageCount(); /** * The offset to be taken according to the page number and capacity. It's minimal value is 0. * * @return The offset to be taken according to the page number and capacity */ int getOffset(); /** * Whether the page has data at all. * * @return true if this page has data, otherwise return false */ boolean isEmpty(); /** * The real data size of this page. It's minimal value is 0. * * @return the real data size of this page */ int getSize(); /** * Whether the current page is the first page. * * @return true if this page is the first page, otherwise return false */ boolean isFirst(); /** * Whether the current page is the last page. * * @return true if this page is the last page, otherwise return false */ boolean isLast(); /** * Build a new page instance. * * @param number the page number * @param capacity the page maximal size * @param rows the page data * @param totalCount the total amount of all rows in the store * @param the type of the row data * @return the page instance holds the data */ static Page build(int number, int capacity, List rows, long totalCount) { // Make this class can not be reached from outside. class PageImpl implements Page { private int number; private int capacity; private List rows; private long totalCount; private PageImpl(int number, int capacity, List rows, long totalCount) { this.number = Math.max(1, number); this.capacity = toValidCapacity(capacity); this.rows = rows != null ? Collections.unmodifiableList(rows) : Collections.emptyList(); this.totalCount = Math.max(0, totalCount); } @Override public int getNumber() { return number; } @Override public int getCapacity() { return capacity; } @Override public List getRows() { return rows; } @Override public long getTotalCount() { return totalCount; } @Override public int getPageCount() { return (int) Math.ceil((double) totalCount / (double) capacity); } @Override public int getOffset() { return (number - 1) * capacity; } @Override public boolean isEmpty() { return rows.isEmpty(); } @Override public int getSize() { return rows.size(); } @Override public boolean isFirst() { return number <= 1; } @Override public boolean isLast() { return number + 1 > getPageCount(); } // implement the {@link Iterable} interface @Override public Iterator iterator() { return rows.iterator(); } @Override public void forEach(Consumer action) { Objects.requireNonNull(action); for (TT t : this.getRows()) { action.accept(t); } } } return new PageImpl<>(number, capacity, rows, totalCount); } /** * Calculate the offset value * * @param number the page number, default to 1 if less then 1 * @param capacity the page capacity, default to {@link Page#DEFAULT_CAPACITY} if less then 1 * @return the offset value, it's minimal value is zero */ static int calculateOffset(int number, int capacity) { number = Math.max(1, number); capacity = toValidCapacity(capacity); return (number - 1) * capacity; } /** * Convert the specific capacity to a valid value. * If the specific capacity less then 1, return {@link Page#DEFAULT_CAPACITY}, otherwise return the specific capacity. * * @param capacity the specific capacity * @return a valid capacity */ static int toValidCapacity(int capacity) { return capacity < 1 ? DEFAULT_CAPACITY : capacity; } }