@@ -148,78 +148,11 @@ private static QueryParams parseParams(XContentParser p) throws IOException {
148148 XContentParser .Token token = p .currentToken ();
149149
150150 if (token == XContentParser .Token .START_ARRAY ) {
151- Object paramValue = null ;
152- DataType type = null ;
153- QueryParam currentParam = null ;
154- TempObjects param ;
155-
156151 while ((token = p .nextToken ()) != XContentParser .Token .END_ARRAY ) {
157- XContentLocation loc = p .getTokenLocation ();
158152 if (token == XContentParser .Token .START_OBJECT ) {
159- param = PARAM_PARSER .apply (p , null );
160- if (param .fields .size () > 1 ) {
161- errors .add (
162- new XContentParseException (
163- loc ,
164- "Cannot parse more than one key:value pair as parameter, found [" + param .fields () + "]"
165- )
166- );
167- }
168- for (Map .Entry <String , Object > entry : param .fields .entrySet ()) {
169- ParserUtils .ParamClassification classification = null ;
170- String paramName = entry .getKey ();
171- checkParamNameValidity (paramName , errors , loc );
172-
173- if (entry .getValue () instanceof Map <?, ?> value ) {// parameter specified as a key:value pair
174- checkParamValueSize (paramName , value , loc , errors );
175- for (Object keyName : value .keySet ()) {
176- classification = getParamClassification (keyName .toString (), errors , loc );
177- if (classification != null ) {
178- paramValue = value .get (keyName );
179- checkParamValueValidity (entry , classification , paramValue , loc , errors );
180- }
181- }
182- } else {// parameter specifies a single or multi value
183- paramValue = entry .getValue ();
184- classification = VALUE ;
185- checkParamValueValidity (entry , classification , paramValue , loc , errors );
186- }
187- type = DataType .fromJava (paramValue );
188- currentParam = new QueryParam (
189- paramName ,
190- paramValue ,
191- (classification == VALUE ) ? type : DataType .NULL ,
192- classification
193- );
194- namedParams .add (currentParam );
195- }
153+ parseNamedParameter (p , namedParams , errors );
196154 } else {
197- if (token == XContentParser .Token .START_ARRAY ) {
198- DataType arrayType = null ;
199- List <Object > paramValues = new ArrayList <>();
200- while ((p .nextToken ()) != XContentParser .Token .END_ARRAY ) {
201- ParamValueAndType valueAndDataType = parseSingleParamValue (p , errors );
202- DataType currentType = valueAndDataType .type ;
203- if (currentType == DataType .NULL ) {
204- errors .add (new XContentParseException (loc , "Unnamed parameter contains a null in a multivalued value" ));
205- continue ;
206- }
207- if (arrayType != null && arrayType != currentType ) {
208- errors .add (
209- new XContentParseException (
210- loc ,
211- "Unnamed parameter has values from different types, found " + arrayType + " and " + currentType
212- )
213- );
214- }
215- arrayType = currentType ;
216- paramValues .add (valueAndDataType .value );
217- }
218- unNamedParams .add (new QueryParam (null , paramValues , arrayType , VALUE ));
219- } else {
220- ParamValueAndType valueAndDataType = parseSingleParamValue (p , errors );
221- unNamedParams .add (new QueryParam (null , valueAndDataType .value , valueAndDataType .type , VALUE ));
222- }
155+ parseUnnamedParameter (p , unNamedParams , errors );
223156 }
224157 }
225158 }
@@ -243,6 +176,94 @@ private static QueryParams parseParams(XContentParser p) throws IOException {
243176 return new QueryParams (namedParams .isEmpty () ? unNamedParams : namedParams );
244177 }
245178
179+ private static void parseNamedParameter (XContentParser p , List <QueryParam > namedParams , List <XContentParseException > errors ) {
180+ XContentLocation loc = p .getTokenLocation ();
181+ TempObjects param = PARAM_PARSER .apply (p , null );
182+ if (param .fields .size () > 1 ) {
183+ errors .add (
184+ new XContentParseException (loc , "Cannot parse more than one key:value pair as parameter, found [" + param .fields () + "]" )
185+ );
186+ return ;
187+ }
188+
189+ for (Map .Entry <String , Object > entry : param .fields .entrySet ()) {
190+ String paramName = entry .getKey ();
191+ checkParamNameValidity (paramName , errors , loc );
192+
193+ QueryParam qp = buildNamedQueryParam (entry , loc , errors );
194+ if (qp != null ) {
195+ namedParams .add (qp );
196+ }
197+ }
198+ }
199+
200+ private static QueryParam buildNamedQueryParam (
201+ Map .Entry <String , Object > entry ,
202+ XContentLocation loc ,
203+ List <XContentParseException > errors
204+ ) {
205+ String paramName = entry .getKey ();
206+ Object rawValue = entry .getValue ();
207+ ParserUtils .ParamClassification classification ;
208+ Object paramValue ;
209+
210+ if (rawValue instanceof Map <?, ?> valueMap ) {
211+ checkParamValueSize (paramName , valueMap , loc , errors );
212+ if (valueMap .size () != 1 ) {
213+ return null ;
214+ }
215+ String classificationKey = valueMap .keySet ().iterator ().next ().toString ();
216+ classification = getParamClassification (classificationKey , errors , loc );
217+ if (classification == null ) {
218+ return null ;
219+ }
220+ paramValue = valueMap .get (classificationKey );
221+ } else {
222+ classification = VALUE ;
223+ paramValue = rawValue ;
224+ }
225+
226+ checkParamValueValidity (entry , classification , paramValue , loc , errors );
227+
228+ DataType type = DataType .fromJava (paramValue );
229+ return new QueryParam (paramName , paramValue , (classification == VALUE ) ? type : DataType .NULL , classification );
230+ }
231+
232+ private static void parseUnnamedParameter (XContentParser p , List <QueryParam > unNamedParams , List <XContentParseException > errors )
233+ throws IOException {
234+ if (p .currentToken () == XContentParser .Token .START_ARRAY ) {
235+ unNamedParams .add (parseUnnamedMultiValuedParameter (p , errors ));
236+ } else {
237+ ParamValueAndType valueAndDataType = parseSingleParamValue (p , errors );
238+ unNamedParams .add (new QueryParam (null , valueAndDataType .value , valueAndDataType .type , VALUE ));
239+ }
240+ }
241+
242+ private static QueryParam parseUnnamedMultiValuedParameter (XContentParser p , List <XContentParseException > errors ) throws IOException {
243+ XContentLocation loc = p .getTokenLocation ();
244+ DataType arrayType = null ;
245+ List <Object > paramValues = new ArrayList <>();
246+ while ((p .nextToken ()) != XContentParser .Token .END_ARRAY ) {
247+ ParamValueAndType valueAndDataType = parseSingleParamValue (p , errors );
248+ DataType currentType = valueAndDataType .type ;
249+ if (currentType == DataType .NULL ) {
250+ errors .add (new XContentParseException (loc , "Unnamed parameter contains a null in a multivalued value" ));
251+ continue ;
252+ }
253+ if (arrayType != null && arrayType != currentType ) {
254+ errors .add (
255+ new XContentParseException (
256+ loc ,
257+ "Unnamed parameter has values from different types, found " + arrayType + " and " + currentType
258+ )
259+ );
260+ }
261+ arrayType = currentType ;
262+ paramValues .add (valueAndDataType .value );
263+ }
264+ return new QueryParam (null , paramValues , arrayType , VALUE );
265+ }
266+
246267 private record ParamValueAndType (Object value , DataType type ) {}
247268
248269 private static ParamValueAndType parseSingleParamValue (XContentParser p , List <XContentParseException > errors ) throws IOException {
@@ -354,39 +375,7 @@ private static void checkParamValueValidity(
354375 List <XContentParseException > errors
355376 ) {
356377 if (value instanceof List <?> valueList ) {
357- if (classification != VALUE ) {
358- errors .add (
359- new XContentParseException (
360- loc ,
361- entry + " parameter is multivalued, only " + VALUE .name () + " parameters can be multivalued"
362- )
363- );
364- return ;
365- }
366- // Multivalued field
367- DataType arrayType = null ;
368- for (Object currentValue : valueList ) {
369- checkParamValueValidity (entry , classification , currentValue , loc , errors );
370- DataType currentType = DataType .fromJava (currentValue );
371- if (currentType == DataType .NULL ) {
372- errors .add (
373- new XContentParseException (
374- loc ,
375- "Parameter [" + entry .getKey () + "] contains a null value. Null values are not allowed for multivalues"
376- )
377- );
378- continue ;
379- } else if (arrayType != null && arrayType != currentType ) {
380- errors .add (
381- new XContentParseException (
382- loc ,
383- "Parameter [" + entry .getKey () + "] has values from different types, found " + arrayType + " and " + currentType
384- )
385- );
386- continue ;
387- }
388- arrayType = currentType ;
389- }
378+ checkMultiValuedParamValidity (entry , classification , valueList , loc , errors );
390379 return ;
391380 }
392381
@@ -416,4 +405,43 @@ private static void checkParamValueValidity(
416405 }
417406 }
418407 }
408+
409+ private static void checkMultiValuedParamValidity (
410+ Map .Entry <String , Object > entry ,
411+ ParserUtils .ParamClassification classification ,
412+ List <?> valueList ,
413+ XContentLocation loc ,
414+ List <XContentParseException > errors
415+ ) {
416+ if (classification != VALUE ) {
417+ errors .add (
418+ new XContentParseException (loc , entry + " parameter is multivalued, only " + VALUE .name () + " parameters can be multivalued" )
419+ );
420+ return ;
421+ }
422+ // Multivalued field
423+ DataType arrayType = null ;
424+ for (Object currentValue : valueList ) {
425+ checkParamValueValidity (entry , classification , currentValue , loc , errors );
426+ DataType currentType = DataType .fromJava (currentValue );
427+ if (currentType == DataType .NULL ) {
428+ errors .add (
429+ new XContentParseException (
430+ loc ,
431+ "Parameter [" + entry .getKey () + "] contains a null value. Null values are not allowed for multivalues"
432+ )
433+ );
434+ continue ;
435+ } else if (arrayType != null && arrayType != currentType ) {
436+ errors .add (
437+ new XContentParseException (
438+ loc ,
439+ "Parameter [" + entry .getKey () + "] has values from different types, found " + arrayType + " and " + currentType
440+ )
441+ );
442+ continue ;
443+ }
444+ arrayType = currentType ;
445+ }
446+ }
419447}
0 commit comments