diff --git a/README.md b/README.md index 90e8502..b959c29 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This library provides extended validation of fields and field arguments for [gra # Status This code is currently under construction. It is fairly complete in providing powerful validation -but as it has NOT be consumed by a production like project then its API usefulness has not been tested +but as it has NOT been consumed by a production like project then its API usefulness has not been tested and battle tested. But the project welcomes all feedback and input on code design and validation requirements. @@ -21,13 +21,13 @@ But the project welcomes all feedback and input on code design and validation re com.graphql-java graphql-java-extended-validation - 0.0.3 + 0.0.4 pom ``` ```groovy -compile 'com.graphql-java:graphql-java-extended-validation:0.0.3' +compile 'com.graphql-java:graphql-java-extended-validation:0.0.4' ``` Its currently available from JCenter repo and Maven central is pending. @@ -409,7 +409,7 @@ The String must match the specified regular expression, which follows the Java r - Example : `updateDriver( licencePlate : String @Patttern(regex : "[A-Z][A-Z][A-Z]-[0-9][0-9][0-9]") : DriverDetails` -- Applies to : `String` +- Applies to : `String`, `Lists` - SDL : `directive @Pattern(regexp : String! =".*", message : String = "graphql.validation.Pattern.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION` diff --git a/src/main/java/graphql/validation/constraints/standard/PatternConstraint.java b/src/main/java/graphql/validation/constraints/standard/PatternConstraint.java index c4e4631..3889caf 100644 --- a/src/main/java/graphql/validation/constraints/standard/PatternConstraint.java +++ b/src/main/java/graphql/validation/constraints/standard/PatternConstraint.java @@ -4,16 +4,23 @@ import graphql.Scalars; import graphql.schema.GraphQLDirective; import graphql.schema.GraphQLInputType; +import graphql.schema.GraphQLList; +import graphql.schema.GraphQLType; import graphql.validation.constraints.AbstractDirectiveConstraint; import graphql.validation.constraints.Documentation; import graphql.validation.rules.ValidationEnvironment; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static graphql.schema.GraphQLTypeUtil.isList; +import static graphql.schema.GraphQLTypeUtil.isScalar; import static java.util.Collections.emptyList; public class PatternConstraint extends AbstractDirectiveConstraint { @@ -31,9 +38,9 @@ public Documentation getDocumentation() { .description("The String must match the specified regular expression, which follows the Java regular expression conventions.") - .example("updateDriver( licencePlate : String @Patttern(regex : \"[A-Z][A-Z][A-Z]-[0-9][0-9][0-9]\") : DriverDetails") + .example("updateDriver( licencePlate : String @Pattern(regexp : \"[A-Z][A-Z][A-Z]-[0-9][0-9][0-9]\") : DriverDetails") - .applicableTypeNames(Scalars.GraphQLString.getName()) + .applicableTypeNames(Scalars.GraphQLString.getName(), "Lists") .directiveSDL("directive @Pattern(regexp : String! =\".*\", message : String = \"%s\") " + "on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION", @@ -44,32 +51,45 @@ public Documentation getDocumentation() { @Override public boolean appliesToType(GraphQLInputType inputType) { return isOneOfTheseTypes(inputType, - Scalars.GraphQLString - ); + Scalars.GraphQLString) || isList(inputType); } @Override protected List runConstraint(ValidationEnvironment validationEnvironment) { Object validatedValue = validationEnvironment.getValidatedValue(); + GraphQLInputType argumentType = validationEnvironment.getValidatedType(); + if (validatedValue == null) { return emptyList(); } - String strValue = String.valueOf(validatedValue); - GraphQLDirective directive = validationEnvironment.getContextObject(GraphQLDirective.class); + List validatedValues; + + if (isList(argumentType)) { + validatedValues = (ArrayList)validatedValue; + } else { + validatedValues = Arrays.asList(validatedValue); + } + + for (Object value : validatedValues) { + String strValue = String.valueOf(value); - String patternArg = getStrArg(directive, "regexp"); - Pattern pattern = cachedPattern(patternArg); + GraphQLDirective directive = validationEnvironment.getContextObject(GraphQLDirective.class); - Matcher matcher = pattern.matcher(strValue); - if (!matcher.matches()) { - return mkError(validationEnvironment, directive, mkMessageParams(validatedValue, validationEnvironment, - "regexp", patternArg - )); + String patternArg = getStrArg(directive, "regexp"); + Pattern pattern = cachedPattern(patternArg); + + Matcher matcher = pattern.matcher(strValue); + if (!matcher.matches()) { + return mkError(validationEnvironment, directive, + mkMessageParams(validatedValue, validationEnvironment, "regexp", patternArg)); + } } return emptyList(); } + + private Pattern cachedPattern(String patternArg) { return SEEN_PATTERNS.computeIfAbsent(patternArg, Pattern::compile); } diff --git a/src/test/groovy/graphql/validation/constraints/standard/PatternConstraintTest.groovy b/src/test/groovy/graphql/validation/constraints/standard/PatternConstraintTest.groovy index 5291eea..d46d02d 100644 --- a/src/test/groovy/graphql/validation/constraints/standard/PatternConstraintTest.groovy +++ b/src/test/groovy/graphql/validation/constraints/standard/PatternConstraintTest.groovy @@ -22,6 +22,8 @@ class PatternConstraintTest extends BaseConstraintTestSupport { fieldDeclaration | argVal | expectedMessage 'field( arg : String @Pattern(regexp:"[A-Z]*") ) : ID' | "ABCd" | 'Pattern;path=/arg;val:ABCd;\t' 'field( arg : String @Pattern(regexp:"[A-Z]*") ) : ID' | "ABC" | '' + 'field( arg : [String] @Pattern(regexp:"[A-Z]*") ) : ID' | ["ABC"] | '' + 'field( arg : [String] @Pattern(regexp:"[A-Z]*") ) : ID' | ["ABC", "ABCd"] | 'Pattern;path=/arg;val:[ABC, ABCd];\t' // nulls are valid 'field( arg : String @Pattern(regexp:"[A-Z]*") ) : ID' | null | ''