001/*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube 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 * SonarQube 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 */
020
021package org.sonar.api.utils;
022
023/**
024 * @since 3.6
025 */
026public class Paging {
027
028  private final int pageSize;
029  private final int pageIndex;
030  private final int total;
031
032  private Paging(int pageSize, int pageIndex, int total) {
033    if (pageSize < 1) {
034      throw new IllegalArgumentException("Page size must be strictly positive. Got " + pageSize);
035    }
036    if (pageIndex < 1) {
037      throw new IllegalArgumentException("Page index must be strictly positive. Got " + pageIndex);
038    }
039    if (total < 0) {
040      throw new IllegalArgumentException("Total items must be positive. Got " + total);
041    }
042
043    this.pageSize = pageSize;
044    this.pageIndex = pageIndex;
045    this.total = total;
046  }
047
048  /**
049   * @deprecated since 5.2 please use the forPageIndex(...) builder method
050   */
051  @Deprecated
052  public static Paging create(int pageSize, int pageIndex, int totalItems) {
053    return new Paging(pageSize, pageIndex, totalItems);
054  }
055
056  public static Builder forPageIndex(int pageIndex) {
057    return new Builder(pageIndex);
058  }
059
060  /**
061   * Page index, starting with 1.
062   */
063  public int pageIndex() {
064    return pageIndex;
065  }
066
067  /**
068   * Maximum number of items per page. It is greater than 0.
069   */
070  public int pageSize() {
071    return pageSize;
072  }
073
074  /**
075   * Total number of items. It is greater than or equal 0.
076   */
077  public int total() {
078    return total;
079  }
080
081  public int offset() {
082    return (pageIndex - 1) * pageSize;
083  }
084
085  /**
086   * Number of pages. It is greater than or equal 0.
087   */
088  public int pages() {
089    int p = total / pageSize;
090    if (total % pageSize > 0) {
091      p++;
092    }
093    return p;
094  }
095
096  /**
097   *
098   * @since 4.1
099   */
100  public boolean hasNextPage() {
101    return pageIndex() < pages();
102  }
103
104  public static class Builder {
105    private int pageSize;
106    private int pageIndex;
107
108    private Builder(int pageIndex) {
109      this.pageIndex = pageIndex;
110    }
111
112    public Builder withPageSize(int pageSize) {
113      this.pageSize = pageSize;
114      return this;
115    }
116
117    public Paging andTotal(int total) {
118      return new Paging(pageSize, pageIndex, total);
119    }
120  }
121}