/*
* Copyright 2011 Global Biodiversity Information Facility (GBIF)
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gbif.checklistbank.index.service;
import org.gbif.api.model.Constants;
import org.gbif.api.model.checklistbank.search.NameUsageSearchParameter;
import org.gbif.api.model.checklistbank.search.NameUsageSearchRequest;
import org.gbif.api.model.checklistbank.search.NameUsageSearchResult;
import org.gbif.api.model.checklistbank.search.NameUsageSuggestRequest;
import org.gbif.api.model.checklistbank.search.NameUsageSuggestResult;
import org.gbif.api.model.common.search.SearchResponse;
import org.gbif.api.service.checklistbank.NameUsageSearchService;
import org.gbif.common.search.SearchException;
import java.io.IOException;
import java.util.List;
import com.google.inject.Inject;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Checklist Bank Search interface implementation using Solr/lucene.
* This class uses a remote to interact with CLB index.
*/
public class NameUsageSearchServiceImpl implements NameUsageSearchService {
private static final Logger LOG = LoggerFactory.getLogger(NameUsageSearchServiceImpl.class);
private static final int DEFAULT_SUGGEST_LIMIT = 10;
private static final int MAX_SUGGEST_LIMIT = 100;
/*
* Solr server instance, this abstract type is used because it can hold instance of:
* CommonsHttpSolrServer or EmbeddedSolrServer.
*/
private final SolrClient solrClient;
private final ResponseBuilder responseBuilder = new ResponseBuilder();
private final SolrQueryBuilder queryBuilder = new SolrQueryBuilder();
/**
* Default constructor.
*/
@Inject
public NameUsageSearchServiceImpl(SolrClient solrClient) {
this.solrClient = solrClient;
}
/**
* Issues a SolrQuery and converts the response to a SearchResponse object. Besides, the facets and paging
* parameter and responses are handled in the request and response objects.
*
* @param request the request that contains the search parameters
* @return the SearchResponse of the search operation
*/
@Override
public SearchResponse<NameUsageSearchResult, NameUsageSearchParameter> search(NameUsageSearchRequest request) {
SolrQuery solrQuery = queryBuilder.build(request);
QueryResponse response = query(solrQuery);
return responseBuilder.buildSearch(request, response);
}
@Override
public List<NameUsageSuggestResult> suggest(NameUsageSuggestRequest request) {
// add defaults
if (!request.getParameters().containsKey(NameUsageSearchParameter.DATASET_KEY)) {
// if the datasetKey parameters is not in the list, the GBIF nub is used by default
request.addParameter(NameUsageSearchParameter.DATASET_KEY, Constants.NUB_DATASET_KEY.toString());
}
if (request.getLimit() < 1 || request.getLimit() > MAX_SUGGEST_LIMIT) {
LOG.info("Suggest request with limit {} found. Reset to default {}", request.getLimit(), DEFAULT_SUGGEST_LIMIT);
request.setLimit(DEFAULT_SUGGEST_LIMIT);
}
if (request.getOffset() > 0) {
LOG.debug("Suggest request with offset {} found", request.getOffset());
}
// execute
SolrQuery solrQuery = queryBuilder.build(request);
QueryResponse response = query(solrQuery);
return responseBuilder.buildSuggest(response);
}
private QueryResponse query(SolrQuery query) {
try {
// Executes the search operation in Solr
LOG.debug("Solr query executed: {}", query);
return solrClient.query(query);
} catch (SolrServerException e) {
if (e.getRootCause() instanceof IllegalArgumentException) {
LOG.error("Bad query", e);
throw (IllegalArgumentException) e.getRootCause();
} else {
LOG.error("Error querying solr {}", query, e);
throw new SearchException(e);
}
} catch (IOException e) {
LOG.error("Error querying solr {}", query, e);
throw new SearchException(e);
}
}
}