package uk.kludje; /** * Adapts any type to {@link AutoCloseable} so that its instances can be closed by try blocks. * * Usage: * * <pre><code> * try (Res<SomeResource> someResource = Res.res(SomeResource::release, new SomeResource)) { * someResource.unwrap().foo(); * } * </code></pre> * * @param <R> the underlying resource type */ public class Res<R> implements CloseableResource { private final CloseFunction<R> closeFunction; private final R resource; private Res(CloseFunction<R> closeFunction, R resource) { Fatal.when(closeFunction == null, "closeFunction == null"); Fatal.when(resource == null, "resource == null"); this.closeFunction = closeFunction; this.resource = resource; } /** * @return the resource instance */ public R unwrap() { return resource; } /** * Throws any exception thrown by {@link CloseFunction#close(Object)} * including checked exceptions. * * If the {@link CloseFunction} throws a checked exception not declared by any other call use {@link #expected()} * to tell the compiler to expect it. */ @Override public void close() { try { closeFunction.close(resource); } catch (Exception e) { Exceptions.throwChecked(e); } } /** * Creates a new {@link Res} instance. * * @param closeFunction the function for releasing the resource * @param resource the resource instance * @param <R> the resource type * @return */ public static <R> Res<R> res(CloseFunction<R> closeFunction, R resource) { return new Res<>(closeFunction, resource); } @Override public <T extends Throwable> Res<R> expected() throws T { return this; } /** * Functional interface for closing a resource. * * @param <R> the resource type * @see Res#res(CloseFunction, Object) */ @FunctionalInterface public interface CloseFunction<R> { /** * Releases the resource argument. * * @param resource the resource to close * @throws Exception on error */ void close(R resource) throws Exception; } }