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 static org.gbif.api.model.common.paging.PagingConstants.DEFAULT_PARAM_LIMIT; 017import static org.gbif.api.model.common.paging.PagingConstants.DEFAULT_PARAM_OFFSET; 018 019import io.swagger.v3.oas.annotations.Hidden; 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.Optional; 027import java.util.Set; 028import java.util.StringJoiner; 029import lombok.Getter; 030import lombok.Setter; 031import org.gbif.api.annotation.Experimental; 032import org.gbif.api.model.common.paging.Pageable; 033import org.gbif.api.model.common.paging.PageableBase; 034import org.gbif.api.util.IsoDateInterval; 035 036/** 037 * Generic request class for search operations. This class contains a list of parameters, a list of 038 * desired facets and paging options (page size and offset). 039 */ 040@SuppressWarnings("unused") 041public abstract class BaseSearchRequest<P extends SearchParameter> extends PageableBase 042 implements SearchRequest<P> { 043 044 @Hidden private Map<P, Set<String>> parameters = new HashMap<>(); 045 046 @Hidden private String q; 047 048 @Hidden private boolean highlight; 049 050 @Hidden private boolean spellCheck; 051 052 @Hidden private int spellCheckCount; 053 054 @Hidden private Set<QueryField> qFields = new HashSet<>(); 055 056 @Hidden private Set<QueryField> highlightFields = new HashSet<>(); 057 058 @Hidden @Experimental @Setter private Boolean matchCase; 059 060 /** 061 * This flag allows to sort the results in a random order by specifying a seed. The seed makes the 062 * random results reproducible so we can use paging. The same seed has to be sent for each page. 063 */ 064 @Hidden @Experimental @Getter @Setter private String shuffle; 065 066 /** 067 * This flag enables the use of case-sensitive matches and aggregations on certain search 068 * parameters. 069 * 070 * <p>Fields that support this feature are: occurrenceId, recordedBy, samplingProtocol, 071 * catalogNumber, collectionCode, institutionCode, eventId, parentEventId, waterBody, 072 * stateProvince, recordNumber, identifiedBy, organismId and locality. 073 * 074 * <p>This is an experimental feature, and its implementation may change or be removed at any 075 * time. 076 * 077 * <p>Be aware that this is not a per-field flag, all possible fields will match case sensitively. 078 */ 079 @Override 080 @Experimental 081 public Boolean isMatchCase() { 082 return Optional.ofNullable(matchCase).orElse(Boolean.FALSE); 083 } 084 085 /** Constructor with default paging offset & limit. */ 086 public BaseSearchRequest() { 087 super(DEFAULT_PARAM_OFFSET, DEFAULT_PARAM_LIMIT); 088 } 089 090 /** 091 * Simple query constructor with default paging offset & limit. 092 * 093 * @param query string for request 094 */ 095 public BaseSearchRequest(String query) { 096 super(DEFAULT_PARAM_OFFSET, DEFAULT_PARAM_LIMIT); 097 q = query; 098 } 099 100 /** Minimal paging constructor. */ 101 public BaseSearchRequest(Pageable page) { 102 super(page.getOffset(), page.getLimit()); 103 } 104 105 /** Minimal paging constructor. */ 106 public BaseSearchRequest(long offset, int limit) { 107 super(offset, limit); 108 } 109 110 /** 111 * @return true if highlighted search matches are requested 112 */ 113 @Override 114 public boolean isHighlight() { 115 return highlight; 116 } 117 118 /** 119 * @param highlight the highlight to set 120 */ 121 @Override 122 public void setHighlight(boolean highlight) { 123 this.highlight = highlight; 124 } 125 126 /** 127 * @return true if spellCheck search is requested 128 */ 129 @Override 130 public boolean isSpellCheck() { 131 return spellCheck; 132 } 133 134 /** 135 * @param spellCheck the highlight to set 136 */ 137 @Override 138 public void setSpellCheck(boolean spellCheck) { 139 this.spellCheck = spellCheck; 140 } 141 142 /** 143 * @return max number of spell check suggestions requested 144 */ 145 @Override 146 public int getSpellCheckCount() { 147 return spellCheckCount; 148 } 149 150 /** 151 * @param spellCheckCount number of spell check suggestions 152 */ 153 @Override 154 public void setSpellCheckCount(int spellCheckCount) { 155 this.spellCheckCount = spellCheckCount; 156 } 157 158 /** Defines whether to match against fields with scientific or vernacular names or both. */ 159 @Hidden 160 @Override 161 public Set<QueryField> getQFields() { 162 return qFields; 163 } 164 165 @Hidden 166 @Override 167 public void setQFields(Set<QueryField> qFields) { 168 this.qFields = qFields; 169 } 170 171 /** Defines the fields to be highlighted if highlighting is activated. */ 172 @Override 173 public Set<QueryField> getHighlightFields() { 174 return highlightFields; 175 } 176 177 @Override 178 public void setHighlightFields(Set<QueryField> highlightFields) { 179 this.highlightFields = highlightFields; 180 } 181 182 /** 183 * List of input parameters of the search operation. The parameters are handled as the parameter 184 * name and the string representation of its value. 185 * 186 * @return the list of parameters 187 */ 188 @Override 189 public Map<P, Set<String>> getParameters() { 190 return parameters; 191 } 192 193 /** Sets the list of parameters. */ 194 @Override 195 public void setParameters(Map<P, Set<String>> parameters) { 196 this.parameters = parameters; 197 } 198 199 /** 200 * Query parameter. 201 * 202 * @return the q 203 */ 204 @Override 205 public String getQ() { 206 return q; 207 } 208 209 /** 210 * @param q the q to set 211 */ 212 @Override 213 public void setQ(String q) { 214 this.q = q; 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 @Override 224 public void addParameter(P parameter, Iterable<String> values) { 225 if (parameters.containsKey(parameter)) { 226 Set<String> paramValues = parameters.get(parameter); 227 values.forEach(paramValues::add); 228 } else { 229 Set<String> paramValues = new HashSet<>(); 230 values.forEach(paramValues::add); 231 parameters.put(parameter, paramValues); 232 } 233 } 234 235 /** 236 * Adds the specified parameter. 237 * 238 * @param parameter parameter to add values for 239 * @param values list of values of the parameter to add 240 */ 241 @Override 242 public void addParameter(P parameter, String... values) { 243 for (String value : values) { 244 addParameter(parameter, value); 245 } 246 } 247 248 /** 249 * Adds the specified parameter. 250 * 251 * @param parameter parameter to add values for 252 * @param value value of the parameter to add 253 */ 254 @Override 255 public void addParameter(P parameter, String value) { 256 if (value != null) { 257 if (parameters.containsKey(parameter)) { 258 Set<String> paramValues = parameters.get(parameter); 259 paramValues.add(value); 260 } else { 261 Set<String> paramValues = new HashSet<>(); 262 paramValues.add(value); 263 parameters.put(parameter, paramValues); 264 } 265 } 266 } 267 268 /** 269 * Adds the specified long parameter. 270 * 271 * @param parameter parameter to add values for 272 * @param value value of the parameter to add 273 */ 274 @Override 275 public void addParameter(P parameter, long value) { 276 addParameter(parameter, String.valueOf(value)); 277 } 278 279 /** 280 * Adds the specified int parameter. 281 * 282 * @param parameter parameter to add values for 283 * @param value value of the parameter to add 284 */ 285 @Override 286 public void addParameter(P parameter, int value) { 287 addParameter(parameter, String.valueOf(value)); 288 } 289 290 /** 291 * Adds the specified double parameter. 292 * 293 * @param parameter parameter to add values for 294 * @param value value of the parameter to add 295 */ 296 @Override 297 public void addParameter(P parameter, double value) { 298 addParameter(parameter, String.valueOf(value)); 299 } 300 301 /** 302 * Adds the specified boolean parameter. 303 * 304 * @param parameter parameter to add values for 305 * @param value value of the parameter to add 306 */ 307 @Override 308 public void addParameter(P parameter, boolean value) { 309 addParameter(parameter, String.valueOf(value)); 310 } 311 312 /** 313 * Adds the specified parameter. 314 * 315 * @param parameter parameter to add values for 316 * @param value enum value of the parameter to add 317 */ 318 @Override 319 public void addParameter(P parameter, Enum<?> value) { 320 if (value != null) { 321 addParameter(parameter, value.name()); 322 } 323 } 324 325 /** 326 * Adds the specified date parameter as an ISO date. 327 * 328 * @param parameter parameter to add date for 329 * @param value date value of the parameter to add 330 */ 331 @Override 332 public void addParameter(P parameter, Date value) { 333 if (value != null) { 334 // not thread safe, new instance 335 DateFormat iso = new SimpleDateFormat("yyyy-MM-dd"); 336 addParameter(parameter, iso.format(value)); 337 } 338 } 339 340 /** 341 * Adds the specified date parameter as an ISO date interval. 342 * 343 * @param parameter parameter to add date interval for 344 * @param value date value of the parameter to add 345 */ 346 @Override 347 public void addParameter(P parameter, IsoDateInterval value) { 348 if (value != null) { 349 addParameter(parameter, value.toString()); 350 } 351 } 352 353 @Override 354 public void copyPagingValues(Pageable pageable) { 355 super.copyPagingValues(pageable); 356 } 357 358 @Override 359 public String toString() { 360 return new StringJoiner(", ", BaseSearchRequest.class.getSimpleName() + "[", "]") 361 .add("parameters=" + parameters) 362 .add("q='" + q + "'") 363 .add("highlight=" + highlight) 364 .add("spellCheck=" + spellCheck) 365 .add("spellCheckCount=" + spellCheckCount) 366 .add("offset=" + offset) 367 .add("limit=" + limit) 368 .toString(); 369 } 370}