Remove ParseFieldMatcher from AbstractXContentParser
Currently we are able to set a ParseFieldMatcher on XContentParsers, mainly to conveniently carry it around to be available where the actual parsing happens. This was just recently introduced together with ObjectParser so that ObjectParser can make use of deprecation logging and throwing errors while parsing. This however is trappy because we create parsers in so many places in the code and it is easy to forget setting the right ParseFieldMatcher. Instead we should hold the ParseFieldMatcher only in the parse contexts (e.g. QueryParseContext). This PR removes the ParseFieldMatcher from XContentParser. ObjectParser can still make use of it because we can make the otherwise unbounded `context` type to extend an interface that makes sure contexts used in ObjectParser can supply a ParseFieldMatcher. Contexts in ObjectParser are now no longer optional, but it is sufficient to pass in a small lambda expression in places where no other context is available. Relates to #17417
This commit is contained in:
parent
cf80b00507
commit
15c59d07b3
|
@ -24,14 +24,14 @@ import org.elasticsearch.action.ActionRequestValidationException;
|
|||
import org.elasticsearch.action.support.master.MasterNodeRequest;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.elasticsearch.action.ValidateActions.addValidationError;
|
||||
|
||||
|
@ -40,7 +40,8 @@ import static org.elasticsearch.action.ValidateActions.addValidationError;
|
|||
*/
|
||||
public class ClusterAllocationExplainRequest extends MasterNodeRequest<ClusterAllocationExplainRequest> {
|
||||
|
||||
private static ObjectParser<ClusterAllocationExplainRequest, Void> PARSER = new ObjectParser("cluster/allocation/explain");
|
||||
private static ObjectParser<ClusterAllocationExplainRequest, ParseFieldMatcherSupplier> PARSER = new ObjectParser(
|
||||
"cluster/allocation/explain");
|
||||
static {
|
||||
PARSER.declareString(ClusterAllocationExplainRequest::setIndex, new ParseField("index"));
|
||||
PARSER.declareInt(ClusterAllocationExplainRequest::setShard, new ParseField("shard"));
|
||||
|
@ -148,7 +149,7 @@ public class ClusterAllocationExplainRequest extends MasterNodeRequest<ClusterAl
|
|||
}
|
||||
|
||||
public static ClusterAllocationExplainRequest parse(XContentParser parser) throws IOException {
|
||||
ClusterAllocationExplainRequest req = PARSER.parse(parser, new ClusterAllocationExplainRequest());
|
||||
ClusterAllocationExplainRequest req = PARSER.parse(parser, new ClusterAllocationExplainRequest(), () -> ParseFieldMatcher.STRICT);
|
||||
Exception e = req.validate();
|
||||
if (e != null) {
|
||||
throw new ElasticsearchParseException("'index', 'shard', and 'primary' must be specified in allocation explain request", e);
|
||||
|
|
|
@ -25,17 +25,14 @@ import org.elasticsearch.action.support.master.AcknowledgedRequest;
|
|||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommandRegistry;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommands;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Request to submit cluster reroute allocation commands
|
||||
|
@ -105,7 +102,6 @@ public class ClusterRerouteRequest extends AcknowledgedRequest<ClusterRerouteReq
|
|||
public ClusterRerouteRequest source(BytesReference source, AllocationCommandRegistry registry, ParseFieldMatcher parseFieldMatcher)
|
||||
throws Exception {
|
||||
try (XContentParser parser = XContentHelper.createParser(source)) {
|
||||
parser.setParseFieldMatcher(parseFieldMatcher);
|
||||
XContentParser.Token token;
|
||||
String currentFieldName = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
|
@ -113,7 +109,7 @@ public class ClusterRerouteRequest extends AcknowledgedRequest<ClusterRerouteReq
|
|||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
if ("commands".equals(currentFieldName)) {
|
||||
this.commands = AllocationCommands.fromXContent(parser, registry);
|
||||
this.commands = AllocationCommands.fromXContent(parser, parseFieldMatcher, registry);
|
||||
} else {
|
||||
throw new ElasticsearchParseException("failed to parse reroute request, got start array with wrong field name [{}]", currentFieldName);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.elasticsearch.cluster.routing;
|
|||
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
@ -45,7 +47,8 @@ public class AllocationId implements ToXContent {
|
|||
private static final String ID_KEY = "id";
|
||||
private static final String RELOCATION_ID_KEY = "relocation_id";
|
||||
|
||||
private static final ObjectParser<AllocationId.Builder, Void> ALLOCATION_ID_PARSER = new ObjectParser<>("allocationId");
|
||||
private static final ObjectParser<AllocationId.Builder, ParseFieldMatcherSupplier> ALLOCATION_ID_PARSER = new ObjectParser<>(
|
||||
"allocationId");
|
||||
|
||||
static {
|
||||
ALLOCATION_ID_PARSER.declareString(AllocationId.Builder::setId, new ParseField(ID_KEY));
|
||||
|
@ -198,6 +201,6 @@ public class AllocationId implements ToXContent {
|
|||
}
|
||||
|
||||
public static AllocationId fromXContent(XContentParser parser) throws IOException {
|
||||
return ALLOCATION_ID_PARSER.parse(parser, new AllocationId.Builder()).build();
|
||||
return ALLOCATION_ID_PARSER.parse(parser, new AllocationId.Builder(), () -> ParseFieldMatcher.STRICT).build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
|||
import org.elasticsearch.cluster.routing.allocation.decider.Decision;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
|
@ -47,8 +48,8 @@ public abstract class AbstractAllocateAllocationCommand implements AllocationCom
|
|||
private static final String SHARD_FIELD = "shard";
|
||||
private static final String NODE_FIELD = "node";
|
||||
|
||||
protected static <T extends Builder<?>> ObjectParser<T, Void> createAllocateParser(String command) {
|
||||
ObjectParser<T, Void> parser = new ObjectParser<>(command);
|
||||
protected static <T extends Builder<?>> ObjectParser<T, ParseFieldMatcherSupplier> createAllocateParser(String command) {
|
||||
ObjectParser<T, ParseFieldMatcherSupplier> parser = new ObjectParser<>(command);
|
||||
parser.declareString(Builder::setIndex, new ParseField(INDEX_FIELD));
|
||||
parser.declareInt(Builder::setShard, new ParseField(SHARD_FIELD));
|
||||
parser.declareString(Builder::setNode, new ParseField(NODE_FIELD));
|
||||
|
|
|
@ -28,6 +28,8 @@ import org.elasticsearch.cluster.routing.allocation.RerouteExplanation;
|
|||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
||||
import org.elasticsearch.cluster.routing.allocation.decider.Decision;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -45,7 +47,8 @@ public class AllocateEmptyPrimaryAllocationCommand extends BasePrimaryAllocation
|
|||
public static final String NAME = "allocate_empty_primary";
|
||||
public static final ParseField COMMAND_NAME_FIELD = new ParseField(NAME);
|
||||
|
||||
private static final ObjectParser<Builder, Void> EMPTY_PRIMARY_PARSER = BasePrimaryAllocationCommand.createAllocatePrimaryParser(NAME);
|
||||
private static final ObjectParser<Builder, ParseFieldMatcherSupplier> EMPTY_PRIMARY_PARSER = BasePrimaryAllocationCommand
|
||||
.createAllocatePrimaryParser(NAME);
|
||||
|
||||
/**
|
||||
* Creates a new {@link AllocateEmptyPrimaryAllocationCommand}
|
||||
|
@ -78,7 +81,7 @@ public class AllocateEmptyPrimaryAllocationCommand extends BasePrimaryAllocation
|
|||
|
||||
@Override
|
||||
public Builder parse(XContentParser parser) throws IOException {
|
||||
return EMPTY_PRIMARY_PARSER.parse(parser, this);
|
||||
return EMPTY_PRIMARY_PARSER.parse(parser, this, () -> ParseFieldMatcher.STRICT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,6 +28,8 @@ import org.elasticsearch.cluster.routing.allocation.RerouteExplanation;
|
|||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
||||
import org.elasticsearch.cluster.routing.allocation.decider.Decision;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -44,7 +46,8 @@ public class AllocateReplicaAllocationCommand extends AbstractAllocateAllocation
|
|||
public static final String NAME = "allocate_replica";
|
||||
public static final ParseField COMMAND_NAME_FIELD = new ParseField(NAME);
|
||||
|
||||
private static final ObjectParser<AllocateReplicaAllocationCommand.Builder, Void> REPLICA_PARSER = createAllocateParser(NAME);
|
||||
private static final ObjectParser<AllocateReplicaAllocationCommand.Builder, ParseFieldMatcherSupplier> REPLICA_PARSER =
|
||||
createAllocateParser(NAME);
|
||||
|
||||
/**
|
||||
* Creates a new {@link AllocateReplicaAllocationCommand}
|
||||
|
@ -77,7 +80,7 @@ public class AllocateReplicaAllocationCommand extends AbstractAllocateAllocation
|
|||
|
||||
@Override
|
||||
public Builder parse(XContentParser parser) throws IOException {
|
||||
return REPLICA_PARSER.parse(parser, this);
|
||||
return REPLICA_PARSER.parse(parser, this, () -> ParseFieldMatcher.STRICT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,6 +28,8 @@ import org.elasticsearch.cluster.routing.allocation.RerouteExplanation;
|
|||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
||||
import org.elasticsearch.cluster.routing.allocation.decider.Decision;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -44,7 +46,8 @@ public class AllocateStalePrimaryAllocationCommand extends BasePrimaryAllocation
|
|||
public static final String NAME = "allocate_stale_primary";
|
||||
public static final ParseField COMMAND_NAME_FIELD = new ParseField(NAME);
|
||||
|
||||
private static final ObjectParser<Builder, Void> STALE_PRIMARY_PARSER = BasePrimaryAllocationCommand.createAllocatePrimaryParser(NAME);
|
||||
private static final ObjectParser<Builder, ParseFieldMatcherSupplier> STALE_PRIMARY_PARSER = BasePrimaryAllocationCommand
|
||||
.createAllocatePrimaryParser(NAME);
|
||||
|
||||
/**
|
||||
* Creates a new {@link AllocateStalePrimaryAllocationCommand}
|
||||
|
@ -78,7 +81,7 @@ public class AllocateStalePrimaryAllocationCommand extends BasePrimaryAllocation
|
|||
|
||||
@Override
|
||||
public Builder parse(XContentParser parser) throws IOException {
|
||||
return STALE_PRIMARY_PARSER.parse(parser, this);
|
||||
return STALE_PRIMARY_PARSER.parse(parser, this, () -> ParseFieldMatcher.STRICT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.elasticsearch.cluster.routing.allocation.command;
|
|||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
||||
import org.elasticsearch.cluster.routing.allocation.RoutingExplanations;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
|
@ -128,7 +129,8 @@ public class AllocationCommands {
|
|||
* @return {@link AllocationCommands} read
|
||||
* @throws IOException if something bad happens while reading the stream
|
||||
*/
|
||||
public static AllocationCommands fromXContent(XContentParser parser, AllocationCommandRegistry registry) throws IOException {
|
||||
public static AllocationCommands fromXContent(XContentParser parser, ParseFieldMatcher parseFieldMatcher,
|
||||
AllocationCommandRegistry registry) throws IOException {
|
||||
AllocationCommands commands = new AllocationCommands();
|
||||
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
|
@ -157,7 +159,7 @@ public class AllocationCommands {
|
|||
token = parser.nextToken();
|
||||
String commandName = parser.currentName();
|
||||
token = parser.nextToken();
|
||||
commands.add(registry.lookup(commandName, parser).fromXContent(parser));
|
||||
commands.add(registry.lookup(commandName, parser, parseFieldMatcher).fromXContent(parser));
|
||||
// move to the end object one
|
||||
if (parser.nextToken() != XContentParser.Token.END_OBJECT) {
|
||||
throw new ElasticsearchParseException("allocation command is malformed, done parsing a command, but didn't get END_OBJECT, got [{}] instead", token);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.elasticsearch.cluster.routing.allocation.command;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
|
@ -34,8 +35,8 @@ public abstract class BasePrimaryAllocationCommand extends AbstractAllocateAlloc
|
|||
|
||||
private static final String ACCEPT_DATA_LOSS_FIELD = "accept_data_loss";
|
||||
|
||||
protected static <T extends Builder<?>> ObjectParser<T, Void> createAllocatePrimaryParser(String command) {
|
||||
ObjectParser<T, Void> parser = AbstractAllocateAllocationCommand.createAllocateParser(command);
|
||||
protected static <T extends Builder<?>> ObjectParser<T, ParseFieldMatcherSupplier> createAllocatePrimaryParser(String command) {
|
||||
ObjectParser<T, ParseFieldMatcherSupplier> parser = AbstractAllocateAllocationCommand.createAllocateParser(command);
|
||||
parser.declareBoolean(Builder::setAcceptDataLoss, new ParseField(ACCEPT_DATA_LOSS_FIELD));
|
||||
return parser;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.common;
|
||||
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
|
||||
/**
|
||||
* This interface should be implemented by classes like {@link QueryParseContext} or {@link QueryShardContext} that
|
||||
* are able to carry a {@link ParseFieldMatcher}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ParseFieldMatcherSupplier {
|
||||
|
||||
/**
|
||||
* @return the parseFieldMatcher
|
||||
*/
|
||||
ParseFieldMatcher parseFieldMatcher();
|
||||
}
|
|
@ -20,6 +20,7 @@ package org.elasticsearch.common.xcontent;
|
|||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -51,7 +52,7 @@ import static org.elasticsearch.common.xcontent.XContentParser.Token.VALUE_STRIN
|
|||
* use the high level declare methods like {@link #declareString(BiConsumer, ParseField)} instead of {@link #declareField} which can be used
|
||||
* to implement exceptional parsing operations not covered by the high level methods.
|
||||
*/
|
||||
public final class ObjectParser<Value, Context> implements BiFunction<XContentParser, Context, Value> {
|
||||
public final class ObjectParser<Value, Context extends ParseFieldMatcherSupplier> implements BiFunction<XContentParser, Context, Value> {
|
||||
/**
|
||||
* Adapts an array (or varags) setter into a list setter.
|
||||
*/
|
||||
|
@ -87,32 +88,22 @@ public final class ObjectParser<Value, Context> implements BiFunction<XContentPa
|
|||
/**
|
||||
* Parses a Value from the given {@link XContentParser}
|
||||
* @param parser the parser to build a value from
|
||||
* @param context must at least provide a {@link ParseFieldMatcher}
|
||||
* @return a new value instance drawn from the provided value supplier on {@link #ObjectParser(String, Supplier)}
|
||||
* @throws IOException if an IOException occurs.
|
||||
*/
|
||||
public Value parse(XContentParser parser) throws IOException {
|
||||
public Value parse(XContentParser parser, Context context) throws IOException {
|
||||
if (valueSupplier == null) {
|
||||
throw new NullPointerException("valueSupplier is not set");
|
||||
}
|
||||
return parse(parser, valueSupplier.get(), null);
|
||||
return parse(parser, valueSupplier.get(), context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a Value from the given {@link XContentParser}
|
||||
* @param parser the parser to build a value from
|
||||
* @param value the value to fill from the parser
|
||||
* @return the parsed value
|
||||
* @throws IOException if an IOException occurs.
|
||||
*/
|
||||
public Value parse(XContentParser parser, Value value) throws IOException {
|
||||
return parse(parser, value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a Value from the given {@link XContentParser}
|
||||
* @param parser the parser to build a value from
|
||||
* @param value the value to fill from the parser
|
||||
* @param context an optional context that is passed along to all declared field parsers
|
||||
* @param context a context that is passed along to all declared field parsers
|
||||
* @return the parsed value
|
||||
* @throws IOException if an IOException occurs.
|
||||
*/
|
||||
|
@ -138,7 +129,7 @@ public final class ObjectParser<Value, Context> implements BiFunction<XContentPa
|
|||
throw new IllegalStateException("[" + name + "] no field found");
|
||||
}
|
||||
assert fieldParser != null;
|
||||
fieldParser.assertSupports(name, token, currentFieldName, parser.getParseFieldMatcher());
|
||||
fieldParser.assertSupports(name, token, currentFieldName, context.parseFieldMatcher());
|
||||
parseSub(parser, fieldParser, currentFieldName, value, context);
|
||||
fieldParser = null;
|
||||
}
|
||||
|
|
|
@ -68,13 +68,13 @@ public class ParseFieldRegistry<T> {
|
|||
* Lookup a value from the registry by name while checking that the name matches the ParseField.
|
||||
*
|
||||
* @param name The name of the thing to look up.
|
||||
* @param parser The parser from which the name was looked up. This is used to resolve the {@link ParseFieldMatcher} and to build nice
|
||||
* error messages.
|
||||
* @param parser The parser from which the name was looked up.
|
||||
* @param parseFieldMatcher to build nice error messages.
|
||||
* @return The value being looked up. Never null.
|
||||
* @throws ParsingException if the named thing isn't in the registry or the name was deprecated and deprecated names aren't supported.
|
||||
*/
|
||||
public T lookup(String name, XContentParser parser) {
|
||||
T value = lookupReturningNullIfNotFound(name, parser);
|
||||
public T lookup(String name, XContentParser parser, ParseFieldMatcher parseFieldMatcher) {
|
||||
T value = lookupReturningNullIfNotFound(name, parseFieldMatcher);
|
||||
if (value == null) {
|
||||
throw new ParsingException(parser.getTokenLocation(), "no [" + registryName + "] registered for [" + name + "]");
|
||||
}
|
||||
|
@ -85,19 +85,19 @@ public class ParseFieldRegistry<T> {
|
|||
* Lookup a value from the registry by name while checking that the name matches the ParseField.
|
||||
*
|
||||
* @param name The name of the thing to look up.
|
||||
* @param parser The parser from which the name was looked up. This is used to resolve the {@link ParseFieldMatcher} and to build nice
|
||||
* @param parseFieldMatcher The parseFieldMatcher. This is used to resolve the {@link ParseFieldMatcher} and to build nice
|
||||
* error messages.
|
||||
* @return The value being looked up or null if it wasn't found.
|
||||
* @throws ParsingException if the named thing isn't in the registry or the name was deprecated and deprecated names aren't supported.
|
||||
*/
|
||||
public T lookupReturningNullIfNotFound(String name, XContentParser parser) {
|
||||
public T lookupReturningNullIfNotFound(String name, ParseFieldMatcher parseFieldMatcher) {
|
||||
Tuple<ParseField, T> parseFieldAndValue = registry.get(name);
|
||||
if (parseFieldAndValue == null) {
|
||||
return null;
|
||||
}
|
||||
ParseField parseField = parseFieldAndValue.v1();
|
||||
T value = parseFieldAndValue.v2();
|
||||
boolean match = parser.getParseFieldMatcher().match(name, parseField);
|
||||
boolean match = parseFieldMatcher.match(name, parseField);
|
||||
//this is always expected to match, ParseField is useful for deprecation warnings etc. here
|
||||
assert match : "ParseField did not match registered name [" + name + "][" + registryName + "]";
|
||||
return value;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.elasticsearch.common.xcontent;
|
||||
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.lease.Releasable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -187,7 +186,7 @@ public interface XContentParser extends Releasable {
|
|||
float floatValue(boolean coerce) throws IOException;
|
||||
|
||||
double doubleValue(boolean coerce) throws IOException;
|
||||
|
||||
|
||||
short shortValue() throws IOException;
|
||||
|
||||
int intValue() throws IOException;
|
||||
|
@ -241,21 +240,10 @@ public interface XContentParser extends Releasable {
|
|||
/**
|
||||
* Used for error reporting to highlight where syntax errors occur in
|
||||
* content being parsed.
|
||||
*
|
||||
*
|
||||
* @return last token's location or null if cannot be determined
|
||||
*/
|
||||
XContentLocation getTokenLocation();
|
||||
|
||||
boolean isClosed();
|
||||
|
||||
/**
|
||||
* Returns this parsers {@link ParseFieldMatcher}
|
||||
*/
|
||||
ParseFieldMatcher getParseFieldMatcher();
|
||||
|
||||
|
||||
/**
|
||||
* Sets this parsers {@link ParseFieldMatcher}
|
||||
*/
|
||||
void setParseFieldMatcher(ParseFieldMatcher matcher) ;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ package org.elasticsearch.common.xcontent.support;
|
|||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Booleans;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -37,8 +36,6 @@ import java.util.Map;
|
|||
*/
|
||||
public abstract class AbstractXContentParser implements XContentParser {
|
||||
|
||||
private ParseFieldMatcher matcher = ParseFieldMatcher.STRICT;
|
||||
|
||||
// Currently this is not a setting that can be changed and is a policy
|
||||
// that relates to how parsing of things like "boost" are done across
|
||||
// the whole of Elasticsearch (eg if String "1.0" is a valid float).
|
||||
|
@ -337,12 +334,4 @@ public abstract class AbstractXContentParser implements XContentParser {
|
|||
|
||||
@Override
|
||||
public abstract boolean isClosed();
|
||||
|
||||
public ParseFieldMatcher getParseFieldMatcher() {
|
||||
return matcher;
|
||||
}
|
||||
|
||||
public void setParseFieldMatcher(ParseFieldMatcher matcher) {
|
||||
this.matcher = matcher;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,13 +21,14 @@ package org.elasticsearch.index.query;
|
|||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class QueryParseContext {
|
||||
public class QueryParseContext implements ParseFieldMatcherSupplier {
|
||||
|
||||
private static final ParseField CACHE = new ParseField("_cache").withAllDeprecated("Elasticsearch makes its own caching decisions");
|
||||
private static final ParseField CACHE_KEY = new ParseField("_cache_key").withAllDeprecated("Filters are always used as cache keys");
|
||||
|
@ -44,9 +45,6 @@ public class QueryParseContext {
|
|||
public void reset(XContentParser jp) {
|
||||
this.parseFieldMatcher = ParseFieldMatcher.EMPTY;
|
||||
this.parser = jp;
|
||||
if (parser != null) {
|
||||
this.parser.setParseFieldMatcher(parseFieldMatcher);
|
||||
}
|
||||
}
|
||||
|
||||
public XContentParser parser() {
|
||||
|
@ -57,9 +55,6 @@ public class QueryParseContext {
|
|||
if (parseFieldMatcher == null) {
|
||||
throw new IllegalArgumentException("parseFieldMatcher must not be null");
|
||||
}
|
||||
if (parser != null) {
|
||||
parser.setParseFieldMatcher(parseFieldMatcher);
|
||||
}
|
||||
this.parseFieldMatcher = parseFieldMatcher;
|
||||
}
|
||||
|
||||
|
@ -120,7 +115,7 @@ public class QueryParseContext {
|
|||
if (token != XContentParser.Token.START_OBJECT && token != XContentParser.Token.START_ARRAY) {
|
||||
throw new ParsingException(parser.getTokenLocation(), "[_na] query malformed, no field after start_object");
|
||||
}
|
||||
QueryBuilder<?> result = indicesQueriesRegistry.lookup(queryName, parser).fromXContent(this);
|
||||
QueryBuilder<?> result = indicesQueriesRegistry.lookup(queryName, parser, parseFieldMatcher).fromXContent(this);
|
||||
if (parser.currentToken() == XContentParser.Token.END_OBJECT || parser.currentToken() == XContentParser.Token.END_ARRAY) {
|
||||
// if we are at END_OBJECT, move to the next one...
|
||||
parser.nextToken();
|
||||
|
@ -128,6 +123,7 @@ public class QueryParseContext {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParseFieldMatcher parseFieldMatcher() {
|
||||
return parseFieldMatcher;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.apache.lucene.search.similarities.Similarity;
|
|||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
|
@ -49,7 +50,6 @@ import org.elasticsearch.index.mapper.core.TextFieldMapper;
|
|||
import org.elasticsearch.index.mapper.object.ObjectMapper;
|
||||
import org.elasticsearch.index.percolator.PercolatorQueryCache;
|
||||
import org.elasticsearch.index.query.support.InnerHitBuilder;
|
||||
import org.elasticsearch.index.query.support.InnerHitsBuilder;
|
||||
import org.elasticsearch.index.query.support.NestedScope;
|
||||
import org.elasticsearch.index.similarity.SimilarityService;
|
||||
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
||||
|
@ -69,7 +69,7 @@ import static java.util.Collections.unmodifiableMap;
|
|||
/**
|
||||
* Context object used to create lucene queries on the shard level.
|
||||
*/
|
||||
public class QueryShardContext extends QueryRewriteContext {
|
||||
public class QueryShardContext extends QueryRewriteContext implements ParseFieldMatcherSupplier {
|
||||
|
||||
private final MapperService mapperService;
|
||||
private final SimilarityService similarityService;
|
||||
|
@ -118,6 +118,7 @@ public class QueryShardContext extends QueryRewriteContext {
|
|||
this.parseContext.parseFieldMatcher(parseFieldMatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParseFieldMatcher parseFieldMatcher() {
|
||||
return parseContext.parseFieldMatcher();
|
||||
}
|
||||
|
|
|
@ -476,7 +476,8 @@ public class FunctionScoreQueryBuilder extends AbstractQueryBuilder<FunctionScor
|
|||
|
||||
// we try to parse a score function. If there is no score function for the current field name,
|
||||
// getScoreFunction will throw.
|
||||
ScoreFunctionBuilder<?> scoreFunction = scoreFunctionsRegistry.lookup(currentFieldName, parseContext.parser())
|
||||
ScoreFunctionBuilder<?> scoreFunction = scoreFunctionsRegistry
|
||||
.lookup(currentFieldName, parseContext.parser(), parseContext.parseFieldMatcher())
|
||||
.fromXContent(parseContext);
|
||||
filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(scoreFunction));
|
||||
}
|
||||
|
@ -581,7 +582,8 @@ public class FunctionScoreQueryBuilder extends AbstractQueryBuilder<FunctionScor
|
|||
"failed to parse function_score functions. already found [{}], now encountering [{}].",
|
||||
scoreFunction.getName(), currentFieldName);
|
||||
}
|
||||
scoreFunction = scoreFunctionsRegistry.lookup(currentFieldName, parser).fromXContent(parseContext);
|
||||
scoreFunction = scoreFunctionsRegistry.lookup(currentFieldName, parser, parseContext.parseFieldMatcher())
|
||||
.fromXContent(parseContext);
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if (parseContext.parseFieldMatcher().match(currentFieldName, WEIGHT_FIELD)) {
|
||||
|
|
|
@ -23,6 +23,8 @@ import org.elasticsearch.cluster.Diff;
|
|||
import org.elasticsearch.cluster.DiffableUtils;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
|
@ -45,7 +47,8 @@ public final class IngestMetadata implements MetaData.Custom {
|
|||
public final static String TYPE = "ingest";
|
||||
public final static IngestMetadata PROTO = new IngestMetadata();
|
||||
private static final ParseField PIPELINES_FIELD = new ParseField("pipeline");
|
||||
private static final ObjectParser<List<PipelineConfiguration>, Void> INGEST_METADATA_PARSER = new ObjectParser<>("ingest_metadata", ArrayList::new);
|
||||
private static final ObjectParser<List<PipelineConfiguration>, ParseFieldMatcherSupplier> INGEST_METADATA_PARSER = new ObjectParser<>(
|
||||
"ingest_metadata", ArrayList::new);
|
||||
|
||||
static {
|
||||
INGEST_METADATA_PARSER.declareObjectArray(List::addAll , PipelineConfiguration.getParser(), PIPELINES_FIELD);
|
||||
|
@ -94,7 +97,7 @@ public final class IngestMetadata implements MetaData.Custom {
|
|||
@Override
|
||||
public IngestMetadata fromXContent(XContentParser parser) throws IOException {
|
||||
Map<String, PipelineConfiguration> pipelines = new HashMap<>();
|
||||
List<PipelineConfiguration> configs = INGEST_METADATA_PARSER.parse(parser);
|
||||
List<PipelineConfiguration> configs = INGEST_METADATA_PARSER.parse(parser, () -> ParseFieldMatcher.STRICT);
|
||||
for (PipelineConfiguration pipeline : configs) {
|
||||
pipelines.put(pipeline.getId(), pipeline);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.elasticsearch.ingest;
|
|||
|
||||
import org.elasticsearch.cluster.AbstractDiffable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
@ -46,7 +47,7 @@ public final class PipelineConfiguration extends AbstractDiffable<PipelineConfig
|
|||
public static PipelineConfiguration readPipelineConfiguration(StreamInput in) throws IOException {
|
||||
return PROTOTYPE.readFrom(in);
|
||||
}
|
||||
private final static ObjectParser<Builder, Void> PARSER = new ObjectParser<>("pipeline_config", Builder::new);
|
||||
private final static ObjectParser<Builder, ParseFieldMatcherSupplier> PARSER = new ObjectParser<>("pipeline_config", Builder::new);
|
||||
static {
|
||||
PARSER.declareString(Builder::setId, new ParseField("id"));
|
||||
PARSER.declareField((parser, builder, aVoid) -> {
|
||||
|
@ -56,7 +57,7 @@ public final class PipelineConfiguration extends AbstractDiffable<PipelineConfig
|
|||
}, new ParseField("config"), ObjectParser.ValueType.OBJECT);
|
||||
}
|
||||
|
||||
public static BiFunction<XContentParser, Void,PipelineConfiguration> getParser() {
|
||||
public static BiFunction<XContentParser, ParseFieldMatcherSupplier, PipelineConfiguration> getParser() {
|
||||
return (p, c) -> PARSER.apply(p ,c).build();
|
||||
}
|
||||
private static class Builder {
|
||||
|
@ -110,6 +111,7 @@ public final class PipelineConfiguration extends AbstractDiffable<PipelineConfig
|
|||
return new PipelineConfiguration(in.readString(), in.readBytesReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(id);
|
||||
out.writeBytesReference(config);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.elasticsearch.search.aggregations;
|
||||
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.xcontent.ParseFieldRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -49,22 +50,22 @@ public class AggregatorParsers {
|
|||
* Returns the parser that is registered under the given aggregation type.
|
||||
*
|
||||
* @param type The aggregation type
|
||||
* @param parser the parser the type was read from. Used to lookup the ParseFieldMatcher and for making error messages.
|
||||
* @param parseFieldMatcher used for making error messages.
|
||||
* @return The parser associated with the given aggregation type or null if it wasn't found.
|
||||
*/
|
||||
public Aggregator.Parser parser(String type, XContentParser parser) {
|
||||
return aggregationParserRegistry.lookupReturningNullIfNotFound(type, parser);
|
||||
public Aggregator.Parser parser(String type, ParseFieldMatcher parseFieldMatcher) {
|
||||
return aggregationParserRegistry.lookupReturningNullIfNotFound(type, parseFieldMatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parser that is registered under the given pipeline aggregator type.
|
||||
*
|
||||
* @param type The pipeline aggregator type
|
||||
* @param parser the parser the type was read from. Used to lookup the ParseFieldMatcher and for making error messages.
|
||||
* @param parseFieldMatcher used for making error messages.
|
||||
* @return The parser associated with the given pipeline aggregator type or null if it wasn't found.
|
||||
*/
|
||||
public PipelineAggregator.Parser pipelineParser(String type, XContentParser parser) {
|
||||
return pipelineAggregationParserRegistry.lookupReturningNullIfNotFound(type, parser);
|
||||
public PipelineAggregator.Parser pipelineParser(String type, ParseFieldMatcher parseFieldMatcher) {
|
||||
return pipelineAggregationParserRegistry.lookupReturningNullIfNotFound(type, parseFieldMatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -142,9 +143,10 @@ public class AggregatorParsers {
|
|||
+ aggregationName + "]: [" + pipelineAggregatorFactory + "] and [" + fieldName + "]");
|
||||
}
|
||||
|
||||
Aggregator.Parser aggregatorParser = parser(fieldName, parser);
|
||||
Aggregator.Parser aggregatorParser = parser(fieldName, parseContext.parseFieldMatcher());
|
||||
if (aggregatorParser == null) {
|
||||
PipelineAggregator.Parser pipelineAggregatorParser = pipelineParser(fieldName, parser);
|
||||
PipelineAggregator.Parser pipelineAggregatorParser = pipelineParser(fieldName,
|
||||
parseContext.parseFieldMatcher());
|
||||
if (pipelineAggregatorParser == null) {
|
||||
throw new ParsingException(parser.getTokenLocation(),
|
||||
"Could not find aggregator type [" + fieldName + "] in [" + aggregationName + "]");
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.elasticsearch.search.suggest.completion;
|
|||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
@ -70,7 +72,7 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
|
|||
* "payload" : STRING_ARRAY
|
||||
* }
|
||||
*/
|
||||
private static ObjectParser<CompletionSuggestionBuilder.InnerBuilder, Void> TLP_PARSER =
|
||||
private static ObjectParser<CompletionSuggestionBuilder.InnerBuilder, ParseFieldMatcherSupplier> TLP_PARSER =
|
||||
new ObjectParser<>(SUGGESTION_NAME, null);
|
||||
static {
|
||||
TLP_PARSER.declareStringArray(CompletionSuggestionBuilder.InnerBuilder::payload, PAYLOAD_FIELD);
|
||||
|
@ -80,12 +82,12 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
|
|||
completionSuggestionContext.fuzzyOptions = new FuzzyOptions.Builder().build();
|
||||
}
|
||||
} else {
|
||||
completionSuggestionContext.fuzzyOptions = FuzzyOptions.parse(parser);
|
||||
completionSuggestionContext.fuzzyOptions = FuzzyOptions.parse(parser, context);
|
||||
}
|
||||
},
|
||||
FuzzyOptions.FUZZY_OPTIONS, ObjectParser.ValueType.OBJECT_OR_BOOLEAN);
|
||||
TLP_PARSER.declareField((parser, completionSuggestionContext, context) ->
|
||||
completionSuggestionContext.regexOptions = RegexOptions.parse(parser),
|
||||
completionSuggestionContext.regexOptions = RegexOptions.parse(parser, context),
|
||||
RegexOptions.REGEX_OPTIONS, ObjectParser.ValueType.OBJECT);
|
||||
TLP_PARSER.declareString(CompletionSuggestionBuilder.InnerBuilder::field, SuggestUtils.Fields.FIELD);
|
||||
TLP_PARSER.declareString(CompletionSuggestionBuilder.InnerBuilder::analyzer, SuggestUtils.Fields.ANALYZER);
|
||||
|
@ -263,7 +265,7 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
|
|||
|
||||
static CompletionSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
|
||||
CompletionSuggestionBuilder.InnerBuilder builder = new CompletionSuggestionBuilder.InnerBuilder();
|
||||
TLP_PARSER.parse(parseContext.parser(), builder);
|
||||
TLP_PARSER.parse(parseContext.parser(), builder, () -> ParseFieldMatcher.STRICT);
|
||||
String field = builder.field;
|
||||
// now we should have field name, check and copy fields over to the suggestion builder we return
|
||||
if (field == null) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.lucene.search.suggest.document.FuzzyCompletionQuery;
|
|||
import org.apache.lucene.util.automaton.Operations;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
|
@ -56,7 +57,8 @@ public class FuzzyOptions implements ToXContent, Writeable<FuzzyOptions> {
|
|||
* "max_determinized_states" : INT
|
||||
* }
|
||||
*/
|
||||
private static ObjectParser<Builder, Void> PARSER = new ObjectParser<>(FUZZY_OPTIONS.getPreferredName(), Builder::new);
|
||||
private static ObjectParser<Builder, ParseFieldMatcherSupplier> PARSER = new ObjectParser<>(FUZZY_OPTIONS.getPreferredName(),
|
||||
Builder::new);
|
||||
static {
|
||||
PARSER.declareInt(Builder::setFuzzyMinLength, MIN_LENGTH_FIELD);
|
||||
PARSER.declareInt(Builder::setMaxDeterminizedStates, MAX_DETERMINIZED_STATES_FIELD);
|
||||
|
@ -111,8 +113,8 @@ public class FuzzyOptions implements ToXContent, Writeable<FuzzyOptions> {
|
|||
out.writeVInt(maxDeterminizedStates);
|
||||
}
|
||||
|
||||
static FuzzyOptions parse(XContentParser parser) throws IOException {
|
||||
return PARSER.parse(parser).build();
|
||||
static FuzzyOptions parse(XContentParser parser, ParseFieldMatcherSupplier context) throws IOException {
|
||||
return PARSER.parse(parser, context).build();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.lucene.util.automaton.Operations;
|
|||
import org.apache.lucene.util.automaton.RegExp;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
|
@ -48,7 +49,8 @@ public class RegexOptions implements ToXContent, Writeable<RegexOptions> {
|
|||
* "max_determinized_states" : INT
|
||||
* }
|
||||
*/
|
||||
private static ObjectParser<Builder, Void> PARSER = new ObjectParser<>(REGEX_OPTIONS.getPreferredName(), Builder::new);
|
||||
private static ObjectParser<Builder, ParseFieldMatcherSupplier> PARSER = new ObjectParser<>(REGEX_OPTIONS.getPreferredName(),
|
||||
Builder::new);
|
||||
static {
|
||||
PARSER.declareInt(Builder::setMaxDeterminizedStates, MAX_DETERMINIZED_STATES);
|
||||
PARSER.declareField((parser, builder, aVoid) -> {
|
||||
|
@ -105,8 +107,8 @@ public class RegexOptions implements ToXContent, Writeable<RegexOptions> {
|
|||
return new Builder();
|
||||
}
|
||||
|
||||
static RegexOptions parse(XContentParser parser) throws IOException {
|
||||
return PARSER.parse(parser).build();
|
||||
static RegexOptions parse(XContentParser parser, ParseFieldMatcherSupplier context) throws IOException {
|
||||
return PARSER.parse(parser, context).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.elasticsearch.search.suggest.completion.context;
|
|||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
@ -95,7 +97,7 @@ public final class CategoryQueryContext implements ToXContent {
|
|||
return result;
|
||||
}
|
||||
|
||||
private static ObjectParser<Builder, Void> CATEGORY_PARSER = new ObjectParser<>(NAME, null);
|
||||
private static ObjectParser<Builder, ParseFieldMatcherSupplier> CATEGORY_PARSER = new ObjectParser<>(NAME, null);
|
||||
static {
|
||||
CATEGORY_PARSER.declareString(Builder::setCategory, new ParseField(CONTEXT_VALUE));
|
||||
CATEGORY_PARSER.declareInt(Builder::setBoost, new ParseField(CONTEXT_BOOST));
|
||||
|
@ -106,7 +108,7 @@ public final class CategoryQueryContext implements ToXContent {
|
|||
XContentParser.Token token = parser.currentToken();
|
||||
Builder builder = builder();
|
||||
if (token == XContentParser.Token.START_OBJECT) {
|
||||
CATEGORY_PARSER.parse(parser, builder);
|
||||
CATEGORY_PARSER.parse(parser, builder, () -> ParseFieldMatcher.STRICT);
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
builder.setCategory(parser.text());
|
||||
} else {
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.elasticsearch.search.suggest.completion.context;
|
|||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.geo.GeoUtils;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
|
@ -111,7 +113,7 @@ public final class GeoQueryContext implements ToXContent {
|
|||
return new Builder();
|
||||
}
|
||||
|
||||
private static ObjectParser<GeoQueryContext.Builder, Void> GEO_CONTEXT_PARSER = new ObjectParser<>(NAME, null);
|
||||
private static ObjectParser<GeoQueryContext.Builder, ParseFieldMatcherSupplier> GEO_CONTEXT_PARSER = new ObjectParser<>(NAME, null);
|
||||
static {
|
||||
GEO_CONTEXT_PARSER.declareField((parser, geoQueryContext, geoContextMapping) -> geoQueryContext.setGeoPoint(GeoUtils.parseGeoPoint(parser)), new ParseField(CONTEXT_VALUE), ObjectParser.ValueType.OBJECT);
|
||||
GEO_CONTEXT_PARSER.declareInt(GeoQueryContext.Builder::setBoost, new ParseField(CONTEXT_BOOST));
|
||||
|
@ -127,7 +129,7 @@ public final class GeoQueryContext implements ToXContent {
|
|||
XContentParser.Token token = parser.currentToken();
|
||||
GeoQueryContext.Builder builder = new Builder();
|
||||
if (token == XContentParser.Token.START_OBJECT) {
|
||||
GEO_CONTEXT_PARSER.parse(parser, builder);
|
||||
GEO_CONTEXT_PARSER.parse(parser, builder, () -> ParseFieldMatcher.STRICT);
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
builder.setGeoPoint(GeoPoint.fromGeohash(parser.text()));
|
||||
} else {
|
||||
|
|
|
@ -375,13 +375,15 @@ public final class DirectCandidateGeneratorBuilder
|
|||
DirectCandidateGeneratorBuilder tempGenerator = new DirectCandidateGeneratorBuilder("_na_");
|
||||
// bucket for the field name, needed as constructor arg later
|
||||
Set<String> tmpFieldName = new HashSet<>(1);
|
||||
PARSER.parse(parseContext.parser(), new Tuple<Set<String>, DirectCandidateGeneratorBuilder>(tmpFieldName, tempGenerator));
|
||||
PARSER.parse(parseContext.parser(), new Tuple<Set<String>, DirectCandidateGeneratorBuilder>(tmpFieldName, tempGenerator),
|
||||
parseContext);
|
||||
if (tmpFieldName.size() != 1) {
|
||||
throw new IllegalArgumentException("[" + TYPE + "] expects exactly one field parameter, but found " + tmpFieldName);
|
||||
}
|
||||
return replaceField(tmpFieldName.iterator().next(), tempGenerator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhraseSuggestionContext.DirectCandidateGenerator build(MapperService mapperService) throws IOException {
|
||||
PhraseSuggestionContext.DirectCandidateGenerator generator = new PhraseSuggestionContext.DirectCandidateGenerator();
|
||||
generator.setField(this.field);
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.elasticsearch.cluster.routing.allocation.command.AllocationCommands;
|
|||
import org.elasticsearch.cluster.routing.allocation.command.CancelAllocationCommand;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.MoveAllocationCommand;
|
||||
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
|
@ -452,7 +453,7 @@ public class AllocationCommandsTests extends ESAllocationTestCase {
|
|||
parser.nextToken();
|
||||
AllocationCommandRegistry registry = new NetworkModule(null, Settings.EMPTY, true, new NamedWriteableRegistry())
|
||||
.getAllocationCommandRegistry();
|
||||
AllocationCommands sCommands = AllocationCommands.fromXContent(parser, registry);
|
||||
AllocationCommands sCommands = AllocationCommands.fromXContent(parser, ParseFieldMatcher.STRICT, registry);
|
||||
|
||||
assertThat(sCommands.commands().size(), equalTo(5));
|
||||
assertThat(((AllocateEmptyPrimaryAllocationCommand) (sCommands.commands().get(0))).shardId(), equalTo(1));
|
||||
|
|
|
@ -18,22 +18,25 @@
|
|||
*/
|
||||
package org.elasticsearch.common.xcontent;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser.NamedObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser.NamedObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
public class ObjectParserTests extends ESTestCase {
|
||||
|
||||
private final static ParseFieldMatcherSupplier STRICT_PARSING = () -> ParseFieldMatcher.STRICT;
|
||||
|
||||
public void testBasics() throws IOException {
|
||||
XContentParser parser = XContentType.JSON.xContent().createParser(
|
||||
"{\n"
|
||||
|
@ -53,14 +56,13 @@ public class ObjectParserTests extends ESTestCase {
|
|||
this.ints = ints;
|
||||
}
|
||||
}
|
||||
ObjectParser<TestStruct, Void> objectParser = new ObjectParser<>("foo");
|
||||
ObjectParser<TestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo");
|
||||
TestStruct s = new TestStruct();
|
||||
|
||||
objectParser.declareField((i, c, x) -> c.test = i.text(), new ParseField("test"), ObjectParser.ValueType.STRING);
|
||||
objectParser.declareInt(TestStruct::setTestNumber, new ParseField("test_number"));
|
||||
objectParser.declareIntArray(TestStruct::setInts, new ParseField("test_array"));
|
||||
parser.setParseFieldMatcher(ParseFieldMatcher.STRICT);
|
||||
objectParser.parse(parser, s);
|
||||
objectParser.parse(parser, s, STRICT_PARSING);
|
||||
assertEquals(s.test, "foo");
|
||||
assertEquals(s.testNumber, 2);
|
||||
assertEquals(s.ints, Arrays.asList(1, 2, 3, 4));
|
||||
|
@ -74,17 +76,17 @@ public class ObjectParserTests extends ESTestCase {
|
|||
|
||||
public void testObjectOrDefault() throws IOException {
|
||||
XContentParser parser = XContentType.JSON.xContent().createParser("{\"object\" : { \"test\": 2}}");
|
||||
ObjectParser<StaticTestStruct, Void> objectParser = new ObjectParser<>("foo", StaticTestStruct::new);
|
||||
ObjectParser<StaticTestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo", StaticTestStruct::new);
|
||||
objectParser.declareInt(StaticTestStruct::setTest, new ParseField("test"));
|
||||
objectParser.declareObjectOrDefault(StaticTestStruct::setObject, objectParser, StaticTestStruct::new, new ParseField("object"));
|
||||
StaticTestStruct s = objectParser.parse(parser);
|
||||
StaticTestStruct s = objectParser.parse(parser, STRICT_PARSING);
|
||||
assertEquals(s.object.test, 2);
|
||||
parser = XContentType.JSON.xContent().createParser("{\"object\" : false }");
|
||||
s = objectParser.parse(parser);
|
||||
s = objectParser.parse(parser, STRICT_PARSING);
|
||||
assertNull(s.object);
|
||||
|
||||
parser = XContentType.JSON.xContent().createParser("{\"object\" : true }");
|
||||
s = objectParser.parse(parser);
|
||||
s = objectParser.parse(parser, STRICT_PARSING);
|
||||
assertNotNull(s.object);
|
||||
assertEquals(s.object.test, 0);
|
||||
|
||||
|
@ -96,12 +98,12 @@ public class ObjectParserTests extends ESTestCase {
|
|||
public void setTest(int test) {
|
||||
}
|
||||
}
|
||||
ObjectParser<TestStruct, TestStruct> objectParser = new ObjectParser<>("the_parser");
|
||||
ObjectParser<TestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("the_parser");
|
||||
TestStruct s = new TestStruct();
|
||||
objectParser.declareInt(TestStruct::setTest, new ParseField("test"));
|
||||
|
||||
try {
|
||||
objectParser.parse(parser, s);
|
||||
objectParser.parse(parser, s, STRICT_PARSING);
|
||||
fail("numeric value expected");
|
||||
} catch (ParsingException ex) {
|
||||
assertEquals(ex.getMessage(), "[the_parser] failed to parse field [test]");
|
||||
|
@ -110,7 +112,7 @@ public class ObjectParserTests extends ESTestCase {
|
|||
|
||||
parser = XContentType.JSON.xContent().createParser("{\"not_supported_field\" : \"foo\"}");
|
||||
try {
|
||||
objectParser.parse(parser, s);
|
||||
objectParser.parse(parser, s, STRICT_PARSING);
|
||||
fail("field not supported");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
assertEquals(ex.getMessage(), "[the_parser] unknown field [not_supported_field], parser not found");
|
||||
|
@ -122,14 +124,13 @@ public class ObjectParserTests extends ESTestCase {
|
|||
class TestStruct {
|
||||
public String test;
|
||||
}
|
||||
ObjectParser<TestStruct, Void> objectParser = new ObjectParser<>("foo");
|
||||
ObjectParser<TestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo");
|
||||
TestStruct s = new TestStruct();
|
||||
|
||||
objectParser.declareField((i, v, c) -> v.test = i.text(), new ParseField("test", "old_test"), ObjectParser.ValueType.STRING);
|
||||
parser.setParseFieldMatcher(ParseFieldMatcher.STRICT);
|
||||
|
||||
try {
|
||||
objectParser.parse(parser, s);
|
||||
objectParser.parse(parser, s, STRICT_PARSING);
|
||||
fail("deprecated value");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
assertEquals(ex.getMessage(), "Deprecated field [old_test] used, expected [test] instead");
|
||||
|
@ -137,8 +138,7 @@ public class ObjectParserTests extends ESTestCase {
|
|||
}
|
||||
assertNull(s.test);
|
||||
parser = XContentType.JSON.xContent().createParser("{\"old_test\" : \"foo\"}");
|
||||
parser.setParseFieldMatcher(ParseFieldMatcher.EMPTY);
|
||||
objectParser.parse(parser, s);
|
||||
objectParser.parse(parser, s, () -> ParseFieldMatcher.EMPTY);
|
||||
assertEquals("foo", s.test);
|
||||
}
|
||||
|
||||
|
@ -147,13 +147,12 @@ public class ObjectParserTests extends ESTestCase {
|
|||
class TestStruct {
|
||||
public String test;
|
||||
}
|
||||
ObjectParser<TestStruct, Void> objectParser = new ObjectParser<>("foo");
|
||||
ObjectParser<TestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo");
|
||||
TestStruct s = new TestStruct();
|
||||
|
||||
objectParser.declareField((i, c, x) -> c.test = i.text(), new ParseField("numeric_value"), ObjectParser.ValueType.FLOAT);
|
||||
parser.setParseFieldMatcher(ParseFieldMatcher.STRICT);
|
||||
try {
|
||||
objectParser.parse(parser, s);
|
||||
objectParser.parse(parser, s, STRICT_PARSING);
|
||||
fail("wrong type - must be number");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
assertEquals(ex.getMessage(), "[foo] numeric_value doesn't support values of type: VALUE_BOOLEAN");
|
||||
|
@ -166,39 +165,40 @@ public class ObjectParserTests extends ESTestCase {
|
|||
public int test;
|
||||
TestStruct object;
|
||||
}
|
||||
ObjectParser<TestStruct, Void> objectParser = new ObjectParser<>("foo");
|
||||
ObjectParser<TestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo");
|
||||
TestStruct s = new TestStruct();
|
||||
s.object = new TestStruct();
|
||||
objectParser.declareField((i, c, x) -> c.test = i.intValue(), new ParseField("test"), ValueType.INT);
|
||||
objectParser.declareField((i, c, x) -> objectParser.parse(parser, c.object), new ParseField("object"), ValueType.OBJECT);
|
||||
objectParser.parse(parser, s);
|
||||
objectParser.declareField((i, c, x) -> objectParser.parse(parser, c.object, STRICT_PARSING), new ParseField("object"),
|
||||
ValueType.OBJECT);
|
||||
objectParser.parse(parser, s, STRICT_PARSING);
|
||||
assertEquals(s.test, 1);
|
||||
assertEquals(s.object.test, 2);
|
||||
}
|
||||
|
||||
public void testParseNestedShortcut() throws IOException {
|
||||
XContentParser parser = XContentType.JSON.xContent().createParser("{ \"test\" : 1, \"object\" : { \"test\": 2}}");
|
||||
ObjectParser<StaticTestStruct, Void> objectParser = new ObjectParser<>("foo", StaticTestStruct::new);
|
||||
ObjectParser<StaticTestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo", StaticTestStruct::new);
|
||||
objectParser.declareInt(StaticTestStruct::setTest, new ParseField("test"));
|
||||
objectParser.declareObject(StaticTestStruct::setObject, objectParser, new ParseField("object"));
|
||||
StaticTestStruct s = objectParser.parse(parser);
|
||||
StaticTestStruct s = objectParser.parse(parser, STRICT_PARSING);
|
||||
assertEquals(s.test, 1);
|
||||
assertEquals(s.object.test, 2);
|
||||
}
|
||||
|
||||
public void testEmptyObject() throws IOException {
|
||||
XContentParser parser = XContentType.JSON.xContent().createParser("{\"object\" : {}}");
|
||||
ObjectParser<StaticTestStruct, Void> objectParser = new ObjectParser<>("foo", StaticTestStruct::new);
|
||||
ObjectParser<StaticTestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo", StaticTestStruct::new);
|
||||
objectParser.declareObject(StaticTestStruct::setObject, objectParser, new ParseField("object"));
|
||||
StaticTestStruct s = objectParser.parse(parser);
|
||||
StaticTestStruct s = objectParser.parse(parser, STRICT_PARSING);
|
||||
assertNotNull(s.object);
|
||||
}
|
||||
|
||||
public void testEmptyObjectInArray() throws IOException {
|
||||
XContentParser parser = XContentType.JSON.xContent().createParser("{\"object_array\" : [{}]}");
|
||||
ObjectParser<StaticTestStruct, Void> objectParser = new ObjectParser<>("foo", StaticTestStruct::new);
|
||||
ObjectParser<StaticTestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo", StaticTestStruct::new);
|
||||
objectParser.declareObjectArray(StaticTestStruct::setObjectArray, objectParser, new ParseField("object_array"));
|
||||
StaticTestStruct s = objectParser.parse(parser);
|
||||
StaticTestStruct s = objectParser.parse(parser, STRICT_PARSING);
|
||||
assertNotNull(s.objectArray);
|
||||
}
|
||||
|
||||
|
@ -233,9 +233,9 @@ public class ObjectParserTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
XContentParser parser = XContentType.JSON.xContent().createParser("{ \"test\" : \"FOO\" }");
|
||||
ObjectParser<TestStruct, Void> objectParser = new ObjectParser<>("foo");
|
||||
ObjectParser<TestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo");
|
||||
objectParser.declareString((struct, value) -> struct.set(TestEnum.valueOf(value)), new ParseField("test"));
|
||||
TestStruct s = objectParser.parse(parser, new TestStruct());
|
||||
TestStruct s = objectParser.parse(parser, new TestStruct(), STRICT_PARSING);
|
||||
assertEquals(s.test, TestEnum.FOO);
|
||||
}
|
||||
|
||||
|
@ -329,7 +329,7 @@ public class ObjectParserTests extends ESTestCase {
|
|||
this.string_or_null = string_or_null;
|
||||
}
|
||||
}
|
||||
ObjectParser<TestStruct, Void> objectParser = new ObjectParser<>("foo");
|
||||
ObjectParser<TestStruct, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("foo");
|
||||
objectParser.declareInt(TestStruct::setInt_field, new ParseField("int_field"));
|
||||
objectParser.declareIntArray(TestStruct::setInt_array_field, new ParseField("int_array_field"));
|
||||
objectParser.declareLong(TestStruct::setLong_field, new ParseField("long_field"));
|
||||
|
@ -343,7 +343,7 @@ public class ObjectParserTests extends ESTestCase {
|
|||
|
||||
objectParser.declareStringOrNull(TestStruct::setString_or_null, new ParseField("string_or_null"));
|
||||
objectParser.declareBoolean(TestStruct::setNull_value, new ParseField("boolean_field"));
|
||||
TestStruct parse = objectParser.parse(parser, new TestStruct());
|
||||
TestStruct parse = objectParser.parse(parser, new TestStruct(), STRICT_PARSING);
|
||||
assertArrayEquals(parse.double_array_field.toArray(), Arrays.asList(2.1d).toArray());
|
||||
assertEquals(parse.double_field, 2.1d, 0.0d);
|
||||
|
||||
|
@ -372,7 +372,7 @@ public class ObjectParserTests extends ESTestCase {
|
|||
"{\"named\": {\n"
|
||||
+ " \"a\": {}"
|
||||
+ "}}");
|
||||
NamedObjectHolder h = NamedObjectHolder.PARSER.apply(parser, null);
|
||||
NamedObjectHolder h = NamedObjectHolder.PARSER.apply(parser, STRICT_PARSING);
|
||||
assertThat(h.named, hasSize(1));
|
||||
assertEquals("a", h.named.get(0).name);
|
||||
assertFalse(h.namedSuppliedInOrder);
|
||||
|
@ -383,7 +383,7 @@ public class ObjectParserTests extends ESTestCase {
|
|||
"{\"named\": [\n"
|
||||
+ " {\"a\": {}}"
|
||||
+ "]}");
|
||||
NamedObjectHolder h = NamedObjectHolder.PARSER.apply(parser, null);
|
||||
NamedObjectHolder h = NamedObjectHolder.PARSER.apply(parser, STRICT_PARSING);
|
||||
assertThat(h.named, hasSize(1));
|
||||
assertEquals("a", h.named.get(0).name);
|
||||
assertTrue(h.namedSuppliedInOrder);
|
||||
|
@ -394,7 +394,7 @@ public class ObjectParserTests extends ESTestCase {
|
|||
"{\"named\": [\n"
|
||||
+ " {\"a\": {}, \"b\": {}}"
|
||||
+ "]}");
|
||||
ParsingException e = expectThrows(ParsingException.class, () -> NamedObjectHolder.PARSER.apply(parser, null));
|
||||
ParsingException e = expectThrows(ParsingException.class, () -> NamedObjectHolder.PARSER.apply(parser, STRICT_PARSING));
|
||||
assertEquals("[named_object_holder] failed to parse field [named]", e.getMessage());
|
||||
assertEquals(
|
||||
"[named] can be a single object with any number of fields or an array where each entry is an object with a single field",
|
||||
|
@ -406,7 +406,7 @@ public class ObjectParserTests extends ESTestCase {
|
|||
"{\"named\": [\n"
|
||||
+ " {}"
|
||||
+ "]}");
|
||||
ParsingException e = expectThrows(ParsingException.class, () -> NamedObjectHolder.PARSER.apply(parser, null));
|
||||
ParsingException e = expectThrows(ParsingException.class, () -> NamedObjectHolder.PARSER.apply(parser, STRICT_PARSING));
|
||||
assertEquals("[named_object_holder] failed to parse field [named]", e.getMessage());
|
||||
assertEquals(
|
||||
"[named] can be a single object with any number of fields or an array where each entry is an object with a single field",
|
||||
|
@ -418,7 +418,7 @@ public class ObjectParserTests extends ESTestCase {
|
|||
"{\"named\": [\n"
|
||||
+ " \"junk\""
|
||||
+ "]}");
|
||||
ParsingException e = expectThrows(ParsingException.class, () -> NamedObjectHolder.PARSER.apply(parser, null));
|
||||
ParsingException e = expectThrows(ParsingException.class, () -> NamedObjectHolder.PARSER.apply(parser, STRICT_PARSING));
|
||||
assertEquals("[named_object_holder] failed to parse field [named]", e.getMessage());
|
||||
assertEquals(
|
||||
"[named] can be a single object with any number of fields or an array where each entry is an object with a single field",
|
||||
|
@ -432,17 +432,18 @@ public class ObjectParserTests extends ESTestCase {
|
|||
+ "]}");
|
||||
|
||||
// Create our own parser for this test so we can disable support for the "ordered" mode specified by the array above
|
||||
ObjectParser<NamedObjectHolder, Void> objectParser = new ObjectParser<>("named_object_holder", NamedObjectHolder::new);
|
||||
ObjectParser<NamedObjectHolder, ParseFieldMatcherSupplier> objectParser = new ObjectParser<>("named_object_holder",
|
||||
NamedObjectHolder::new);
|
||||
objectParser.declareNamedObjects(NamedObjectHolder::setNamed, NamedObject.PARSER, new ParseField("named"));
|
||||
|
||||
// Now firing the xml through it fails
|
||||
ParsingException e = expectThrows(ParsingException.class, () -> objectParser.apply(parser, null));
|
||||
ParsingException e = expectThrows(ParsingException.class, () -> objectParser.apply(parser, STRICT_PARSING));
|
||||
assertEquals("[named_object_holder] failed to parse field [named]", e.getMessage());
|
||||
assertEquals("[named] doesn't support arrays. Use a single object with multiple fields.", e.getCause().getMessage());
|
||||
}
|
||||
|
||||
static class NamedObjectHolder {
|
||||
public static final ObjectParser<NamedObjectHolder, Void> PARSER = new ObjectParser<>("named_object_holder",
|
||||
public static final ObjectParser<NamedObjectHolder, ParseFieldMatcherSupplier> PARSER = new ObjectParser<>("named_object_holder",
|
||||
NamedObjectHolder::new);
|
||||
static {
|
||||
PARSER.declareNamedObjects(NamedObjectHolder::setNamed, NamedObject.PARSER, NamedObjectHolder::keepNamedInOrder,
|
||||
|
@ -462,11 +463,11 @@ public class ObjectParserTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public static class NamedObject {
|
||||
public static final NamedObjectParser<NamedObject, Void> PARSER;
|
||||
public static final NamedObjectParser<NamedObject, ParseFieldMatcherSupplier> PARSER;
|
||||
static {
|
||||
ObjectParser<NamedObject, Void> parser = new ObjectParser<>("named");
|
||||
ObjectParser<NamedObject, ParseFieldMatcherSupplier> parser = new ObjectParser<>("named");
|
||||
parser.declareInt(NamedObject::setFoo, new ParseField("foo"));
|
||||
PARSER = (XContentParser p, Void v, String name) -> parser.parse(p, new NamedObject(name));
|
||||
PARSER = (XContentParser p, ParseFieldMatcherSupplier v, String name) -> parser.parse(p, new NamedObject(name), STRICT_PARSING);
|
||||
}
|
||||
|
||||
final String name;
|
||||
|
|
|
@ -98,19 +98,17 @@ public class SearchModuleTests extends ModuleTestCase {
|
|||
|
||||
IndicesQueriesRegistry indicesQueriesRegistry = module.getQueryParserRegistry();
|
||||
XContentParser dummyParser = XContentHelper.createParser(new BytesArray("{}"));
|
||||
dummyParser.setParseFieldMatcher(ParseFieldMatcher.EMPTY);
|
||||
for (String queryName : supportedQueries) {
|
||||
indicesQueriesRegistry.lookup(queryName, dummyParser);
|
||||
indicesQueriesRegistry.lookup(queryName, dummyParser, ParseFieldMatcher.EMPTY);
|
||||
}
|
||||
|
||||
dummyParser.setParseFieldMatcher(ParseFieldMatcher.STRICT);
|
||||
for (String queryName : NON_DEPRECATED_QUERIES) {
|
||||
QueryParser<?> queryParser = indicesQueriesRegistry.lookup(queryName, dummyParser);
|
||||
QueryParser<?> queryParser = indicesQueriesRegistry.lookup(queryName, dummyParser, ParseFieldMatcher.STRICT);
|
||||
assertThat(queryParser, notNullValue());
|
||||
}
|
||||
for (String queryName : DEPRECATED_QUERIES) {
|
||||
try {
|
||||
indicesQueriesRegistry.lookup(queryName, dummyParser);
|
||||
indicesQueriesRegistry.lookup(queryName, dummyParser, ParseFieldMatcher.STRICT);
|
||||
fail("query is deprecated, getQueryParser should have failed in strict mode");
|
||||
} catch(IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("Deprecated field [" + queryName + "] used"));
|
||||
|
|
|
@ -235,7 +235,7 @@ public abstract class BaseAggregationTestCase<AB extends AggregatorBuilder<AB>>
|
|||
assertSame(XContentParser.Token.FIELD_NAME, parser.nextToken());
|
||||
assertEquals(testAgg.type.name(), parser.currentName());
|
||||
assertSame(XContentParser.Token.START_OBJECT, parser.nextToken());
|
||||
AggregatorBuilder newAgg = aggParsers.parser(testAgg.getType(), parser).parse(testAgg.name, parseContext);
|
||||
AggregatorBuilder<?> newAgg = aggParsers.parser(testAgg.getType(), ParseFieldMatcher.STRICT).parse(testAgg.name, parseContext);
|
||||
assertSame(XContentParser.Token.END_OBJECT, parser.currentToken());
|
||||
assertSame(XContentParser.Token.END_OBJECT, parser.nextToken());
|
||||
assertSame(XContentParser.Token.END_OBJECT, parser.nextToken());
|
||||
|
|
|
@ -237,7 +237,7 @@ public abstract class BasePipelineAggregationTestCase<AF extends PipelineAggrega
|
|||
assertSame(XContentParser.Token.FIELD_NAME, parser.nextToken());
|
||||
assertEquals(testAgg.type(), parser.currentName());
|
||||
assertSame(XContentParser.Token.START_OBJECT, parser.nextToken());
|
||||
PipelineAggregatorBuilder<?> newAgg = aggParsers.pipelineParser(testAgg.getWriteableName(), parser)
|
||||
PipelineAggregatorBuilder<?> newAgg = aggParsers.pipelineParser(testAgg.getWriteableName(), ParseFieldMatcher.STRICT)
|
||||
.parse(testAgg.name(), parseContext);
|
||||
assertSame(XContentParser.Token.END_OBJECT, parser.currentToken());
|
||||
assertSame(XContentParser.Token.END_OBJECT, parser.nextToken());
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.search.aggregations.pipeline.moving.avg;
|
||||
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
|
@ -116,8 +117,8 @@ public class MovAvgTests extends BasePipelineAggregationTestCase<MovAvgPipelineA
|
|||
assertSame(XContentParser.Token.FIELD_NAME, parser.nextToken());
|
||||
assertEquals(expected.type(), parser.currentName());
|
||||
assertSame(XContentParser.Token.START_OBJECT, parser.nextToken());
|
||||
PipelineAggregatorBuilder<?> newAgg = aggParsers.pipelineParser(expected.getWriteableName(), parser).parse(expected.name(),
|
||||
parseContext);
|
||||
PipelineAggregatorBuilder<?> newAgg = aggParsers.pipelineParser(expected.getWriteableName(), ParseFieldMatcher.STRICT)
|
||||
.parse(expected.name(), parseContext);
|
||||
assertSame(XContentParser.Token.END_OBJECT, parser.currentToken());
|
||||
assertSame(XContentParser.Token.END_OBJECT, parser.nextToken());
|
||||
assertSame(XContentParser.Token.END_OBJECT, parser.nextToken());
|
||||
|
|
|
@ -47,7 +47,7 @@ public class SortParserTests extends ESSingleNodeTestCase {
|
|||
sortBuilder.endArray();
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.field("mode", "max");
|
||||
sortBuilder.endObject();
|
||||
parse(context, sortBuilder);
|
||||
|
||||
|
@ -58,7 +58,7 @@ public class SortParserTests extends ESSingleNodeTestCase {
|
|||
sortBuilder.endArray();
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.field("mode", "max");
|
||||
sortBuilder.endObject();
|
||||
parse(context, sortBuilder);
|
||||
|
||||
|
@ -69,7 +69,7 @@ public class SortParserTests extends ESSingleNodeTestCase {
|
|||
sortBuilder.endArray();
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.field("mode", "max");
|
||||
sortBuilder.endObject();
|
||||
parse(context, sortBuilder);
|
||||
|
||||
|
@ -80,7 +80,7 @@ public class SortParserTests extends ESSingleNodeTestCase {
|
|||
sortBuilder.endArray();
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.field("mode", "max");
|
||||
sortBuilder.endObject();
|
||||
parse(context, sortBuilder);
|
||||
|
||||
|
@ -91,7 +91,7 @@ public class SortParserTests extends ESSingleNodeTestCase {
|
|||
sortBuilder.endArray();
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.field("mode", "max");
|
||||
sortBuilder.endObject();
|
||||
parse(context, sortBuilder);
|
||||
|
||||
|
@ -100,7 +100,7 @@ public class SortParserTests extends ESSingleNodeTestCase {
|
|||
sortBuilder.field("location", new GeoPoint(1, 2));
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.field("mode", "max");
|
||||
sortBuilder.endObject();
|
||||
parse(context, sortBuilder);
|
||||
|
||||
|
@ -109,7 +109,7 @@ public class SortParserTests extends ESSingleNodeTestCase {
|
|||
sortBuilder.field("location", "1,2");
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.field("mode", "max");
|
||||
sortBuilder.endObject();
|
||||
parse(context, sortBuilder);
|
||||
|
||||
|
@ -118,7 +118,7 @@ public class SortParserTests extends ESSingleNodeTestCase {
|
|||
sortBuilder.field("location", "s3y0zh7w1z0g");
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.field("mode", "max");
|
||||
sortBuilder.endObject();
|
||||
parse(context, sortBuilder);
|
||||
|
||||
|
@ -129,16 +129,36 @@ public class SortParserTests extends ESSingleNodeTestCase {
|
|||
sortBuilder.endArray();
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.field("mode", "max");
|
||||
sortBuilder.endObject();
|
||||
parse(context, sortBuilder);
|
||||
}
|
||||
|
||||
public void testGeoDistanceSortDeprecatedSortModeException() throws Exception {
|
||||
XContentBuilder mapping = jsonBuilder();
|
||||
mapping.startObject().startObject("type").startObject("properties").startObject("location").field("type", "geo_point").endObject().endObject().endObject().endObject();
|
||||
IndexService indexService = createIndex("testidx", Settings.builder().build(), "type", mapping);
|
||||
TestSearchContext context = (TestSearchContext) createSearchContext(indexService);
|
||||
context.getQueryShardContext().setTypes("type");
|
||||
|
||||
XContentBuilder sortBuilder = jsonBuilder();
|
||||
sortBuilder.startObject();
|
||||
sortBuilder.startArray("location");
|
||||
sortBuilder.startArray().value(1.2).value(3).endArray().startArray().value(5).value(6).endArray();
|
||||
sortBuilder.endArray();
|
||||
sortBuilder.field("order", "desc");
|
||||
sortBuilder.field("unit", "km");
|
||||
sortBuilder.field("sort_mode", "max");
|
||||
sortBuilder.endObject();
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> parse(context, sortBuilder));
|
||||
assertEquals("Deprecated field [sort_mode] used, expected [mode] instead", ex.getMessage());
|
||||
}
|
||||
|
||||
protected void parse(TestSearchContext context, XContentBuilder sortBuilder) throws Exception {
|
||||
QueryParseContext parseContext = context.getQueryShardContext().parseContext();
|
||||
XContentParser parser = XContentHelper.createParser(sortBuilder.bytes());
|
||||
parser.setParseFieldMatcher(ParseFieldMatcher.STRICT);
|
||||
parseContext.reset(parser);
|
||||
parseContext.parseFieldMatcher(ParseFieldMatcher.STRICT);
|
||||
parser.nextToken();
|
||||
GeoDistanceSortBuilder.fromXContent(parseContext, null);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ import org.elasticsearch.action.search.SearchRequest;
|
|||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
@ -80,7 +82,7 @@ public class RestReindexAction extends AbstractBaseReindexRestHandler<ReindexReq
|
|||
search.source().parseXContent(context.queryParseContext, context.aggParsers, context.suggesters);
|
||||
};
|
||||
|
||||
ObjectParser<IndexRequest, Void> destParser = new ObjectParser<>("dest");
|
||||
ObjectParser<IndexRequest, ParseFieldMatcherSupplier> destParser = new ObjectParser<>("dest");
|
||||
destParser.declareString(IndexRequest::index, new ParseField("index"));
|
||||
destParser.declareString(IndexRequest::type, new ParseField("type"));
|
||||
destParser.declareString(IndexRequest::routing, new ParseField("routing"));
|
||||
|
@ -94,7 +96,7 @@ public class RestReindexAction extends AbstractBaseReindexRestHandler<ReindexReq
|
|||
new ParseField("ttl"));
|
||||
|
||||
PARSER.declareField((p, v, c) -> sourceParser.parse(p, v.getSearchRequest(), c), new ParseField("source"), ValueType.OBJECT);
|
||||
PARSER.declareField((p, v, c) -> destParser.parse(p, v.getDestination(), null), new ParseField("dest"), ValueType.OBJECT);
|
||||
PARSER.declareField((p, v, c) -> destParser.parse(p, v.getDestination(), c), new ParseField("dest"), ValueType.OBJECT);
|
||||
PARSER.declareInt(ReindexRequest::setSize, new ParseField("size"));
|
||||
PARSER.declareField((p, v, c) -> v.setScript(Script.parse(p, c.queryParseContext.parseFieldMatcher())), new ParseField("script"),
|
||||
ValueType.OBJECT);
|
||||
|
@ -169,7 +171,7 @@ public class RestReindexAction extends AbstractBaseReindexRestHandler<ReindexReq
|
|||
}
|
||||
}
|
||||
|
||||
private class ReindexParseContext {
|
||||
private class ReindexParseContext implements ParseFieldMatcherSupplier{
|
||||
private final QueryParseContext queryParseContext;
|
||||
private final AggregatorParsers aggParsers;
|
||||
private final Suggesters suggesters;
|
||||
|
@ -180,5 +182,10 @@ public class RestReindexAction extends AbstractBaseReindexRestHandler<ReindexReq
|
|||
this.aggParsers = aggParsers;
|
||||
this.suggesters = suggesters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParseFieldMatcher getParseFieldMatcher() {
|
||||
return queryParseContext.parseFieldMatcher();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue