/*
* Copyright 2016-2017 the original author or authors.
*
* 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.springframework.data.solr.core.query;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.solr.common.params.SpellingParams;
/**
* {@link SpellcheckOptions} allows modification of query parameters targeting the SpellCheck component is designed to
* provide inline query suggestions based on other, similar, terms.
*
* @author Christoph Strobl
* @since 2.1
*/
public class SpellcheckOptions {
private Query query;
private Map<String, Object> params;
private SpellcheckOptions(Query query, Map<String, Object> params) {
this.query = query;
this.params = new LinkedHashMap<>(params);
}
/**
* Creates new {@link SpellcheckOptions}.
*
* @return
*/
public static SpellcheckOptions spellcheck() {
return new SpellcheckOptions(null, new LinkedHashMap<>());
}
/**
* Creates new {@link SpellcheckOptions} with a given {@link Query}.
*
* @param q
* @return
*/
public static SpellcheckOptions spellcheck(Query q) {
return new SpellcheckOptions(q, new LinkedHashMap<>());
}
/**
* Get the query to be used for spellchecking.
*
* @return can be {@literal null}.
*/
public Query getQuery() {
return query;
}
/**
* @return never {@literal null}.
*/
public Map<String, Object> getParams() {
return Collections.unmodifiableMap(params);
}
/**
* If set, Solr creates the dictionary that the SolrSpellChecker will use for spell-checking.
*
* @return new {@link SpellcheckOptions}
*/
public SpellcheckOptions buildDictionary() {
return createNewAndAppend(SpellingParams.SPELLCHECK_BUILD, true);
}
/**
* @return can be {@literal null}.
*/
public boolean buildDirectory() {
return params.containsKey(SpellingParams.SPELLCHECK_BUILD) ? (Boolean) params.get(SpellingParams.SPELLCHECK_BUILD)
: false;
}
/**
* If set, Solr will take the best suggestion for each token (if one exists) and construct a new query from the
* suggestions.
*
* @return new {@link SpellcheckOptions}
*/
public SpellcheckOptions collate() {
return createNewAndAppend(SpellingParams.SPELLCHECK_COLLATE, true);
}
/**
* @return can be {@literal null}.
*/
public boolean getCollate() {
return params.containsKey(SpellingParams.SPELLCHECK_COLLATE)
? (Boolean) params.get(SpellingParams.SPELLCHECK_COLLATE) : false;
}
/**
* The maximum number of collations to return.
*
* @param max
* @return
*/
public SpellcheckOptions maxCollations(long max) {
return potentiallySetCollate().createNewAndAppend(SpellingParams.SPELLCHECK_MAX_COLLATIONS, max);
}
/**
* @return can be {@literal null}.
*/
public Long getMaxCollations() {
return (Long) params.get(SpellingParams.SPELLCHECK_MAX_COLLATIONS);
}
/**
* This parameter specifies the number of collation possibilities for Solr to try before giving up.
*
* @param tries
* @return
*/
public SpellcheckOptions maxCollationTries(long tries) {
return potentiallySetCollate().createNewAndAppend(SpellingParams.SPELLCHECK_MAX_COLLATION_TRIES, tries);
}
/**
* @return can be {@literal null}.
*/
public Long getMaxCollationTries() {
return (Long) params.get(SpellingParams.SPELLCHECK_MAX_COLLATION_TRIES);
}
/**
* This parameter specifies the maximum number of word correction combinations to rank and evaluate prior to deciding
* which collation candidates to test against the index.
*
* @param evaluations
* @return
*/
public SpellcheckOptions maxCollationEvaluations(long evaluations) {
return potentiallySetCollate().createNewAndAppend(SpellingParams.SPELLCHECK_MAX_COLLATION_EVALUATIONS, evaluations);
}
/**
* @return can be {@literal null}.
*/
public Long getMaxCollationEvaluations() {
return (Long) params.get(SpellingParams.SPELLCHECK_MAX_COLLATION_EVALUATIONS);
}
/**
* Enable the extended response format, which is more complicated but richer. Returns the document frequency for each
* suggestion and returns one suggestion block for each term in the query string.
*
* @return
*/
public SpellcheckOptions extendedResults() {
return createNewAndAppend(SpellingParams.SPELLCHECK_EXTENDED_RESULTS, true);
}
/**
* @return can be {@literal null}.
*/
public Boolean getExtendedResults() {
return (Boolean) params.get(SpellingParams.SPELLCHECK_EXTENDED_RESULTS);
}
/**
* Instructs Solr to return an expanded response format detailing the collations found.
*
* @return
*/
public SpellcheckOptions collateExtendedResults() {
return potentiallySetCollate().createNewAndAppend(SpellingParams.SPELLCHECK_COLLATE_EXTENDED_RESULTS, true);
}
/**
* @return
*/
public boolean getCollateExtendedResults() {
return params.containsKey(SpellingParams.SPELLCHECK_COLLATE_EXTENDED_RESULTS)
? (Boolean) params.get(SpellingParams.SPELLCHECK_COLLATE_EXTENDED_RESULTS) : false;
}
/**
* This parameter specifies the maximum number of documents that should be collect when testing potential collations
* against the index.
*
* @param nr
* @return
*/
public SpellcheckOptions maxCollationCollectDocs(long nr) {
return potentiallySetCollate().createNewAndAppend(SpellingParams.SPELLCHECK_COLLATE_MAX_COLLECT_DOCS, nr);
}
/**
* @return can be {@literal null}.
*/
public Long getMaxCollationCollectDocs() {
return (Long) params.get(SpellingParams.SPELLCHECK_COLLATE_MAX_COLLECT_DOCS);
}
/**
* This parameter prefix can be used to specify any additional parameters that you wish to the Spellchecker to use
* when internally validating collation queries.
*
* @param param
* @param value
* @return
*/
public SpellcheckOptions collateParam(String param, Object value) {
return potentiallySetCollate().createNewAndAppend(SpellingParams.SPELLCHECK_COLLATE_PARAM_OVERRIDE + param, value);
}
/**
* @return can be {@literal null}.
*/
public Map<String, Object> getCollateParams() {
Map<String, Object> tmp = new LinkedHashMap<>();
for (Entry<String, Object> entry : params.entrySet()) {
if (entry.getKey().startsWith(SpellingParams.SPELLCHECK_COLLATE_PARAM_OVERRIDE)) {
tmp.put(entry.getKey().substring(SpellingParams.SPELLCHECK_COLLATE_PARAM_OVERRIDE.length()), entry.getValue());
}
}
return tmp;
}
/**
* Specifies the maximum number of spelling suggestions to be returned.
*
* @param nr
* @return
*/
public SpellcheckOptions count(long nr) {
return createNewAndAppend(SpellingParams.SPELLCHECK_COUNT, nr);
}
/**
* @return can be {@literal null}.
*/
public Long getCount() {
return (Long) params.get(SpellingParams.SPELLCHECK_COUNT);
}
/**
* This parameter causes Solr to use the dictionary named in the parameter's argument. The default setting is
* "default". This parameter can be used to invoke a specific spellchecker on a per request basis.
*
* @return
*/
public SpellcheckOptions dictionaries(String... names) {
return createNewAndAppend(SpellingParams.SPELLCHECK_DICT, names);
}
/**
* @return can be {@literal null}.
*/
public String[] getDictionary() {
return (String[]) params.get(SpellingParams.SPELLCHECK_DICT);
}
/**
* Limits spellcheck responses to queries that are more popular than the original query.
*
* @return
*/
public SpellcheckOptions onlyMorePopular() {
return createNewAndAppend(SpellingParams.SPELLCHECK_ONLY_MORE_POPULAR, true);
}
/**
* @return never {@literal null}.
*/
public boolean getOnlyMorePopular() {
return params.containsKey(SpellingParams.SPELLCHECK_ONLY_MORE_POPULAR)
? (Boolean) params.get(SpellingParams.SPELLCHECK_ONLY_MORE_POPULAR) : false;
}
/**
* The maximum number of hits the request can return in order to both generate spelling suggestions and set the
* {@literal correctlySpelled} element to {@literal false}.
*
* @param nr
* @return
*/
public SpellcheckOptions maxResultsForSuggest(long nr) {
return createNewAndAppend(SpellingParams.SPELLCHECK_MAX_RESULTS_FOR_SUGGEST, nr);
}
/**
* @return can be {@literal null}.
*/
public Long getMaxResultsForSuggest() {
return (Long) params.get(SpellingParams.SPELLCHECK_MAX_RESULTS_FOR_SUGGEST);
}
/**
* The count of suggestions to return for each query term existing in the index and/or dictionary.
*
* @param nr
* @return
*/
public SpellcheckOptions alternativeTermCount(long nr) {
return createNewAndAppend(SpellingParams.SPELLCHECK_ALTERNATIVE_TERM_COUNT, nr);
}
/**
* @return can be {@literal null}.
*/
public Long getAlternativeTermCount() {
return (Long) params.get(SpellingParams.SPELLCHECK_ALTERNATIVE_TERM_COUNT);
}
/**
* Specifies an accuracy value to be used by the spell checking implementation to decide whether a result is
* worthwhile or not. The value is a float between 0 and 1.
*
* @param nr
* @return
*/
public SpellcheckOptions accuracy(float nr) {
return createNewAndAppend(SpellingParams.SPELLCHECK_ACCURACY, nr);
}
/**
* @return can be {@literal null}.
*/
public Float getAccuracy() {
return (Float) params.get(SpellingParams.SPELLCHECK_ACCURACY);
}
private SpellcheckOptions potentiallySetCollate() {
if (params.containsKey(SpellingParams.SPELLCHECK_COLLATE)) {
return this;
}
return collate();
}
private SpellcheckOptions createNewAndAppend(String key, Object value) {
SpellcheckOptions so = new SpellcheckOptions(query, params);
so.params.put(key, value);
return so;
}
}