-
Notifications
You must be signed in to change notification settings - Fork 7
How it works
Java has two types of exceptions: checked and unchecked. If you want to throw a checked exception, you have to say so in your method signature. You're allowed to throw an unchecked exception whenever you want.
This library works by exploiting this system. It catches checked exceptions and rethrows them as unchecked exceptions so that the method signature is compatible with that of java.util.stream.Stream. Then, in a terminal operation, it catches the unchecked exception and rethrows it as the checked exception.
Here's a simplified example:
class StreamBridge<T, X extends Throwable> implements ThrowingStream<T, X> {
private static class BridgeException extends RuntimeException {
public BridgeException(Throwable cause) {
super(cause);
}
}
private final Stream<T> delegate;
private final Class<X> x;
StreamBridge(Stream<T> delegate, Class<X> x) {
this.delegate = delegate;
this.x = x;
}
private <R> R maskException(ThrowingSupplier<R, X> method) {
try {
return method.get();
} catch (Throwable t) {
if (x.isInstance(t)) {
throw new BridgeException(t);
} else {
throw t;
}
}
}
@Override
public ThrowingStream<T, X> filter(ThrowingPredicate<T, X> predicate) {
return new StreamBridge<>(
delegate.filter(t -> maskException(() -> predicate.test(t))), x);
}
@Override
public <R> ThrowingStream<R, X> map(ThrowingFunction<T, R, X> mapper) {
return new StreamBridge<>(
delegate.map(t -> maskException(() -> mapper.apply(t))), x);
}
private <R> R unmaskBridgeException(Supplier<R> method) throws X {
try {
return method.get();
} catch (BridgeException e) {
throw x.cast(e.getCause());
}
}
@Override
public <A, R> R collect(Collector<T, A, R> collector) throws X {
return unmaskBridgeException(() -> delegate.collect(collector));
}
}
The two important methods here are maskException and unmaskBridgeException. launder catches a checked exception and cleans it up by wrapping it in a BridgeException. unmaskBridgeException does the opposite: it catches BridgeExceptions and rethrows the original, generic exception.