2525import graphql .schema .GraphQLType ;
2626import graphql .schema .visibility .GraphqlFieldVisibility ;
2727
28+ import java .util .ArrayDeque ;
2829import java .util .ArrayList ;
30+ import java .util .Arrays ;
2931import java .util .Collections ;
32+ import java .util .Deque ;
3033import java .util .LinkedHashMap ;
3134import java .util .List ;
3235import java .util .Map ;
@@ -58,7 +61,7 @@ public Map<String, Object> coerceVariableValues(GraphQLSchema schema, List<Varia
5861 Map <String , Object > coercedValues = new LinkedHashMap <>();
5962 for (VariableDefinition variableDefinition : variableDefinitions ) {
6063 String variableName = variableDefinition .getName ();
61- List <Object > nameStack = new ArrayList <>();
64+ Deque <Object > nameStack = new ArrayDeque <>();
6265 GraphQLType variableType = TypeFromAST .getTypeFromAST (schema , variableDefinition .getType ());
6366 Assert .assertTrue (variableType instanceof GraphQLInputType );
6467 // can be NullValue
@@ -153,15 +156,14 @@ private Map<String, Argument> argumentMap(List<Argument> arguments) {
153156
154157
155158 @ SuppressWarnings ("unchecked" )
156- private Object coerceValue (GraphqlFieldVisibility fieldVisibility , VariableDefinition variableDefinition , String inputName , GraphQLType graphQLType , Object value , List <Object > nameStack ) {
159+ private Object coerceValue (GraphqlFieldVisibility fieldVisibility , VariableDefinition variableDefinition , String inputName , GraphQLType graphQLType , Object value , Deque <Object > nameStack ) {
160+ nameStack .addLast (inputName );
157161 try {
158- nameStack .add (inputName );
159-
160162 if (isNonNull (graphQLType )) {
161163 Object returnValue =
162164 coerceValue (fieldVisibility , variableDefinition , inputName , unwrapOne (graphQLType ), value , nameStack );
163165 if (returnValue == null ) {
164- throw new NonNullableValueCoercedAsNullException (variableDefinition , inputName , nameStack , graphQLType );
166+ throw new NonNullableValueCoercedAsNullException (variableDefinition , inputName , Arrays . asList ( nameStack . toArray ()) , graphQLType );
165167 }
166168 return returnValue ;
167169 }
@@ -183,7 +185,7 @@ private Object coerceValue(GraphqlFieldVisibility fieldVisibility, VariableDefin
183185 throw CoercingParseValueException .newCoercingParseValueException ()
184186 .message ("Expected type 'Map' but was '" + value .getClass ().getSimpleName () +
185187 "'. Variables for input objects must be an instance of type 'Map'." )
186- .path (nameStack )
188+ .path (Arrays . asList ( nameStack . toArray ()) )
187189 .build ();
188190 }
189191 } else {
@@ -198,14 +200,20 @@ private Object coerceValue(GraphqlFieldVisibility fieldVisibility, VariableDefin
198200 .extensions (e .getExtensions ())
199201 .cause (e .getCause ())
200202 .sourceLocation (variableDefinition .getSourceLocation ())
201- .path (nameStack )
203+ .path (Arrays . asList ( nameStack . toArray ()) )
202204 .build ();
205+ } finally {
206+ nameStack .removeLast ();
203207 }
204208
205209 }
206210
207- private Object coerceValueForInputObjectType (GraphqlFieldVisibility fieldVisibility , VariableDefinition variableDefinition , GraphQLInputObjectType inputObjectType , Map <String , Object > inputMap , List <Object > nameStack ) {
208- Map <String , Object > result = new LinkedHashMap <>();
211+ private Object coerceValueForInputObjectType (GraphqlFieldVisibility fieldVisibility ,
212+ VariableDefinition variableDefinition ,
213+ GraphQLInputObjectType inputObjectType ,
214+ Map <String , Object > inputMap ,
215+ Deque <Object > nameStack ) {
216+ // Map<String, Object> result = new LinkedHashMap<>();
209217 List <GraphQLInputObjectField > fields = fieldVisibility .getFieldDefinitions (inputObjectType );
210218 List <String > fieldNames = map (fields , GraphQLInputObjectField ::getName );
211219 for (String inputFieldName : inputMap .keySet ()) {
@@ -214,20 +222,60 @@ private Object coerceValueForInputObjectType(GraphqlFieldVisibility fieldVisibil
214222 }
215223 }
216224
217- for (GraphQLInputObjectField inputField : fields ) {
218- if (inputMap .containsKey (inputField .getName ()) || alwaysHasValue (inputField )) {
219- // getOrDefault will return a null value if its present in the map as null
220- // defaulting only applies if the key is missing - we want this
221- Object inputValue = inputMap .getOrDefault (inputField .getName (), inputField .getDefaultValue ());
222- Object coerceValue = coerceValue (fieldVisibility , variableDefinition ,
223- inputField .getName (),
224- inputField .getType (),
225- inputValue ,
226- nameStack );
227- result .put (inputField .getName (), coerceValue == null ? inputField .getDefaultValue () : coerceValue );
225+ Map <String , Object > coercedValues = new LinkedHashMap <>();
226+
227+ List <GraphQLInputObjectField > inputFieldTypes = fieldVisibility .getFieldDefinitions (inputObjectType );
228+ for (GraphQLInputObjectField inputFieldType : inputFieldTypes ) {
229+
230+ GraphQLInputType fieldType = inputFieldType .getType ();
231+ String fieldName = inputFieldType .getName ();
232+ Object defaultValue = inputFieldType .getDefaultValue ();
233+ boolean hasValue = inputMap .containsKey (fieldName );
234+ Object value ;
235+ Object fieldValue = inputMap .getOrDefault (fieldName , null );
236+ value = fieldValue ;
237+ if (!hasValue && inputFieldType .hasSetDefaultValue ()) {
238+ //TODO: default value should be coerced
239+ coercedValues .put (fieldName , defaultValue );
240+ } else if (isNonNull (fieldType ) && (!hasValue || value == null )) {
241+ nameStack .addLast (fieldName );
242+ throw new NonNullableValueCoercedAsNullException (inputFieldType , Arrays .asList (nameStack .toArray ()));
243+ } else if (hasValue ) {
244+ if (value == null ) {
245+ coercedValues .put (fieldName , null );
246+ } else if (fieldValue instanceof VariableReference ) {
247+ coercedValues .put (fieldName , value );
248+ } else {
249+ value = coerceValue (fieldVisibility ,
250+ variableDefinition ,
251+ inputFieldType .getName (),
252+ fieldType ,
253+ value ,
254+ nameStack );
255+ coercedValues .put (fieldName , value );
256+ }
257+ } else {
258+ // nullable type && hasValue == false && hasDefaultValue == false
259+ // meaning no value was provided for this field
228260 }
229261 }
230- return result ;
262+ return coercedValues ;
263+
264+
265+ // for (GraphQLInputObjectField inputField : fields) {
266+ // if (inputMap.containsKey(inputField.getName()) || alwaysHasValue(inputField)) {
267+ // // getOrDefault will return a null value if its present in the map as null
268+ // // defaulting only applies if the key is missing - we want this
269+ // Object inputValue = inputMap.getOrDefault(inputField.getName(), inputField.getDefaultValue());
270+ // Object coerceValue = coerceValue(fieldVisibility, variableDefinition,
271+ // inputField.getName(),
272+ // inputField.getType(),
273+ // inputValue,
274+ // nameStack);
275+ // result.put(inputField.getName(), coerceValue == null ? inputField.getDefaultValue() : coerceValue);
276+ // }
277+ // }
278+ // return result;
231279 }
232280
233281 private boolean alwaysHasValue (GraphQLInputObjectField inputField ) {
@@ -243,7 +291,7 @@ private Object coerceValueForEnum(GraphQLEnumType graphQLEnumType, Object value)
243291 return graphQLEnumType .parseValue (value );
244292 }
245293
246- private List coerceValueForList (GraphqlFieldVisibility fieldVisibility , VariableDefinition variableDefinition , String inputName , GraphQLList graphQLList , Object value , List <Object > nameStack ) {
294+ private List coerceValueForList (GraphqlFieldVisibility fieldVisibility , VariableDefinition variableDefinition , String inputName , GraphQLList graphQLList , Object value , Deque <Object > nameStack ) {
247295 if (value instanceof Iterable ) {
248296 List <Object > result = new ArrayList <>();
249297 for (Object val : (Iterable ) value ) {
0 commit comments