From 1b9b6a3237cb09960196a508a1fec4d179180cf5 Mon Sep 17 00:00:00 2001 From: Banana Date: Tue, 5 Jul 2022 12:48:30 +0200 Subject: [PATCH] future timestamp validator for magnolia --- .../validator/FutureTimestampDefinition.java | 33 ++++++++++++ .../validator/FutureTimestampFactory.java | 26 +++++++++ .../validator/FutureTimestampValidator.java | 54 +++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampDefinition.java create mode 100644 magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampFactory.java create mode 100644 magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampValidator.java diff --git a/magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampDefinition.java b/magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampDefinition.java new file mode 100644 index 0000000..1a61428 --- /dev/null +++ b/magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampDefinition.java @@ -0,0 +1,33 @@ +package net.bananasplayground.validator; + +import info.magnolia.ui.field.ConfiguredFieldValidatorDefinition; +import info.magnolia.ui.field.ValidatorType; +import lombok.Getter; +import lombok.Setter; + +/** + * Checks if datetime selection is >= now+timeToAdd + * + * works on LocalDateTime object + * + * timeToAdd time in lowercase, date uppercase + * timeToAdd: 1h|2D + * + * futureDate: + * $type: futureTimestamp + * timeToAdd: 1h + * errorMessage: bla + * + */ + +@Getter +@Setter +@ValidatorType("futureTimestamp") +public class FutureTimestampDefinition extends ConfiguredFieldValidatorDefinition { + + private String timeToAdd; + + public FutureTimestampDefinition() { + setFactoryClass(FutureTimestampFactory.class); + } +} diff --git a/magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampFactory.java b/magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampFactory.java new file mode 100644 index 0000000..77f1b3b --- /dev/null +++ b/magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampFactory.java @@ -0,0 +1,26 @@ +package net.bananasplayground.validator; + +import java.time.LocalDateTime; + +import javax.inject.Inject; + +import com.vaadin.data.Validator; + +import info.magnolia.ui.field.AbstractFieldValidatorFactory; + +/** + * @see net.bananasplayground.validator.FutureTimestampDefinition + */ + +public class FutureTimestampFactory extends AbstractFieldValidatorFactory { + + @Inject + public FutureTimestampFactory(FutureTimestampDefinition definition) { + super(definition); + } + + @Override + public Validator createValidator() { + return new FutureTimestampValidator(getI18nErrorMessage(), definition.getTimeToAdd()); + } +} diff --git a/magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampValidator.java b/magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampValidator.java new file mode 100644 index 0000000..667efdc --- /dev/null +++ b/magnolia/futureTimestampValidator/net/bananasplayground/validator/FutureTimestampValidator.java @@ -0,0 +1,54 @@ +package net.bananasplayground.validator; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.Period; +import java.time.temporal.TemporalAmount; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.data.ValidationResult; +import com.vaadin.data.ValueContext; +import com.vaadin.data.validator.AbstractValidator; + +/** + * @see net.bananasplayground.validator.FutureTimestampDefinition + */ + +public class FutureTimestampValidator extends AbstractValidator { + + private final String errorMessage; + private final String timeToAdd; + + protected FutureTimestampValidator(String errorMessage, String timeToAdd) { + super(errorMessage); + this.errorMessage = errorMessage; + this.timeToAdd = timeToAdd; + } + + @Override + public ValidationResult apply(LocalDateTime value, ValueContext context) { + if(StringUtils.isBlank(timeToAdd)) return ValidationResult.ok(); + boolean isValid = false; + + // date-based units (year, month, week, day) are denoted with uppercase abbreviations + // (Y, M, W and D) while the time-based ones (hour and minute) are lowercase (h and m). + // Test the case of the last character of the string to decide whether to parse into + // a Period or a Duration. I exploit the fact that both of Period.parse and Duration.parse + // accept the letters in either case. + TemporalAmount toAddToCurrentDateTime; + if (Character.isUpperCase(timeToAdd.charAt(timeToAdd.length() - 1))) { + toAddToCurrentDateTime = Period.parse("P" + timeToAdd); + } else { + toAddToCurrentDateTime = Duration.parse("PT" + timeToAdd); + } + + LocalDateTime now = LocalDateTime.now(); + LocalDateTime futureDateTime = now.plus(toAddToCurrentDateTime); + if(value.isEqual(futureDateTime) || value.isAfter(futureDateTime)) { + isValid = true; + } + + return isValid ? ValidationResult.ok() : ValidationResult.error(this.errorMessage); + } +} -- 2.39.5