Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add exclusive mode to MinDuration and MaxDuration annotations #2167

Merged
merged 5 commits into from Nov 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 to, if in 'inclusive' mode) {value} {unit}";

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

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

/**
* @return {@code true} if the validation is to allow values equal to {@link #value()}.
* False if the validation is to be exclusive.
* Defaults to {@code true}.
*/
boolean inclusive() default true;
}
Expand Up @@ -14,15 +14,28 @@ public class MaxDurationValidator implements ConstraintValidator<MaxDuration, Du

private long maxQty = 0;
private TimeUnit maxUnit = TimeUnit.MILLISECONDS;
private boolean inclusive = true;

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

@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 (inclusive) {
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 to, if in 'inclusive' mode) {value} {unit}";

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

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

/**
* @return {@code true} if the validation is to allow values equal to {@link #value()}.
* False if the validation is to be exclusive.
* Defaults to {@code true}.
*/
boolean inclusive() default true;
}
Expand Up @@ -14,15 +14,28 @@ public class MinDurationValidator implements ConstraintValidator<MinDuration, Du

private long minQty = 0;
private TimeUnit minUnit = TimeUnit.MILLISECONDS;
private boolean inclusive = true;

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

@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 (inclusive) {
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, inclusive = false)
private Duration tooBigExclusive = Duration.seconds(30);

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

@MinDuration(value = 30, unit = TimeUnit.SECONDS, inclusive = false)
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 to, if in 'inclusive' mode) 30 SECONDS",
"tooBigExclusive must be less than (or equal to, if in 'inclusive' mode) 30 SECONDS",
"tooSmall must be greater than (or equal to, if in 'inclusive' mode) 30 SECONDS",
"tooSmallExclusive must be greater than (or equal to, if in 'inclusive' mode) 30 SECONDS",
"maxDurs[0].<collection element> must be less than (or equal to, if in 'inclusive' mode) 30 SECONDS",
"minDurs[0].<collection element> must be greater than (or equal to, if in 'inclusive' mode) 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