-
Notifications
You must be signed in to change notification settings - Fork 0
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
0 parents
commit a31f764
Showing
7 changed files
with
285 additions
and
0 deletions.
There are no files selected for viewing
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,2 @@ | ||
target/ | ||
.idea/ |
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,54 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>io.github.jadefalke</groupId> | ||
<artifactId>Try-Catch</artifactId> | ||
<version>0.0.1-alpha</version> | ||
<packaging>jar</packaging> | ||
|
||
<properties> | ||
<maven.compiler.source>17</maven.compiler.source> | ||
<maven.compiler.target>17</maven.compiler.target> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>4.13.2</version> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.projectlombok</groupId> | ||
<artifactId>lombok</artifactId> | ||
<version>1.18.22</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-dependency-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<id>copy-dependencies</id> | ||
<phase>prepare-package</phase> | ||
<goals> | ||
<goal>copy-dependencies</goal> | ||
</goals> | ||
<configuration> | ||
<outputDirectory> | ||
${project.build.directory}/libs | ||
</outputDirectory> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
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,149 @@ | ||
package io.github.jadefalke2; | ||
|
||
import io.github.jadefalke2.exceptions.CatchBlockAlreadyExistsException; | ||
import io.github.jadefalke2.interfaces.UnsafeRunnable; | ||
import io.github.jadefalke2.interfaces.UnsafeSupplier; | ||
import lombok.NonNull; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.function.Consumer; | ||
|
||
/** | ||
* This class describes a wrapper around a try-catch-finally block. | ||
* @param <T> the return type of this try-catch-finally block | ||
*/ | ||
public class Try <T> { | ||
|
||
private final UnsafeSupplier<T> attempt; | ||
private final Map<Class<? extends Exception>, Consumer<? super Exception>> catchClauses; | ||
private Runnable onFinally; | ||
|
||
/** | ||
* Constructs a new Try-catch-builder with the given Exception-throwing supplier as the code to execute | ||
* @param attempt the code to run inside the try-block | ||
*/ | ||
private Try (UnsafeSupplier<T> attempt) { | ||
this.attempt = attempt; | ||
catchClauses = new HashMap<>(); | ||
} | ||
|
||
/** | ||
* Factory method for a try without a return type | ||
* @param runnable the code to be executed | ||
* @return the newly constructed try | ||
*/ | ||
public static Try<Void> attempt (@NonNull UnsafeRunnable runnable) { | ||
return attempt(() -> { | ||
runnable.run(); | ||
return null; | ||
}); | ||
} | ||
|
||
/** | ||
* Factory method for a try | ||
* @param supplier the code to run and return a value inside the try | ||
* @param <T> the type to be returned | ||
* @return the newly constructed try | ||
*/ | ||
public static <T> Try<T> attempt (@NonNull UnsafeSupplier<T> supplier) { | ||
return new Try<>(supplier); | ||
} | ||
|
||
/** | ||
* Appends a catch-block with the given type | ||
* @param exceptionType the type of exception | ||
* @param onCatch the code to run when this catch block is executed | ||
* @return the try instance | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
public <E extends Exception> Try<T> onCatch (@NonNull Class<E> exceptionType, @NonNull Consumer<? super E> onCatch) { | ||
if (catchClauses.containsKey(exceptionType)) | ||
throw new CatchBlockAlreadyExistsException(); | ||
|
||
catchClauses.put(exceptionType, (Consumer<? super Exception>) onCatch); | ||
return this; | ||
} | ||
|
||
/** | ||
* Appends a catch-block with the Exception type | ||
* @param onCatch the code to run when this catch block is executed | ||
* @return the try instance | ||
*/ | ||
public Try<T> onCatch (@NonNull Consumer<? super Exception> onCatch) { | ||
return onCatch(Exception.class, onCatch); | ||
} | ||
|
||
/** | ||
* Appends a finally-block | ||
* @param onFinally the code run to run in the finally-block | ||
* @return the try instance | ||
*/ | ||
public Try<T> onFinally (@NonNull Runnable onFinally) { | ||
this.onFinally = onFinally; | ||
return this; | ||
} | ||
|
||
/** | ||
* Executes the code in the try-block, catching with the respective catch-block in case an Exception. | ||
* Finally, whatever branch is executed prior the finally-block will be executed. | ||
*/ | ||
public void run () { | ||
get(); | ||
} | ||
|
||
/** | ||
* Executes the code in the try-block, catching with the respective catch-block in case an Exception. | ||
* Finally, whatever branch is executed prior the finally-block will be executed. | ||
* @return the Optional describing the value obtained within the try-catch block | ||
*/ | ||
public Optional<T> get () { | ||
Optional<T> val = Optional.empty(); | ||
try { | ||
val = Optional.ofNullable(attempt.supply()); | ||
} catch (Exception e) { | ||
getCatchClause(e.getClass()) | ||
.ifPresent(exConsumer -> exConsumer.accept(e)); | ||
} finally { | ||
if (onFinally != null) | ||
onFinally.run(); | ||
} | ||
return val; | ||
} | ||
|
||
/** | ||
* Executes the code in the try-block, catching with the respective catch-block in case an Exception. | ||
* Finally, whatever branch is executed prior the finally-block will be executed. | ||
* @return the value obtained by the computation | ||
*/ | ||
public T getOrThrow () { | ||
return get().orElseThrow(); | ||
} | ||
|
||
/** | ||
* Executes the code in the try-block, catching with the respective catch-block in case an Exception. | ||
* Finally, whatever branch is executed prior the finally-block will be executed. | ||
* @param val the value to be returned if the value obtained in the try catch block is null | ||
* @return the value obtained | ||
*/ | ||
public T getOrElse (T val) { | ||
return get().orElse(val); | ||
} | ||
|
||
/** | ||
* Gets the correct catch clause for the given class | ||
* @param c the Exception class | ||
* @return the optional Exception from the map | ||
*/ | ||
private Optional<Consumer<? super Exception>> getCatchClause (Class<?> c) { | ||
if (catchClauses.containsKey(c)) { | ||
return Optional.of(catchClauses.get(c)); | ||
} else { | ||
if (c.getSuperclass().equals(Exception.class) || catchClauses.isEmpty()) { | ||
return Optional.empty(); | ||
} | ||
return getCatchClause(c.getSuperclass()); | ||
} | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/io/github/jadefalke2/exceptions/CatchBlockAlreadyExistsException.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,5 @@ | ||
package io.github.jadefalke2.exceptions; | ||
|
||
public class CatchBlockAlreadyExistsException extends RuntimeException { | ||
|
||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/io/github/jadefalke2/interfaces/UnsafeRunnable.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,5 @@ | ||
package io.github.jadefalke2.interfaces; | ||
|
||
public interface UnsafeRunnable { | ||
void run () throws Exception; | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/io/github/jadefalke2/interfaces/UnsafeSupplier.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,5 @@ | ||
package io.github.jadefalke2.interfaces; | ||
|
||
public interface UnsafeSupplier<T> { | ||
T supply() throws Exception; | ||
} |
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,65 @@ | ||
import io.github.jadefalke2.Try; | ||
import io.github.jadefalke2.exceptions.CatchBlockAlreadyExistsException; | ||
import io.github.jadefalke2.interfaces.UnsafeSupplier; | ||
import org.junit.Test; | ||
|
||
import java.io.IOException; | ||
import java.util.NoSuchElementException; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
public class APITest { | ||
|
||
@Test | ||
public void testMultipleCatchBlocks () { | ||
assertThrows(CatchBlockAlreadyExistsException.class, | ||
() -> Try.attempt(() -> System.out.println("Test")) | ||
.onCatch(RuntimeException.class, Throwable::printStackTrace) | ||
.onCatch(RuntimeException.class, e -> System.out.println(e.getMessage())) | ||
); | ||
} | ||
|
||
@Test | ||
public void testCorrectCatchClause () { | ||
Try.attempt(() -> {throw new IOException();}) | ||
.onCatch(IOException.class, e -> {}) | ||
.onCatch(Exception.class, e -> fail()) | ||
.run(); | ||
|
||
Try.attempt(() -> {throw new Exception();}) | ||
.onCatch(Exception.class, e -> {}) | ||
.onCatch(IOException.class, e -> fail()); | ||
|
||
AtomicBoolean done = new AtomicBoolean(false); | ||
Try.attempt(() -> {throw new Exception();}) | ||
.onCatch(e -> done.set(true)) | ||
.run(); | ||
assertTrue(done.get()); | ||
} | ||
|
||
@Test | ||
public void testSuccessfulRun () { | ||
AtomicBoolean done = new AtomicBoolean(false); | ||
Try.attempt(() -> done.set(true)) | ||
.onCatch(e -> fail()) | ||
.run(); | ||
assertTrue(done.get()); | ||
} | ||
|
||
@Test | ||
public void testReturnValue () { | ||
assertEquals(Integer.valueOf(5), | ||
Try.attempt(() -> 5).getOrThrow()); | ||
|
||
assertEquals(10, Try.attempt(() -> {throw new IOException();}) | ||
.getOrElse(10)); | ||
|
||
assertThrows(NoSuchElementException.class, () -> | ||
Try.attempt(() -> null).getOrThrow()); | ||
|
||
assertThrows(NoSuchElementException.class, () -> | ||
Try.attempt((UnsafeSupplier<?>) () -> {throw new Exception();}).getOrThrow()); | ||
} | ||
|
||
} |