001/* 002 * Copyright 2020 Global Biodiversity Information Facility (GBIF) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.gbif.api.model.common.search; 017 018import io.swagger.v3.oas.annotations.Hidden; 019import io.swagger.v3.oas.annotations.Parameter; 020import io.swagger.v3.oas.annotations.enums.Explode; 021import io.swagger.v3.oas.annotations.enums.ParameterIn; 022import io.swagger.v3.oas.annotations.media.ArraySchema; 023import io.swagger.v3.oas.annotations.media.Schema; 024 025import org.gbif.api.model.common.paging.Pageable; 026import org.gbif.api.model.common.paging.PagingRequest; 027 028import java.lang.annotation.Inherited; 029import java.lang.annotation.Retention; 030import java.lang.annotation.RetentionPolicy; 031import java.lang.annotation.Target; 032import java.util.Arrays; 033import java.util.HashMap; 034import java.util.HashSet; 035import java.util.Map; 036import java.util.Set; 037 038import static java.lang.annotation.ElementType.METHOD; 039 040/** 041 * Generic request class for search operations requesting facets. 042 * It extends a search request with a list of desired facets and optional settings. 043 */ 044@SuppressWarnings("unused") 045public class FacetedSearchRequest<P extends SearchParameter> extends SearchRequest<P> { 046 047 @Hidden 048 private Set<P> facets = new HashSet<>(); 049 050 @Hidden 051 private boolean facetMultiSelect; 052 053 @Hidden 054 private Integer facetMinCount; 055 056 @Hidden 057 private Integer facetLimit = 10; 058 059 @Hidden 060 private Integer facetOffset; 061 062 //Holds the paging configuration for each requested facet 063 @Hidden 064 private Map<P, Pageable> facetPages = new HashMap<>(); 065 066 /** 067 * Annotation to document the facet query parameters. 068 */ 069 @Target({METHOD}) 070 @Retention(RetentionPolicy.RUNTIME) 071 @Inherited 072 @io.swagger.v3.oas.annotations.Parameters( 073 value = { 074 @Parameter( 075 name = "facet", 076 description = "A facet name used to retrieve the most frequent values for a field. This parameter may be " + 077 "repeated to request multiple facets.", 078 array = @ArraySchema(schema = @Schema(implementation = String.class)), 079 in = ParameterIn.QUERY, 080 explode = Explode.TRUE), 081 @Parameter( 082 name = "facetMinCount", 083 description = 084 "Used in combination with the facet parameter. Set `facetMinCount={#}` to exclude facets with a count less than `{#}`.", 085 schema = @Schema(implementation = Integer.class), 086 in = ParameterIn.QUERY), 087 @Parameter( 088 name = "facetMultiselect", 089 description = 090 "Used in combination with the facet parameter. Set `facetMultiselect=true` to still return counts for values that are not currently filtered.", 091 schema = @Schema(implementation = Boolean.class), 092 in = ParameterIn.QUERY), 093 @Parameter( 094 name = "facetLimit", 095 description = 096 "Facet parameters allow paging requests using the parameters facetOffset and facetLimit", 097 schema = @Schema(implementation = Integer.class), 098 in = ParameterIn.QUERY), 099 @Parameter( 100 name = "facetOffset", 101 description = 102 "Facet parameters allow paging requests using the parameters facetOffset and facetLimit", 103 schema = @Schema(implementation = Integer.class, minimum = "0"), 104 in = ParameterIn.QUERY) 105 } 106 ) 107 public @interface FacetParameters {} 108 109 public FacetedSearchRequest() { 110 } 111 112 public FacetedSearchRequest(Pageable page) { 113 super(page); 114 } 115 116 public FacetedSearchRequest(SearchRequest<P> searchRequest) { 117 super(searchRequest); 118 setHighlight(searchRequest.isHighlight()); 119 setParameters(searchRequest.getParameters()); 120 setQ(searchRequest.getQ()); 121 } 122 123 public FacetedSearchRequest(long offset, int limit) { 124 super(offset, limit); 125 } 126 127 /** 128 * Min count of facet to return, if the facet count is less than this number the facet won't be included. 129 */ 130 public Integer getFacetMinCount() { 131 return facetMinCount; 132 } 133 134 public void setFacetMinCount(Integer facetMinCount) { 135 this.facetMinCount = facetMinCount; 136 } 137 138 /** 139 * Gets the list of requested facets by the search operation. 140 * The facets are a list of search parameters. 141 */ 142 public Set<P> getFacets() { 143 return facets; 144 } 145 146 /** 147 * Sets the list of facets. 148 */ 149 public void setFacets(Set<P> facets) { 150 this.facets = facets; 151 } 152 153 /** 154 * @return the facetMultiSelect 155 */ 156 public boolean isFacetMultiSelect() { 157 return facetMultiSelect; 158 } 159 160 /** 161 * @param facetMultiSelect the facetMultiSelect to set 162 */ 163 public void setFacetMultiSelect(boolean facetMultiSelect) { 164 this.facetMultiSelect = facetMultiSelect; 165 } 166 167 /** 168 * Page size of the facet request. 169 */ 170 public Integer getFacetLimit() { 171 return facetLimit; 172 } 173 174 public void setFacetLimit(Integer facetLimit) { 175 this.facetLimit = facetLimit; 176 } 177 178 /** 179 * Holds the paging configuration for each requested facet. 180 */ 181 public Map<P, Pageable> getFacetPages() { 182 return facetPages; 183 } 184 185 public void setFacetPages(Map<P, Pageable> facetPages) { 186 this.facetPages = facetPages; 187 } 188 189 /** 190 * Sets the paging setting of facet parameter. 191 */ 192 public void addFacetPage(P parameter, int facetOffset, int facetLimit){ 193 facetPages.put(parameter, new PagingRequest(facetOffset,facetLimit)); 194 } 195 196 /** 197 * Gets the paging configuration of a facet parameter. 198 */ 199 public Pageable getFacetPage(P parameter) { 200 return facetPages.get(parameter); 201 } 202 203 /** 204 * Offset of the facet request. 205 */ 206 public Integer getFacetOffset() { 207 return facetOffset; 208 } 209 210 public void setFacetOffset(Integer facetOffset) { 211 this.facetOffset = facetOffset; 212 } 213 214 public void addFacets(P... facets) { 215 if (this.facets == null) { 216 this.facets = new HashSet<>(Arrays.asList(facets)); 217 } else { 218 this.facets.addAll(new HashSet<>(Arrays.asList(facets))); 219 } 220 } 221}