|
@@ -20,9 +20,35 @@
|
|
|
package org.elasticsearch.action.admin.indices.analyze;
|
|
|
|
|
|
import org.elasticsearch.action.Action;
|
|
|
+import org.elasticsearch.action.ActionRequestValidationException;
|
|
|
+import org.elasticsearch.action.ActionResponse;
|
|
|
+import org.elasticsearch.action.support.single.shard.SingleShardRequest;
|
|
|
+import org.elasticsearch.common.ParseField;
|
|
|
+import org.elasticsearch.common.Strings;
|
|
|
+import org.elasticsearch.common.io.stream.StreamInput;
|
|
|
+import org.elasticsearch.common.io.stream.StreamOutput;
|
|
|
import org.elasticsearch.common.io.stream.Writeable;
|
|
|
+import org.elasticsearch.common.settings.Settings;
|
|
|
+import org.elasticsearch.common.xcontent.ObjectParser;
|
|
|
+import org.elasticsearch.common.xcontent.ToXContentFragment;
|
|
|
+import org.elasticsearch.common.xcontent.ToXContentObject;
|
|
|
+import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
|
+import org.elasticsearch.common.xcontent.XContentFactory;
|
|
|
+import org.elasticsearch.common.xcontent.XContentParseException;
|
|
|
+import org.elasticsearch.common.xcontent.XContentParser;
|
|
|
+import org.elasticsearch.common.xcontent.XContentType;
|
|
|
|
|
|
-public class AnalyzeAction extends Action<AnalyzeResponse> {
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.TreeMap;
|
|
|
+
|
|
|
+import static org.elasticsearch.action.ValidateActions.addValidationError;
|
|
|
+
|
|
|
+public class AnalyzeAction extends Action<AnalyzeAction.Response> {
|
|
|
|
|
|
public static final AnalyzeAction INSTANCE = new AnalyzeAction();
|
|
|
public static final String NAME = "indices:admin/analyze";
|
|
@@ -32,12 +58,802 @@ public class AnalyzeAction extends Action<AnalyzeResponse> {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public Writeable.Reader<AnalyzeResponse> getResponseReader() {
|
|
|
- return AnalyzeResponse::new;
|
|
|
+ public Writeable.Reader<Response> getResponseReader() {
|
|
|
+ return Response::new;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public AnalyzeResponse newResponse() {
|
|
|
+ public Response newResponse() {
|
|
|
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A request to analyze a text associated with a specific index. Allow to provide
|
|
|
+ * the actual analyzer name to perform the analysis with.
|
|
|
+ */
|
|
|
+ public static class Request extends SingleShardRequest<Request> {
|
|
|
+
|
|
|
+ private String[] text;
|
|
|
+ private String analyzer;
|
|
|
+ private NameOrDefinition tokenizer;
|
|
|
+ private final List<NameOrDefinition> tokenFilters = new ArrayList<>();
|
|
|
+ private final List<NameOrDefinition> charFilters = new ArrayList<>();
|
|
|
+ private String field;
|
|
|
+ private boolean explain = false;
|
|
|
+ private String[] attributes = Strings.EMPTY_ARRAY;
|
|
|
+ private String normalizer;
|
|
|
+
|
|
|
+ public static class NameOrDefinition implements Writeable {
|
|
|
+ // exactly one of these two members is not null
|
|
|
+ public final String name;
|
|
|
+ public final Settings definition;
|
|
|
+
|
|
|
+ NameOrDefinition(String name) {
|
|
|
+ this.name = Objects.requireNonNull(name);
|
|
|
+ this.definition = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ NameOrDefinition(Map<String, ?> definition) {
|
|
|
+ this.name = null;
|
|
|
+ Objects.requireNonNull(definition);
|
|
|
+ try {
|
|
|
+ XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON);
|
|
|
+ builder.map(definition);
|
|
|
+ this.definition = Settings.builder().loadFromSource(Strings.toString(builder), builder.contentType()).build();
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new IllegalArgumentException("Failed to parse [" + definition + "]", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ NameOrDefinition(StreamInput in) throws IOException {
|
|
|
+ name = in.readOptionalString();
|
|
|
+ if (in.readBoolean()) {
|
|
|
+ definition = Settings.readSettingsFromStream(in);
|
|
|
+ } else {
|
|
|
+ definition = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ out.writeOptionalString(name);
|
|
|
+ boolean isNotNullDefinition = this.definition != null;
|
|
|
+ out.writeBoolean(isNotNullDefinition);
|
|
|
+ if (isNotNullDefinition) {
|
|
|
+ Settings.writeSettingsToStream(definition, out);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static NameOrDefinition fromXContent(XContentParser parser) throws IOException {
|
|
|
+ if (parser.currentToken() == XContentParser.Token.VALUE_STRING) {
|
|
|
+ return new NameOrDefinition(parser.text());
|
|
|
+ }
|
|
|
+ if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
|
|
|
+ return new NameOrDefinition(parser.map());
|
|
|
+ }
|
|
|
+ throw new XContentParseException(parser.getTokenLocation(),
|
|
|
+ "Expected [VALUE_STRING] or [START_OBJECT], got " + parser.currentToken());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request() {
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Constructs a new analyzer request for the provided index.
|
|
|
+ *
|
|
|
+ * @param index The text to analyze
|
|
|
+ */
|
|
|
+ public Request(String index) {
|
|
|
+ this.index(index);
|
|
|
+ }
|
|
|
+
|
|
|
+ public String[] text() {
|
|
|
+ return this.text;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request text(String... text) {
|
|
|
+ this.text = text;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request text(List<String> text) {
|
|
|
+ this.text = text.toArray(new String[]{});
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request analyzer(String analyzer) {
|
|
|
+ this.analyzer = analyzer;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String analyzer() {
|
|
|
+ return this.analyzer;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request tokenizer(String tokenizer) {
|
|
|
+ this.tokenizer = new NameOrDefinition(tokenizer);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request tokenizer(Map<String, ?> tokenizer) {
|
|
|
+ this.tokenizer = new NameOrDefinition(tokenizer);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void tokenizer(NameOrDefinition tokenizer) {
|
|
|
+ this.tokenizer = tokenizer;
|
|
|
+ }
|
|
|
+
|
|
|
+ public NameOrDefinition tokenizer() {
|
|
|
+ return this.tokenizer;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request addTokenFilter(String tokenFilter) {
|
|
|
+ this.tokenFilters.add(new NameOrDefinition(tokenFilter));
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request addTokenFilter(Map<String, ?> tokenFilter) {
|
|
|
+ this.tokenFilters.add(new NameOrDefinition(tokenFilter));
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setTokenFilters(List<NameOrDefinition> tokenFilters) {
|
|
|
+ this.tokenFilters.addAll(tokenFilters);
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<NameOrDefinition> tokenFilters() {
|
|
|
+ return this.tokenFilters;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request addCharFilter(Map<String, ?> charFilter) {
|
|
|
+ this.charFilters.add(new NameOrDefinition(charFilter));
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request addCharFilter(String charFilter) {
|
|
|
+ this.charFilters.add(new NameOrDefinition(charFilter));
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setCharFilters(List<NameOrDefinition> charFilters) {
|
|
|
+ this.charFilters.addAll(charFilters);
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<NameOrDefinition> charFilters() {
|
|
|
+ return this.charFilters;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request field(String field) {
|
|
|
+ this.field = field;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String field() {
|
|
|
+ return this.field;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request explain(boolean explain) {
|
|
|
+ this.explain = explain;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean explain() {
|
|
|
+ return this.explain;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request attributes(String... attributes) {
|
|
|
+ if (attributes == null) {
|
|
|
+ throw new IllegalArgumentException("attributes must not be null");
|
|
|
+ }
|
|
|
+ this.attributes = attributes;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void attributes(List<String> attributes) {
|
|
|
+ this.attributes = attributes.toArray(new String[]{});
|
|
|
+ }
|
|
|
+
|
|
|
+ public String[] attributes() {
|
|
|
+ return this.attributes;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String normalizer() {
|
|
|
+ return this.normalizer;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request normalizer(String normalizer) {
|
|
|
+ this.normalizer = normalizer;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ActionRequestValidationException validate() {
|
|
|
+ ActionRequestValidationException validationException = null;
|
|
|
+ if (text == null || text.length == 0) {
|
|
|
+ validationException = addValidationError("text is missing", validationException);
|
|
|
+ }
|
|
|
+ if ((index == null || index.length() == 0) && normalizer != null) {
|
|
|
+ validationException = addValidationError("index is required if normalizer is specified", validationException);
|
|
|
+ }
|
|
|
+ if (normalizer != null && (tokenizer != null || analyzer != null)) {
|
|
|
+ validationException
|
|
|
+ = addValidationError("tokenizer/analyze should be null if normalizer is specified", validationException);
|
|
|
+ }
|
|
|
+ return validationException;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void readFrom(StreamInput in) throws IOException {
|
|
|
+ super.readFrom(in);
|
|
|
+ text = in.readStringArray();
|
|
|
+ analyzer = in.readOptionalString();
|
|
|
+ tokenizer = in.readOptionalWriteable(NameOrDefinition::new);
|
|
|
+ tokenFilters.addAll(in.readList(NameOrDefinition::new));
|
|
|
+ charFilters.addAll(in.readList(NameOrDefinition::new));
|
|
|
+ field = in.readOptionalString();
|
|
|
+ explain = in.readBoolean();
|
|
|
+ attributes = in.readStringArray();
|
|
|
+ normalizer = in.readOptionalString();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ super.writeTo(out);
|
|
|
+ out.writeStringArray(text);
|
|
|
+ out.writeOptionalString(analyzer);
|
|
|
+ out.writeOptionalWriteable(tokenizer);
|
|
|
+ out.writeList(tokenFilters);
|
|
|
+ out.writeList(charFilters);
|
|
|
+ out.writeOptionalString(field);
|
|
|
+ out.writeBoolean(explain);
|
|
|
+ out.writeStringArray(attributes);
|
|
|
+ out.writeOptionalString(normalizer);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Request fromXContent(XContentParser parser, String index) throws IOException {
|
|
|
+ Request request = new Request(index);
|
|
|
+ PARSER.parse(parser, request, null);
|
|
|
+ return request;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final ObjectParser<Request, Void> PARSER = new ObjectParser<>("analyze_request", null);
|
|
|
+ static {
|
|
|
+ PARSER.declareStringArray(Request::text, new ParseField("text"));
|
|
|
+ PARSER.declareString(Request::analyzer, new ParseField("analyzer"));
|
|
|
+ PARSER.declareField(Request::tokenizer, (p, c) -> NameOrDefinition.fromXContent(p),
|
|
|
+ new ParseField("tokenizer"), ObjectParser.ValueType.OBJECT_OR_STRING);
|
|
|
+ PARSER.declareObjectArray(Request::setTokenFilters, (p, c) -> NameOrDefinition.fromXContent(p),
|
|
|
+ new ParseField("filter"));
|
|
|
+ PARSER.declareObjectArray(Request::setCharFilters, (p, c) -> NameOrDefinition.fromXContent(p),
|
|
|
+ new ParseField("char_filter"));
|
|
|
+ PARSER.declareString(Request::field, new ParseField("field"));
|
|
|
+ PARSER.declareBoolean(Request::explain, new ParseField("explain"));
|
|
|
+ PARSER.declareStringArray(Request::attributes, new ParseField("attributes"));
|
|
|
+ PARSER.declareString(Request::normalizer, new ParseField("normalizer"));
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class Response extends ActionResponse implements ToXContentObject {
|
|
|
+
|
|
|
+ private final DetailAnalyzeResponse detail;
|
|
|
+ private final List<AnalyzeToken> tokens;
|
|
|
+
|
|
|
+ public Response(List<AnalyzeToken> tokens, DetailAnalyzeResponse detail) {
|
|
|
+ this.tokens = tokens;
|
|
|
+ this.detail = detail;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Response(StreamInput in) throws IOException {
|
|
|
+ super.readFrom(in);
|
|
|
+ int size = in.readVInt();
|
|
|
+ if (size > 0) {
|
|
|
+ tokens = new ArrayList<>(size);
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ tokens.add(new AnalyzeToken(in));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ tokens = null;
|
|
|
+ }
|
|
|
+ detail = in.readOptionalWriteable(DetailAnalyzeResponse::new);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void readFrom(StreamInput in) throws IOException {
|
|
|
+ throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<AnalyzeToken> getTokens() {
|
|
|
+ return this.tokens;
|
|
|
+ }
|
|
|
+
|
|
|
+ public DetailAnalyzeResponse detail() {
|
|
|
+ return this.detail;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
|
+ builder.startObject();
|
|
|
+ if (tokens != null) {
|
|
|
+ builder.startArray(Fields.TOKENS);
|
|
|
+ for (AnalyzeToken token : tokens) {
|
|
|
+ token.toXContent(builder, params);
|
|
|
+ }
|
|
|
+ builder.endArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (detail != null) {
|
|
|
+ builder.startObject(Fields.DETAIL);
|
|
|
+ detail.toXContent(builder, params);
|
|
|
+ builder.endObject();
|
|
|
+ }
|
|
|
+ builder.endObject();
|
|
|
+ return builder;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ super.writeTo(out);
|
|
|
+ if (tokens != null) {
|
|
|
+ out.writeVInt(tokens.size());
|
|
|
+ for (AnalyzeToken token : tokens) {
|
|
|
+ token.writeTo(out);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ out.writeVInt(0);
|
|
|
+ }
|
|
|
+ out.writeOptionalWriteable(detail);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) return true;
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ Response that = (Response) o;
|
|
|
+ return Objects.equals(detail, that.detail) &&
|
|
|
+ Objects.equals(tokens, that.tokens);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return Objects.hash(detail, tokens);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String toString() {
|
|
|
+ return Strings.toString(this, true, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ static final class Fields {
|
|
|
+ static final String TOKENS = "tokens";
|
|
|
+
|
|
|
+ static final String DETAIL = "detail";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class AnalyzeToken implements Writeable, ToXContentObject {
|
|
|
+ private final String term;
|
|
|
+ private final int startOffset;
|
|
|
+ private final int endOffset;
|
|
|
+ private final int position;
|
|
|
+ private final int positionLength;
|
|
|
+ private final Map<String, Object> attributes;
|
|
|
+ private final String type;
|
|
|
+
|
|
|
+ static final String TOKEN = "token";
|
|
|
+ static final String START_OFFSET = "start_offset";
|
|
|
+ static final String END_OFFSET = "end_offset";
|
|
|
+ static final String TYPE = "type";
|
|
|
+ static final String POSITION = "position";
|
|
|
+ static final String POSITION_LENGTH = "positionLength";
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) return true;
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ AnalyzeToken that = (AnalyzeToken) o;
|
|
|
+ return startOffset == that.startOffset &&
|
|
|
+ endOffset == that.endOffset &&
|
|
|
+ position == that.position &&
|
|
|
+ positionLength == that.positionLength &&
|
|
|
+ Objects.equals(term, that.term) &&
|
|
|
+ Objects.equals(attributes, that.attributes) &&
|
|
|
+ Objects.equals(type, that.type);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return Objects.hash(term, startOffset, endOffset, position, positionLength, attributes, type);
|
|
|
+ }
|
|
|
+
|
|
|
+ public AnalyzeToken(String term, int position, int startOffset, int endOffset, int positionLength,
|
|
|
+ String type, Map<String, Object> attributes) {
|
|
|
+ this.term = term;
|
|
|
+ this.position = position;
|
|
|
+ this.startOffset = startOffset;
|
|
|
+ this.endOffset = endOffset;
|
|
|
+ this.positionLength = positionLength;
|
|
|
+ this.type = type;
|
|
|
+ this.attributes = attributes;
|
|
|
+ }
|
|
|
+
|
|
|
+ AnalyzeToken(StreamInput in) throws IOException {
|
|
|
+ term = in.readString();
|
|
|
+ startOffset = in.readInt();
|
|
|
+ endOffset = in.readInt();
|
|
|
+ position = in.readVInt();
|
|
|
+ Integer len = in.readOptionalVInt();
|
|
|
+ if (len != null) {
|
|
|
+ positionLength = len;
|
|
|
+ } else {
|
|
|
+ positionLength = 1;
|
|
|
+ }
|
|
|
+ type = in.readOptionalString();
|
|
|
+ attributes = in.readMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getTerm() {
|
|
|
+ return this.term;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getStartOffset() {
|
|
|
+ return this.startOffset;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getEndOffset() {
|
|
|
+ return this.endOffset;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getPosition() {
|
|
|
+ return this.position;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getPositionLength() {
|
|
|
+ return this.positionLength;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getType() {
|
|
|
+ return this.type;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Map<String, Object> getAttributes(){
|
|
|
+ return this.attributes;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
|
+ builder.startObject();
|
|
|
+ builder.field(TOKEN, term);
|
|
|
+ builder.field(START_OFFSET, startOffset);
|
|
|
+ builder.field(END_OFFSET, endOffset);
|
|
|
+ builder.field(TYPE, type);
|
|
|
+ builder.field(POSITION, position);
|
|
|
+ if (positionLength > 1) {
|
|
|
+ builder.field(POSITION_LENGTH, positionLength);
|
|
|
+ }
|
|
|
+ if (attributes != null && !attributes.isEmpty()) {
|
|
|
+ Map<String, Object> sortedAttributes = new TreeMap<>(attributes);
|
|
|
+ for (Map.Entry<String, Object> entity : sortedAttributes.entrySet()) {
|
|
|
+ builder.field(entity.getKey(), entity.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ builder.endObject();
|
|
|
+ return builder;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ out.writeString(term);
|
|
|
+ out.writeInt(startOffset);
|
|
|
+ out.writeInt(endOffset);
|
|
|
+ out.writeVInt(position);
|
|
|
+ out.writeOptionalVInt(positionLength > 1 ? positionLength : null);
|
|
|
+ out.writeOptionalString(type);
|
|
|
+ out.writeMapWithConsistentOrder(attributes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class DetailAnalyzeResponse implements Writeable, ToXContentFragment {
|
|
|
+
|
|
|
+ private final boolean customAnalyzer;
|
|
|
+ private final AnalyzeTokenList analyzer;
|
|
|
+ private final CharFilteredText[] charfilters;
|
|
|
+ private final AnalyzeTokenList tokenizer;
|
|
|
+ private final AnalyzeTokenList[] tokenfilters;
|
|
|
+
|
|
|
+ public DetailAnalyzeResponse(AnalyzeTokenList analyzer) {
|
|
|
+ this(false, analyzer, null, null, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ public DetailAnalyzeResponse(CharFilteredText[] charfilters, AnalyzeTokenList tokenizer, AnalyzeTokenList[] tokenfilters) {
|
|
|
+ this(true, null, charfilters, tokenizer, tokenfilters);
|
|
|
+ }
|
|
|
+
|
|
|
+ DetailAnalyzeResponse(boolean customAnalyzer,
|
|
|
+ AnalyzeTokenList analyzer,
|
|
|
+ CharFilteredText[] charfilters,
|
|
|
+ AnalyzeTokenList tokenizer,
|
|
|
+ AnalyzeTokenList[] tokenfilters) {
|
|
|
+ this.customAnalyzer = customAnalyzer;
|
|
|
+ this.analyzer = analyzer;
|
|
|
+ this.charfilters = charfilters;
|
|
|
+ this.tokenizer = tokenizer;
|
|
|
+ this.tokenfilters = tokenfilters;
|
|
|
+ }
|
|
|
+
|
|
|
+ DetailAnalyzeResponse(StreamInput in) throws IOException {
|
|
|
+ this.customAnalyzer = in.readBoolean();
|
|
|
+ if (customAnalyzer) {
|
|
|
+ tokenizer = new AnalyzeTokenList(in);
|
|
|
+ int size = in.readVInt();
|
|
|
+ if (size > 0) {
|
|
|
+ charfilters = new CharFilteredText[size];
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ charfilters[i] = new CharFilteredText(in);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ charfilters = null;
|
|
|
+ }
|
|
|
+ size = in.readVInt();
|
|
|
+ if (size > 0) {
|
|
|
+ tokenfilters = new AnalyzeTokenList[size];
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ tokenfilters[i] = new AnalyzeTokenList(in);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ tokenfilters = null;
|
|
|
+ }
|
|
|
+ analyzer = null;
|
|
|
+ } else {
|
|
|
+ analyzer = new AnalyzeTokenList(in);
|
|
|
+ tokenfilters = null;
|
|
|
+ tokenizer = null;
|
|
|
+ charfilters = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public AnalyzeTokenList analyzer() {
|
|
|
+ return this.analyzer;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CharFilteredText[] charfilters() {
|
|
|
+ return this.charfilters;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AnalyzeTokenList tokenizer() {
|
|
|
+ return tokenizer;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AnalyzeTokenList[] tokenfilters() {
|
|
|
+ return tokenfilters;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) return true;
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ DetailAnalyzeResponse that = (DetailAnalyzeResponse) o;
|
|
|
+ return customAnalyzer == that.customAnalyzer &&
|
|
|
+ Objects.equals(analyzer, that.analyzer) &&
|
|
|
+ Arrays.equals(charfilters, that.charfilters) &&
|
|
|
+ Objects.equals(tokenizer, that.tokenizer) &&
|
|
|
+ Arrays.equals(tokenfilters, that.tokenfilters);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ int result = Objects.hash(customAnalyzer, analyzer, tokenizer);
|
|
|
+ result = 31 * result + Arrays.hashCode(charfilters);
|
|
|
+ result = 31 * result + Arrays.hashCode(tokenfilters);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
|
+ builder.field("custom_analyzer", customAnalyzer);
|
|
|
+
|
|
|
+ if (analyzer != null) {
|
|
|
+ builder.startObject("analyzer");
|
|
|
+ analyzer.toXContentWithoutObject(builder, params);
|
|
|
+ builder.endObject();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (charfilters != null) {
|
|
|
+ builder.startArray("charfilters");
|
|
|
+ for (CharFilteredText charfilter : charfilters) {
|
|
|
+ charfilter.toXContent(builder, params);
|
|
|
+ }
|
|
|
+ builder.endArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tokenizer != null) {
|
|
|
+ builder.startObject("tokenizer");
|
|
|
+ tokenizer.toXContentWithoutObject(builder, params);
|
|
|
+ builder.endObject();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tokenfilters != null) {
|
|
|
+ builder.startArray("tokenfilters");
|
|
|
+ for (AnalyzeTokenList tokenfilter : tokenfilters) {
|
|
|
+ tokenfilter.toXContent(builder, params);
|
|
|
+ }
|
|
|
+ builder.endArray();
|
|
|
+ }
|
|
|
+ return builder;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ out.writeBoolean(customAnalyzer);
|
|
|
+ if (customAnalyzer) {
|
|
|
+ tokenizer.writeTo(out);
|
|
|
+ if (charfilters != null) {
|
|
|
+ out.writeVInt(charfilters.length);
|
|
|
+ for (CharFilteredText charfilter : charfilters) {
|
|
|
+ charfilter.writeTo(out);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ out.writeVInt(0);
|
|
|
+ }
|
|
|
+ if (tokenfilters != null) {
|
|
|
+ out.writeVInt(tokenfilters.length);
|
|
|
+ for (AnalyzeTokenList tokenfilter : tokenfilters) {
|
|
|
+ tokenfilter.writeTo(out);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ out.writeVInt(0);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ analyzer.writeTo(out);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class AnalyzeTokenList implements Writeable, ToXContentObject {
|
|
|
+ private final String name;
|
|
|
+ private final AnalyzeToken[] tokens;
|
|
|
+
|
|
|
+ static final String NAME = "name";
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) return true;
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ AnalyzeTokenList that = (AnalyzeTokenList) o;
|
|
|
+ return Objects.equals(name, that.name) &&
|
|
|
+ Arrays.equals(tokens, that.tokens);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ int result = Objects.hash(name);
|
|
|
+ result = 31 * result + Arrays.hashCode(tokens);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AnalyzeTokenList(String name, AnalyzeToken[] tokens) {
|
|
|
+ this.name = name;
|
|
|
+ this.tokens = tokens;
|
|
|
+ }
|
|
|
+
|
|
|
+ AnalyzeTokenList(StreamInput in) throws IOException {
|
|
|
+ name = in.readString();
|
|
|
+ int size = in.readVInt();
|
|
|
+ if (size > 0) {
|
|
|
+ tokens = new AnalyzeToken[size];
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ tokens[i] = new AnalyzeToken(in);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ tokens = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getName() {
|
|
|
+ return name;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AnalyzeToken[] getTokens() {
|
|
|
+ return tokens;
|
|
|
+ }
|
|
|
+
|
|
|
+ void toXContentWithoutObject(XContentBuilder builder, Params params) throws IOException {
|
|
|
+ builder.field(NAME, this.name);
|
|
|
+ builder.startArray(Response.Fields.TOKENS);
|
|
|
+ if (tokens != null) {
|
|
|
+ for (AnalyzeToken token : tokens) {
|
|
|
+ token.toXContent(builder, params);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ builder.endArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
|
+ builder.startObject();
|
|
|
+ toXContentWithoutObject(builder, params);
|
|
|
+ builder.endObject();
|
|
|
+ return builder;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ out.writeString(name);
|
|
|
+ if (tokens != null) {
|
|
|
+ out.writeVInt(tokens.length);
|
|
|
+ for (AnalyzeToken token : tokens) {
|
|
|
+ token.writeTo(out);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ out.writeVInt(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class CharFilteredText implements Writeable, ToXContentObject {
|
|
|
+ private final String name;
|
|
|
+ private final String[] texts;
|
|
|
+
|
|
|
+ static final String NAME = "name";
|
|
|
+ static final String FILTERED_TEXT = "filtered_text";
|
|
|
+
|
|
|
+ public CharFilteredText(String name, String[] texts) {
|
|
|
+ this.name = name;
|
|
|
+ if (texts != null) {
|
|
|
+ this.texts = texts;
|
|
|
+ } else {
|
|
|
+ this.texts = Strings.EMPTY_ARRAY;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ CharFilteredText(StreamInput in) throws IOException {
|
|
|
+ name = in.readString();
|
|
|
+ texts = in.readStringArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getName() {
|
|
|
+ return name;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String[] getTexts() {
|
|
|
+ return texts;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
|
+ builder.startObject();
|
|
|
+ builder.field(NAME, name);
|
|
|
+ builder.array(FILTERED_TEXT, texts);
|
|
|
+ builder.endObject();
|
|
|
+ return builder;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ out.writeString(name);
|
|
|
+ out.writeStringArray(texts);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) return true;
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ CharFilteredText that = (CharFilteredText) o;
|
|
|
+ return Objects.equals(name, that.name) &&
|
|
|
+ Arrays.equals(texts, that.texts);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ int result = Objects.hash(name);
|
|
|
+ result = 31 * result + Arrays.hashCode(texts);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|