Skip to content

Commit 65b2b15

Browse files
committed
Refactor RequestXContent
1 parent ab1146d commit 65b2b15

File tree

1 file changed

+130
-102
lines changed

1 file changed

+130
-102
lines changed

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java

Lines changed: 130 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)