From 448fb03dd184d84999cf1324590c20bcdd0d3f15 Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Thu, 27 Feb 2020 14:56:57 +0000 Subject: [PATCH 1/2] Allow specifying an exclusive set of fields on ObjectParser --- .../common/xcontent/AbstractObjectParser.java | 18 +++ .../xcontent/ConstructingObjectParser.java | 10 ++ .../common/xcontent/ObjectParser.java | 28 +++- .../ConstructingObjectParserTests.java | 41 +++++ .../common/xcontent/ObjectParserTests.java | 63 +++++--- .../percolator/PercolateQueryBuilder.java | 153 ++++++------------ .../PercolateQueryBuilderTests.java | 6 +- 7 files changed, 192 insertions(+), 127 deletions(-) diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java index b041e6aa8a725..0da89089651ca 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java @@ -38,6 +38,7 @@ public abstract class AbstractObjectParser implements BiFunction, ContextParser { final List requiredFieldSets = new ArrayList<>(); + final List exclusiveFieldSets = new ArrayList<>(); /** * Declare some field. Usually it is easier to use {@link #declareString(BiConsumer, ParseField)} or @@ -294,6 +295,23 @@ public void declareRequiredFieldSet(String... requiredSet) { this.requiredFieldSets.add(requiredSet); } + /** + * Declares a set of fields of which at most one must appear for parsing to succeed + * + * E.g. declareExclusiveFieldSet("foo", "bar"); means that only one of 'foo' + * or 'bar' must be present, and if both appear then an exception will be thrown. + * + * Multiple exclusive sets may be declared + * + * @param exclusiveSet a set of field names, at most one of which must appear + */ + public void declareExclusiveFieldSet(String... exclusiveSet) { + if (exclusiveSet.length == 0) { + return; + } + this.exclusiveFieldSets.add(exclusiveSet); + } + private interface IOSupplier { T get() throws IOException; } diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ConstructingObjectParser.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ConstructingObjectParser.java index 70d867fe5079f..099701e688136 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ConstructingObjectParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ConstructingObjectParser.java @@ -299,6 +299,16 @@ public String getName() { return objectParser.getName(); } + @Override + public void declareRequiredFieldSet(String... requiredSet) { + objectParser.declareRequiredFieldSet(requiredSet); + } + + @Override + public void declareExclusiveFieldSet(String... exclusiveSet) { + objectParser.declareExclusiveFieldSet(exclusiveSet); + } + private Consumer wrapOrderedModeCallBack(Consumer callback) { return (target) -> { if (target.targetObject != null) { diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java index f173223eed79c..8e122f141405d 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java @@ -274,6 +274,10 @@ public Value parse(XContentParser parser, Value value, Context context) throws I String currentFieldName = null; XContentLocation currentPosition = null; List requiredFields = new ArrayList<>(this.requiredFieldSets); + List> exclusiveFields = new ArrayList<>(); + for (int i = 0; i < this.exclusiveFieldSets.size(); i++) { + exclusiveFields.add(new ArrayList<>()); + } while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { @@ -302,18 +306,40 @@ public Value parse(XContentParser parser, Value value, Context context) throws I } } + // Check if this field is in an exclusive set, if it is then mark + // it as seen. If the set is already marked, then we have a duplicate + // so throw an exception + for (int i = 0; i < this.exclusiveFieldSets.size(); i++) { + for (String field : this.exclusiveFieldSets.get(i)) { + if (field.equals(currentFieldName)) { + exclusiveFields.get(i).add(currentFieldName); + } + } + } + parseSub(parser, fieldParser, currentFieldName, value, context); } fieldParser = null; } } + + StringBuilder message = new StringBuilder(); + for (List fieldset : exclusiveFields) { + if (fieldset.size() > 1) { + message.append("The following fields are not allowed together: ").append(fieldset.toString()).append(" "); + } + } + if (message.length() > 0) { + throw new IllegalArgumentException(message.toString()); + } + if (requiredFields.isEmpty() == false) { - StringBuilder message = new StringBuilder(); for (String[] fields : requiredFields) { message.append("Required one of fields ").append(Arrays.toString(fields)).append(", but none were specified. "); } throw new IllegalArgumentException(message.toString()); } + return value; } diff --git a/libs/x-content/src/test/java/org/elasticsearch/common/xcontent/ConstructingObjectParserTests.java b/libs/x-content/src/test/java/org/elasticsearch/common/xcontent/ConstructingObjectParserTests.java index 9020e962e12da..928d27d6f51be 100644 --- a/libs/x-content/src/test/java/org/elasticsearch/common/xcontent/ConstructingObjectParserTests.java +++ b/libs/x-content/src/test/java/org/elasticsearch/common/xcontent/ConstructingObjectParserTests.java @@ -528,4 +528,45 @@ public void keepNamedInOrder() { namedSuppliedInOrder = true; } } + + public void testRequiredAndExclusiveFields() throws IOException { + + class TestStruct { + final String a; + final long b; + TestStruct(String a) { + this.a = a; + this.b = 0; + } + TestStruct(long b) { + this.a = null; + this.b = b; + } + } + + XContentParser ok = createParser(JsonXContent.jsonXContent, "{ \"a\" : \"a\" }"); + XContentParser toomany = createParser(JsonXContent.jsonXContent, "{ \"a\" : \"a\", \"b\" : 1 }"); + XContentParser notenough = createParser(JsonXContent.jsonXContent, "{ }"); + + ConstructingObjectParser parser = new ConstructingObjectParser<>("teststruct", args -> { + if (args[0] != null) { + return new TestStruct((String) args[0]); + } + return new TestStruct((Long) args[1]); + }); + parser.declareString(optionalConstructorArg(), new ParseField("a")); + parser.declareLong(optionalConstructorArg(), new ParseField("b")); + parser.declareExclusiveFieldSet("a", "b"); + parser.declareRequiredFieldSet("a", "b"); + + TestStruct actual = parser.parse(ok, null); + assertThat(actual.a, equalTo("a")); + assertThat(actual.b, equalTo(0L)); + + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> parser.parse(toomany, null)); + assertThat(e.getMessage(), containsString("allowed together: [a, b]")); + + e = expectThrows(IllegalArgumentException.class, () -> parser.parse(notenough, null)); + assertThat(e.getMessage(), containsString("Required one of fields [a, b], but none were specified.")); + } } diff --git a/libs/x-content/src/test/java/org/elasticsearch/common/xcontent/ObjectParserTests.java b/libs/x-content/src/test/java/org/elasticsearch/common/xcontent/ObjectParserTests.java index 290604a863d84..3e8d5dee8614f 100644 --- a/libs/x-content/src/test/java/org/elasticsearch/common/xcontent/ObjectParserTests.java +++ b/libs/x-content/src/test/java/org/elasticsearch/common/xcontent/ObjectParserTests.java @@ -850,29 +850,30 @@ private void setB(long value) { assertThat(obj.b, equalTo(456L)); } - public void testMultipleRequiredFieldSet() throws IOException { - class TestStruct { - private Long a; - private Long b; - private Long c; - private Long d; + private static class TestStruct { + private Long a; + private Long b; + private Long c; + private Long d; - private void setA(long value) { - this.a = value; - } + private void setA(long value) { + this.a = value; + } - private void setB(long value) { - this.b = value; - } + private void setB(long value) { + this.b = value; + } - private void setC(long value) { - this.c = value; - } + private void setC(long value) { + this.c = value; + } - private void setD(long value) { - this.d = value; - } + private void setD(long value) { + this.d = value; } + } + + public void testMultipleRequiredFieldSet() throws IOException { XContentParser parser = createParser(JsonXContent.jsonXContent, "{\"unrelated\": \"123\"}"); ObjectParser objectParser = new ObjectParser<>("foo", true, TestStruct::new); @@ -888,6 +889,32 @@ private void setD(long value) { "Required one of fields [c, d], but none were specified. ")); } + public void testExclusiveFieldSet() throws IOException { + + XContentParser goodA = createParser(JsonXContent.jsonXContent, "{\"a\" : 1, \"c\" : 4}"); + XContentParser bad = createParser(JsonXContent.jsonXContent, "{\"a\" : 1, \"b\" : 2}"); + XContentParser badmulti = createParser(JsonXContent.jsonXContent, "{\"a\" : 1, \"b\" : 2, \"c\" : 3, \"d\" : 4 }"); + + ObjectParser parser = new ObjectParser<>("foo", TestStruct::new); + parser.declareLong(TestStruct::setA, new ParseField("a")); + parser.declareLong(TestStruct::setB, new ParseField("b")); + parser.declareLong(TestStruct::setC, new ParseField("c")); + parser.declareLong(TestStruct::setD, new ParseField("d")); + parser.declareExclusiveFieldSet("a", "b"); + parser.declareExclusiveFieldSet("c", "d"); + + TestStruct actualA = parser.parse(goodA, null); + assertThat(actualA.a, equalTo(1L)); + assertThat(actualA.c, equalTo(4L)); + + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> parser.parse(bad, null)); + assertThat(e.getMessage(), containsString("The following fields are not allowed together: [a, b]")); + + e = expectThrows(IllegalArgumentException.class, () -> parser.parse(badmulti, null)); + assertThat(e.getMessage(), + containsString("allowed together: [a, b] The following fields are not allowed together: [c, d]")); + } + @Override protected NamedXContentRegistry xContentRegistry() { return new NamedXContentRegistry(Arrays.asList( diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java index bc0e04ed42bcb..9380fa39d8b4d 100644 --- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java +++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java @@ -48,13 +48,13 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.InputStreamStreamInput; import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -90,6 +90,8 @@ import java.util.Objects; import java.util.function.Supplier; +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; import static org.elasticsearch.search.SearchService.ALLOW_EXPENSIVE_QUERIES; public class PercolateQueryBuilder extends AbstractQueryBuilder { @@ -316,113 +318,52 @@ protected void doXContent(XContentBuilder builder, Params params) throws IOExcep builder.endObject(); } - public static PercolateQueryBuilder fromXContent(XContentParser parser) throws IOException { - float boost = AbstractQueryBuilder.DEFAULT_BOOST; - - String field = null; - String name = null; - - String indexedDocumentIndex = null; - String indexedDocumentId = null; - String indexedDocumentRouting = null; - String indexedDocumentPreference = null; - Long indexedDocumentVersion = null; - - List documents = new ArrayList<>(); - - String queryName = null; - String currentFieldName = null; - - boolean documentsSpecified = false; - boolean documentSpecified = false; - - XContentParser.Token token; - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { - if (token == XContentParser.Token.FIELD_NAME) { - currentFieldName = parser.currentName(); - } else if (token == XContentParser.Token.START_ARRAY) { - if (DOCUMENTS_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { - if (documentSpecified) { - throw new IllegalArgumentException("[" + PercolateQueryBuilder.NAME + - "] Either specified [document] or [documents], not both"); - } - documentsSpecified = true; - while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { - if (token == XContentParser.Token.START_OBJECT) { - try (XContentBuilder builder = XContentFactory.jsonBuilder()) { - builder.copyCurrentStructure(parser); - builder.flush(); - documents.add(BytesReference.bytes(builder)); - } - } else { - throw new ParsingException(parser.getTokenLocation(), "[" + PercolateQueryBuilder.NAME + - "] query does not support [" + token + "]"); - } - } - } else { - throw new ParsingException(parser.getTokenLocation(), "[" + PercolateQueryBuilder.NAME + - "] query does not field name [" + currentFieldName + "]"); - } - } else if (token == XContentParser.Token.START_OBJECT) { - if (DOCUMENT_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { - if (documentsSpecified) { - throw new IllegalArgumentException("[" + PercolateQueryBuilder.NAME + - "] Either specified [document] or [documents], not both"); - } - documentSpecified = true; - try (XContentBuilder builder = XContentFactory.jsonBuilder()) { - builder.copyCurrentStructure(parser); - builder.flush(); - documents.add(BytesReference.bytes(builder)); - } - } else { - throw new ParsingException(parser.getTokenLocation(), "[" + PercolateQueryBuilder.NAME + - "] query does not support field name [" + currentFieldName + "]"); - } - } else if (token.isValue() || token == XContentParser.Token.VALUE_NULL) { - if (QUERY_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { - field = parser.text(); - } else if (NAME_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { - name = parser.textOrNull(); - } else if (INDEXED_DOCUMENT_FIELD_INDEX.match(currentFieldName, parser.getDeprecationHandler())) { - indexedDocumentIndex = parser.text(); - } else if (INDEXED_DOCUMENT_FIELD_ID.match(currentFieldName, parser.getDeprecationHandler())) { - indexedDocumentId = parser.text(); - } else if (INDEXED_DOCUMENT_FIELD_ROUTING.match(currentFieldName, parser.getDeprecationHandler())) { - indexedDocumentRouting = parser.text(); - } else if (INDEXED_DOCUMENT_FIELD_PREFERENCE.match(currentFieldName, parser.getDeprecationHandler())) { - indexedDocumentPreference = parser.text(); - } else if (INDEXED_DOCUMENT_FIELD_VERSION.match(currentFieldName, parser.getDeprecationHandler())) { - indexedDocumentVersion = parser.longValue(); - } else if (AbstractQueryBuilder.BOOST_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { - boost = parser.floatValue(); - } else if (AbstractQueryBuilder.NAME_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { - queryName = parser.text(); - } else { - throw new ParsingException(parser.getTokenLocation(), "[" + PercolateQueryBuilder.NAME + - "] query does not support [" + currentFieldName + "]"); - } - } else { - throw new ParsingException(parser.getTokenLocation(), "[" + PercolateQueryBuilder.NAME + - "] query does not support [" + token + "]"); - } - } - - PercolateQueryBuilder queryBuilder; - if (documents.isEmpty() == false) { - queryBuilder = new PercolateQueryBuilder(field, documents, XContentType.JSON); - } else if (indexedDocumentId != null) { - queryBuilder = new PercolateQueryBuilder(field, indexedDocumentIndex, indexedDocumentId, indexedDocumentRouting, - indexedDocumentPreference, indexedDocumentVersion); + @SuppressWarnings("unchecked") + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(NAME, args -> { + String field = (String) args[0]; + BytesReference document = (BytesReference) args[1]; + List documents = (List) args[2]; + String indexedDocId = (String) args[3]; + String indexedDocIndex = (String) args[4]; + String indexDocRouting = (String) args[5]; + String indexDocPreference = (String) args[6]; + Long indexedDocVersion = (Long) args[7]; + if (indexedDocId != null) { + return new PercolateQueryBuilder(field, indexedDocIndex, indexedDocId, indexDocRouting, indexDocPreference, indexedDocVersion); + } else if (document != null) { + return new PercolateQueryBuilder(field, List.of(document), XContentType.JSON); } else { - throw new IllegalArgumentException("[" + PercolateQueryBuilder.NAME + "] query, nothing to percolate"); - } - if (name != null) { - queryBuilder.setName(name); + return new PercolateQueryBuilder(field, documents, XContentType.JSON); + } + }); + static { + PARSER.declareString(constructorArg(), QUERY_FIELD); + PARSER.declareObject(optionalConstructorArg(), (p, c) -> parseDocument(p), DOCUMENT_FIELD); + PARSER.declareObjectArray(optionalConstructorArg(), (p, c) -> parseDocument(p), DOCUMENTS_FIELD); + PARSER.declareString(optionalConstructorArg(), INDEXED_DOCUMENT_FIELD_ID); + PARSER.declareString(optionalConstructorArg(), INDEXED_DOCUMENT_FIELD_INDEX); + PARSER.declareString(optionalConstructorArg(), INDEXED_DOCUMENT_FIELD_ROUTING); + PARSER.declareString(optionalConstructorArg(), INDEXED_DOCUMENT_FIELD_PREFERENCE); + PARSER.declareLong(optionalConstructorArg(), INDEXED_DOCUMENT_FIELD_VERSION); + PARSER.declareString(PercolateQueryBuilder::setName, NAME_FIELD); + PARSER.declareString(PercolateQueryBuilder::queryName, AbstractQueryBuilder.NAME_FIELD); + PARSER.declareFloat(PercolateQueryBuilder::boost, BOOST_FIELD); + PARSER.declareRequiredFieldSet(DOCUMENT_FIELD.getPreferredName(), + DOCUMENTS_FIELD.getPreferredName(), INDEXED_DOCUMENT_FIELD_ID.getPreferredName()); + PARSER.declareExclusiveFieldSet(DOCUMENT_FIELD.getPreferredName(), + DOCUMENTS_FIELD.getPreferredName(), INDEXED_DOCUMENT_FIELD_ID.getPreferredName()); + } + + private static BytesReference parseDocument(XContentParser parser) throws IOException { + try (XContentBuilder builder = XContentFactory.jsonBuilder()) { + builder.copyCurrentStructure(parser); + builder.flush(); + return BytesReference.bytes(builder); } - queryBuilder.queryName(queryName); - queryBuilder.boost(boost); - return queryBuilder; + } + + public static PercolateQueryBuilder fromXContent(XContentParser parser) throws IOException { + return PARSER.parse(parser, null); } @Override diff --git a/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolateQueryBuilderTests.java b/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolateQueryBuilderTests.java index f5decb7303e64..48ca69b6b97a8 100644 --- a/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolateQueryBuilderTests.java +++ b/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolateQueryBuilderTests.java @@ -57,6 +57,7 @@ import java.util.function.Supplier; import static org.elasticsearch.index.seqno.SequenceNumbers.UNASSIGNED_SEQ_NO; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -244,9 +245,10 @@ public void testFromJsonNoType() throws IOException { rewriteAndFetch(queryBuilder, queryShardContext).toQuery(queryShardContext); } - public void testBothDocumentAndDocumentsSpecified() throws IOException { - expectThrows(IllegalArgumentException.class, + public void testBothDocumentAndDocumentsSpecified() { + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> parseQuery("{\"percolate\" : { \"document\": {}, \"documents\": [{}, {}], \"field\":\"" + queryField + "\"}}")); + assertThat(e.getMessage(), containsString("The following fields are not allowed together: [document, documents]")); } private static BytesReference randomSource(Set usedFields) { From f34c7ea2f42187f90688bd121eed5b2f819fa87d Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Mon, 2 Mar 2020 09:37:05 +0000 Subject: [PATCH 2/2] feedback --- .../elasticsearch/common/xcontent/AbstractObjectParser.java | 4 +++- .../java/org/elasticsearch/common/xcontent/ObjectParser.java | 5 +++-- .../org/elasticsearch/percolator/PercolateQueryBuilder.java | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java index 0da89089651ca..e0ea0d511e277 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java @@ -299,7 +299,9 @@ public void declareRequiredFieldSet(String... requiredSet) { * Declares a set of fields of which at most one must appear for parsing to succeed * * E.g. declareExclusiveFieldSet("foo", "bar"); means that only one of 'foo' - * or 'bar' must be present, and if both appear then an exception will be thrown. + * or 'bar' must be present, and if both appear then an exception will be thrown. Note + * that this does not make 'foo' or 'bar' required - see {@link #declareRequiredFieldSet(String...)} + * for required fields. * * Multiple exclusive sets may be declared * diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java index 8e122f141405d..7526fc7bd6922 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java @@ -307,8 +307,7 @@ public Value parse(XContentParser parser, Value value, Context context) throws I } // Check if this field is in an exclusive set, if it is then mark - // it as seen. If the set is already marked, then we have a duplicate - // so throw an exception + // it as seen. for (int i = 0; i < this.exclusiveFieldSets.size(); i++) { for (String field : this.exclusiveFieldSets.get(i)) { if (field.equals(currentFieldName)) { @@ -323,6 +322,8 @@ public Value parse(XContentParser parser, Value value, Context context) throws I } } + // Check for a) multiple entries appearing in exclusive field sets and b) empty + // required field entries StringBuilder message = new StringBuilder(); for (List fieldset : exclusiveFields) { if (fieldset.size() > 1) { diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java index 9380fa39d8b4d..8f07358bb07e1 100644 --- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java +++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java @@ -318,10 +318,10 @@ protected void doXContent(XContentBuilder builder, Params params) throws IOExcep builder.endObject(); } - @SuppressWarnings("unchecked") private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(NAME, args -> { String field = (String) args[0]; BytesReference document = (BytesReference) args[1]; + @SuppressWarnings("unchecked") List documents = (List) args[2]; String indexedDocId = (String) args[3]; String indexedDocIndex = (String) args[4];