From 7201261bad70189ac7c5d2ae0fa9e3c49867729f Mon Sep 17 00:00:00 2001
From: 2bllw8 <2bllw8@gmail.com>
Date: Sat, 19 Feb 2022 21:17:52 +0100
Subject: [PATCH] Add CheckedSupplier to replace CheckedException
---
README.md | 14 ++-----
.../exe/bbllw8/either/CheckedException.java | 8 ++--
.../exe/bbllw8/either/CheckedSupplier.java | 18 +++++++++
.../main/java/exe/bbllw8/either/Failure.java | 14 +++++++
lib/src/main/java/exe/bbllw8/either/Try.java | 40 +++++--------------
.../java/exe/bbllw8/either/FailureTest.java | 30 ++++++++++++++
.../java/exe/bbllw8/either/SuccessTest.java | 2 +-
.../test/java/exe/bbllw8/either/TryTest.java | 2 +-
8 files changed, 83 insertions(+), 45 deletions(-)
create mode 100644 lib/src/main/java/exe/bbllw8/either/CheckedSupplier.java
diff --git a/README.md b/README.md
index 736816a..a970735 100644
--- a/README.md
+++ b/README.md
@@ -34,9 +34,7 @@ implementation 'io.github.2bllw8:either:3.1.0'
## Usage
```java
-import exe.bbllw8.either.CheckedException;
import exe.bbllw8.either.Try;
-import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
@@ -45,14 +43,10 @@ import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
- Arrays.stream(args).map((String arg) -> Try.from(() -> {
- try {
- return Files.lines(Paths.get(arg))
- .collect(Collectors.joining("\n"));
- } catch (IOException e) {
- throw new CheckedException(e);
- }
- }).filter(text -> text.length() > 2)
+ Arrays.stream(args).map((String arg) -> Try.from(() ->
+ Files.lines(Paths.get(arg))
+ .collect(Collectors.joining("\n")))
+ .filter(text -> text.length() > 2)
.map(text -> text.substring(2))
.flatMap(text -> Try.from(() -> Integer.parseInt(text)))
.toEither()
diff --git a/lib/src/main/java/exe/bbllw8/either/CheckedException.java b/lib/src/main/java/exe/bbllw8/either/CheckedException.java
index 6790617..2a0a602 100644
--- a/lib/src/main/java/exe/bbllw8/either/CheckedException.java
+++ b/lib/src/main/java/exe/bbllw8/either/CheckedException.java
@@ -4,11 +4,9 @@
*/
package exe.bbllw8.either;
-import java.util.function.Supplier;
-
/**
* A CheckedException instance is used to catch checked Exceptions for usage in {@link
- * Try#from(Supplier)}.
+ * Try#from(CheckedSupplier)}.
*
*
* public class Example {
@@ -25,9 +23,11 @@
*
*
* @author 2bllw8
- * @see Try#from(Supplier)
+ * @see Try#from(CheckedSupplier)
* @since 2.2.0
+ * @deprecated Use {@link CheckedSupplier} instead of thowing wrapped exceptions.
*/
+@Deprecated
public final class CheckedException extends RuntimeException {
private static final long serialVersionUID = 2896775411630760282L;
diff --git a/lib/src/main/java/exe/bbllw8/either/CheckedSupplier.java b/lib/src/main/java/exe/bbllw8/either/CheckedSupplier.java
new file mode 100644
index 0000000..7f061c6
--- /dev/null
+++ b/lib/src/main/java/exe/bbllw8/either/CheckedSupplier.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022 2bllw8
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package exe.bbllw8.either;
+
+/**
+ * Represents a supplier of results that may throw a {@link Throwable}.
+ *
+ * @param The type of result supplied by this supplier
+ * @author 2bllw8
+ * @since 3.2.0
+ */
+@FunctionalInterface
+public interface CheckedSupplier {
+
+ T get() throws Throwable;
+}
diff --git a/lib/src/main/java/exe/bbllw8/either/Failure.java b/lib/src/main/java/exe/bbllw8/either/Failure.java
index 12deec5..d3f9fa0 100644
--- a/lib/src/main/java/exe/bbllw8/either/Failure.java
+++ b/lib/src/main/java/exe/bbllw8/either/Failure.java
@@ -21,6 +21,7 @@ public final class Failure extends Try {
private transient final Throwable throwable;
public Failure(Throwable throwable) {
+ assertNotFatal(throwable);
this.throwable = throwable;
}
@@ -140,4 +141,17 @@ public int hashCode() {
public String toString() {
return "Failure(" + throwable + ')';
}
+
+ /**
+ * Assert that the given throwable is not fatal.
+ */
+ private static void assertNotFatal(Throwable t) {
+ if (t instanceof VirtualMachineError) {
+ throw (VirtualMachineError) t;
+ } else if (t instanceof ThreadDeath) {
+ throw (ThreadDeath) t;
+ } else if (t instanceof LinkageError) {
+ throw (LinkageError) t;
+ }
+ }
}
diff --git a/lib/src/main/java/exe/bbllw8/either/Try.java b/lib/src/main/java/exe/bbllw8/either/Try.java
index b60cf8b..5e1b23e 100644
--- a/lib/src/main/java/exe/bbllw8/either/Try.java
+++ b/lib/src/main/java/exe/bbllw8/either/Try.java
@@ -7,7 +7,6 @@
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
-import java.util.function.Supplier;
/**
* The {@link Try} type represents a computation that may either result in an exception, or return a
@@ -40,7 +39,7 @@ public abstract class Try {
*
* - {@link Success}
* - {@link Failure}
- * - {@link Try#from(Supplier)}
+ * - {@link Try#from(CheckedSupplier)}
*
*
* @hidden
@@ -205,36 +204,19 @@ public static Try flatten(Try> tryTry) {
*
* @since 3.0.0
*/
- @SuppressWarnings({"PMD.AvoidCatchingThrowable"})
- public static Try from(Supplier supplier) {
+ @SuppressWarnings({
+ "deprecation",
+ "PMD.AvoidCatchingThrowable",
+ })
+ public static Try from(CheckedSupplier supplier) {
+ //noinspection deprecation
try {
return new Success<>(supplier.get());
- } catch (CheckedException e) {
- // Wrapped checked exception
- final Throwable t = e.getCause();
- if (isFatal(t)) {
- // Fatal
- throw e;
- } else {
- return new Failure<>(t);
- }
+ } catch (CheckedException t) {
+ // TODO: remove this clause when CheckedException is removed
+ return new Failure<>(t.getCause());
} catch (Throwable t) {
- if (isFatal(t)) {
- // Fatal
- throw t;
- } else {
- return new Failure<>(t);
- }
+ return new Failure<>(t);
}
}
-
- /**
- * @return Returns whether the given throwable is fatal.
- */
- private static boolean isFatal(Throwable t) {
- return t instanceof VirtualMachineError
- || t instanceof ThreadDeath
- || t instanceof InterruptedException
- || t instanceof LinkageError;
- }
}
diff --git a/lib/src/test/java/exe/bbllw8/either/FailureTest.java b/lib/src/test/java/exe/bbllw8/either/FailureTest.java
index e18187a..cdda861 100644
--- a/lib/src/test/java/exe/bbllw8/either/FailureTest.java
+++ b/lib/src/test/java/exe/bbllw8/either/FailureTest.java
@@ -187,4 +187,34 @@ public void stringRepresentation() {
throw new IllegalStateException("something");
}).toString());
}
+
+ @Test
+ public void multipleThrow() {
+ Assert.assertTrue("Multiple thrown classes are handled (throwable #1)",
+ Try.from(() -> new IntToBoolean().convert(2))
+ .recover(t -> t instanceof IllegalAccessException)
+ .get());
+ Assert.assertTrue("Multiple thrown classes are handled (throwable #2)",
+ Try.from(() -> new IntToBoolean().convert(3))
+ .recover(t -> t instanceof IllegalArgumentException)
+ .get());
+ }
+
+ private static class IntToBoolean {
+
+ boolean convert(int result) throws IllegalAccessException, IllegalArgumentException {
+ switch (result) {
+ case 0:
+ return false;
+ case 1:
+ return true;
+ case 2:
+ // You have no authority to discover the dark truth about
+ // the third hidden boolean value
+ throw new IllegalAccessException();
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+ }
}
diff --git a/lib/src/test/java/exe/bbllw8/either/SuccessTest.java b/lib/src/test/java/exe/bbllw8/either/SuccessTest.java
index c8c961b..da5bee8 100644
--- a/lib/src/test/java/exe/bbllw8/either/SuccessTest.java
+++ b/lib/src/test/java/exe/bbllw8/either/SuccessTest.java
@@ -108,7 +108,7 @@ public void transform() {
new Success<>(12),
Try.from(() -> "12").transform(value -> Try.from(() -> Integer.parseInt(value)),
t -> Try.from(() -> {
- throw new CheckedException(t);
+ throw t;
})));
}
diff --git a/lib/src/test/java/exe/bbllw8/either/TryTest.java b/lib/src/test/java/exe/bbllw8/either/TryTest.java
index 01f2044..772c108 100644
--- a/lib/src/test/java/exe/bbllw8/either/TryTest.java
+++ b/lib/src/test/java/exe/bbllw8/either/TryTest.java
@@ -28,7 +28,7 @@ public void flatten() {
public void from() {
Assert.assertTrue("A supplier throwing an exception should return a failure",
Try.from(() -> {
- throw new CheckedException(new Throwable());
+ throw new Throwable();
}).isFailure());
Assert.assertTrue("A supplier throwing an exception should return a failure",
Try.from(() -> Integer.parseInt("-")).isFailure());