I am trying to create a validator abstraction layer. These are the points I am trying to achieve:
- My abstraction should be open for extension but closed for modification
- The clients should not have a
if...elseblock to handle success or failure scenario.
Validation statuses
public interface ValidationStatus {
default void process() {
}
public static ValidationStatus fail(ValidationFailureCause cause, String messages) {
ValidationFailure validationFailure = new ValidationFailure();
validationFailure.setCause(cause);
validationFailure.setErrorMessages(messages);
return validationFailure;
}
public static ValidationStatus success() {
return new ValidationSuccess();
}
}
public class ValidationFailure implements ValidationStatus {
private ValidationFailureCause cause;
private String errorMessages;
public void setCause(ValidationFailureCause cause) {
this.cause = cause;
}
public void setErrorMessages(String errorMessages) {
this.errorMessages = errorMessages;
}
@Override
public void process() {
if (ValidationFailureCause.MISSING_MANDATORY_FIELDS.equals(cause)) {
throw new MandatoryElementsMissing(errorMessages);
}
}
}
public class ValidationSuccess implements ValidationStatus {
}
public enum ValidationFailureCause {
MISSING_MANDATORY_FIELDS
}
The validators
public interface Validator<T> {
/**
* Validate an object and return the validation result as a Status.
*
* @param request
* Data to be validated
* @return can be ValidationFailure or ValidationSuccess class instance
*/
ValidationStatus validate(T request);
boolean isValid(T request);
}
public class StringValidator implements Validator<String> {
@Override
public ValidationStatus validate(String request) {
if (isValid(request)) {
return ValidationStatus.success();
}
return ValidationStatus.fail(ValidationFailureCause.MISSING_MANDATORY_FIELDS, "Missing mandatory parameter");
}
@Override
public boolean isValid(String request) {
return StringUtils.isNotBlank(request);
}
}
public class PersonValidator implements Validator<FlightProposalRequest> {
@Override
public ValidationStatus validate(FlightProposalRequest request) {
if (isValid(request)) {
return ValidationStatus.success();
} else {
return ValidationStatus.fail(ValidationFailureCause.MISSING_MANDATORY_FIELDS, "Request is null");
}
}
@Override
public boolean isValid(FlightProposalRequest request) {
if (request == null) {
return false;
}
Validator<String> requestValidator = RequestValidatorFactory.getRequestValidator(String.class);
boolean result = requestValidator.isValid(request.getArrivalAirport());
result = result && requestValidator.isValid(request.getDepartureAirport());
result = result && requestValidator.isValid(request.getDepartureDate());
result = result && requestValidator.isValid(request.getReturnDate());
return result;
}
}
This is my attempt at this problem. Kindly provide your feedback on my approach. With the current setup as mentioned here, my tests are passing.