package org.limewire.concurrent;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.limewire.listener.EventListener;
import org.limewire.listener.EventListenerList;
import org.limewire.listener.EventListenerList.EventListenerListContext;
/**
* Delegates from one ListeningFuture to another, converting from the Source
* type to the Result type.
*/
public abstract class ListeningFutureDelegator<S, R> implements ListeningFuture<R> {
private final ListeningFuture<S> delegate;
private final EventListenerListContext listenerContext;
public ListeningFutureDelegator(ListeningFuture<S> delegate) {
this.delegate = delegate;
this.listenerContext = new EventListenerListContext();
}
public void addFutureListener(final EventListener<FutureEvent<R>> listener) {
// If we're done, we can just dispatch immediately w/o having to
// worry about creating a delegate listener.
if(isDone()) {
EventListenerList.dispatch(listener, FutureEvent.createEvent(this), listenerContext);
} else {
delegate.addFutureListener(new EventListener<FutureEvent<S>>() {
public void handleEvent(FutureEvent<S> event) {
EventListenerList.dispatch(listener, FutureEvent.createEvent(ListeningFutureDelegator.this), listenerContext);
}
});
}
}
public boolean cancel(boolean mayInterruptIfRunning) {
return delegate.cancel(mayInterruptIfRunning);
}
public R get() throws InterruptedException, ExecutionException {
S s;
try {
s = delegate.get();
} catch(ExecutionException ee) {
return convertException(ee);
}
return convertSource(s);
}
public R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException,
TimeoutException {
S s;
try {
s = delegate.get(timeout, unit);
} catch(ExecutionException ee) {
return convertException(ee);
}
return convertSource(s);
}
public boolean isCancelled() {
return delegate.isCancelled();
}
public boolean isDone() {
return delegate.isDone();
}
/** Converts from S to R. If it cannot be converted, throws an ExecutionException. */
protected abstract R convertSource(S source) throws ExecutionException;
/** Converts from an ExecutionException. If it cannot be converted, rethrows an ExecutionException. */
protected abstract R convertException(ExecutionException ee) throws ExecutionException;
}