3131import java .util .Map ;
3232
3333import static graphql .schema .GraphQLTypeUtil .isList ;
34+ import static graphql .validation .rules .ValidationEnvironment .ValidatedElement .FIELD ;
35+ import static graphql .validation .rules .ValidationEnvironment .ValidatedElement .INPUT_OBJECT_FIELD ;
3436import static java .util .Collections .singletonList ;
3537
3638@ SuppressWarnings ("UnnecessaryLocalVariable" )
@@ -85,48 +87,55 @@ public boolean appliesTo(GraphQLArgument argument, GraphQLFieldDefinition fieldD
8587 return suitable ;
8688 }
8789
90+ /**
91+ * A derived class will be called to indicate whether this input type applies to the constraint
92+ *
93+ * @param inputType the input type
94+ *
95+ * @return true if the constraint can handle that type
96+ */
8897 abstract protected boolean appliesToType (GraphQLInputType inputType );
8998
99+ /**
100+ * This is called to perform the constraint validation
101+ *
102+ * @param validationEnvironment the validation environment
103+ *
104+ * @return a list of errors or an empty one if there are no errors
105+ */
90106 abstract protected List <GraphQLError > runConstraint (ValidationEnvironment validationEnvironment );
91107
92108
93109 @ SuppressWarnings ("unchecked" )
94110 @ Override
95111 public List <GraphQLError > runValidation (ValidationEnvironment validationEnvironment ) {
96112
113+ // output fields are special
114+ if (validationEnvironment .getValidatedElement () == FIELD ) {
115+ return runFieldValidationImpl (validationEnvironment );
116+ }
117+
97118 GraphQLArgument argument = validationEnvironment .getArgument ();
98119 Object validatedValue = validationEnvironment .getValidatedValue ();
99- List <GraphQLDirective > directives = argument .getDirectives ();
120+ List <GraphQLDirective > directives = argument == null ? Collections . emptyList () : argument .getDirectives ();
100121
101122 //
102123 // all the directives validation code does NOT care for NULL ness since the graphql engine covers that.
103124 // eg a @NonNull validation directive makes no sense in graphql like it might in Java
104125 //
105- GraphQLInputType inputType = Util .unwrapNonNull (validationEnvironment .getFieldOrArgumentType ());
106- validationEnvironment = validationEnvironment .transform (b -> b .fieldOrArgumentType (inputType ));
126+ GraphQLInputType inputType = Util .unwrapNonNull (validationEnvironment .getValidatedType ());
127+ validationEnvironment = validationEnvironment .transform (b -> b .validatedType (inputType ));
107128
108129 return runValidationImpl (validationEnvironment , inputType , validatedValue , directives );
109130 }
110131
132+ private List <GraphQLError > runFieldValidationImpl (ValidationEnvironment validationEnvironment ) {
133+ return runConstraintOnDirectives (validationEnvironment , validationEnvironment .getFieldDefinition ().getDirectives ());
134+ }
135+
111136 @ SuppressWarnings ("unchecked" )
112137 private List <GraphQLError > runValidationImpl (ValidationEnvironment validationEnvironment , GraphQLInputType inputType , Object validatedValue , List <GraphQLDirective > directives ) {
113- List <GraphQLError > errors = new ArrayList <>();
114- // run them in a stable order
115- directives = Util .sort (directives , GraphQLDirective ::getName );
116- for (GraphQLDirective directive : directives ) {
117- // we get called for arguments and input field types which can have multiple directive constraints on them and hence no just for this one
118- boolean isOurDirective = directive .getName ().equals (this .getName ());
119- if (!isOurDirective ) {
120- continue ;
121- }
122-
123- validationEnvironment = validationEnvironment .transform (b -> b .context (GraphQLDirective .class , directive ));
124- //
125- // now run the directive rule with this directive instance
126- List <GraphQLError > ruleErrors = this .runConstraint (validationEnvironment );
127- errors .addAll (ruleErrors );
128- }
129-
138+ List <GraphQLError > errors = runConstraintOnDirectives (validationEnvironment , directives );
130139 if (validatedValue == null ) {
131140 return errors ;
132141 }
@@ -151,6 +160,26 @@ private List<GraphQLError> runValidationImpl(ValidationEnvironment validationEnv
151160 return errors ;
152161 }
153162
163+ private List <GraphQLError > runConstraintOnDirectives (ValidationEnvironment validationEnvironment , List <GraphQLDirective > directives ) {
164+ List <GraphQLError > errors = new ArrayList <>();
165+ directives = Util .sort (directives , GraphQLDirective ::getName );
166+
167+ for (GraphQLDirective directive : directives ) {
168+ // we get called for arguments and input field and field types which can have multiple directive constraints on them and hence no just for this one
169+ boolean isOurDirective = directive .getName ().equals (this .getName ());
170+ if (!isOurDirective ) {
171+ continue ;
172+ }
173+
174+ validationEnvironment = validationEnvironment .transform (b -> b .context (GraphQLDirective .class , directive ));
175+ //
176+ // now run the directive rule with this directive instance
177+ List <GraphQLError > ruleErrors = this .runConstraint (validationEnvironment );
178+ errors .addAll (ruleErrors );
179+ }
180+ return errors ;
181+ }
182+
154183 private List <GraphQLError > walkObjectArg (ValidationEnvironment validationEnvironment , GraphQLInputObjectType argumentType , Map <String , Object > objectMap ) {
155184 List <GraphQLError > errors = new ArrayList <>();
156185
@@ -165,12 +194,13 @@ private List<GraphQLError> walkObjectArg(ValidationEnvironment validationEnviron
165194 continue ;
166195 }
167196
168- ExecutionPath fieldOrArgPath = validationEnvironment .getFieldOrArgumentPath ().segment (inputField .getName ());
197+ ExecutionPath newPath = validationEnvironment .getValidatedPath ().segment (inputField .getName ());
169198
170199 ValidationEnvironment newValidationEnvironment = validationEnvironment .transform (builder -> builder
171- .fieldOrArgumentPath ( fieldOrArgPath )
200+ .validatedPath ( newPath )
172201 .validatedValue (validatedValue )
173- .fieldOrArgumentType (fieldType )
202+ .validatedType (fieldType )
203+ .validatedElement (INPUT_OBJECT_FIELD )
174204 );
175205
176206 List <GraphQLError > ruleErrors = runValidationImpl (newValidationEnvironment , fieldType , validatedValue , directives );
@@ -192,12 +222,12 @@ private List<GraphQLError> walkListArg(ValidationEnvironment validationEnvironme
192222 int ix = 0 ;
193223 for (Object value : objectList ) {
194224
195- ExecutionPath fieldOrArgPath = validationEnvironment .getFieldOrArgumentPath ().segment (ix );
225+ ExecutionPath newPath = validationEnvironment .getValidatedPath ().segment (ix );
196226
197227 ValidationEnvironment newValidationEnvironment = validationEnvironment .transform (builder -> builder
198- .fieldOrArgumentPath ( fieldOrArgPath )
228+ .validatedPath ( newPath )
199229 .validatedValue (value )
200- .fieldOrArgumentType (listItemType )
230+ .validatedType (listItemType )
201231 );
202232
203233 List <GraphQLError > ruleErrors = runValidationImpl (newValidationEnvironment , listItemType , value , directives );
@@ -331,7 +361,7 @@ protected Map<String, Object> mkMessageParams(Object validatedValue, ValidationE
331361 Map <String , Object > params = new LinkedHashMap <>();
332362 params .put ("validatedValue" , validatedValue );
333363 params .put ("constraint" , getName ());
334- params .put ("path" , mkFieldOrArgPath ( validationEnvironment ));
364+ params .put ("path" , validationEnvironment . getValidatedPath ( ));
335365
336366 params .putAll (mkMap (args ));
337367 return params ;
@@ -357,15 +387,6 @@ protected Map<String, Object> mkMap(Object... args) {
357387 return params ;
358388 }
359389
360-
361- private Object mkFieldOrArgPath (ValidationEnvironment validationEnvironment ) {
362- ExecutionPath executionPath = validationEnvironment .getExecutionPath ();
363- ExecutionPath fieldOrArgumentPath = validationEnvironment .getFieldOrArgumentPath ();
364-
365- executionPath = Util .concatPaths (executionPath , fieldOrArgumentPath );
366- return executionPath == null ? "/" : executionPath .toString ();
367- }
368-
369390 /**
370391 * Creates a new {@link graphql.GraphQLError}
371392 *
0 commit comments