// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.query.parser;
import com.yahoo.language.Language;
import com.yahoo.search.query.Model;
import com.yahoo.search.query.Select;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
*
This class encapsulates all the parameters required to call {@link Parser#parse(Parsable)}. Because all set-
* methods return a reference to self, you can write very compact calls to the parser:
*
*
* parser.parse(new Parsable()
* .setQuery("foo")
* .setFilter("bar")
* .setDefaultIndexName("default")
* .setLanguage(Language.ENGLISH))
*
*
* In case you are parsing the content of a {@link Model}, you can use the {@link #fromQueryModel(Model)} factory for
* convenience.
*
* @author Simon Thoresen Hult
*/
public final class Parsable {
private final Set sourceList = new HashSet<>();
private final Set restrictList = new HashSet<>();
private String query;
private String filter;
private String defaultIndexName;
private Language language; // TODO: Initialize to UNKNOWN
private Optional explicitLanguage = Optional.empty();
private Select select;
/** If this is set it will be used to determine the language, if not set explicitly */
private Optional model = Optional.empty();
public String getQuery() {
return query;
}
public Parsable setQuery(String query) {
this.query = query;
return this;
}
public String getFilter() {
return filter;
}
public Parsable setFilter(String filter) {
this.filter = filter;
return this;
}
public String getDefaultIndexName() {
return defaultIndexName;
}
public Parsable setDefaultIndexName(String defaultIndexName) {
this.defaultIndexName = defaultIndexName;
return this;
}
/**
* Returns the language to use when parsing, or null to decide during parsing.
*/
public Language getLanguage() {
return language;
}
/**
* Returns the language to use when parsing, with a text to use for detection if necessary.
* if not decided by the item under parsing. This is never null or UNKNOWN
*/
public Language getOrDetectLanguage(String languageDetectionText) {
if (language != null && language != Language.UNKNOWN) return language;
if (model.isPresent()) return model.get().getParsingLanguage(languageDetectionText);
return Language.UNKNOWN; // against the promise in the JavaDoc, but it is not locally ensured
}
public Parsable setLanguage(Language language) {
Objects.requireNonNull(language, "Language cannot be null");
this.language = language;
return this;
}
/** Returns the language explicitly set to be used when parsing, or empty if none is set. */
public Optional getExplicitLanguage() { return explicitLanguage; }
public Parsable setExplicitLanguage(Optional language) {
Objects.requireNonNull(language, "Explicit language cannot be null");
this.explicitLanguage = language;
return this;
}
public Parsable setModel(Model model) {
Objects.requireNonNull(model, "Model cannot be null");
this.model = Optional.of(model);
return this;
}
public Set getSources() {
return sourceList;
}
public Parsable addSource(String sourceName) {
sourceList.add(sourceName);
return this;
}
public Parsable addSources(Collection sourceNames) {
sourceList.addAll(sourceNames);
return this;
}
public Set getRestrict() {
return restrictList;
}
public Parsable addRestrict(String restrictName) {
restrictList.add(restrictName);
return this;
}
public Parsable addRestricts(Collection restrictNames) {
restrictList.addAll(restrictNames);
return this;
}
public Parsable setSelect(Select select){
this.select = select;
return this;
}
public Select getSelect(){
return this.select;
}
public static Parsable fromQueryModel(Model model) {
return new Parsable()
.setModel(model)
.setQuery(model.getQueryString())
.setFilter(model.getFilter())
.setExplicitLanguage(Optional.ofNullable(model.getLanguage()))
.setDefaultIndexName(model.getDefaultIndex())
.addSources(model.getSources())
.addRestricts(model.getRestrict())
.setSelect(model.getParent().getSelect());
}
}