-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
1,494 additions
and
702 deletions.
There are no files selected for viewing
193 changes: 193 additions & 0 deletions
193
src/main/java/io/github/joselion/maybe/CloseableHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
package io.github.joselion.maybe; | ||
|
||
import java.util.Optional; | ||
|
||
import io.github.joselion.maybe.helpers.Commons; | ||
import io.github.joselion.maybe.util.Either; | ||
import io.github.joselion.maybe.util.function.ThrowingConsumer; | ||
import io.github.joselion.maybe.util.function.ThrowingFunction; | ||
|
||
/** | ||
* CloseableHandler is an API that allows to solve or run an effect using an | ||
* {@link AutoCloseable} resource. This resource will be automatically closed | ||
* after the {@code solve} or the {@code effect} operation is finished. | ||
* | ||
* @param <T> The autoclosable type | ||
* @param <E> The throwable type | ||
* | ||
* @author Jose Luis Leon | ||
* @since v1.3.0 | ||
*/ | ||
public class CloseableHandler<T extends AutoCloseable, E extends Throwable> { | ||
|
||
private final Either<E, T> value; | ||
|
||
private CloseableHandler(final T resource) { | ||
this.value = Either.ofRight(resource); | ||
} | ||
|
||
private CloseableHandler(final E error) { | ||
this.value = Either.ofLeft(error); | ||
} | ||
|
||
/** | ||
* Internal use method to instatiate a CloseableHandler from a given resource. | ||
* | ||
* @param <T> the type of the resource | ||
* @param <E> the type of the error | ||
* @param resource the resource to instantiate the CloseableHandler with | ||
* @return a new instance of CloseableHandler with the given resource | ||
*/ | ||
static <T extends AutoCloseable, E extends Throwable> CloseableHandler<T, E> from(final T resource) { | ||
return new CloseableHandler<>(resource); | ||
} | ||
|
||
/** | ||
* Internal use method to instatiate a failed CloseableHandler from an exception. | ||
* | ||
* @param <T> the type of the resource | ||
* @param <E> the type of the error | ||
* @param error the error to instantiate the failed CloseableHandler | ||
* @return a new instance of the failed CloseableHandler with the error | ||
*/ | ||
static <T extends AutoCloseable, E extends Throwable> CloseableHandler<T, E> failure(final E error) { | ||
return new CloseableHandler<>(error); | ||
} | ||
|
||
/** | ||
* Internal use only. | ||
* | ||
* @return the possible stored resource | ||
*/ | ||
Optional<T> resource() { | ||
return this.value.rightToOptional(); | ||
} | ||
|
||
/** | ||
* Internal use only. | ||
* | ||
* @return the possible propagated error | ||
*/ | ||
Optional<E> error() { | ||
return this.value.leftToOptional(); | ||
} | ||
|
||
/** | ||
* If the resource is present, solves the value of a throwing operation | ||
* using a {@link ThrowingFunction} expression which has the previously | ||
* prepared resource in the argument. The resource is automatically closed | ||
* after the operation finishes, just like a common try-with-resources | ||
* statement. | ||
* <p> | ||
* Returs a {@link SolveHandler} which allows to handle the possible error | ||
* and return a safe value. The returned handler is {@code empty} if neither | ||
* the resource nor the error is present. | ||
* | ||
* @param <S> the type of the value returned by the {@code solver} | ||
* @param <X> the type of exception the {@code solver} may throw | ||
* @param solver the checked function operation to solve | ||
* @return a {@link SolveHandler} with either the value solved or the thrown | ||
* exception to be handled | ||
*/ | ||
public <S, X extends Throwable> SolveHandler<S, X> solve( | ||
final ThrowingFunction<? super T, ? extends S, ? extends X> solver | ||
) { | ||
return this.value | ||
.mapLeft(Commons::<X>cast) | ||
.unwrap( | ||
SolveHandler::ofError, | ||
resource -> { | ||
try (var res = resource) { | ||
return SolveHandler.ofSuccess(solver.apply(res)); | ||
} catch (final Throwable e) { //NOSONAR | ||
final var error = Commons.<X>cast(e); | ||
return SolveHandler.ofError(error); | ||
} | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* If the resource is present, solves the value of a throwing operation | ||
* using a {@link ThrowingFunction} expression which has the previously | ||
* prepared resource in the argument. The resource is automatically closed | ||
* after the operation finishes, just like a common try-with-resources | ||
* statement. | ||
* <p> | ||
* Returs a {@link SolveHandler} which allows to handle the possible error | ||
* and return a safe value. The returned handler is {@code empty} if neither | ||
* the resource nor the error is present. | ||
* | ||
* @param <S> the type of the value returned by the {@code solver} | ||
* @param <X> the type of exception the {@code solver} may throw | ||
* @param solver the checked function operation to solve | ||
* @return a {@link SolveHandler} with either the value solved or the thrown | ||
* exception to be handled | ||
* @deprecated in favor of {@link #solve(ThrowingFunction)} | ||
*/ | ||
@Deprecated(forRemoval = true, since = "3.4.0") | ||
public <S, X extends Throwable> SolveHandler<S, X> resolveClosing(// NOSONAR | ||
final ThrowingFunction<? super T, ? extends S, ? extends X> solver | ||
) { | ||
return this.solve(solver); | ||
} | ||
|
||
/** | ||
* If the resource is present, runs an effect that may throw an exception | ||
* using a {@link ThrowingConsumer} expression which has the previously | ||
* prepared resource in the argument. The resource is automatically closed | ||
* after the operation finishes, just like a common try-with-resources | ||
* statement. | ||
* <p> | ||
* Returning then an {@link EffectHandler} which allows to handle the | ||
* possible error. The returned handler is {@code empty} if neither the | ||
* resource nor the error is present. | ||
* | ||
* @param <X> the type of exception the {@code effect} may throw | ||
* @param effect the checked consumer operation to execute | ||
* @return an {@link EffectHandler} with either the thrown exception to be | ||
* handled or empty | ||
*/ | ||
public <X extends Throwable> EffectHandler<X> effect( | ||
final ThrowingConsumer<? super T, ? extends X> effect | ||
) { | ||
return this.value | ||
.mapLeft(Commons::<X>cast) | ||
.unwrap( | ||
EffectHandler::ofError, | ||
resource -> { | ||
try (var res = resource) { | ||
effect.accept(res); | ||
return EffectHandler.empty(); | ||
} catch (final Throwable e) { // NOSONAR | ||
final var error = Commons.<X>cast(e); | ||
return EffectHandler.ofError(error); | ||
} | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* If the resource is present, runs an effect that may throw an exception | ||
* using a {@link ThrowingConsumer} expression which has the previously | ||
* prepared resource in the argument. The resource is automatically closed | ||
* after the operation finishes, just like a common try-with-resources | ||
* statement. | ||
* <p> | ||
* Returning then an {@link EffectHandler} which allows to handle the | ||
* possible error. The returned handler is {@code empty} if neither the | ||
* resource nor the error is present. | ||
* | ||
* @param <X> the type of exception the {@code effect} may throw | ||
* @param effect the checked consumer operation to execute | ||
* @return an {@link EffectHandler} with either the thrown exception to be | ||
* handled or empty | ||
* @deprecated in favor of {@link #effect(ThrowingConsumer)} | ||
*/ | ||
@Deprecated(forRemoval = true, since = "3.4.0") | ||
public <X extends Throwable> EffectHandler<X> runEffectClosing(// NOSONAR | ||
final ThrowingConsumer<? super T, ? extends X> effect | ||
) { | ||
return this.effect(effect); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.