Reputation: 11
I have list of "User" validations to be performed, each validation implements Predicate (from Guava). I have following method which fills the List of validations to be performed and creates composed Predicate of all validations.
List<Validation> validations = new ArrayList();
Predicate<User> composedUserValidations;
private void setupValidations() {
validations.add(userEmailIsValid());
validations.add(userPhoneIsValid());
validations.add(userLoginIsValid());
.....
//creating composite
composedUserValidations = and(validations);
}
Question: when I will trigger apply to composedUserValidations and one of them will fail, is there a way to find which one exactly is failing. Now I have:
public boolean isUserValid(User user) {
if (!composedUserValidations.apply(user)) {
return false;
}
}
and I want to have something like:
public void validateUser(User user) {
if (!composedUserValidations.apply(ticket)) {
throw new ValidationExcepction("Predicate which failed");
}
}
What will be the best way to do it?
Upvotes: 1
Views: 406
Reputation: 62864
You could design a builder for your User
class, let's name it UserBuilder
.
For each of the User
's properties (login, email, phone) in the builder class, you could not only provide the value you would like to set for the User
instance, but also the Predicate
, which you can immediately apply. If any of the predicates fail, you could easily throw an Exception and/or output a message, etc.
For all the instances you create, you could optionally pass different validation rules, or you could additionally design your builder to skip the validation for any of the User
fields.
Example:
public class UserBuilder {
private String phone;
private String email;
//add more properties here;
public void phone(String phone, Predicate<String> phoneValidator) {
if (!phoneValidator.test(phone)) {
throw new UserBuilderException("Invalid phone provided");
}
this.phone = phone;
return this;
}
public void email(String email, Predicate<String> emailValidator) {
if (!emailValidator.test(email)) {
throw new UserBuilderException("Invalid email provided");
}
this.email = email;
return this;
}
//add more builder methods here
public User build() {
return new User(phone, email);
}
}
You could use that with:
Predicate<String> phoneValidator = ....
Predicate<String> emailValidator = ....
User user = new UserBuilder()
.phone("123567", phoneValidator)
.email("[email protected]", emailValidator)
.build();
What you get with that is:
User
instance you have.User
instances created with invalid content. A User
instance will be created only for the property tuples, which pass all the Predicate
s provided in their builders.Upvotes: 2