blob: 4a0d652bd0788b83af40e44fcf9acfc18f797f21 [file] [log] [blame]
/*
* Copyright (c) 2018 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.vts.util;
import com.google.cloud.datastore.Cursor;
import com.google.cloud.datastore.QueryResults;
import com.googlecode.objectify.cmd.Query;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/** Helper class for pagination. */
public class Pagination<T> implements Iterable<T> {
/** the default page size */
public static final int DEFAULT_PAGE_SIZE = 10;
/** the default page window size */
private static final int DEFAULT_PAGE_WINDOW = 10;
/** the current page */
private int page;
/** the page window size */
private int pageSize = DEFAULT_PAGE_SIZE;
/** the total number of found entities */
private int totalCount;
/** the previous cursor string token where to start */
private String previousPageCountToken = "";
/** the previous cursor string token where to start */
private String currentPageCountToken = "";
/** the next cursor string token where to start */
private String nextPageCountToken = "";
/** the previous cursor string token list where to start */
private LinkedHashSet<String> pageCountTokenSet;
/** the maximum number of pages */
private int maxPages;
/** the list of object on the page */
private List<T> list = new ArrayList<>();
public Pagination(List<T> list, int page, int pageSize, int totalCount) {
this.list = list;
this.page = page;
this.pageSize = pageSize;
this.totalCount = totalCount;
}
public Pagination(
Query<T> query,
int page,
int pageSize,
String startPageToken,
LinkedHashSet<String> pageCountTokenSet) {
this.page = page;
this.pageSize = pageSize;
this.pageCountTokenSet = pageCountTokenSet;
this.currentPageCountToken = startPageToken;
List<String> pageCountTokenList =
this.pageCountTokenSet.stream().collect(Collectors.toList());
if (pageCountTokenList.size() > 0) {
int foundIndex = pageCountTokenList.indexOf(startPageToken);
if (foundIndex <= 0) {
this.previousPageCountToken = "";
} else {
this.previousPageCountToken = pageCountTokenList.get(foundIndex - 1);
}
}
int limitValue = pageSize * DEFAULT_PAGE_WINDOW + pageSize / 2;
query = query.limit(limitValue);
if (startPageToken.equals("")) {
this.totalCount = query.count();
} else {
query = query.startAt(Cursor.fromUrlSafe(startPageToken));
this.totalCount = query.count();
}
this.maxPages =
this.totalCount / this.pageSize + (this.totalCount % this.pageSize == 0 ? 0 : 1);
int iteratorIndex = 0;
int startIndex = (page % pageSize == 0 ? 9 : page % pageSize - 1) * pageSize;
QueryResults<T> resultIterator = query.iterator();
while (resultIterator.hasNext()) {
if (startIndex <= iteratorIndex && iteratorIndex < startIndex + this.pageSize)
this.list.add(resultIterator.next());
else resultIterator.next();
if (iteratorIndex == DEFAULT_PAGE_WINDOW * this.pageSize) {
if ( Objects.nonNull(resultIterator) && Objects.nonNull(resultIterator.getCursorAfter()) ) {
this.nextPageCountToken = resultIterator.getCursorAfter().toUrlSafe();
}
}
iteratorIndex++;
}
}
public Iterator<T> iterator() {
return list.iterator();
}
/**
* Gets the total number of objects.
*
* @return the total number of objects as an int
*/
public int getTotalCount() {
return totalCount;
}
/**
* Gets the number of page window.
*
* @return the number of page window as an int
*/
public int getPageSize() {
return pageSize;
}
/**
* Gets the maximum number of pages.
*
* @return the maximum number of pages as an int
*/
public int getMaxPages() {
return this.maxPages;
}
/**
* Gets the page.
*
* @return the page as an int
*/
public int getPage() {
return page;
}
/**
* Gets the minimum page in the window.
*
* @return the page number
*/
public int getMinPageRange() {
if (this.getPage() <= this.getPageSize()) {
return 1;
} else {
if ((this.getPage() % this.getPageSize()) == 0) {
return (this.getPage() / this.getPageSize() - 1) * this.getPageSize() + 1;
} else {
return this.getPage() / this.getPageSize() * this.getPageSize() + 1;
}
}
}
/**
* Gets the maximum page in the window.
*
* @return the page number
*/
public int getMaxPageRange() {
if (this.getMaxPages() > this.getPageSize()) {
return getMinPageRange() + this.getPageSize() - 1;
} else {
return this.getMinPageRange() + this.getMaxPages() - 1;
}
}
/**
* Gets the subset of the list for the current page.
*
* @return a List
*/
public List<T> getList() {
return this.list;
}
/**
* Gets the cursor token for the previous page starting point.
*
* @return a string of cursor of previous starting point
*/
public String getPreviousPageCountToken() {
return this.previousPageCountToken;
}
/**
* Gets the cursor token for the current page starting point.
*
* @return a string of cursor of current starting point
*/
public String getCurrentPageCountToken() {
return this.currentPageCountToken;
}
/**
* Gets the cursor token for the next page starting point.
*
* @return a string of cursor of next starting point
*/
public String getNextPageCountToken() {
return this.nextPageCountToken;
}
}