javascalautils.Try Maven / Gradle / Ivy
/**
* Copyright 2015 Peter Nerg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javascalautils;
import java.util.Iterator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
/**
* The 'Try' type represents a computation that may either result in an exception, or return a successfully computed value.
* Typical use case is situations where parallel computation takes place resulting in more than one response where it's possible that one or more computations
* fail.
* Though it might not be desirable to raise an exception for failed computations hence the Try acts a place holder for a response that is either failed or
* successful.
* Instances of 'Try', are either an instance of {@link Success} or {@link Failure}.
* Example of usage:
*
*
*
*
* Try<SomeData> getSomeData(SomeInput input) {
* try {
* // readUserFromDB throws if no user exists
* SomeData data = readUserFromDB(input);
* return new Success<>(data);
* } catch (SomeException ex) {
* return new Failure<>(ex);
* }
* }
*
*
*
*
* A more elaborate way is to provide a {@link ThrowableFunction0 checked function} provided to the {@link #apply(ThrowableFunction0)} method.
*
*
*
*
* Try<Integer> resultSuccess = Try.apply(() -> 9 / 3); // results in Success(3)
* Try<Integer> resultFailure = Try.apply(() -> 9 / 0); // results in Failure(ArithmeticException)
*
*
*
*
* Or let us re-write the first example to use the {@link #apply(ThrowableFunction0)} method.
*
*
*
*
* Try<SomeData> getSomeData(SomeInput input) {
* // readUserFromDB throws if no user exists
* Try.apply(() -> readUserFromDB(input));
* }
*
*
*
*
* @author Peter Nerg
* @since 1.0
* @param
* The type of the value represented by this Try
*/
public interface Try extends Iterable {
/**
* Creates an instance of Try.
* If a null
or non-throwable value is provided then {@link Success} is returned containing the value, else {@link Failure} containing the
* provided throwable.
*
* @param
* The type for the Try
* @param value
* The value for this to create a Try
* @return The Try instance
*/
static Try apply(T value) {
return value instanceof Throwable ? new Failure((Throwable) value) : new Success(value);
}
/**
* Creates an instance of Try wrapping the result of the provided function.
* If the function results in a value then {@link Success} with the value is returned.
* In case the function raises an exception then {@link Failure} is returned containing that exception.
* If null
is provided as argument then the {@link #apply(Object)} is invoked.
* Example simple division by zero results in an exception.
*
*
*
*
* Try<Integer> resultSuccess = Try.apply(() -> 9 / 3); // results in Success(3)
* Try<Integer> resultFailure = Try.apply(() -> 9 / 0); // results in Failure(ArithmeticException)
*
*
*
*
* @param
* The type for the Try
* @param function
* The function to render either the value T or raise an exception.
* @return The resulting Try instance wrapping what the function resulted in
* @since 1.3
*/
static Try apply(ThrowableFunction0 function) {
if (function == null) {
return apply((T) null);
}
try {
return new Success<>(function.apply());
} catch (Throwable ex) {
return new Failure(ex);
}
}
/**
* Returns true
if the 'Try' is a {@link Failure}, false
otherwise.
*
* @return If the Try is a {@link Failure}
*/
default boolean isFailure() {
return !isSuccess();
}
/**
* Returns true
if the 'Try' is a {@link Success}, false
otherwise.
*
* @return If the Try is a {@link Success}
*/
boolean isSuccess();
/**
* Returns the value from this {@link Success} or the value provided by the supplier if this is a {@link Failure}.
*
* @param supplier
* The supplier to return the value in case of a {@link Failure}
* @return The value from the Try or the supplier
*/
T getOrElse(Supplier supplier);
/**
* Returns the value if it is a {@link Success}, else null
.
*
* @return The value of the Try or null
.
*/
default T orNull() {
return getOrElse(() -> null);
}
/**
* Returns this 'Try' if it's a {@link Success} or the value provided by the supplier if this is a {@link Failure}.
*
* @param supplier
* The supplier to return the value in case of a {@link Failure}
* @return This try or the value from the supplier
*/
Try orElse(Supplier> supplier);
/**
* Returns the value from this {@link Success} or throws the exception if this is a {@link Failure}.
*
* @return The value of the {@link Success}
* @throws Throwable
* The Throwable in case of a {@link Failure}
*/
T get() throws Throwable;
/**
* Completes this 'Try' with an exception wrapped in a {@link Success}.
* The exception is either the exception that the 'Try' failed with (if a {@link Failure}) or an 'UnsupportedOperationException'.
*
* @return The value of the {@link Failure} in a {@link Success}
*/
Try failed();
/**
* Returns the Try's value in an {@link Iterator} if it is a {@link Success}, or an empty {@link Iterator} if it is Failure.
* Should it be a {@link Success} containing a null
value then the iterator will also be empty.
*
* @return The iterator for the Try
*/
default Iterator iterator() {
return stream().iterator();
}
/**
* Maps the given function to the value from this {@link Success} or returns this
if this is a {@link Failure}.
*
* @param
* The type for the return value from the function
* @param function
* The function to use
* @return The Option containing the mapped value
*/
Try map(Function function);
/**
* Maps the given function to the value from this {@link Success} or returns this
if this is a {@link Failure}.
*
* @param
* The type for the return value from the function
* @param function
* The function to use
* @return The Option containing the mapped value
* @since 1.2
*/
Try flatMap(Function> function);
/**
* Returns the Try's value in a Stream if it is a {@link Success}, or an empty Stream if it is a {@link Failure}.
* Should it be a {@link Success} containing a null
value then the stream will also be empty.
*
* @return The stream for the Try
*/
default Stream stream() {
return asOption().stream();
}
/**
* Returns this {@link Try} as an {@link Option}.
* If it is a {@link Success} then the value is wrapped in {@link Some} else {@link None} is returned.
* Should the {@link Success} contain a null
value the result will be {@link None} as null
values are per definition
* none/nothing.
*
* @return The {@link Option} representing this Try
*/
default Option asOption() {
return Option.apply(orNull());
}
}