Class Maybe<T,E extends Throwable>

java.lang.Object
com.google.mu.util.Maybe<T,E>

public abstract class Maybe<T,E extends Throwable> extends Object
Class that wraps checked exceptions and tunnels them through stream operations or future graphs.

The idea is to wrap checked exceptions inside Stream<Maybe<T, E>>, then map(), flatMap() and filter() away through normal stream operations. Exception is only thrown during terminal operations. For example, the following code fetches and runs pending jobs using a stream of Maybe:


   private Job fetchJob(long jobId) throws IOException;

   void runPendingJobs() throws IOException {
     Stream<Maybe<Job, IOException>> stream = activeJobIds.stream()
         .map(maybe(this::fetchJob))
         .filter(byValue(Job::isPending));
     Iterate.through(stream, m -> m.orElseThrow(IOException::new).runJob());
   }
 
When it comes to futures, the following asynchronous code example handles exceptions type safely using Maybe.catchException():

   CompletionStage<User> assumeAnonymousIfNotAuthenticated(CompletionStage<User> stage) {
     CompletionStage<Maybe<User, AuthenticationException>> authenticated =
         Maybe.catchException(AuthenticationException.class, stage);
     return authenticated.thenApply(maybe -> maybe.orElse(e -> new AnonymousUser()));
   }
 
  • Method Details

    • of

      public static <T, E extends Throwable> Maybe<T,E> of(T value)
      Creates a Maybe for value.
      Parameters:
      value - can be null
    • except

      public static <T, E extends Throwable> Maybe<T,E> except(E exception)
      Creates an exceptional Maybe for exception.

      If exception is an InterruptedException, the current thread is re-interrupted as a standard practice to avoid swallowing the interruption signal.

    • map

      public abstract <T2> Maybe<T2,E> map(Function<? super T,? extends T2> function)
      Maps this using function unless it wraps exception.
    • flatMap

      public abstract <T2> Maybe<T2,E> flatMap(Function<? super T,Maybe<T2,E>> function)
      Flat maps this using f unless it wraps exception.
    • isPresent

      public abstract boolean isPresent()
      Returns true unless this is exceptional.
    • ifPresent

      public abstract Maybe<T,E> ifPresent(Consumer<? super T> consumer)
      Applies consumer if this is present. Returns this.
    • orElse

      public abstract <X extends Throwable> T orElse(CheckedFunction<? super E,? extends T,X> function) throws X
      Either returns the encapsulated value, or translates exception using function.
      Throws:
      X
    • orElseThrow

      public final T orElseThrow() throws E
      Returns the encapsulated value or throws exception.

      If this encapsulates an exception, a wrapper exception of type E is thrown to capture the caller's stack trace with the original exception as the cause.

      Consider to use orElseThrow(Function) to retain stack trace by wrapping exceptions, for example: orElseThrow(IOException::new).

      If InterruptedException is thrown, the current thread's Thread.interrupted() bit is cleared because it's what most code expects when they catch an InterruptedException.

      No exception wrapping is attempted for InterruptedException.

      Throws:
      E
    • orElseThrow

      public final <X extends Throwable> T orElseThrow(Function<? super E,X> exceptionWrapper) throws X
      Either returns success value, or throws exception created by exceptionWrapper.

      It's recommended for exceptionWrapper to wrap the original exception as the cause.

      Throws:
      X
    • catching

      public final <X extends Throwable> Stream<T> catching(CheckedConsumer<? super E,? extends X> handler) throws X
      Catches and handles exception with handler, and then skips it in the returned Stream. This is specially useful in a Stream chain to handle and then ignore exceptional results.
      Throws:
      X
    • byValue

      public static <T, E extends Throwable> Predicate<Maybe<T,E>> byValue(Predicate<? super T> condition)
      Turns condition to a Predicate over Maybe. The returned predicate matches any Maybe with a matching value, as well as any exceptional Maybe so as not to accidentally swallow exceptions.
    • maybe

      public static <T, E extends Throwable> Maybe<T,E> maybe(CheckedSupplier<? extends T,? extends E> supplier)
      Invokes supplier and wraps the returned object or thrown exception in a Maybe<T, E>.

      Unchecked exceptions will be immediately propagated without being wrapped.

    • maybeStream

      public static <T, E extends Throwable> Stream<Maybe<T,E>> maybeStream(CheckedSupplier<? extends Stream<? extends T>,E> supplier)
      Invokes supplier and wraps the returned Stream<T> or thrown exception into a stream of Maybe<T, E>.

      Useful to be passed to Stream.flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>).

      Unchecked exceptions will be immediately propagated without being wrapped.

    • maybe

      public static <F, T, E extends Throwable> Function<F,Maybe<T,E>> maybe(CheckedFunction<? super F,? extends T,E> function)
      Wraps function to be used for a stream of Maybe.

      Unchecked exceptions will be immediately propagated without being wrapped.

    • maybeStream

      public static <F, T, E extends Throwable> Function<F,Stream<Maybe<T,E>>> maybeStream(CheckedFunction<? super F,? extends Stream<? extends T>,E> function)
      Wraps function that returns Stream<T> to one that returns Stream<Maybe<T, E>> with exceptions of type E wrapped.

      Useful to be passed to Stream.flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>).

      Unchecked exceptions will be immediately propagated without being wrapped.

    • maybe

      public static <A, B, T, E extends Throwable> BiFunction<A,B,Maybe<T,E>> maybe(CheckedBiFunction<? super A,? super B,? extends T,? extends E> function)
      Wraps function to be used for a stream of Maybe.

      Unchecked exceptions will be immediately propagated without being wrapped.

    • maybeStream

      public static <A, B, T, E extends Throwable> BiFunction<A,B,Stream<Maybe<T,E>>> maybeStream(CheckedBiFunction<? super A,? super B,? extends Stream<? extends T>,? extends E> function)
      Wraps function that returns Stream<T> to one that returns Stream<Maybe<T, E>> with exceptions of type E wrapped.

      Useful to be passed to Stream.flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>).

      Unchecked exceptions will be immediately propagated without being wrapped.

    • maybe

      public static <T, E extends Throwable> Maybe<T,E> maybe(CheckedSupplier<? extends T,? extends E> supplier, Class<E> exceptionType)
      Wraps supplier to be used for a stream of Maybe.

      Normally one should use maybe(CheckedSupplier) unless E is an unchecked exception type.

      For GWT code, wrap the supplier manually, as in:

      
         private static <T> Maybe<T, FooException> foo(
             CheckedSupplier<T, FooException> supplier) {
           try {
             return Maybe.of(supplier.get());
           } catch (FooException e) {
             return Maybe.except(e);
           }
         }
       
    • maybeStream

      public static <T, E extends Throwable> Stream<Maybe<T,E>> maybeStream(CheckedSupplier<? extends Stream<? extends T>,? extends E> supplier, Class<E> exceptionType)
      Invokes supplier and wraps the returned Stream<T> or thrown exception into a stream of Maybe<T, E>.
    • maybe

      public static <F, T, E extends Throwable> Function<F,Maybe<T,E>> maybe(CheckedFunction<? super F,? extends T,? extends E> function, Class<E> exceptionType)
      Wraps function to be used for a stream of Maybe.

      Normally one should use maybe(CheckedFunction) unless E is an unchecked exception type.

      For GWT code, wrap the function manually, as in:

      
         private static <F, T> Function<F, Maybe<T, FooException>> foo(
             CheckedFunction<F, T, FooException> function) {
           return from -> {
             try {
               return Maybe.of(function.apply(from));
             } catch (FooException e) {
               return Maybe.except(e);
             }
           };
         }
       
    • maybeStream

      public static <F, T, E extends Throwable> Function<F,Stream<Maybe<T,E>>> maybeStream(CheckedFunction<? super F,? extends Stream<? extends T>,? extends E> function, Class<E> exceptionType)
      Wraps function that returns Stream<T> to one that returns Stream<Maybe<T, E>> with exceptions of type E wrapped.
    • maybe

      public static <A, B, T, E extends Throwable> BiFunction<A,B,Maybe<T,E>> maybe(CheckedBiFunction<? super A,? super B,? extends T,? extends E> function, Class<E> exceptionType)
      Wraps function to be used for a stream of Maybe.

      Normally one should use maybe(CheckedBiFunction) unless E is an unchecked exception type.

      For GWT code, wrap the function manually, as in:

      
         private static <A, B, T> BiFunction<A, B, Maybe<T, FooException>> foo(
             CheckedBiFunction<A, B, T, FooException> function) {
           return (a, b) -> {
             try {
               return Maybe.of(function.apply(a, b));
             } catch (FooException e) {
               return Maybe.except(e);
             }
           };
         }
       
    • maybeStream

      public static <A, B, T, E extends Throwable> BiFunction<A,B,Stream<Maybe<T,E>>> maybeStream(CheckedBiFunction<? super A,? super B,? extends Stream<? extends T>,? extends E> function, Class<E> exceptionType)
      Wraps function that returns Stream<T> to one that returns Stream<Maybe<T, E>> with exceptions of type E wrapped.
    • maybeToList

      public static <T, E extends Throwable> Collector<Maybe<T,E>,?,Maybe<List<T>,E>> maybeToList()
      Collects a stream of Maybe to an immutable Maybe<List<T>, E>, which will wrap the exception if any input Maybe is exceptional.
      Since:
      7.0
    • maybeToSet

      public static <T, E extends Throwable> Collector<Maybe<T,E>,?,Maybe<Set<T>,E>> maybeToSet()
      Collects a stream of Maybe to an immutable Maybe<Set<T>, E>, which will wrap the exception if any input Maybe is exceptional.
      Since:
      7.0
    • catchException

      public static <T, E extends Throwable> CompletionStage<Maybe<T,E>> catchException(Class<E> exceptionType, CompletionStage<? extends T> stage)
      Returns a wrapper of stage that if stage failed with exception of exceptionType, that exception is caught and wrapped inside a Maybe to complete the wrapper stage normally.

      This is useful if the asynchronous code is interested in recovering from its own exception without having to deal with other exception types.