Skip to content

Commit c229f69

Browse files
committed
More code and some early tests
1 parent c2ee1f3 commit c229f69

File tree

12 files changed

+226
-31
lines changed

12 files changed

+226
-31
lines changed

src/main/java/graphql/validation/directives/AbstractDirectiveValidationRule.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
public abstract class AbstractDirectiveValidationRule implements DirectiveValidationRule {
2828

29-
protected final String name;
29+
private final String name;
3030

3131
public AbstractDirectiveValidationRule(String name) {
3232
this.name = name;
@@ -42,7 +42,7 @@ public boolean appliesToArgument(GraphQLArgument argument, GraphQLFieldDefinitio
4242
boolean applicable = appliesToType(argument.getType());
4343
if (!applicable) {
4444
String argType = argument.getType().getName();
45-
Assert.assertShouldNeverHappen("The directive %s cannot be placed in arguments of type %s", getName(), argType);
45+
Assert.assertShouldNeverHappen("The directive %s cannot be placed on arguments of type %s", getName(), argType);
4646
}
4747
return true;
4848
}
@@ -74,7 +74,9 @@ protected GraphQLDirective getArgDirective(ValidationRuleEnvironment ruleEnviron
7474

7575
protected int getIntArg(GraphQLDirective directive, String argName, int defaultValue) {
7676
GraphQLArgument argument = directive.getArgument(argName);
77-
Assert.assertNotNull(argument);
77+
if (argument == null) {
78+
return defaultValue;
79+
}
7880
Number value = (Number) argument.getValue();
7981
if (value == null) {
8082
return defaultValue;
@@ -111,7 +113,7 @@ protected GraphQLInputType unwrap(GraphQLInputType inputType) {
111113

112114
protected List<GraphQLError> mkError(ValidationRuleEnvironment ruleEnvironment, GraphQLDirective directive, Map<String, Object> msgParams) {
113115
String messageTemplate = getMessageTemplate(directive);
114-
GraphQLError error = ruleEnvironment.getInterpolator().interpolate(messageTemplate, msgParams);
116+
GraphQLError error = ruleEnvironment.getInterpolator().interpolate(messageTemplate, msgParams, ruleEnvironment);
115117
return singletonList(error);
116118
}
117119

src/main/java/graphql/validation/directives/DirectiveValidationRule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public interface DirectiveValidationRule extends ValidationRule {
1414

1515
String getName();
1616

17+
String getDirectiveDeclarationSDL();
18+
1719
@Override
1820
default boolean appliesToArgument(GraphQLArgument argument, GraphQLFieldDefinition fieldDefinition, GraphQLFieldsContainer fieldsContainer) {
1921
return false;

src/main/java/graphql/validation/directives/DirectiveValidationRules.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ public Map<String, DirectiveValidationRule> getDirectiveRules() {
2929
return directiveRules;
3030
}
3131

32+
public String getDirectivesDeclarationSDL() {
33+
StringBuilder sb = new StringBuilder();
34+
for (DirectiveValidationRule value : directiveRules.values()) {
35+
sb.append("\n ").append(value.getDirectiveDeclarationSDL()).append("\n");
36+
}
37+
return sb.toString();
38+
}
39+
3240
public static Builder newDirectiveValidationRules() {
3341
return new Builder();
3442
}

src/main/java/graphql/validation/directives/standardrules/MaxRule.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ public MaxRule() {
1818
super("Max");
1919
}
2020

21+
@Override
22+
public String getDirectiveDeclarationSDL() {
23+
return String.format("directive @%s(value : Int = %d, message : String = \"%s\") " +
24+
"on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION",
25+
getName(), Integer.MAX_VALUE, "graphql.validation.Max.message");
26+
}
2127

2228
@Override
2329
protected boolean appliesToType(GraphQLInputType argumentType) {

src/main/java/graphql/validation/directives/standardrules/NotBlankRule.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ public NotBlankRule() {
1818
}
1919

2020

21+
@Override
22+
public String getDirectiveDeclarationSDL() {
23+
return String.format("directive @%s(message : String = \"%s\") " +
24+
"on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION",
25+
getName(), "graphql.validation.NotBlank.message");
26+
}
27+
2128
@Override
2229
protected boolean appliesToType(GraphQLInputType argumentType) {
2330
return appliesToTypes(argumentType, Scalars.GraphQLString);

src/main/java/graphql/validation/directives/standardrules/NotEmptyRule.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ public NotEmptyRule() {
1717
}
1818

1919

20+
@Override
21+
public String getDirectiveDeclarationSDL() {
22+
return String.format("directive @%s(message : String = \"%s\") " +
23+
"on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION",
24+
getName(), "graphql.validation.NotEmpty.message");
25+
}
26+
2027
@Override
2128
protected boolean appliesToType(GraphQLInputType argumentType) {
2229
return isStringOrListOrMap(argumentType);
@@ -29,11 +36,11 @@ public List<GraphQLError> runValidation(ValidationRuleEnvironment ruleEnvironmen
2936
GraphQLInputType argumentType = ruleEnvironment.getArgumentType();
3037

3138
GraphQLDirective ruleDirective = getArgDirective(ruleEnvironment, getName());
32-
int valLen = getStringOrObjectOrMapLength(argumentType, argumentValue);
39+
int size = getStringOrObjectOrMapLength(argumentType, argumentValue);
3340

34-
if (valLen <= 0) {
41+
if (size <= 0) {
3542
return mkError(ruleEnvironment, ruleDirective, mkMessageParams(
36-
"length", valLen,
43+
"size", size,
3744
"argumentValue", argumentValue));
3845
}
3946
return Collections.emptyList();

src/main/java/graphql/validation/directives/standardrules/SizeRule.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,20 @@
1010
import java.util.List;
1111
import java.util.Map;
1212

13-
// @Size(min : Int = 0, max : Int = 9999999, message : String = "graphql.validation.Size.message"
1413
public class SizeRule extends AbstractDirectiveValidationRule {
1514

1615
public SizeRule() {
1716
super("Size");
1817
}
1918

2019

20+
@Override
21+
public String getDirectiveDeclarationSDL() {
22+
return String.format("directive @%s(min : Int = %d, max : Int = %d, message : String = \"%s\") " +
23+
"on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION",
24+
getName(), 0, Integer.MAX_VALUE, "graphql.validation.Size.message");
25+
}
26+
2127
@Override
2228
protected boolean appliesToType(GraphQLInputType argumentType) {
2329
return isStringOrListOrMap(argumentType);
@@ -33,18 +39,18 @@ public List<GraphQLError> runValidation(ValidationRuleEnvironment ruleEnvironmen
3339
int max = getIntArg(sizeDirective, "max", Integer.MAX_VALUE);
3440

3541

36-
int valLen = getStringOrObjectOrMapLength(argType, argumentValue);
42+
int size = getStringOrObjectOrMapLength(argType, argumentValue);
3743

3844
Map<String, Object> msgParams = mkMessageParams(
3945
"min", min,
4046
"max", max,
41-
"length", valLen,
47+
"size", size,
4248
"argumentValue", argumentValue);
4349

44-
if (valLen < min) {
50+
if (size < min) {
4551
return mkError(ruleEnvironment, sizeDirective, msgParams);
4652
}
47-
if (valLen > max) {
53+
if (size > max) {
4854
return mkError(ruleEnvironment, sizeDirective, msgParams);
4955
}
5056
return Collections.emptyList();
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package graphql.validation.interpolation;
22

33
import graphql.GraphQLError;
4+
import graphql.validation.rules.ValidationRuleEnvironment;
45

56
import java.util.Map;
67

78
public interface MessageInterpolator {
89

9-
GraphQLError interpolate(String messageTemplate, Map<String, Object> messageParams);
10+
GraphQLError interpolate(String messageTemplate, Map<String, Object> messageParams, ValidationRuleEnvironment ruleEnvironment);
1011
}

src/main/java/graphql/validation/rules/ValidationRuleEnvironment.java

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package graphql.validation.rules;
22

3+
import graphql.execution.ExecutionPath;
4+
import graphql.language.SourceLocation;
35
import graphql.schema.DataFetchingEnvironment;
46
import graphql.schema.GraphQLArgument;
57
import graphql.schema.GraphQLFieldDefinition;
@@ -10,28 +12,42 @@
1012

1113
public class ValidationRuleEnvironment {
1214

13-
private final DataFetchingEnvironment dataFetchingEnvironment;
15+
private final GraphQLFieldsContainer fieldsContainer;
16+
private final GraphQLFieldDefinition fieldDefinition;
1417
private final GraphQLArgument argument;
1518
private final Object argumentValue;
19+
private final ExecutionPath executionPath;
20+
private final SourceLocation location;
1621
private final MessageInterpolator interpolator;
1722

1823
private ValidationRuleEnvironment(Builder builder) {
19-
this.dataFetchingEnvironment = builder.dataFetchingEnvironment;
2024
this.argument = builder.argument;
2125
this.argumentValue = builder.argumentValue;
2226
this.interpolator = builder.interpolator;
27+
this.fieldsContainer = builder.fieldsContainer;
28+
this.fieldDefinition = builder.fieldDefinition;
29+
this.executionPath = builder.executionPath;
30+
this.location = builder.location;
2331
}
2432

2533
public static Builder newValidationRuleEnvironment() {
2634
return new Builder();
2735
}
2836

2937
public GraphQLFieldsContainer getFieldsContainer() {
30-
return dataFetchingEnvironment.getExecutionStepInfo().getFieldContainer();
38+
return fieldsContainer;
3139
}
3240

3341
public GraphQLFieldDefinition getFieldDefinition() {
34-
return dataFetchingEnvironment.getExecutionStepInfo().getFieldDefinition();
42+
return fieldDefinition;
43+
}
44+
45+
public ExecutionPath getExecutionPath() {
46+
return executionPath;
47+
}
48+
49+
public SourceLocation getLocation() {
50+
return location;
3551
}
3652

3753
public GraphQLArgument getArgument() {
@@ -50,22 +66,29 @@ public Object getArgumentValue() {
5066
return argumentValue;
5167
}
5268

53-
public DataFetchingEnvironment getDataFetchingEnvironment() {
54-
return dataFetchingEnvironment;
55-
}
56-
5769
public MessageInterpolator getInterpolator() {
5870
return interpolator;
5971
}
6072

6173
public static class Builder {
62-
private DataFetchingEnvironment dataFetchingEnvironment;
74+
private GraphQLFieldsContainer fieldsContainer;
75+
private GraphQLFieldDefinition fieldDefinition;
6376
private GraphQLArgument argument;
6477
private Object argumentValue;
78+
private ExecutionPath executionPath;
79+
private SourceLocation location;
6580
private MessageInterpolator interpolator;
6681

6782
public Builder dataFetchingEnvironment(DataFetchingEnvironment dataFetchingEnvironment) {
68-
this.dataFetchingEnvironment = dataFetchingEnvironment;
83+
fieldsContainer(dataFetchingEnvironment.getExecutionStepInfo().getFieldContainer());
84+
fieldDefinition(dataFetchingEnvironment.getFieldDefinition());
85+
executionPath(dataFetchingEnvironment.getExecutionStepInfo().getPath());
86+
location(dataFetchingEnvironment.getField().getSourceLocation());
87+
return this;
88+
}
89+
90+
public Builder argumentValue(Object argValue) {
91+
this.argumentValue = argValue;
6992
return this;
7093
}
7194

@@ -74,8 +97,23 @@ public Builder argument(GraphQLArgument argument) {
7497
return this;
7598
}
7699

77-
public Builder argumentValue(Object argValue) {
78-
this.argumentValue = argValue;
100+
public Builder fieldsContainer(GraphQLFieldsContainer fieldsContainer) {
101+
this.fieldsContainer = fieldsContainer;
102+
return this;
103+
}
104+
105+
public Builder fieldDefinition(GraphQLFieldDefinition fieldDefinition) {
106+
this.fieldDefinition = fieldDefinition;
107+
return this;
108+
}
109+
110+
public Builder executionPath(ExecutionPath executionPath) {
111+
this.executionPath = executionPath;
112+
return this;
113+
}
114+
115+
public Builder location(SourceLocation location) {
116+
this.location = location;
79117
return this;
80118
}
81119

src/test/groovy/graphql/validation/directives/DirectiveValidationRulesTest.groovy

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package graphql.validation.directives
22

3+
import graphql.GraphQLError
4+
import graphql.GraphqlErrorBuilder
35
import graphql.schema.GraphQLArgument
46
import graphql.schema.GraphQLFieldDefinition
57
import graphql.schema.GraphQLFieldsContainer
68
import graphql.validation.TestUtil
9+
import graphql.validation.interpolation.MessageInterpolator
710
import graphql.validation.rules.ValidationRuleEnvironment
811
import spock.lang.Specification
912

@@ -18,34 +21,52 @@ class DirectiveValidationRulesTest extends Specification {
1821
}
1922

2023
def "basic size testing"() {
24+
25+
def rules = DirectiveValidationRules.newDirectiveValidationRules().build()
26+
2127
def field = '''
22-
field( argUnderTest : String) : String
28+
field( argUnderTest : String @Size(max : 10) ) : String
2329
'''
2430

2531
def sdl = """
32+
33+
${rules.directivesDeclarationSDL}
34+
2635
type Query {
2736
${field}
2837
}
2938
"""
3039

3140
def schema = TestUtil.schema(sdl)
3241

33-
GraphQLFieldsContainer containerType = schema.getObjectType("Query") as GraphQLFieldsContainer
34-
GraphQLFieldDefinition fieldDefinition = containerType.getFieldDefinition("field")
42+
GraphQLFieldsContainer fieldsContainer = schema.getObjectType("Query") as GraphQLFieldsContainer
43+
GraphQLFieldDefinition fieldDefinition = fieldsContainer.getFieldDefinition("field")
3544
GraphQLArgument argUnderTest = fieldDefinition.getArgument("argUnderTest")
3645

46+
MessageInterpolator interpolator = new MessageInterpolator() {
47+
48+
@Override
49+
GraphQLError interpolate(String messageTemplate, Map<String, Object> messageParams, ValidationRuleEnvironment ruleEnvironment) {
50+
def s = messageTemplate
51+
s += ":"
52+
messageParams.forEach({ k, v -> s += k + "=" + v + ";" })
53+
return GraphqlErrorBuilder.newError().message(s).build()
54+
}
55+
}
3756

3857
when:
39-
def rules = DirectiveValidationRules.newDirectiveValidationRules().build()
4058

4159
def ruleEnvironment = ValidationRuleEnvironment.newValidationRuleEnvironment()
4260
.argument(argUnderTest)
43-
.argumentValue("argumentValue")
61+
.argumentValue("1234567891011")
62+
.fieldDefinition(fieldDefinition)
63+
.fieldsContainer(fieldsContainer)
64+
.messageInterpolator(interpolator)
4465
.build()
4566

4667

4768
then:
48-
rules.appliesToArgument(argUnderTest, fieldDefinition, containerType)
69+
rules.appliesToArgument(argUnderTest, fieldDefinition, fieldsContainer)
4970
rules.runValidation(ruleEnvironment).size() == 0
5071

5172

0 commit comments

Comments
 (0)