/* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch licenses this file to you 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.elasticsearch.search.suggest.completion.context; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.xcontent.ObjectParser; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.query.QueryParseContext; import java.io.IOException; import java.util.Objects; import static org.elasticsearch.search.suggest.completion.context.CategoryContextMapping.CONTEXT_BOOST; import static org.elasticsearch.search.suggest.completion.context.CategoryContextMapping.CONTEXT_PREFIX; import static org.elasticsearch.search.suggest.completion.context.CategoryContextMapping.CONTEXT_VALUE; /** * Defines the query context for {@link CategoryContextMapping} */ public final class CategoryQueryContext implements ToXContent { public static final String NAME = "category"; private final String category; private final boolean isPrefix; private final int boost; private CategoryQueryContext(String category, int boost, boolean isPrefix) { this.category = category; this.boost = boost; this.isPrefix = isPrefix; } /** * Returns the category of the context */ public String getCategory() { return category; } /** * Returns if the context should be treated as a prefix */ public boolean isPrefix() { return isPrefix; } /** * Returns the query-time boost of the context */ public int getBoost() { return boost; } public static Builder builder() { return new Builder(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CategoryQueryContext that = (CategoryQueryContext) o; if (isPrefix != that.isPrefix) return false; if (boost != that.boost) return false; return category != null ? category.equals(that.category) : that.category == null; } @Override public int hashCode() { int result = category != null ? category.hashCode() : 0; result = 31 * result + (isPrefix ? 1 : 0); result = 31 * result + boost; return result; } private static ObjectParser<Builder, Void> CATEGORY_PARSER = new ObjectParser<>(NAME, null); static { CATEGORY_PARSER.declareField(Builder::setCategory, XContentParser::text, new ParseField(CONTEXT_VALUE), ObjectParser.ValueType.VALUE); CATEGORY_PARSER.declareInt(Builder::setBoost, new ParseField(CONTEXT_BOOST)); CATEGORY_PARSER.declareBoolean(Builder::setPrefix, new ParseField(CONTEXT_PREFIX)); } public static CategoryQueryContext fromXContent(QueryParseContext context) throws IOException { XContentParser parser = context.parser(); XContentParser.Token token = parser.currentToken(); Builder builder = builder(); if (token == XContentParser.Token.START_OBJECT) { try { CATEGORY_PARSER.parse(parser, builder, null); } catch(ParsingException e) { throw new ElasticsearchParseException("category context must be a string, number or boolean"); } } else if (token == XContentParser.Token.VALUE_STRING || token == XContentParser.Token.VALUE_BOOLEAN || token == XContentParser.Token.VALUE_NUMBER) { builder.setCategory(parser.text()); } else { throw new ElasticsearchParseException("category context must be an object, string, number or boolean"); } return builder.build(); } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); builder.field(CONTEXT_VALUE, category); builder.field(CONTEXT_BOOST, boost); builder.field(CONTEXT_PREFIX, isPrefix); builder.endObject(); return builder; } public static class Builder { private String category; private boolean isPrefix = false; private int boost = 1; public Builder() { } /** * Sets the category of the category. * This is a required field */ public Builder setCategory(String category) { Objects.requireNonNull(category, "category must not be null"); this.category = category; return this; } /** * Sets if the context should be treated as a prefix or not. * Defaults to false */ public Builder setPrefix(boolean prefix) { this.isPrefix = prefix; return this; } /** * Sets the query-time boost of the context. * Defaults to 1. */ public Builder setBoost(int boost) { if (boost <= 0) { throw new IllegalArgumentException("boost must be greater than 0"); } this.boost = boost; return this; } public CategoryQueryContext build() { Objects.requireNonNull(category, "category must not be null"); return new CategoryQueryContext(category, boost, isPrefix); } } }