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