diff --git a/src/main/java/net/kapcake/bankingservice/model/dtos/PaymentFilter.java b/src/main/java/net/kapcake/bankingservice/model/dtos/PaymentFilter.java index f947be8..0fb7622 100644 --- a/src/main/java/net/kapcake/bankingservice/model/dtos/PaymentFilter.java +++ b/src/main/java/net/kapcake/bankingservice/model/dtos/PaymentFilter.java @@ -3,12 +3,14 @@ package net.kapcake.bankingservice.model.dtos; import jakarta.validation.constraints.AssertTrue; import lombok.Data; import lombok.experimental.Accessors; +import net.kapcake.bankingservice.validation.AtLeastOneFieldNotEmpty; import java.io.Serializable; import java.util.Date; @Data @Accessors(chain = true) +@AtLeastOneFieldNotEmpty(fieldNames = {"beneficiaryAccountNumber", "startDate", "endDate"}) public class PaymentFilter implements Serializable { private String beneficiaryAccountNumber; @@ -23,11 +25,4 @@ public class PaymentFilter implements Serializable { return startDate.compareTo(endDate) <= 0; } } - - @AssertTrue(message = "At least one field needs to be supplied") - public boolean isAtLeastOneFieldFilled() { - return startDate != null || - endDate != null || - (beneficiaryAccountNumber != null && !beneficiaryAccountNumber.isBlank()); - } } diff --git a/src/main/java/net/kapcake/bankingservice/validation/AtLeastOneFieldNotEmpty.java b/src/main/java/net/kapcake/bankingservice/validation/AtLeastOneFieldNotEmpty.java new file mode 100644 index 0000000..a8ae226 --- /dev/null +++ b/src/main/java/net/kapcake/bankingservice/validation/AtLeastOneFieldNotEmpty.java @@ -0,0 +1,20 @@ +package net.kapcake.bankingservice.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = AtLeastOneFieldNotEmptyValidator.class) +@Documented +public @interface AtLeastOneFieldNotEmpty { + String message() default "At least one field needs to be supplied"; + + String[] fieldNames(); + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/src/main/java/net/kapcake/bankingservice/validation/AtLeastOneFieldNotEmptyValidator.java b/src/main/java/net/kapcake/bankingservice/validation/AtLeastOneFieldNotEmptyValidator.java new file mode 100644 index 0000000..c9cd738 --- /dev/null +++ b/src/main/java/net/kapcake/bankingservice/validation/AtLeastOneFieldNotEmptyValidator.java @@ -0,0 +1,34 @@ +package net.kapcake.bankingservice.validation; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import org.springframework.beans.BeanUtils; + +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; + +public class AtLeastOneFieldNotEmptyValidator implements ConstraintValidator { + private String[] fieldNames; + + @Override + public void initialize(AtLeastOneFieldNotEmpty constraintAnnotation) { + this.fieldNames = constraintAnnotation.fieldNames(); + } + + @Override + public boolean isValid(Object obj, ConstraintValidatorContext context) { + if (obj == null) { + return false; + } + Object[] fieldValues = new Object[fieldNames.length]; + try { + for (int i = 0; i < fieldValues.length; i++) { + fieldValues[i] = BeanUtils.getPropertyDescriptor(obj.getClass(), fieldNames[i]).getReadMethod().invoke(obj); + } + } catch (InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + boolean isEveryValueNullOrEmpty = Arrays.stream(fieldValues).allMatch(value -> value == null || (value instanceof String) && ((String) value).isBlank()); + return !isEveryValueNullOrEmpty; + } +}