|
1 | 1 | package graphql.execution; |
2 | 2 |
|
| 3 | +import java.lang.reflect.Array; |
| 4 | +import java.util.ArrayList; |
| 5 | +import java.util.List; |
| 6 | +import java.util.Map; |
| 7 | +import java.util.Optional; |
| 8 | +import java.util.concurrent.CompletableFuture; |
| 9 | +import java.util.concurrent.CompletionException; |
| 10 | +import java.util.stream.IntStream; |
| 11 | +import org.slf4j.Logger; |
| 12 | +import org.slf4j.LoggerFactory; |
| 13 | + |
3 | 14 | import graphql.ExecutionResult; |
4 | 15 | import graphql.ExecutionResultImpl; |
5 | 16 | import graphql.PublicSpi; |
6 | 17 | import graphql.SerializationError; |
| 18 | +import graphql.TypeMismatchError; |
7 | 19 | import graphql.TypeResolutionEnvironment; |
8 | 20 | import graphql.execution.instrumentation.Instrumentation; |
9 | 21 | import graphql.execution.instrumentation.InstrumentationContext; |
|
28 | 40 | import graphql.schema.GraphQLType; |
29 | 41 | import graphql.schema.GraphQLUnionType; |
30 | 42 | import graphql.schema.visibility.GraphqlFieldVisibility; |
31 | | -import org.slf4j.Logger; |
32 | | -import org.slf4j.LoggerFactory; |
33 | | - |
34 | | -import java.lang.reflect.Array; |
35 | | -import java.util.ArrayList; |
36 | | -import java.util.List; |
37 | | -import java.util.Map; |
38 | | -import java.util.Optional; |
39 | | -import java.util.concurrent.CompletableFuture; |
40 | | -import java.util.concurrent.CompletionException; |
41 | | -import java.util.stream.IntStream; |
42 | 43 |
|
43 | 44 | import static graphql.execution.ExecutionTypeInfo.newTypeInfo; |
44 | 45 | import static graphql.execution.FieldCollectorParameters.newParameters; |
@@ -354,7 +355,7 @@ protected CompletableFuture<ExecutionResult> completeValue(ExecutionContext exec |
354 | 355 | if (result == null) { |
355 | 356 | return completedFuture(new ExecutionResultImpl(parameters.nonNullFieldValidator().validate(parameters.path(), null), null)); |
356 | 357 | } else if (fieldType instanceof GraphQLList) { |
357 | | - return completeValueForList(executionContext, parameters, toIterable(result)); |
| 358 | + return completeValueForList(executionContext, parameters, result); |
358 | 359 | } else if (fieldType instanceof GraphQLScalarType) { |
359 | 360 | return completeValueForScalar(executionContext, parameters, (GraphQLScalarType) fieldType, result); |
360 | 361 | } else if (fieldType instanceof GraphQLEnumType) { |
@@ -552,7 +553,41 @@ private Object handleCoercionProblem(ExecutionContext context, ExecutionStrategy |
552 | 553 | * |
553 | 554 | * @param executionContext contains the top level execution parameters |
554 | 555 | * @param parameters contains the parameters holding the fields to be executed and source object |
555 | | - * @param iterableValues the values to complete |
| 556 | + * @param result the result to complete, raw result |
| 557 | + * |
| 558 | + * @return an {@link ExecutionResult} |
| 559 | + */ |
| 560 | + protected CompletableFuture<ExecutionResult> completeValueForList(ExecutionContext executionContext, ExecutionStrategyParameters parameters, Object result) { |
| 561 | + Iterable<Object> resultIterable = toIterable(executionContext, parameters, result); |
| 562 | + resultIterable = parameters.nonNullFieldValidator().validate(parameters.path(), resultIterable); |
| 563 | + if (resultIterable == null) { |
| 564 | + return completedFuture(new ExecutionResultImpl(null, null)); |
| 565 | + } |
| 566 | + return completeValueForList(executionContext, parameters, resultIterable); |
| 567 | + } |
| 568 | + |
| 569 | + protected Iterable<Object> toIterable(ExecutionContext context, ExecutionStrategyParameters parameters, Object result) { |
| 570 | + if (result.getClass().isArray() || result instanceof Iterable) { |
| 571 | + return toIterable(result); |
| 572 | + } |
| 573 | + |
| 574 | + handleTypeMismatchProblem(context, parameters, result); |
| 575 | + return null; |
| 576 | + } |
| 577 | + |
| 578 | + private void handleTypeMismatchProblem(ExecutionContext context, ExecutionStrategyParameters parameters, Object result) { |
| 579 | + TypeMismatchError error = new TypeMismatchError(parameters.path(), parameters.typeInfo().getType()); |
| 580 | + log.warn("{} got {}", error.getMessage(), result.getClass()); |
| 581 | + context.addError(error, parameters.path()); |
| 582 | + } |
| 583 | + |
| 584 | + /** |
| 585 | + * Called to complete a list of value for a field based on a list type. This iterates the values and calls |
| 586 | + * {@link #completeValue(ExecutionContext, ExecutionStrategyParameters)} for each value. |
| 587 | + * |
| 588 | + * @param executionContext contains the top level execution parameters |
| 589 | + * @param parameters contains the parameters holding the fields to be executed and source object |
| 590 | + * @param iterableValues the values to complete, can't be null |
556 | 591 | * |
557 | 592 | * @return an {@link ExecutionResult} |
558 | 593 | */ |
|
0 commit comments