1010import java .math .BigDecimal ;
1111import java .util .Collections ;
1212import java .util .List ;
13+ import java .util .Optional ;
1314
1415import static graphql .validation .constraints .GraphQLScalars .GRAPHQL_NUMBER_AND_STRING_TYPES ;
1516
@@ -21,14 +22,14 @@ public DigitsConstraint() {
2122 @ Override
2223 public Documentation getDocumentation () {
2324 return Documentation .newDocumentation ()
24- .messageTemplate (getMessageTemplate ())
25- .description ("The element must be a number inside the specified `integer` and `fraction` range." )
26- .example ("buyCar( carCost : Float @Digits(integer : 5, fraction : 2) : DriverDetails" )
27- .applicableTypes (GRAPHQL_NUMBER_AND_STRING_TYPES )
28- .directiveSDL ("directive @Digits(integer : Int!, fraction : Int! , message : String = \" %s\" ) " +
29- "on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION" ,
30- getMessageTemplate ())
31- .build ();
25+ .messageTemplate (getMessageTemplate ())
26+ .description ("The element must be a number inside the specified `integer` and optionally inside `fraction` range." )
27+ .example ("buyCar( carCost : Float @Digits(integer : 5, fraction : 2) : DriverDetails" )
28+ .applicableTypes (GRAPHQL_NUMBER_AND_STRING_TYPES )
29+ .directiveSDL ("directive @Digits(integer : Int!, fraction : Int, message : String = \" %s\" ) " +
30+ "on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION" ,
31+ getMessageTemplate ())
32+ .build ();
3233 }
3334
3435 @ Override
@@ -43,28 +44,40 @@ protected List<GraphQLError> runConstraint(ValidationEnvironment validationEnvir
4344
4445 GraphQLAppliedDirective directive = validationEnvironment .getContextObject (GraphQLAppliedDirective .class );
4546 int maxIntegerLength = getIntArg (directive , "integer" );
46- int maxFractionLength = getIntArg (directive , "fraction" );
47+ Optional < Integer > maxFractionLengthOpt = getIntArgOpt (directive , "fraction" );
4748
4849 boolean isOk ;
4950 try {
5051 BigDecimal bigNum = asBigDecimal (validatedValue );
51- isOk = isOk (bigNum , maxIntegerLength , maxFractionLength );
52+ boolean isFractionPartOk = maxFractionLengthOpt
53+ .map (maxFractionLength -> isFractionPartOk (bigNum , maxFractionLength ))
54+ .orElse (true );
55+
56+ isOk = isFractionPartOk && isIntegerPartOk (bigNum , maxIntegerLength );
5257 } catch (NumberFormatException e ) {
5358 isOk = false ;
5459 }
5560
5661 if (!isOk ) {
57- return mkError (validationEnvironment , "integer" , maxIntegerLength , "fraction" , maxFractionLength );
62+ return mkError (
63+ validationEnvironment ,
64+ "integer" ,
65+ maxIntegerLength , "fraction" ,
66+ maxFractionLengthOpt .map (Object ::toString ).orElse ("unlimited" )
67+ );
5868 }
5969
6070 return Collections .emptyList ();
6171 }
6272
63- private boolean isOk (BigDecimal bigNum , int maxIntegerLength , int maxFractionLength ) {
64- int integerPartLength = bigNum .precision () - bigNum .scale ();
65- int fractionPartLength = Math .max (bigNum .scale (), 0 );
73+ private static boolean isIntegerPartOk (BigDecimal bigNum , int maxIntegerLength ) {
74+ final int integerPartLength = bigNum .precision () - bigNum .scale ();
75+ return maxIntegerLength >= integerPartLength ;
76+ }
6677
67- return maxIntegerLength >= integerPartLength && maxFractionLength >= fractionPartLength ;
78+ private static boolean isFractionPartOk (BigDecimal bigNum , int maxFractionLength ) {
79+ final int fractionPartLength = Math .max (bigNum .scale (), 0 );
80+ return maxFractionLength >= fractionPartLength ;
6881 }
6982
7083 @ Override
0 commit comments