All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.conqat.lib.commons.concurrent.FutureWithException Maven / Gradle / Ivy

There is a newer version: 2024.7.2
Show newest version
package org.conqat.lib.commons.concurrent;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.conqat.lib.commons.function.FunctionWithException;

/**
 * Extension of the general {@link Future}, that is ready to handle Exceptions of type {@code E}.
 */
public class FutureWithException implements Future {

	private final Future delegate;

	private final Class expectedException;

	public FutureWithException(Future delegate, Class expectedException) {
		this.delegate = delegate;
		this.expectedException = expectedException;
	}

	/**
	 * Creates a resolved {@link FutureWithException} with the provided {@code resolved} value
	 */
	public static  FutureWithException resolved(T resolved) {
		@SuppressWarnings("unchecked")
		FutureWithException result = (FutureWithException) new FutureWithException<>(
				CompletableFuture.completedFuture(resolved), Exception.class);
		return result;
	}

	/**
	 * Creates a failed {@link FutureWithException} with the provided {@code exception} value
	 */
	public static  FutureWithException failed(E exception) {
		CompletableFuture future = new CompletableFuture<>();
		future.completeExceptionally(exception);
		@SuppressWarnings("unchecked")
		Class exceptionClass = (Class) exception.getClass();
		return new FutureWithException<>(future, exceptionClass);
	}

	@Override
	public boolean cancel(boolean mayInterruptIfRunning) {
		return delegate.cancel(mayInterruptIfRunning);
	}

	@Override
	public boolean isCancelled() {
		return delegate.isCancelled();
	}

	@Override
	public boolean isDone() {
		return delegate.isDone();
	}

	@Override
	public T get() throws InterruptedException, ExecutionException {
		return delegate.get();
	}

	@Override
	public T get(long timeout, @NonNull TimeUnit unit)
			throws InterruptedException, ExecutionException, TimeoutException {
		return delegate.get(timeout, unit);
	}

	/**
	 * Waits if necessary for the computation to complete, and then retrieves its result.
	 * 

* If the underlying computation threw an Exception of type {@code E}, it is rethrown. Any other * exception is wrapped in a {@link RuntimeException}. */ public T getWithException() throws InterruptedException, E { try { return get(); } catch (ExecutionException e) { return handleExecutionException(e); } } /** * Waits if necessary for at most the given time for the computation to complete, and then retrieves * its result, if available. *

* If the underlying computation threw an Exception of type {@code E}, it is rethrown. Any other * exception is wrapped in a {@link RuntimeException}. */ public T getWithException(long timeout, @NonNull TimeUnit unit) throws InterruptedException, E, TimeoutException { try { return get(timeout, unit); } catch (ExecutionException e) { return handleExecutionException(e); } } private T handleExecutionException(ExecutionException e) throws E { Throwable cause = e.getCause(); if (expectedException.isInstance(cause)) { throw expectedException.cast(cause); } else { throw new RuntimeException("Unexpected Exception thrown", cause); } } /** * Returns a new {@link FutureWithException}, that applies the {@code transformer} on the result * value. */ public FutureWithException then(FunctionWithException transformer) { return new FutureWithException<>(new Future() { @Override public boolean cancel(boolean mayInterruptIfRunning) { return FutureWithException.this.cancel(mayInterruptIfRunning); } @Override public boolean isCancelled() { return FutureWithException.this.isCancelled(); } @Override public boolean isDone() { return FutureWithException.this.isDone(); } @Override public S get() throws InterruptedException, ExecutionException { try { return transformer.apply(FutureWithException.this.get()); } catch (InterruptedException | ExecutionException | RuntimeException e) { throw e; } catch (Exception e) { throw new ExecutionException(e); } } @Override public S get(long timeout, @NonNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { try { return transformer.apply(FutureWithException.this.get(timeout, unit)); } catch (InterruptedException | ExecutionException | TimeoutException | RuntimeException e) { throw e; } catch (Exception e) { throw new ExecutionException(e); } } }, expectedException); } }