Skip to content

Commit

Permalink
Add 'exclusive' mode to duration validation annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
FredDeschenes committed Oct 31, 2017
1 parent e8f7f6c commit c485085
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 8 deletions.
Expand Up @@ -26,7 +26,7 @@
@Documented
@Constraint(validatedBy = MaxDurationValidator.class)
public @interface MaxDuration {
String message() default "must be less than or equal to {value} {unit}";
String message() default "must be less than or equal (or less than if in 'exclusive' mode) to {value} {unit}";

Class<?>[] groups() default { };

Expand All @@ -41,4 +41,9 @@
* @return unit of the value the element must be higher or equal to
*/
TimeUnit unit() default TimeUnit.SECONDS;

/**
* @return if the validation should exclude the set value (default is inclusive).
*/
boolean exclusive() default false;
}
Expand Up @@ -14,15 +14,28 @@ public class MaxDurationValidator implements ConstraintValidator<MaxDuration, Du

private long maxQty;
private TimeUnit maxUnit;
private boolean exclusive;

@Override
public void initialize(MaxDuration constraintAnnotation) {
this.maxQty = constraintAnnotation.value();
this.maxUnit = constraintAnnotation.unit();
this.exclusive = constraintAnnotation.exclusive();
}

@Override
public boolean isValid(Duration value, ConstraintValidatorContext context) {
return (value == null) || (value.toNanoseconds() <= maxUnit.toNanos(maxQty));
if (value == null) {
return true;
}

long valueNanos = value.toNanoseconds();
long annotationNanos = maxUnit.toNanos(maxQty);

if (exclusive) {
return valueNanos < annotationNanos;
} else {
return valueNanos <= annotationNanos;
}
}
}
Expand Up @@ -26,7 +26,7 @@
@Documented
@Constraint(validatedBy = MinDurationValidator.class)
public @interface MinDuration {
String message() default "must be greater than or equal to {value} {unit}";
String message() default "must be greater than or equal (or greater if in 'exclusive' mode) to {value} {unit}";

Class<?>[] groups() default { };

Expand All @@ -41,4 +41,9 @@
* @return unit of the value the element must be higher or equal to
*/
TimeUnit unit() default TimeUnit.SECONDS;

/**
* @return if the validation should exclude the set value (default is inclusive).
*/
boolean exclusive() default false;
}
Expand Up @@ -14,15 +14,28 @@ public class MinDurationValidator implements ConstraintValidator<MinDuration, Du

private long minQty;
private TimeUnit minUnit;
private boolean exclusive;

@Override
public void initialize(MinDuration constraintAnnotation) {
this.minQty = constraintAnnotation.value();
this.minUnit = constraintAnnotation.unit();
this.exclusive = constraintAnnotation.exclusive();
}

@Override
public boolean isValid(Duration value, ConstraintValidatorContext context) {
return (value == null) || (value.toNanoseconds() >= minUnit.toNanos(minQty));
if (value == null) {
return true;
}

long valueNanos = value.toNanoseconds();
long annotationNanos = minUnit.toNanos(minQty);

if (exclusive) {
return valueNanos > annotationNanos;
} else {
return valueNanos >= annotationNanos;
}
}
}
Expand Up @@ -18,9 +18,15 @@ public static class Example {
@MaxDuration(value = 30, unit = TimeUnit.SECONDS)
private Duration tooBig = Duration.minutes(10);

@MaxDuration(value = 30, unit = TimeUnit.SECONDS, exclusive = true)
private Duration tooBigExclusive = Duration.seconds(30);

@MinDuration(value = 30, unit = TimeUnit.SECONDS)
private Duration tooSmall = Duration.milliseconds(100);

@MinDuration(value = 30, unit = TimeUnit.SECONDS, exclusive = true)
private Duration tooSmallExclusive = Duration.seconds(30);

@DurationRange(min = 10, max = 30, unit = TimeUnit.MINUTES)
private Duration outOfRange = Duration.minutes(60);

Expand All @@ -39,9 +45,15 @@ public static class Example {
public void setTooBig(Duration tooBig) {
this.tooBig = tooBig;
}
public void setTooBigExclusive(Duration tooBigExclusive) {
this.tooBigExclusive = tooBigExclusive;
}
public void setTooSmall(Duration tooSmall) {
this.tooSmall = tooSmall;
}
public void setTooSmallExclusive(Duration tooSmallExclusive) {
this.tooSmallExclusive = tooSmallExclusive;
}
public void setOutOfRange(Duration outOfRange) {
this.outOfRange = outOfRange;
}
Expand All @@ -67,10 +79,12 @@ public void returnsASetOfErrorsForAnObject() throws Exception {
assertThat(errors)
.containsOnly(
"outOfRange must be between 10 MINUTES and 30 MINUTES",
"tooBig must be less than or equal to 30 SECONDS",
"tooSmall must be greater than or equal to 30 SECONDS",
"maxDurs[0].<collection element> must be less than or equal to 30 SECONDS",
"minDurs[0].<collection element> must be greater than or equal to 30 SECONDS",
"tooBig must be less than or equal (or less than if in 'exclusive' mode) to 30 SECONDS",
"tooBigExclusive must be less than or equal (or less than if in 'exclusive' mode) to 30 SECONDS",
"tooSmall must be greater than or equal (or greater if in 'exclusive' mode) to 30 SECONDS",
"tooSmallExclusive must be greater than or equal (or greater if in 'exclusive' mode) to 30 SECONDS",
"maxDurs[0].<collection element> must be less than or equal (or less than if in 'exclusive' mode) to 30 SECONDS",
"minDurs[0].<collection element> must be greater than or equal (or greater if in 'exclusive' mode) to 30 SECONDS",
"rangeDurs[0].<collection element> must be between 10 MINUTES and 30 MINUTES");
}
}
Expand All @@ -79,7 +93,9 @@ public void returnsASetOfErrorsForAnObject() throws Exception {
public void returnsAnEmptySetForAValidObject() throws Exception {
final Example example = new Example();
example.setTooBig(Duration.seconds(10));
example.setTooBigExclusive(Duration.seconds(29));
example.setTooSmall(Duration.seconds(100));
example.setTooSmallExclusive(Duration.seconds(31));
example.setOutOfRange(Duration.minutes(15));
example.setMaxDurs(ImmutableList.of(Duration.seconds(10)));
example.setMinDurs(ImmutableList.of(Duration.seconds(100)));
Expand Down

0 comments on commit c485085

Please sign in to comment.