31
31
import java .util .Map ;
32
32
33
33
import 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 ;
34
36
import static java .util .Collections .singletonList ;
35
37
36
38
@ SuppressWarnings ("UnnecessaryLocalVariable" )
@@ -85,48 +87,55 @@ public boolean appliesTo(GraphQLArgument argument, GraphQLFieldDefinition fieldD
85
87
return suitable ;
86
88
}
87
89
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
+ */
88
97
abstract protected boolean appliesToType (GraphQLInputType inputType );
89
98
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
+ */
90
106
abstract protected List <GraphQLError > runConstraint (ValidationEnvironment validationEnvironment );
91
107
92
108
93
109
@ SuppressWarnings ("unchecked" )
94
110
@ Override
95
111
public List <GraphQLError > runValidation (ValidationEnvironment validationEnvironment ) {
96
112
113
+ // output fields are special
114
+ if (validationEnvironment .getValidatedElement () == FIELD ) {
115
+ return runFieldValidationImpl (validationEnvironment );
116
+ }
117
+
97
118
GraphQLArgument argument = validationEnvironment .getArgument ();
98
119
Object validatedValue = validationEnvironment .getValidatedValue ();
99
- List <GraphQLDirective > directives = argument .getDirectives ();
120
+ List <GraphQLDirective > directives = argument == null ? Collections . emptyList () : argument .getDirectives ();
100
121
101
122
//
102
123
// all the directives validation code does NOT care for NULL ness since the graphql engine covers that.
103
124
// eg a @NonNull validation directive makes no sense in graphql like it might in Java
104
125
//
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 ));
107
128
108
129
return runValidationImpl (validationEnvironment , inputType , validatedValue , directives );
109
130
}
110
131
132
+ private List <GraphQLError > runFieldValidationImpl (ValidationEnvironment validationEnvironment ) {
133
+ return runConstraintOnDirectives (validationEnvironment , validationEnvironment .getFieldDefinition ().getDirectives ());
134
+ }
135
+
111
136
@ SuppressWarnings ("unchecked" )
112
137
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 );
130
139
if (validatedValue == null ) {
131
140
return errors ;
132
141
}
@@ -151,6 +160,26 @@ private List<GraphQLError> runValidationImpl(ValidationEnvironment validationEnv
151
160
return errors ;
152
161
}
153
162
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
+
154
183
private List <GraphQLError > walkObjectArg (ValidationEnvironment validationEnvironment , GraphQLInputObjectType argumentType , Map <String , Object > objectMap ) {
155
184
List <GraphQLError > errors = new ArrayList <>();
156
185
@@ -165,12 +194,13 @@ private List<GraphQLError> walkObjectArg(ValidationEnvironment validationEnviron
165
194
continue ;
166
195
}
167
196
168
- ExecutionPath fieldOrArgPath = validationEnvironment .getFieldOrArgumentPath ().segment (inputField .getName ());
197
+ ExecutionPath newPath = validationEnvironment .getValidatedPath ().segment (inputField .getName ());
169
198
170
199
ValidationEnvironment newValidationEnvironment = validationEnvironment .transform (builder -> builder
171
- .fieldOrArgumentPath ( fieldOrArgPath )
200
+ .validatedPath ( newPath )
172
201
.validatedValue (validatedValue )
173
- .fieldOrArgumentType (fieldType )
202
+ .validatedType (fieldType )
203
+ .validatedElement (INPUT_OBJECT_FIELD )
174
204
);
175
205
176
206
List <GraphQLError > ruleErrors = runValidationImpl (newValidationEnvironment , fieldType , validatedValue , directives );
@@ -192,12 +222,12 @@ private List<GraphQLError> walkListArg(ValidationEnvironment validationEnvironme
192
222
int ix = 0 ;
193
223
for (Object value : objectList ) {
194
224
195
- ExecutionPath fieldOrArgPath = validationEnvironment .getFieldOrArgumentPath ().segment (ix );
225
+ ExecutionPath newPath = validationEnvironment .getValidatedPath ().segment (ix );
196
226
197
227
ValidationEnvironment newValidationEnvironment = validationEnvironment .transform (builder -> builder
198
- .fieldOrArgumentPath ( fieldOrArgPath )
228
+ .validatedPath ( newPath )
199
229
.validatedValue (value )
200
- .fieldOrArgumentType (listItemType )
230
+ .validatedType (listItemType )
201
231
);
202
232
203
233
List <GraphQLError > ruleErrors = runValidationImpl (newValidationEnvironment , listItemType , value , directives );
@@ -331,7 +361,7 @@ protected Map<String, Object> mkMessageParams(Object validatedValue, ValidationE
331
361
Map <String , Object > params = new LinkedHashMap <>();
332
362
params .put ("validatedValue" , validatedValue );
333
363
params .put ("constraint" , getName ());
334
- params .put ("path" , mkFieldOrArgPath ( validationEnvironment ));
364
+ params .put ("path" , validationEnvironment . getValidatedPath ( ));
335
365
336
366
params .putAll (mkMap (args ));
337
367
return params ;
@@ -357,15 +387,6 @@ protected Map<String, Object> mkMap(Object... args) {
357
387
return params ;
358
388
}
359
389
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
-
369
390
/**
370
391
* Creates a new {@link graphql.GraphQLError}
371
392
*
0 commit comments