/* * 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.appengine.api.datastore.Cursor; import com.google.appengine.api.datastore.QueryResultIterator; 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 implements Iterable { /** 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 pageCountTokenSet; /** the maximum number of pages */ private int maxPages; /** the list of object on the page */ private List list = new ArrayList<>(); public Pagination(List list, int page, int pageSize, int totalCount) { this.list = list; this.page = page; this.pageSize = pageSize; this.totalCount = totalCount; } public Pagination( Query query, int page, int pageSize, String startPageToken, LinkedHashSet pageCountTokenSet) { this.page = page; this.pageSize = pageSize; this.pageCountTokenSet = pageCountTokenSet; this.currentPageCountToken = startPageToken; List 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.fromWebSafeString(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; QueryResultIterator 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.getCursor()) ) { this.nextPageCountToken = resultIterator.getCursor().toWebSafeString(); } } iteratorIndex++; } } public Iterator 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 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; } }