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