Available from the Central Repository. In Maven style:
<dependency> <groupId>co.unruly</groupId> <artifactId>validation</artifactId> <version>1.0</version> </dependency>
Create a validation
Validation<String,String> success = Validation.success("woot"); Validation<String,String> failure = Validation.failure("awww");
The first type parameter T is the type of a successful value, the latter S the type of error(s)
Is this a success or a failure?
boolean success = validation.isSuccess(); boolean failure = validation.isFailure();
Get the value
T value = validation.get();
Get the errors
List<S> errors = validation.getErrors()
Map or flatMap
// Add one to contents Validation.success(2).map(i -> i + 1); // Add one to contents using flatMap Validation.success(2).flatMap(i -> Validation.success(i + 1));
Map and flatMap operate on the value of a successful Validation. They do not affect a failure Validation.
Validation.success(2).filter(i -> i > 1);
Filtering a success with a non-truthy predicate will turn it into a failure with empty errors. It does not affect a failure.
Validation.tryTo(() -> /* do something that may throw */)
If an exception is thrown, tryTo will return a failure validation with the exception in the errors.
Map, flatMap or filter with potentially exception throwing functions
validation.tryMap(...) validation.tryFlatMap(...) validation.tryFilter(...)
If an exception is thrown, the Validation is a failure with the exception in the errors.
There are a couple of caveats here:
- The type of the errors of the returned Validation is Object
- If function f throws and function g catches then
map(f).map(g)may not equal
.map(g compose f)
Validation.success(3).compose(Validation.success(4), (a, b) -> a * b);
Two composed successes produce a success with the values combined using the provided function. Otherwise a failure is produced, including errors from each.
There are also some static methods for composing many Validations of type T for a few common types T (Integer, Long, Float, Double, Boolean, Collection, Map) with a sensible default composition function:
Validation.compose(() -> Validation.success(3L), () -> Validation.success(4L));
The use of lambda suppliers here is a pattern for working around Java's type erasure.
There are many similar types in other functional languages.