001/*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 *     http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014package org.gbif.api.model.common.paging;
015
016import java.util.Objects;
017import java.util.StringJoiner;
018
019import io.swagger.v3.oas.annotations.Hidden;
020
021import static org.gbif.api.model.common.paging.PagingConstants.DEFAULT_PARAM_LIMIT;
022import static org.gbif.api.model.common.paging.PagingConstants.DEFAULT_PARAM_OFFSET;
023
024/**
025 * Generically is a class that contains attributes used by operations that are aware of pagination.
026 * Its properties are final to allow calculations in other setter methods.
027 */
028public class PageableBase implements Pageable {
029
030  @Hidden
031  protected long offset;
032
033  @Hidden
034  protected int limit;
035
036  /**
037   * Default constructor with default paging values.
038   */
039  protected PageableBase() {
040    offset = DEFAULT_PARAM_OFFSET;
041    limit = DEFAULT_PARAM_LIMIT;
042  }
043
044  /**
045   * Full constructor based on a request.
046   *
047   * @throws IllegalArgumentException if negative offset or limit.
048   */
049  protected PageableBase(Pageable page) {
050    setOffset(page.getOffset());
051    setLimit(page.getLimit());
052  }
053
054  /**
055   * Full constructor.
056   *
057   * @throws IllegalArgumentException if negative offset or limit.
058   */
059  protected PageableBase(long offset, int limit) {
060    setOffset(offset);
061    setLimit(limit);
062  }
063
064  /**
065   * Total of rows that are returned.
066   */
067  @Override
068  public int getLimit() {
069    return limit;
070  }
071
072  /**
073   * @param limit the non negative limit to set
074   *
075   * @throws IllegalArgumentException if negative
076   */
077  public void setLimit(int limit) {
078    if (limit < 0) {
079      throw new IllegalArgumentException("Limit cannot be negative");
080    }
081    this.limit = limit;
082  }
083
084  /**
085   * Defines how many items to skip before beginning to return rows.
086   */
087  @Override
088  public long getOffset() {
089    return offset;
090  }
091
092  /**
093   * @param offset the non negative offset to set
094   *
095   * @throws IllegalArgumentException if negative
096   */
097  public void setOffset(long offset) {
098    if (offset < 0) {
099      throw new IllegalArgumentException("Offset cannot be negative");
100    }
101    this.offset = offset;
102  }
103
104  /**
105   * Adds to existing offset, setting offset to zero if it would be negative.
106   *
107   * @param offsetDiff to be added to existing offset.
108   */
109  public void addOffset(long offsetDiff) {
110    offset += offsetDiff;
111    if (offset < 0) {
112      offset = 0;
113    }
114  }
115
116  /**
117   * Utility method to copy paging values.
118   */
119  public void copyPagingValues(Pageable pageable) {
120    limit = pageable.getLimit();
121    offset = pageable.getOffset();
122  }
123
124  @Override
125  public boolean equals(Object o) {
126    if (this == o) {
127      return true;
128    }
129    if (o == null || getClass() != o.getClass()) {
130      return false;
131    }
132    PageableBase that = (PageableBase) o;
133    return offset == that.offset &&
134      limit == that.limit;
135  }
136
137  @Override
138  public int hashCode() {
139    return Objects.hash(offset, limit);
140  }
141
142  @Override
143  public String toString() {
144    return new StringJoiner(", ", PageableBase.class.getSimpleName() + "[", "]")
145      .add("offset=" + offset)
146      .add("limit=" + limit)
147      .toString();
148  }
149}