Skip to content

Commit 789de0a

Browse files
rstoyanchevkoenpunt
authored andcommitted
Minor refactoring in GraphQlArgumentBinder
See spring-projectsgh-449
1 parent 4960400 commit 789de0a

File tree

1 file changed

+100
-106
lines changed

1 file changed

+100
-106
lines changed

spring-graphql/src/main/java/org/springframework/graphql/data/GraphQlArgumentBinder.java

Lines changed: 100 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public Object bind(
149149

150150
if (isApproximableCollectionType(rawValue)) {
151151
segments.push(argumentName);
152-
return createCollection((Collection<Object>) rawValue, targetType, bindingResult, segments);
152+
return bindCollection((Collection<Object>) rawValue, targetType, bindingResult, segments);
153153
}
154154

155155
if (targetClass == Optional.class) {
@@ -160,7 +160,7 @@ public Object bind(
160160
// From Map
161161

162162
if (rawValue instanceof Map) {
163-
Object target = createValue((Map<String, Object>) rawValue, targetType, bindingResult, segments);
163+
Object target = bindMap((Map<String, Object>) rawValue, targetType, bindingResult, segments);
164164
return wrapAsOptionalIfNecessary(target, targetType);
165165
}
166166

@@ -195,7 +195,7 @@ private boolean isApproximableCollectionType(@Nullable Object rawValue) {
195195
}
196196

197197
@SuppressWarnings({"ConstantConditions", "unchecked"})
198-
private <T> Collection<T> createCollection(
198+
private <T> Collection<T> bindCollection(
199199
Collection<Object> rawCollection, ResolvableType collectionType,
200200
BindingResult bindingResult, Stack<String> segments) {
201201

@@ -219,7 +219,7 @@ private <T> Collection<T> createCollection(
219219
collection.add((T) rawValue);
220220
}
221221
else if (rawValue instanceof Map) {
222-
collection.add((T) createValueOrNull((Map<String, Object>) rawValue, elementType, bindingResult, segments));
222+
collection.add((T) bindMap((Map<String, Object>) rawValue, elementType, bindingResult, segments));
223223
}
224224
else {
225225
collection.add((T) convertValue(rawValue, elementClass, bindingResult, segments));
@@ -230,134 +230,128 @@ else if (rawValue instanceof Map) {
230230
}
231231

232232
@Nullable
233-
private Object createValueOrNull(
234-
Map<String, Object> rawMap, ResolvableType targetType, BindingResult result, Stack<String> segments) {
235-
236-
try {
237-
return createValue(rawMap, targetType, result, segments);
238-
}
239-
catch (BindException ex) {
240-
return null;
241-
}
242-
}
243-
244233
@SuppressWarnings("unchecked")
245-
private Object createValue(
234+
private Object bindMap(
246235
Map<String, Object> rawMap, ResolvableType targetType, BindingResult bindingResult,
247-
Stack<String> segments) throws BindException {
236+
Stack<String> segments) {
248237

249-
Class<?> targetClass = targetType.resolve();
250-
Assert.notNull(targetClass, "Unknown target class");
251-
252-
if (Map.class.isAssignableFrom(targetClass)) {
253-
ResolvableType valueType = targetType.asMap().getGeneric(1);
254-
Class<?> valueClass = valueType.resolve();
255-
if (valueClass == null) {
256-
bindingResult.rejectValue(toArgumentPath(segments), "unknownMapValueType", "Unknown Map value type");
257-
return Collections.emptyMap();
258-
}
259-
Map<String, Object> map = CollectionFactory.createMap(targetClass, rawMap.size());
260-
for (Map.Entry<String, Object> entry : rawMap.entrySet()) {
261-
Object rawValue = entry.getValue();
262-
segments.push("[" + entry.getKey() + "]");
263-
if (rawValue == null || valueType.isAssignableFrom(rawValue.getClass())) {
264-
map.put(entry.getKey(), entry.getValue());
265-
}
266-
else if (rawValue instanceof Map) {
267-
map.put(entry.getKey(), createValueOrNull(
268-
(Map<String, Object>) rawValue, valueType, bindingResult, segments));
238+
try {
239+
Class<?> targetClass = targetType.resolve();
240+
Assert.notNull(targetClass, "Unknown target class");
241+
242+
if (Map.class.isAssignableFrom(targetClass)) {
243+
ResolvableType valueType = targetType.asMap().getGeneric(1);
244+
Class<?> valueClass = valueType.resolve();
245+
if (valueClass == null) {
246+
bindingResult.rejectValue(toArgumentPath(segments), "unknownMapValueType", "Unknown Map value type");
247+
return Collections.emptyMap();
269248
}
270-
else {
271-
map.put(entry.getKey(), convertValue(rawValue, valueClass, bindingResult, segments));
249+
Map<String, Object> map = CollectionFactory.createMap(targetClass, rawMap.size());
250+
for (Map.Entry<String, Object> entry : rawMap.entrySet()) {
251+
Object rawValue = entry.getValue();
252+
segments.push("[" + entry.getKey() + "]");
253+
if (rawValue == null || valueType.isAssignableFrom(rawValue.getClass())) {
254+
map.put(entry.getKey(), entry.getValue());
255+
}
256+
else if (rawValue instanceof Map) {
257+
map.put(entry.getKey(), bindMap(
258+
(Map<String, Object>) rawValue, valueType, bindingResult, segments));
259+
}
260+
else {
261+
map.put(entry.getKey(), convertValue(rawValue, valueClass, bindingResult, segments));
262+
}
263+
segments.pop();
272264
}
273-
segments.pop();
265+
return map;
274266
}
275-
return map;
276-
}
277-
278-
Object target;
279-
Constructor<?> ctor = BeanUtils.getResolvableConstructor(targetClass);
280267

281-
// Default constructor + data binding via properties
268+
Object target;
269+
Constructor<?> ctor = BeanUtils.getResolvableConstructor(targetClass);
282270

283-
if (ctor.getParameterCount() == 0) {
284-
target = BeanUtils.instantiateClass(ctor);
285-
DataBinder dataBinder = new DataBinder(target);
286-
initDataBinder(dataBinder);
287-
dataBinder.getBindingResult().setNestedPath(toArgumentPath(segments));
288-
dataBinder.setConversionService(getConversionService());
289-
dataBinder.bind(initBindValues(rawMap));
271+
// Default constructor + data binding via properties
290272

291-
if (dataBinder.getBindingResult().hasErrors()) {
292-
addErrors(dataBinder, bindingResult, segments);
293-
throw new BindException(bindingResult);
294-
}
273+
if (ctor.getParameterCount() == 0) {
274+
target = BeanUtils.instantiateClass(ctor);
275+
DataBinder dataBinder = new DataBinder(target);
276+
initDataBinder(dataBinder);
277+
dataBinder.getBindingResult().setNestedPath(toArgumentPath(segments));
278+
dataBinder.setConversionService(getConversionService());
279+
dataBinder.bind(toPropertyValues(rawMap));
295280

296-
return target;
297-
}
281+
if (dataBinder.getBindingResult().hasErrors()) {
282+
addDataBinderErrors(dataBinder, bindingResult, segments);
283+
throw new BindException(bindingResult);
284+
}
298285

299-
// Data class constructor
286+
return target;
287+
}
300288

301-
if (!segments.isEmpty()) {
302-
segments.push(".");
303-
}
289+
// Data class constructor
304290

305-
String[] paramNames = BeanUtils.getParameterNames(ctor);
306-
Class<?>[] paramTypes = ctor.getParameterTypes();
307-
Object[] args = new Object[paramTypes.length];
308-
309-
for (int i = 0; i < paramNames.length; i++) {
310-
String paramName = paramNames[i];
311-
Object rawValue = rawMap.get(paramName);
312-
segments.push(paramName);
313-
MethodParameter methodParam = new MethodParameter(ctor, i);
314-
if (rawValue == null && methodParam.isOptional()) {
315-
args[i] = (paramTypes[i] == Optional.class ? Optional.empty() : null);
291+
if (!segments.isEmpty()) {
292+
segments.push(".");
316293
}
317-
else if (paramTypes[i] == Object.class) {
318-
args[i] = rawValue;
294+
295+
String[] paramNames = BeanUtils.getParameterNames(ctor);
296+
Class<?>[] paramTypes = ctor.getParameterTypes();
297+
Object[] args = new Object[paramTypes.length];
298+
299+
for (int i = 0; i < paramNames.length; i++) {
300+
String paramName = paramNames[i];
301+
Object rawValue = rawMap.get(paramName);
302+
segments.push(paramName);
303+
MethodParameter methodParam = new MethodParameter(ctor, i);
304+
if (rawValue == null && methodParam.isOptional()) {
305+
args[i] = (paramTypes[i] == Optional.class ? Optional.empty() : null);
306+
}
307+
else if (paramTypes[i] == Object.class) {
308+
args[i] = rawValue;
309+
}
310+
else if (isApproximableCollectionType(rawValue)) {
311+
ResolvableType elementType = ResolvableType.forMethodParameter(methodParam);
312+
args[i] = bindCollection((Collection<Object>) rawValue, elementType, bindingResult, segments);
313+
}
314+
else if (rawValue instanceof Map) {
315+
boolean isOptional = (paramTypes[i] == Optional.class);
316+
ResolvableType type = ResolvableType.forMethodParameter(methodParam.nestedIfOptional());
317+
Object value = bindMap((Map<String, Object>) rawValue, type, bindingResult, segments);
318+
args[i] = (isOptional ? Optional.ofNullable(value) : value);
319+
}
320+
else {
321+
args[i] = convertValue(rawValue, paramTypes[i], new TypeDescriptor(methodParam), bindingResult, segments);
322+
}
323+
segments.pop();
319324
}
320-
else if (isApproximableCollectionType(rawValue)) {
321-
ResolvableType elementType = ResolvableType.forMethodParameter(methodParam);
322-
args[i] = createCollection((Collection<Object>) rawValue, elementType, bindingResult, segments);
325+
326+
if (segments.size() > 1) {
327+
segments.pop();
323328
}
324-
else if (rawValue instanceof Map) {
325-
boolean isOptional = (paramTypes[i] == Optional.class);
326-
ResolvableType type = ResolvableType.forMethodParameter(methodParam.nestedIfOptional());
327-
Object value = createValueOrNull((Map<String, Object>) rawValue, type, bindingResult, segments);
328-
args[i] = (isOptional ? Optional.ofNullable(value) : value);
329+
330+
try {
331+
return BeanUtils.instantiateClass(ctor, args);
329332
}
330-
else {
331-
args[i] = convertValue(rawValue, paramTypes[i], new TypeDescriptor(methodParam), bindingResult, segments);
333+
catch (BeanInstantiationException ex) {
334+
// Swallow if we had binding errors, it's as far as we could go
335+
checkBindingResult(bindingResult);
336+
throw ex;
332337
}
333-
segments.pop();
334-
}
335-
336-
if (segments.size() > 1) {
337-
segments.pop();
338338
}
339-
340-
try {
341-
return BeanUtils.instantiateClass(ctor, args);
342-
}
343-
catch (BeanInstantiationException ex) {
344-
// Swallow if we had binding errors, it's as far as we could go
345-
checkBindingResult(bindingResult);
346-
throw ex;
339+
catch (BindException ex) {
340+
return null;
347341
}
348342
}
349343

350-
private MutablePropertyValues initBindValues(Map<String, Object> rawMap) {
344+
private static MutablePropertyValues toPropertyValues(Map<String, Object> rawMap) {
351345
MutablePropertyValues mpvs = new MutablePropertyValues();
352346
Stack<String> segments = new Stack<>();
353347
for (String key : rawMap.keySet()) {
354-
addBindValues(mpvs, key, rawMap.get(key), segments);
348+
addPropertyValue(mpvs, key, rawMap.get(key), segments);
355349
}
356350
return mpvs;
357351
}
358352

359353
@SuppressWarnings("unchecked")
360-
private void addBindValues(MutablePropertyValues mpvs, String name, Object value, Stack<String> segments) {
354+
private static void addPropertyValue(MutablePropertyValues mpvs, String name, Object value, Stack<String> segments) {
361355
if (value instanceof List) {
362356
List<Object> items = (List<Object>) value;
363357
if (items.isEmpty()) {
@@ -367,15 +361,15 @@ private void addBindValues(MutablePropertyValues mpvs, String name, Object value
367361
}
368362
else {
369363
for (int i = 0; i < items.size(); i++) {
370-
addBindValues(mpvs, name + "[" + i + "]", items.get(i), segments);
364+
addPropertyValue(mpvs, name + "[" + i + "]", items.get(i), segments);
371365
}
372366
}
373367
}
374368
else if (value instanceof Map) {
375369
segments.push(name + ".");
376370
Map<String, Object> map = (Map<String, Object>) value;
377371
for (String key : map.keySet()) {
378-
addBindValues(mpvs, key, map.get(key), segments);
372+
addPropertyValue(mpvs, key, map.get(key), segments);
379373
}
380374
segments.pop();
381375
}
@@ -386,7 +380,7 @@ else if (value instanceof Map) {
386380
}
387381
}
388382

389-
private String toArgumentPath(Stack<String> path) {
383+
private static String toArgumentPath(Stack<String> path) {
390384
StringBuilder sb = new StringBuilder();
391385
path.forEach(sb::append);
392386
return sb.toString();
@@ -415,7 +409,7 @@ private Object convertValue(
415409
return null;
416410
}
417411

418-
private void addErrors(DataBinder binder, BindingResult bindingResult, Stack<String> segments) {
412+
private static void addDataBinderErrors(DataBinder binder, BindingResult bindingResult, Stack<String> segments) {
419413
String path = (!segments.isEmpty() ? toArgumentPath(segments) + "." : "");
420414
binder.getBindingResult().getFieldErrors().forEach(error -> bindingResult.addError(
421415
new FieldError(bindingResult.getObjectName(), path + error.getField(),

0 commit comments

Comments
 (0)