Skip to content

Commit f58ea3a

Browse files
bbakermansetchy
andauthored
Adding support for ID scalar type to Pattern, NotEmpty, NotBlank and Size constraints as per #21 (#26)
Co-authored-by: Adam Setch <[email protected]>
1 parent d8ba27b commit f58ea3a

File tree

9 files changed

+64
-26
lines changed

9 files changed

+64
-26
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ The String must contain at least one non-whitespace character, according to Java
386386

387387
- Example : `updateAccident( accidentNotes : String @NotBlank) : DriverDetails`
388388

389-
- Applies to : `String`
389+
- Applies to : `String`, `ID`
390390

391391
- SDL : `directive @NotBlank(message : String = "graphql.validation.NotBlank.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION`
392392

@@ -399,7 +399,7 @@ The element must have a non zero size.
399399

400400
- Example : `updateAccident( accidentNotes : [Notes]! @NotEmpty) : DriverDetails`
401401

402-
- Applies to : `String`, `Lists`, `Input Objects`
402+
- Applies to : `String`, `ID`, `Lists`, `Input Objects`
403403

404404
- SDL : `directive @NotEmpty(message : String = "graphql.validation.NotEmpty.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION`
405405

@@ -410,9 +410,9 @@ The element must have a non zero size.
410410

411411
The String must match the specified regular expression, which follows the Java regular expression conventions.
412412

413-
- Example : `updateDriver( licencePlate : String @Patttern(regex : "[A-Z][A-Z][A-Z]-[0-9][0-9][0-9]") : DriverDetails`
413+
- Example : `updateDriver( licencePlate : String @Pattern(regexp : "[A-Z][A-Z][A-Z]-[0-9][0-9][0-9]") : DriverDetails`
414414

415-
- Applies to : `String`, `Lists`
415+
- Applies to : `String`, `ID`, `Lists`
416416

417417
- SDL : `directive @Pattern(regexp : String! =".*", message : String = "graphql.validation.Pattern.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION`
418418

@@ -464,7 +464,7 @@ The element size must be between the specified `min` and `max` boundaries (inclu
464464

465465
- Example : `updateDrivingNotes( drivingNote : String @Size( min : 1000, max : 100000)) : DriverDetails`
466466

467-
- Applies to : `String`, `Lists`, `Input Objects`
467+
- Applies to : `String`, `ID`, `Lists`, `Input Objects`
468468

469469
- SDL : `directive @Size(min : Int = 0, max : Int = 2147483647, message : String = "graphql.validation.Size.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION`
470470

src/main/java/graphql/validation/constraints/AbstractDirectiveConstraint.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ private List<GraphQLError> runConstraintOnDirectives(ValidationEnvironment valid
161161
* @param inputType the type to check
162162
* @param scalarTypes the array of scalar types
163163
*
164-
* @return true ifits oneof them
164+
* @return true if its one of them
165165
*/
166166
protected boolean isOneOfTheseTypes(GraphQLInputType inputType, GraphQLScalarType... scalarTypes) {
167167
GraphQLInputType type = Util.unwrapNonNull(inputType);
@@ -304,19 +304,31 @@ protected List<GraphQLError> mkError(ValidationEnvironment validationEnvironment
304304
}
305305

306306
/**
307-
* Return true if the type is a String or List type or {@link graphql.schema.GraphQLInputObjectType}, regardless of non null ness
307+
* Return true if the type is a String or ID or List type or {@link graphql.schema.GraphQLInputObjectType}, regardless of non null ness
308308
*
309309
* @param inputType the type to check
310310
*
311311
* @return true if one of the above
312312
*/
313-
protected boolean isStringOrListOrMap(GraphQLInputType inputType) {
313+
protected boolean isStringOrIDOrListOrMap(GraphQLInputType inputType) {
314314
GraphQLInputType unwrappedType = Util.unwrapOneAndAllNonNull(inputType);
315-
return Scalars.GraphQLString.equals(unwrappedType) ||
315+
return isStringOrID(inputType) ||
316316
isList(inputType) ||
317317
(unwrappedType instanceof GraphQLInputObjectType);
318318
}
319319

320+
/**
321+
* Return true if the type is a String or ID
322+
*
323+
* @param inputType the type to check
324+
*
325+
* @return true if one of the above
326+
*/
327+
protected boolean isStringOrID(GraphQLInputType inputType) {
328+
GraphQLInputType unwrappedType = Util.unwrapNonNull(inputType);
329+
return Scalars.GraphQLString.equals(unwrappedType) || Scalars.GraphQLID.equals(unwrappedType);
330+
}
331+
320332
/**
321333
* Casts the object as a Map with an assertion of it is not one
322334
*
@@ -374,18 +386,18 @@ protected boolean asBoolean(Object value) {
374386
}
375387

376388
/**
377-
* Returns the length of a String of the size of a list or size of a Map
389+
* Returns the length of a String, ID, size of a list or size of a Map
378390
*
379391
* @param inputType the input type
380392
* @param value the value
381393
*
382394
* @return the length of a String or Map or List
383395
*/
384-
protected int getStringOrObjectOrMapLength(GraphQLInputType inputType, Object value) {
396+
protected int getStringOrIDOrObjectOrMapLength(GraphQLInputType inputType, Object value) {
385397
int valLen;
386398
if (value == null) {
387399
valLen = 0;
388-
} else if (Scalars.GraphQLString.equals(Util.unwrapNonNull(inputType))) {
400+
} else if (isStringOrID(inputType)) {
389401
valLen = String.valueOf(value).length();
390402
} else if (isList(inputType)) {
391403
valLen = getListLength(value);

src/main/java/graphql/validation/constraints/standard/NotBlankRule.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public Documentation getDocumentation() {
2626

2727
.example("updateAccident( accidentNotes : String @NotBlank) : DriverDetails")
2828

29-
.applicableTypeNames(Scalars.GraphQLString.getName())
29+
.applicableTypeNames(Scalars.GraphQLString.getName(), Scalars.GraphQLID.getName())
3030

3131
.directiveSDL("directive @NotBlank(message : String = \"%s\") " +
3232
"on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION",
@@ -36,7 +36,7 @@ public Documentation getDocumentation() {
3636

3737
@Override
3838
public boolean appliesToType(GraphQLInputType inputType) {
39-
return isOneOfTheseTypes(inputType, Scalars.GraphQLString);
39+
return isStringOrID(inputType);
4040
}
4141

4242
@Override

src/main/java/graphql/validation/constraints/standard/NotEmptyRule.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import graphql.validation.constraints.AbstractDirectiveConstraint;
88
import graphql.validation.constraints.Documentation;
99
import graphql.validation.rules.ValidationEnvironment;
10-
1110
import java.util.Collections;
1211
import java.util.List;
1312

@@ -26,7 +25,7 @@ public Documentation getDocumentation() {
2625

2726
.example("updateAccident( accidentNotes : [Notes]! @NotEmpty) : DriverDetails")
2827

29-
.applicableTypeNames(Scalars.GraphQLString.getName(), "Lists", "Input Objects")
28+
.applicableTypeNames(Scalars.GraphQLString.getName(), Scalars.GraphQLID.getName(), "Lists", "Input Objects")
3029

3130
.directiveSDL("directive @NotEmpty(message : String = \"%s\") " +
3231
"on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION",
@@ -36,7 +35,7 @@ public Documentation getDocumentation() {
3635

3736
@Override
3837
public boolean appliesToType(GraphQLInputType inputType) {
39-
return isStringOrListOrMap(inputType);
38+
return isStringOrIDOrListOrMap(inputType);
4039
}
4140

4241
@Override
@@ -45,7 +44,7 @@ protected List<GraphQLError> runConstraint(ValidationEnvironment validationEnvir
4544
GraphQLInputType argumentType = validationEnvironment.getValidatedType();
4645

4746
GraphQLDirective directive = validationEnvironment.getContextObject(GraphQLDirective.class);
48-
int size = getStringOrObjectOrMapLength(argumentType, validatedValue);
47+
int size = getStringOrIDOrObjectOrMapLength(argumentType, validatedValue);
4948

5049
if (size <= 0) {
5150
return mkError(validationEnvironment, directive, mkMessageParams(validatedValue, validationEnvironment,

src/main/java/graphql/validation/constraints/standard/PatternConstraint.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public Documentation getDocumentation() {
3535

3636
.example("updateDriver( licencePlate : String @Pattern(regexp : \"[A-Z][A-Z][A-Z]-[0-9][0-9][0-9]\") : DriverDetails")
3737

38-
.applicableTypeNames(Scalars.GraphQLString.getName(), "Lists")
38+
.applicableTypeNames(Scalars.GraphQLString.getName(), Scalars.GraphQLID.getName(), "Lists")
3939

4040
.directiveSDL("directive @Pattern(regexp : String! =\".*\", message : String = \"%s\") " +
4141
"on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION",
@@ -45,8 +45,7 @@ public Documentation getDocumentation() {
4545

4646
@Override
4747
public boolean appliesToType(GraphQLInputType inputType) {
48-
return isOneOfTheseTypes(inputType,
49-
Scalars.GraphQLString) || isList(inputType);
48+
return isStringOrID(inputType) || isList(inputType);
5049
}
5150

5251
@Override

src/main/java/graphql/validation/constraints/standard/SizeConstraint.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public Documentation getDocumentation() {
2828

2929
.example("updateDrivingNotes( drivingNote : String @Size( min : 1000, max : 100000)) : DriverDetails")
3030

31-
.applicableTypeNames(Scalars.GraphQLString.getName(), "Lists", "Input Objects")
31+
.applicableTypeNames(Scalars.GraphQLString.getName(), Scalars.GraphQLID.getName(), "Lists", "Input Objects")
3232

3333
.directiveSDL("directive @Size(min : Int = 0, max : Int = %d, message : String = \"%s\") " +
3434
"on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION",
@@ -39,7 +39,7 @@ Integer.MAX_VALUE, getMessageTemplate())
3939

4040
@Override
4141
public boolean appliesToType(GraphQLInputType inputType) {
42-
return isStringOrListOrMap(inputType);
42+
return isStringOrIDOrListOrMap(inputType);
4343
}
4444

4545
@Override
@@ -52,7 +52,7 @@ protected List<GraphQLError> runConstraint(ValidationEnvironment validationEnvir
5252
int max = getIntArg(directive, "max");
5353

5454

55-
int size = getStringOrObjectOrMapLength(argType, validatedValue);
55+
int size = getStringOrIDOrObjectOrMapLength(argType, validatedValue);
5656

5757
if (size < min) {
5858
return mkError(validationEnvironment, directive, mkParams(validatedValue, validationEnvironment, min, max, size));

src/test/groovy/graphql/validation/constraints/standard/NoEmptyBlankConstraintTest.groovy

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,17 @@ class NoEmptyBlankConstraintTest extends BaseConstraintTestSupport {
2020
where:
2121

2222
fieldDeclaration | argVal | expectedMessage
23+
// strings
2324
'field( arg : String @NotBlank ) : ID' | "\t\n\r " | 'NotBlank;path=/arg;val:\t\n\r ;\t'
2425
'field( arg : String @NotBlank ) : ID' | "" | 'NotBlank;path=/arg;val:;\t'
2526
'field( arg : String @NotBlank ) : ID' | "\t\n\r X" | ''
26-
27-
// nulls are INVALID
2827
'field( arg : String @NotBlank ) : ID' | null | 'NotBlank;path=/arg;val:null;\t'
28+
29+
// IDs
30+
'field( arg : ID @NotBlank ) : ID' | "\t\n\r " | 'NotBlank;path=/arg;val:\t\n\r ;\t'
31+
'field( arg : ID @NotBlank ) : ID' | "" | 'NotBlank;path=/arg;val:;\t'
32+
'field( arg : ID @NotBlank ) : ID' | "\t\n\r X" | ''
33+
'field( arg : ID @NotBlank ) : ID' | null | 'NotBlank;path=/arg;val:null;\t'
2934
}
3035

3136
@Unroll
@@ -47,6 +52,13 @@ class NoEmptyBlankConstraintTest extends BaseConstraintTestSupport {
4752
'field( arg : String @NotEmpty ) : ID' | "\t\n\r" | ''
4853
'field( arg : String @NotEmpty ) : ID' | "ABC" | ''
4954

55+
// IDs
56+
'field( arg : ID @NotEmpty ) : ID' | "" | 'NotEmpty;path=/arg;val:;\t'
57+
'field( arg : ID @NotEmpty ) : ID' | null | 'NotEmpty;path=/arg;val:null;\t'
58+
'field( arg : ID @NotEmpty ) : ID' | "\t\n\r" | ''
59+
'field( arg : ID @NotEmpty ) : ID' | "ABC" | ''
60+
61+
5062
// objects
5163
'field( arg : InputObject @NotEmpty ) : ID' | [:] | 'NotEmpty;path=/arg;val:[:];\t'
5264
'field( arg : InputObject @NotEmpty ) : ID' | null | 'NotEmpty;path=/arg;val:null;\t'
@@ -56,6 +68,9 @@ class NoEmptyBlankConstraintTest extends BaseConstraintTestSupport {
5668
'field( arg : [String] @NotEmpty ) : ID' | [] | 'NotEmpty;path=/arg;val:[];\t'
5769
'field( arg : [String] @NotEmpty ) : ID' | null | 'NotEmpty;path=/arg;val:null;\t'
5870
'field( arg : [String] @NotEmpty ) : ID' | ["x"] | ''
71+
'field( arg : [ID] @NotEmpty ) : ID' | [] | 'NotEmpty;path=/arg;val:[];\t'
72+
'field( arg : [ID] @NotEmpty ) : ID' | null | 'NotEmpty;path=/arg;val:null;\t'
73+
'field( arg : [ID] @NotEmpty ) : ID' | ["x"] | ''
5974

6075
}
6176

src/test/groovy/graphql/validation/constraints/standard/PatternConstraintTest.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@ class PatternConstraintTest extends BaseConstraintTestSupport {
2222
fieldDeclaration | argVal | expectedMessage
2323
'field( arg : String @Pattern(regexp:"[A-Z]*") ) : ID' | "ABCd" | 'Pattern;path=/arg;val:ABCd;\t'
2424
'field( arg : String @Pattern(regexp:"[A-Z]*") ) : ID' | "ABC" | ''
25+
'field( arg : ID @Pattern(regexp:"[A-Z]*") ) : ID' | "ABCd" | 'Pattern;path=/arg;val:ABCd;\t'
26+
'field( arg : ID @Pattern(regexp:"[A-Z]*") ) : ID' | "ABC" | ''
2527
'field( arg : [String] @Pattern(regexp:"[A-Z]*") ) : ID' | ["ABC"] | ''
2628
'field( arg : [String] @Pattern(regexp:"[A-Z]*") ) : ID' | ["ABC", "ABCd"] | 'Pattern;path=/arg;val:[ABC, ABCd];\t'
29+
'field( arg : [ID] @Pattern(regexp:"[A-Z]*") ) : ID' | ["ABC"] | ''
30+
'field( arg : [ID] @Pattern(regexp:"[A-Z]*") ) : ID' | ["ABC", "ABCd"] | 'Pattern;path=/arg;val:[ABC, ABCd];\t'
2731

2832
// nulls are valid
2933
'field( arg : String @Pattern(regexp:"[A-Z]*") ) : ID' | null | ''

src/test/groovy/graphql/validation/constraints/standard/SizeConstraintTest.groovy

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,20 @@ class SizeConstraintTest extends BaseConstraintTestSupport {
2020
where:
2121

2222
fieldDeclaration | argVal | expectedMessage
23+
// strings
2324
"field( arg : String @Size(max : 10) ) : ID" | "1234567891011" | "Size;path=/arg;val:1234567891011;\t"
2425
"field( arg : String @Size(max : 100) ) : ID" | "1234567891011" | ""
2526
"field( arg : String @Size(max : 10, min : 5) ) : ID" | "123" | "Size;path=/arg;val:123;\t"
2627

2728
'field( arg : String @Size(min : 5, message : "custom") ) : ID' | "123" | "custom;path=/arg;val:123;\t"
2829
"field( arg : String @Size(min : 5) ) : ID" | null | "Size;path=/arg;val:null;\t"
30+
31+
//IDs
32+
"field( arg : ID @Size(max : 10) ) : ID" | "1234567891011" | "Size;path=/arg;val:1234567891011;\t"
33+
"field( arg : ID @Size(max : 100) ) : ID" | "1234567891011" | ""
34+
"field( arg : ID @Size(max : 10, min : 5) ) : ID" | "123" | "Size;path=/arg;val:123;\t"
35+
36+
'field( arg : ID @Size(min : 5, message : "custom") ) : ID' | "123" | "custom;path=/arg;val:123;\t"
37+
"field( arg : ID @Size(min : 5) ) : ID" | null | "Size;path=/arg;val:null;\t"
2938
}
3039
}

0 commit comments

Comments
 (0)