io.snice.preconditions.ValidationError Maven / Gradle / Ivy
package io.snice.preconditions;
import io.snice.functional.Either;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static io.snice.preconditions.PreConditions.assertArgument;
import static io.snice.preconditions.PreConditions.assertNotNull;
/**
* There are many cases where validation needs to occur, which may yield in errors. E.g., when validating a SIP or
* a Diameter message, you may discover that they are missing mandatory headers (SIP) or AVPs (Diameter). However,
* instead of throwing exceptions, generating a {@link ValidationError} wrapped in an {@link Either} allows for
* a more functional approach in handling these validation errors.
*/
public interface ValidationError {
static ValidationError of(T error) {
assertNotNull(error);
return new DefaultValidationError<>(List.of(error));
}
static ValidationError of(T... errors) {
assertNotNull(errors);
assertArgument(errors.length > 0, "The list of errors cannot be empty");
return new DefaultValidationError<>(List.of(errors));
}
/**
* Convenience method for appending errors to a {@link ValidationError} that, if null, will
* first be created.
*
* @param v the {@link ValidationError} to append the given error to, or if it is null, a new
* one will be created.
* @param error the error that will be appended to the given {@link ValidationError} or to a new
* one if the given one is null.
* @return a new {@link ValidationError} object that contains the given error as well as any previous
* errors from the optional {@link ValidationError} passed in.
*/
static ValidationError append(ValidationError v, T error) {
if (v == null) {
return ValidationError.of(error);
}
return v.append(error);
}
/**
* A list of T describing the issues found while validating.
*
* @return
*/
List getErrors();
/**
* If more errors are found, you can append them.
*
* Note that {@link ValidationError} is a mutable class and as such,
* the {@link ValidationError} returned will be a different instance
* than this one and the current one will be left untouched.
*
* @param errors
* @return a new {@link ValidationError} that contains the list of errors from this
* instance plus the new set of errors.
*/
ValidationError append(T... errors);
class DefaultValidationError implements ValidationError {
private final List errors;
private DefaultValidationError(List errors) {
this.errors = errors;
}
@Override
public List getErrors() {
return errors;
}
@Override
public ValidationError append(T... errors) {
if (errors == null || errors.length == 0) {
return this;
}
final var l = new ArrayList<>(this.errors);
for (int i = 0; i < errors.length; ++i) {
l.add(errors[i]);
}
return new DefaultValidationError<>(Collections.unmodifiableList(l));
}
}
}