|
|
@@ -19,6 +19,7 @@
|
|
|
package org.elasticsearch.search.suggest;
|
|
|
|
|
|
import org.apache.lucene.util.CollectionUtil;
|
|
|
+import org.elasticsearch.common.CheckedFunction;
|
|
|
import org.elasticsearch.common.ParseField;
|
|
|
import org.elasticsearch.common.ParsingException;
|
|
|
import org.elasticsearch.common.io.stream.StreamInput;
|
|
|
@@ -48,7 +49,6 @@ import java.util.HashMap;
|
|
|
import java.util.Iterator;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
-import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
|
|
@@ -384,13 +384,14 @@ public class Suggest implements Iterable<Suggest.Suggestion<? extends Entry<? ex
|
|
|
return builder;
|
|
|
}
|
|
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
public static Suggestion<? extends Entry<? extends Option>> fromXContent(XContentParser parser) throws IOException {
|
|
|
ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);
|
|
|
String typeAndName = parser.currentName();
|
|
|
// we need to extract the type prefix from the name and throw error if it is not present
|
|
|
int delimiterPos = typeAndName.indexOf(InternalAggregation.TYPED_KEYS_DELIMITER);
|
|
|
- String type = null;
|
|
|
- String name = null;
|
|
|
+ String type;
|
|
|
+ String name;
|
|
|
if (delimiterPos > 0) {
|
|
|
type = typeAndName.substring(0, delimiterPos);
|
|
|
name = typeAndName.substring(delimiterPos + 1);
|
|
|
@@ -399,35 +400,17 @@ public class Suggest implements Iterable<Suggest.Suggestion<? extends Entry<? ex
|
|
|
"Cannot parse suggestion response without type information. Set [" + RestSearchAction.TYPED_KEYS_PARAM
|
|
|
+ "] parameter on the request to ensure the type information is added to the response output");
|
|
|
}
|
|
|
- Suggestion suggestion = null;
|
|
|
- Function<XContentParser, Entry> entryParser = null;
|
|
|
- // the "size" parameter and the SortBy for TermSuggestion cannot be parsed from the response, use default values
|
|
|
- // TODO investigate if we can use NamedXContentRegistry instead of this switch
|
|
|
- switch (type) {
|
|
|
- case Suggestion.NAME:
|
|
|
- suggestion = new Suggestion(name, -1);
|
|
|
- entryParser = Suggestion.Entry::fromXContent;
|
|
|
- break;
|
|
|
- case PhraseSuggestion.NAME:
|
|
|
- suggestion = new PhraseSuggestion(name, -1);
|
|
|
- entryParser = PhraseSuggestion.Entry::fromXContent;
|
|
|
- break;
|
|
|
- case TermSuggestion.NAME:
|
|
|
- suggestion = new TermSuggestion(name, -1, SortBy.SCORE);
|
|
|
- entryParser = TermSuggestion.Entry::fromXContent;
|
|
|
- break;
|
|
|
- case CompletionSuggestion.NAME:
|
|
|
- suggestion = new CompletionSuggestion(name, -1);
|
|
|
- entryParser = CompletionSuggestion.Entry::fromXContent;
|
|
|
- break;
|
|
|
- default:
|
|
|
- throw new ParsingException(parser.getTokenLocation(), "Unknown suggestion type [{}]", type);
|
|
|
- }
|
|
|
+
|
|
|
+ return parser.namedObject(Suggestion.class, type, name);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static <E extends Suggestion.Entry<?>> void parseEntries(XContentParser parser, Suggestion<E> suggestion,
|
|
|
+ CheckedFunction<XContentParser, E, IOException> entryParser)
|
|
|
+ throws IOException {
|
|
|
ensureExpectedToken(XContentParser.Token.START_ARRAY, parser.nextToken(), parser::getTokenLocation);
|
|
|
while ((parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
|
|
suggestion.addTerm(entryParser.apply(parser));
|
|
|
}
|
|
|
- return suggestion;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -584,6 +567,7 @@ public class Suggest implements Iterable<Suggest.Suggestion<? extends Entry<? ex
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
protected O newOption(){
|
|
|
return (O) new Option();
|
|
|
}
|