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 io.swagger.v3.oas.annotations.Hidden;
017
018import io.swagger.v3.oas.annotations.media.Schema;
019
020import org.gbif.api.model.common.paging.Pageable;
021import org.gbif.api.model.common.paging.PageableBase;
022import org.gbif.api.util.IsoDateInterval;
023
024import java.text.DateFormat;
025import java.text.SimpleDateFormat;
026import java.util.Date;
027import java.util.HashMap;
028import java.util.HashSet;
029import java.util.Map;
030import java.util.Set;
031import java.util.StringJoiner;
032
033import static org.gbif.api.model.common.paging.PagingConstants.DEFAULT_PARAM_LIMIT;
034import static org.gbif.api.model.common.paging.PagingConstants.DEFAULT_PARAM_OFFSET;
035
036/**
037 * Generic request class for search operations. This class contains a list of parameters,
038 * a list of desired facets and paging options (page size and offset).
039 */
040@SuppressWarnings("unused")
041public class SearchRequest<P extends SearchParameter> extends PageableBase {
042
043  @Hidden
044  private Map<P, Set<String>> parameters = new HashMap<>();
045
046  @Schema(
047    description = "Full-record query parameter."
048  )
049  private String q;
050
051  @Schema(
052    description = "If highlighted search matches are requested."
053  )
054  private boolean highlight;
055
056  @Hidden
057  private boolean spellCheck;
058
059  @Hidden
060  private int spellCheckCount;
061
062  @Hidden
063  private Set<QueryField> qFields = new HashSet<>();
064
065  @Hidden
066  private Set<QueryField> highlightFields = new HashSet<>();
067
068  public interface QueryField {}
069
070  /**
071   * Constructor with default paging offset & limit.
072   */
073  public SearchRequest() {
074    super(DEFAULT_PARAM_OFFSET, DEFAULT_PARAM_LIMIT);
075  }
076
077  /**
078   * Simple query constructor with default paging offset & limit.
079   *
080   * @param query string for request
081   */
082  public SearchRequest(String query) {
083    super(DEFAULT_PARAM_OFFSET, DEFAULT_PARAM_LIMIT);
084    q = query;
085  }
086
087  /**
088   * Minimal paging constructor.
089   */
090  public SearchRequest(Pageable page) {
091    super(page.getOffset(), page.getLimit());
092  }
093
094  /**
095   * Minimal paging constructor.
096   */
097  public SearchRequest(long offset, int limit) {
098    super(offset, limit);
099  }
100
101
102  /**
103   * @return true if highlighted search matches are requested
104   */
105  public boolean isHighlight() {
106    return highlight;
107  }
108
109  /**
110   * @param highlight the highlight to set
111   */
112  public void setHighlight(boolean highlight) {
113    this.highlight = highlight;
114  }
115
116  /**
117   *
118   * @return true if spellCheck search is requested
119   */
120  public boolean isSpellCheck() {
121    return spellCheck;
122  }
123
124  /**
125   * @param spellCheck the highlight to set
126   */
127  public void setSpellCheck(boolean spellCheck) {
128    this.spellCheck = spellCheck;
129  }
130
131  /**
132   *
133   * @return max number of spell check suggestions requested
134   */
135  public int getSpellCheckCount() {
136    return spellCheckCount;
137  }
138
139  /**
140   *
141   * @param spellCheckCount number of spell check suggestions
142   */
143  public void setSpellCheckCount(int spellCheckCount) {
144    this.spellCheckCount = spellCheckCount;
145  }
146
147  /**
148   * Defines whether to match against fields with scientific or vernacular names or both.
149   */
150  @Hidden
151  public Set<QueryField> getQFields() {
152    return qFields;
153  }
154
155  @Hidden
156  public void setQFields(Set<QueryField> qFields) {
157    this.qFields = qFields;
158  }
159
160  /**
161   * Defines the fields to be highlighted if highlighting is activated.
162   */
163  public Set<QueryField> getHighlightFields() {
164    return highlightFields;
165  }
166
167  public void setHighlightFields(Set<QueryField> highlightFields) {
168    this.highlightFields = highlightFields;
169  }
170
171  /**
172   * List of input parameters of the search operation.
173   * The parameters are handled as the parameter name and the string representation of its value.
174   *
175   * @return the list of parameters
176   */
177  public Map<P, Set<String>> getParameters() {
178    return parameters;
179  }
180
181  /**
182   * Sets the list of parameters.
183   */
184  public void setParameters(Map<P, Set<String>> parameters) {
185    this.parameters = parameters;
186  }
187
188  /**
189   * Query parameter.
190   *
191   * @return the q
192   */
193  public String getQ() {
194    return q;
195  }
196
197  /**
198   * @param q the q to set
199   */
200  public void setQ(String q) {
201    this.q = q;
202  }
203
204  /**
205   * Adds the specified parameter.
206   *
207   * @param parameter parameter to add values for
208   * @param values    list of values of the parameter to add
209   */
210  public void addParameter(P parameter, Iterable<String> values) {
211    if (parameters.containsKey(parameter)) {
212      Set<String> paramValues = parameters.get(parameter);
213      values.forEach(paramValues::add);
214    } else {
215      Set<String> paramValues = new HashSet<>();
216      values.forEach(paramValues::add);
217      parameters.put(parameter, paramValues);
218    }
219  }
220
221  /**
222   * Adds the specified parameter.
223   *
224   * @param parameter parameter to add values for
225   * @param values    list of values of the parameter to add
226   */
227  public void addParameter(P parameter, String... values) {
228    for (String value : values) {
229      addParameter(parameter, value);
230    }
231  }
232
233  /**
234   * Adds the specified parameter.
235   *
236   * @param parameter parameter to add values for
237   * @param value     value of the parameter to add
238   */
239  public void addParameter(P parameter, String value) {
240    if (value != null) {
241      if (parameters.containsKey(parameter)) {
242        Set<String> paramValues = parameters.get(parameter);
243        paramValues.add(value);
244      } else {
245        Set<String> paramValues = new HashSet<>();
246        paramValues.add(value);
247        parameters.put(parameter, paramValues);
248      }
249    }
250  }
251
252  /**
253   * Adds the specified long parameter.
254   *
255   * @param parameter parameter to add values for
256   * @param value     value of the parameter to add
257   */
258  public void addParameter(P parameter, long value) {
259    addParameter(parameter, String.valueOf(value));
260  }
261
262  /**
263   * Adds the specified int parameter.
264   *
265   * @param parameter parameter to add values for
266   * @param value     value of the parameter to add
267   */
268  public void addParameter(P parameter, int value) {
269    addParameter(parameter, String.valueOf(value));
270  }
271
272  /**
273   * Adds the specified double parameter.
274   *
275   * @param parameter parameter to add values for
276   * @param value     value of the parameter to add
277   */
278  public void addParameter(P parameter, double value) {
279    addParameter(parameter, String.valueOf(value));
280  }
281
282  /**
283   * Adds the specified boolean parameter.
284   *
285   * @param parameter parameter to add values for
286   * @param value     value of the parameter to add
287   */
288  public void addParameter(P parameter, boolean value) {
289    addParameter(parameter, String.valueOf(value));
290  }
291
292  /**
293   * Adds the specified parameter.
294   *
295   * @param parameter parameter to add values for
296   * @param value     enum value of the parameter to add
297   */
298  public void addParameter(P parameter, Enum<?> value) {
299    if (value != null) {
300      addParameter(parameter, value.name());
301    }
302  }
303
304  /**
305   * Adds the specified date parameter as an ISO date.
306   *
307   * @param parameter parameter to add date for
308   * @param value     date value of the parameter to add
309   */
310  public void addParameter(P parameter, Date value) {
311    if (value != null) {
312      // not thread safe, new instance
313      DateFormat iso = new SimpleDateFormat("yyyy-MM-dd");
314      addParameter(parameter, iso.format(value));
315    }
316  }
317
318  /**
319   * Adds the specified date parameter as an ISO date interval.
320   *
321   * @param parameter parameter to add date interval for
322   * @param value     date value of the parameter to add
323   */
324  public void addParameter(P parameter, IsoDateInterval value) {
325    if (value != null) {
326      addParameter(parameter, value.toString());
327    }
328  }
329
330  @Override
331  public String toString() {
332    return new StringJoiner(", ", SearchRequest.class.getSimpleName() + "[", "]")
333      .add("parameters=" + parameters)
334      .add("q='" + q + "'")
335      .add("highlight=" + highlight)
336      .add("spellCheck=" + spellCheck)
337      .add("spellCheckCount=" + spellCheckCount)
338      .add("offset=" + offset)
339      .add("limit=" + limit)
340      .toString();
341  }
342}