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.search;
015
016import org.gbif.api.model.common.paging.Pageable;
017import org.gbif.api.model.common.paging.PagingResponse;
018
019import java.util.ArrayList;
020import java.util.List;
021import java.util.Objects;
022import java.util.StringJoiner;
023
024import io.swagger.v3.oas.annotations.Hidden;
025import io.swagger.v3.oas.annotations.media.Schema;
026
027/**
028 * Generic response of a search operation. The result is a {@link java.util.List} of elements.
029 * The type of the elements is bounded by the type parameter T. The list of results can be an empty list.
030 * Optionally the response can contain: a count of the total returned elements, an offset, a pageSize and
031 * the list of facets (if those were requested).
032 *
033 * @param <T> the actual type of response content
034 */
035public class SearchResponse<T, P extends SearchParameter> extends PagingResponse<T> {
036
037  @Schema(
038    description = "The resulting facets of a search operation.  The list can be empty if no facets were requested.\n\n" +
039      "If there are no values for a facet, it will not be included in the list, i.e.: a facet should have " +
040      "at least 1 occurrence."
041  )
042  private final List<Facet<P>> facets = new ArrayList<>();
043
044  @Hidden
045  private SpellCheckResponse spellCheckResponse;
046
047  /**
048   * Default constructor.
049   */
050  public SearchResponse() {
051  }
052
053  /**
054   * Minimal paging constructor.
055   */
056  public SearchResponse(Pageable page) {
057    super(page);
058  }
059
060  /**
061   * Minimal paging constructor.
062   */
063  public SearchResponse(PagingResponse<T> response) {
064    super(response, response.getCount(), response.getResults());
065  }
066
067  /**
068   * Minimal paging constructor.
069   */
070  public SearchResponse(long offset, int limit) {
071    super(offset, limit);
072  }
073
074  /**
075   * Full constructor.
076   *
077   * @param facets list of facets, never null
078   */
079  public SearchResponse(long offset, int pageSize, Long count, List<T> results, List<Facet<P>> facets) {
080    super(offset, pageSize, count, results);
081    setFacets(facets);
082  }
083
084  /**
085   * Gets the resulting facets of a search operation, the list can be empty if no facets were requested.
086   * If there are no values for a facet, it will not be included in the list, i.e.: a facet should have
087   * at least 1 occurrence.
088   */
089  public List<Facet<P>> getFacets() {
090    return facets;
091  }
092
093  /**
094   * Sets the list of facets.
095   *
096   * @param facets list of facets, never null
097   */
098  public final void setFacets(List<Facet<P>> facets) {
099    // copy entries
100    this.facets.clear();
101    if (facets != null) {
102      this.facets.addAll(facets);
103    }
104  }
105
106  /**
107   *
108   * @return the spellcheck response if it was requested
109   */
110  public SpellCheckResponse getSpellCheckResponse() {
111    return spellCheckResponse;
112  }
113
114  /**
115   * Sets the spellcheck response.
116   * @param spellCheckResponse if it was requested
117   */
118  public void setSpellCheckResponse(SpellCheckResponse spellCheckResponse) {
119    this.spellCheckResponse = spellCheckResponse;
120  }
121
122  @Override
123  public boolean equals(Object o) {
124    if (this == o) {
125      return true;
126    }
127    if (o == null || getClass() != o.getClass()) {
128      return false;
129    }
130    if (!super.equals(o)) {
131      return false;
132    }
133    SearchResponse<?, ?> that = (SearchResponse<?, ?>) o;
134    return Objects.equals(facets, that.facets) &&
135      Objects.equals(spellCheckResponse, that.spellCheckResponse);
136  }
137
138  @Override
139  public int hashCode() {
140    return Objects.hash(super.hashCode(), facets, spellCheckResponse);
141  }
142
143  @Override
144  public String toString() {
145    return new StringJoiner(", ", SearchResponse.class.getSimpleName() + "[", "]")
146      .add("facets=" + facets)
147      .add("spellCheckResponse=" + spellCheckResponse)
148      .add("offset=" + offset)
149      .add("limit=" + limit)
150      .add("results=" + getResults())
151      .add("count=" + getCount())
152      .toString();
153  }
154}