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