Class ResultOrProblems<T>
An optional-esque that contains the result of some result-yielding operation where it may have had problems which might have stopped it from producing a result.
Used as a functional alternative to using checked exceptions for user-facing errors, typically where the type of the problem is irrelevant - something the user has done has meant we can't proceed and we need to pass it back to the user with some context to help them fix it.
-
Field Summary
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionaddProblemsTo
(Collection<Problem> collection) <U> ResultOrProblems<U>
composeFailure
(Problem parentProblem) Compose a failed result with a new type and a parent error message.composeProblems
(String message, Object... args) Deprecated.For new code, use the i18n Problem-based method below insteadcomposeProblems
(BiFunction<Problem.Severity, List<Problem>, Problem> callback) Variant ofcomposeProblems(Problem)
that allows the problem to be constructed via a callback.composeProblems
(Problem parentProblem) If this result has problems, then this method will return a new ResultOrProblems with a single problem with a new message that has this objects problems as children.drainWarnings
(Consumer<Problem> problemConsumer) Removes any warnings or lower from a successfulResultOrProblems
so that get() doesn't produce a warningdrainWarnings
(Consumer<Problem> problemConsumer, BiFunction<Problem.Severity, List<Problem>, Problem> callback) Removes any warnings or lower from a successfulResultOrProblems
so that get() doesn't produce a warning.boolean
static <T> ResultOrProblems<T>
Shortcut to ResultOrProblems.failed(Problem.error)static <T> ResultOrProblems<T>
Shortcut to ResultOrProblems.failed(Problem.error)static <T> ResultOrProblems<T>
static <T> ResultOrProblems<T>
failed
(Collection<ResultOrProblems<?>> failures) Create a new failedResultOrProblems
that collects all problems from a set of otherResultOrProblems
.static <T> ResultOrProblems<T>
static <T> ResultOrProblems<T>
static <T> ResultOrProblems<T>
failed
(ResultOrProblems<?> firstFailure, ResultOrProblems<?>... restFailures) Create a new failedResultOrProblems
that collects all problems from a set of otherResultOrProblems
.filterProblems
(Class<?> affects) Filters the Problems based on the class of thing the problem affects, e.g.<U> ResultOrProblems<U>
flatMap
(BiFunction<T, List<Problem>, ResultOrProblems<U>> mapper) Maps thisResultOrProblems
to another, only if the result has been set.<U> ResultOrProblems<U>
flatMap
(Function<? super T, ResultOrProblems<U>> mapper) likeflatMap(BiFunction)
, but appends the problem lists together in a newResultOrProblems
objectget()
Returns the Problems found as a single Problem, rather than a List.Flow control helper for use with ResultOrProblems - seeProblemException
for more details.getOrThrow
(Function<List<Problem>, Problem> problemFunction) Flow control helper for use with ResultOrProblems - seeProblemException
for more details.getOrThrow
(Problem parent) Flow control helper for use with ResultOrProblems - seeProblemException
for more details.boolean
Shortcut forhasProblems(Severity.ERROR)
int
hashCode()
boolean
boolean
hasProblems
(Problem.Severity greaterThanEqualTo) void
Call the given consumer function with the result, only if result is set, else call the consumer<U> U
Call the given consumer function with the result, only if result is set, else call the consumer<U> U
Call the given consumer function with the result, only if result is set, else call the consumervoid
Call the given consumer function with the result, only if result is set<U> Optional<U>
ifProblems
(Function<List<Problem>, U> function) Call the given function if there were any problems with thisResultOrProblems
, returning whatever the function returned.boolean
<U> ResultOrProblems<U>
Maps the result of thisResultOrProblems
to another result, only if the result has been set.<U> ResultOrProblems<U>
Maps the result of thisResultOrProblems
to another result, only if the result has been set, as well as supporting remapping problems one at a time regardless of a result.<U> ResultOrProblems<U>
mapOrCombine
(Function<T, U> mapper, ResultOrProblems<?>... dependencies) Likemap(Function)
, but will only map if this and all dependencies succeeded.static <T> ResultOrProblems<T>
of
(T thing) static <T> ResultOrProblems<T>
static <T> ResultOrProblems<T>
static <T> ResultOrProblems<T>
ofNullable
(T thing, List<Problem> withProblems) Constructor where thing may or may not have been successfully created.orElseThrow
(Function<List<Problem>, ? extends X> exceptionSupplier) Mirror ofOptional.orElseThrow(Supplier)
- throws the given exception if there is no computed result.orElseThrow
(Supplier<? extends X> exceptionSupplier) Mirror ofOptional.orElseThrow(Supplier)
- throws the given exception if there is no computed result.toString()
static ResultOrProblems<Anything>
withMoreProblems
(Collection<Problem> moreProblems) withMoreProblems
(Function<T, List<Problem>> validation) Applies the given validation function to the computed result, and returns a new ResultOrProblems with any additional problems that were foundwithMoreProblems
(Problem... moreProblems)
-
Field Details
-
NO_PROBLEMS
-
-
Constructor Details
-
ResultOrProblems
-
-
Method Details
-
of
-
of
-
of
-
ofNullable
Constructor where thing may or may not have been successfully created.
-
failed
Create a new failed
ResultOrProblems
that collects all problems from a set of otherResultOrProblems
. The caller must ensure that there are at least some error level problems among the given arguments.- Type Parameters:
T
- An arbitrary generic type- Parameters:
failures
- a collection of results with some failures- Returns:
- a new failed ResultOrProblems that includes all problems from the given problems
- Throws:
IllegalArgumentException
- if there are no errors among the results
-
failed
public static <T> ResultOrProblems<T> failed(ResultOrProblems<?> firstFailure, ResultOrProblems<?>... restFailures) throws IllegalArgumentException Create a new failed
ResultOrProblems
that collects all problems from a set of otherResultOrProblems
. The caller must ensure that there are at least some error level problems among the given arguments.- Type Parameters:
T
- An arbitrary generic type- Parameters:
firstFailure
- a possibly failed resultrestFailures
- even more possibly failed results- Returns:
- a new failed ResultOrProblems that includes all problems from the given problems
- Throws:
IllegalArgumentException
- if there are no errors among the results
-
failed
-
failed
-
error
Shortcut to ResultOrProblems.failed(Problem.error)
-
error
Shortcut to ResultOrProblems.failed(Problem.error)
-
error
-
unchecked
-
get
- Returns:
- the result of this
ResultOrProblems
- Throws:
ResultComputationException
- if no result was set, with thisResultOrProblems
list of problems attached to it.
-
getOrThrow
Flow control helper for use with ResultOrProblems - see
ProblemException
for more details.- Returns:
- a computed result if one is present, or throws a
ProblemException
with problems if none. - Throws:
ProblemException
- if there is no computed result
-
getOrThrow
Flow control helper for use with ResultOrProblems - see
ProblemException
for more details.- Parameters:
parent
- a problem to wrap around any problems that might be present- Returns:
- a computed result if one is present, or throws a
ProblemException
with problems if none. - Throws:
ProblemException
- if there is no computed result
-
getOrThrow
Flow control helper for use with ResultOrProblems - see
ProblemException
for more details. This variant gives more control over the problem that ultimately gets included in theProblemException
.- Parameters:
problemFunction
- a function that will produce a single problem for the ProblemException that is thrown.- Returns:
- a computed result if one is present, or throws a
ProblemException
with problems if none. - Throws:
ProblemException
- if there is no computed result
-
getWithProblemsIgnored
- Returns:
- computedResult, regardless of any other conditions. Will return a computedResult even if problems occurred - this function is really here to allow debugging/messaging code to report back a semi-successful object back to the user.
-
drainWarnings
Removes any warnings or lower from a successful
ResultOrProblems
so that get() doesn't produce a warning -
drainWarnings
public ResultOrProblems<T> drainWarnings(Consumer<Problem> problemConsumer, BiFunction<Problem.Severity, List<Problem>, Problem> callback) Removes any warnings or lower from a successful
ResultOrProblems
so that get() doesn't produce a warning.Similar to
drainWarnings(java.util.function.Consumer)
except that if non error problems are found then the callback used to get a problem that is then passed to the problemConsumer -
ifProblems
Call the given function if there were any problems with this
ResultOrProblems
, returning whatever the function returned. -
isPresent
public boolean isPresent()- Returns:
- true if result is set.
-
ifPresent
Call the given consumer function with the result, only if result is set
-
ifElse
Call the given consumer function with the result, only if result is set, else call the consumer
-
ifElseReturn
Call the given consumer function with the result, only if result is set, else call the consumer
-
ifElseReturn
public <U> U ifElseReturn(Function<T, U> function, Consumer<List<Problem>> elseConsume, U elseReturn) Call the given consumer function with the result, only if result is set, else call the consumer
-
hasProblems
public boolean hasProblems()- Returns:
- true if this
ResultOrProblems
has any problems, regardless of severity.
-
hasProblems
- Returns:
- true if this object's list of problems contain any that are of an equal or greater severity to the given severity parameter.
-
filterProblems
Filters the Problems based on the class of thing the problem affects, e.g. find all the problems that relate to a parameter.
- Parameters:
affects
- the type of thing affected by the Problem, e.g. Parameter.class, Step.class- Returns:
- A list of Problems that affect the given class
-
flatMap
like
flatMap(BiFunction)
, but appends the problem lists together in a newResultOrProblems
object -
flatMap
Maps this
ResultOrProblems
to another, only if the result has been set. It is up to the BiFunction to produce a new set of problems - normally you want to append problems, so use theFunction
form of this method. -
map
Maps the result of this
ResultOrProblems
to another result, only if the result has been set. -
map
Maps the result of this
ResultOrProblems
to another result, only if the result has been set, as well as supporting remapping problems one at a time regardless of a result.- Parameters:
problemMapper
- a function to convert the problem list.
-
mapOrCombine
public <U> ResultOrProblems<U> mapOrCombine(Function<T, U> mapper, ResultOrProblems<?>... dependencies) Like
map(Function)
, but will only map if this and all dependencies succeeded. A failed result includes problems from this and all dependencies.- Type Parameters:
U
- The mapped result type- Parameters:
mapper
- a mapping function for a successful resultdependencies
- other ResultOrProblems to check for failures before calling the mapping function- Returns:
- a successful result of type or a failed result containing all problems.
-
orElse
- Returns:
- either the set result, or otherThing if result is not set. otherThing can be null.
-
orElse
- Returns:
- either the set result, or otherThing if result is not set. otherThing can be null.
-
orElseGet
- Returns:
- either the set result, or otherThing if result is not set. otherThing can be null.
-
withMoreProblems
- Returns:
- a new
ResultOrProblems
object that contains the existing list of problems as well as the given list of problems.
-
withMoreProblems
Applies the given validation function to the computed result, and returns a new ResultOrProblems with any additional problems that were found
-
withMoreProblems
- Returns:
- a new
ResultOrProblems
object that contains the existing list of problems as well as the given list of problems.
-
orElseThrow
public <X extends Throwable> T orElseThrow(Function<List<Problem>, ? extends X> exceptionSupplier) throws XMirror of
Optional.orElseThrow(Supplier)
- throws the given exception if there is no computed result.- Throws:
X extends Throwable
-
orElseThrow
Mirror of
Optional.orElseThrow(Supplier)
- throws the given exception if there is no computed result.- Throws:
X extends Throwable
-
toString
-
hasErrors
public boolean hasErrors()Shortcut for
hasProblems(Severity.ERROR)
- Returns:
- true if there are any errors
-
equals
-
hashCode
public int hashCode() -
composeProblems
Deprecated.For new code, use the i18n Problem-based method below instead -
composeProblems
If this result has problems, then this method will return a new ResultOrProblems with a single problem with a new message that has this objects problems as children. Acts as a conditional shortcut for Problem.composite(resultOr.getProblems()..) - a common pattern when nesting problems with more context, e.g an expression failed that was part of a step, that was part of a pipeline, etc.
-
composeProblems
public ResultOrProblems<T> composeProblems(BiFunction<Problem.Severity, List<Problem>, Problem> callback) Variant of
composeProblems(Problem)
that allows the problem to be constructed via a callback. Can be more clear or possibly required if a problem can not be constructed without children.- Parameters:
callback
- that will be invoked if there are problems on thisResultOrProblems
object.- Returns:
- a new
ResultOrProblems
with a single problem that was created bycallback
, or the original object if there are no problems on thisResultOrProblems
object.
-
composeFailure
Compose a failed result with a new type and a parent error message. Will fail if this is not already a failure
-
addProblemsTo
-
getAsSingleProblem
Returns the Problems found as a single Problem, rather than a List. This can be useful for propagating errors via a RiskScapeException. Use this API if: - you're pretty sure you're only ever going to have a single problem in the list. - Or, the code you're dealing with is so generic, there's not a more appropriate object/context to use (i.e. you don't really know what the underlying 'thing' is). Otherwise, use the Problems.foundWith() API instead.
-
getProblems
-