66import graphql .schema .*;
77
88import java .util .LinkedHashMap ;
9+ import java .util .List ;
910import java .util .Map ;
11+ import java .util .Set ;
12+ import java .util .function .Predicate ;
13+ import java .util .stream .Collectors ;
1014
1115public class ValidationUtil {
1216
@@ -21,12 +25,29 @@ public TypeName getUnmodifiedType(Type type) {
2125 throw new ShouldNotHappenException ();
2226 }
2327
28+ protected void handleNullError (Value value , GraphQLType type ) {}
29+
30+ protected void handleScalarError (Value value , GraphQLScalarType type ) {}
31+
32+ protected void handleEnumError (Value value , GraphQLEnumType type ) {}
33+
34+ protected void handleNotObjectError (Value value , GraphQLInputObjectType type ) {}
35+
36+ protected void handleMissingFieldsError (Value value , GraphQLInputObjectType type , Set <String > missingFields ) {}
37+
38+ protected void handleExtraFieldError (Value value , GraphQLInputObjectType type , ObjectField objectField ) {}
39+
40+ protected void handleFieldNotValidError (ObjectField objectField , GraphQLInputObjectType type ) {}
41+
42+ protected void handleFieldNotValidError (Value value , GraphQLType type , int index ) {}
43+
2444 public boolean isValidLiteralValue (Value value , GraphQLType type ) {
25- if (value == null ) {
26- return !(type instanceof GraphQLNonNull );
27- }
28- if (value instanceof NullValue ) {
29- return !(type instanceof GraphQLNonNull );
45+ if (value == null || value instanceof NullValue ) {
46+ boolean valid = !(type instanceof GraphQLNonNull );
47+ if (!valid ) {
48+ handleNullError (value , type );
49+ }
50+ return valid ;
3051 }
3152 if (value instanceof VariableReference ) {
3253 return true ;
@@ -36,10 +57,18 @@ public boolean isValidLiteralValue(Value value, GraphQLType type) {
3657 }
3758
3859 if (type instanceof GraphQLScalarType ) {
39- return ((GraphQLScalarType ) type ).getCoercing ().parseLiteral (value ) != null ;
60+ boolean valid = ((GraphQLScalarType ) type ).getCoercing ().parseLiteral (value ) != null ;
61+ if (!valid ) {
62+ handleScalarError (value , (GraphQLScalarType ) type );
63+ }
64+ return valid ;
4065 }
4166 if (type instanceof GraphQLEnumType ) {
42- return ((GraphQLEnumType ) type ).getCoercing ().parseLiteral (value ) != null ;
67+ boolean valid = ((GraphQLEnumType ) type ).getCoercing ().parseLiteral (value ) != null ;
68+ if (!valid ) {
69+ handleEnumError (value , (GraphQLEnumType ) type );
70+ }
71+ return valid ;
4372 }
4473
4574 if (type instanceof GraphQLList ) {
@@ -53,27 +82,40 @@ public boolean isValidLiteralValue(Value value, GraphQLType type) {
5382 }
5483
5584 private boolean isValidLiteralValue (Value value , GraphQLInputObjectType type ) {
56- if (!(value instanceof ObjectValue )) return false ;
85+ if (!(value instanceof ObjectValue )) {
86+ handleNotObjectError (value , type );
87+ return false ;
88+ }
5789 ObjectValue objectValue = (ObjectValue ) value ;
5890 Map <String , ObjectField > objectFieldMap = fieldMap (objectValue );
5991
60- if (isFieldMissing (type , objectFieldMap )) return false ;
92+ Set <String > missingFields = getMissingFields (type , objectFieldMap );
93+ if (!missingFields .isEmpty ()) {
94+ handleMissingFieldsError (value , type , missingFields );
95+ return false ;
96+ }
6197
6298 for (ObjectField objectField : objectValue .getObjectFields ()) {
6399 GraphQLInputObjectField inputObjectField = type .getField (objectField .getName ());
64- if (inputObjectField == null ) return false ;
65- if (!isValidLiteralValue (objectField .getValue (), inputObjectField .getType ())) return false ;
100+ if (inputObjectField == null ) {
101+ handleExtraFieldError (value , type , objectField );
102+ return false ;
103+ }
104+ if (!isValidLiteralValue (objectField .getValue (), inputObjectField .getType ())) {
105+ handleFieldNotValidError (objectField , type );
106+ return false ;
107+ }
66108
67109 }
68110 return true ;
69111 }
70112
71- private boolean isFieldMissing (GraphQLInputObjectType type , Map <String , ObjectField > objectFieldMap ) {
72- for ( GraphQLInputObjectField inputObjectField : type .getFields ()) {
73- if (! objectFieldMap . containsKey ( inputObjectField . getName ()) &&
74- ( inputObjectField . getType () instanceof GraphQLNonNull )) return true ;
75- }
76- return false ;
113+ private Set < String > getMissingFields (GraphQLInputObjectType type , Map <String , ObjectField > objectFieldMap ) {
114+ return type .getFields (). stream ()
115+ . filter ( field -> field . getType () instanceof GraphQLNonNull )
116+ . map ( GraphQLInputObjectField :: getName )
117+ . filter ((( Predicate < String >) objectFieldMap :: containsKey ). negate ())
118+ . collect ( Collectors . toSet ()) ;
77119 }
78120
79121 private Map <String , ObjectField > fieldMap (ObjectValue objectValue ) {
@@ -87,8 +129,12 @@ private Map<String, ObjectField> fieldMap(ObjectValue objectValue) {
87129 private boolean isValidLiteralValue (Value value , GraphQLList type ) {
88130 GraphQLType wrappedType = type .getWrappedType ();
89131 if (value instanceof ArrayValue ) {
90- for (Value innerValue : ((ArrayValue ) value ).getValues ()) {
91- if (!isValidLiteralValue (innerValue , wrappedType )) return false ;
132+ List <Value > values = ((ArrayValue ) value ).getValues ();
133+ for (int i = 0 ; i < values .size (); i ++) {
134+ if (!isValidLiteralValue (values .get (i ), wrappedType )) {
135+ handleFieldNotValidError (values .get (i ), wrappedType , i );
136+ return false ;
137+ }
92138 }
93139 return true ;
94140 } else {
0 commit comments