001/*
002 * SonarQube
003 * Copyright (C) 2009-2017 SonarSource SA
004 * mailto:info AT sonarsource DOT com
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020package org.sonar.api.utils;
021
022import static com.google.common.base.Preconditions.checkArgument;
023
024/**
025 * @since 3.6
026 */
027public class Paging {
028
029  private final int pageSize;
030  private final int pageIndex;
031  private final int total;
032
033  private Paging(int pageSize, int pageIndex, int total) {
034    checkArgument(pageSize >= 1, "Page size must be strictly positive. Got %s", pageSize);
035    checkArgument(pageIndex >= 1, "Page index must be strictly positive. Got %s", pageIndex);
036    checkArgument(total >= 0, "Total items must be positive. Got %s", total);
037    this.pageSize = pageSize;
038    this.pageIndex = pageIndex;
039    this.total = total;
040  }
041
042  /**
043   * @deprecated since 5.2 please use the forPageIndex(...) builder method
044   */
045  @Deprecated
046  public static Paging create(int pageSize, int pageIndex, int totalItems) {
047    return new Paging(pageSize, pageIndex, totalItems);
048  }
049
050  public static Builder forPageIndex(int pageIndex) {
051    return new Builder(pageIndex);
052  }
053
054  /**
055   * Page index, starting with 1.
056   */
057  public int pageIndex() {
058    return pageIndex;
059  }
060
061  /**
062   * Maximum number of items per page. It is greater than 0.
063   */
064  public int pageSize() {
065    return pageSize;
066  }
067
068  /**
069   * Total number of items. It is greater than or equal 0.
070   */
071  public int total() {
072    return total;
073  }
074
075  public int offset() {
076    return (pageIndex - 1) * pageSize;
077  }
078
079  public static int offset(int pageIndex, int pageSize) {
080    return (pageIndex - 1) * pageSize;
081  }
082
083  /**
084   * Number of pages. It is greater than or equal 0.
085   */
086  public int pages() {
087    int p = total / pageSize;
088    if (total % pageSize > 0) {
089      p++;
090    }
091    return p;
092  }
093
094  /**
095   *
096   * @since 4.1
097   */
098  public boolean hasNextPage() {
099    return pageIndex() < pages();
100  }
101
102  public static class Builder {
103    private int pageSize;
104    private int pageIndex;
105
106    private Builder(int pageIndex) {
107      this.pageIndex = pageIndex;
108    }
109
110    public Builder withPageSize(int pageSize) {
111      this.pageSize = pageSize;
112      return this;
113    }
114
115    public Paging andTotal(int total) {
116      return new Paging(pageSize, pageIndex, total);
117    }
118  }
119}