From d7a17800749ffa6e6b2e3ade8eb505c8ca767eee Mon Sep 17 00:00:00 2001 From: Greg Gibeling Date: Fri, 26 Apr 2024 08:46:15 -0700 Subject: [PATCH] Throw multiple exceptions as simply as possible --- .../alexandria/java/core/error/HError.java | 111 ++++++++++-------- 1 file changed, 60 insertions(+), 51 deletions(-) diff --git a/ax-java/src/main/java/com/g2forge/alexandria/java/core/error/HError.java b/ax-java/src/main/java/com/g2forge/alexandria/java/core/error/HError.java index e1f6bf2f..a6d2c010 100644 --- a/ax-java/src/main/java/com/g2forge/alexandria/java/core/error/HError.java +++ b/ax-java/src/main/java/com/g2forge/alexandria/java/core/error/HError.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -16,8 +17,10 @@ import java.util.stream.Stream; import com.g2forge.alexandria.java.concurrent.RuntimeInterruptedException; +import com.g2forge.alexandria.java.core.helpers.HCollection; import com.g2forge.alexandria.java.core.helpers.HCollector.SimpleCollector; import com.g2forge.alexandria.java.core.marker.Helpers; +import com.g2forge.alexandria.java.function.ISupplier; import com.g2forge.alexandria.java.function.IThrowConsumer1; import com.g2forge.alexandria.java.function.IThrowFunction1; import com.g2forge.alexandria.java.function.IThrowRunnable; @@ -28,6 +31,55 @@ @Helpers @UtilityClass public class HError { + public static Collector, ?, R> collector(Supplier<_T> supplier, boolean allowPartial, Collector collector) { + return new SimpleCollector, List>, R>(ArrayList::new, List::add, (left, right) -> { + left.addAll(right); + return left; + }, list -> { + final Map>> grouped = list.stream().collect(Collectors.groupingBy(OrThrowable::isNotEmpty)); + final List> successes = grouped.get(true); + if (!(allowPartial && (successes != null) && !successes.isEmpty())) { + final List> failures = grouped.get(false); + if ((failures != null) && !failures.isEmpty()) HError.throwQuietly(HError.createWithSuppressed(supplier, failures.stream().map(OrThrowable::getThrowable).collect(Collectors.toList()))); + } + return ((successes == null) ? Stream.empty() : successes.stream().map(OrThrowable::get)).collect(collector); + }, Collections.emptySet()); + } + + public static Collector collector(Supplier supplier, boolean allowPartial) { + return new SimpleCollector, Void>(ArrayList::new, List::add, (left, right) -> { + left.addAll(right); + return left; + }, list -> { + if (allowPartial && list.contains(null)) return null; + final List throwables = list.stream().filter(Objects::nonNull).collect(Collectors.toList()); + if (!throwables.isEmpty()) HError.throwQuietly(HError.createWithSuppressed(supplier, throwables)); + return null; + }, Collections.emptySet()); + } + + public static T createWithSuppressed(Supplier supplier, Iterable throwables) { + return withSuppressed(supplier.get(), throwables); + } + + public static T createWithSuppressed(Supplier supplier, Throwable... throwables) { + return withSuppressed(supplier.get(), throwables); + } + + public static void throwQuietly(ISupplier messageSupplier, Collection throwables) { + if (throwables.isEmpty()) return; + if (throwables.size() == 1) throwQuietly(HCollection.getOne(throwables)); + throw withSuppressed(messageSupplier == null ? new RuntimeWrappingException() : new RuntimeWrappingException(messageSupplier.get()), throwables); + } + + public static void throwQuietly(Throwable throwable) { + if (throwable instanceof Error) throw (Error) throwable; + if (throwable instanceof RuntimeException) throw (RuntimeException) throwable; + if (throwable instanceof IOException) throw (RuntimeIOException) throwable; + if (throwable instanceof InterruptedException) throw (RuntimeInterruptedException) throwable; + throw new RuntimeWrappingException(throwable); + } + public static String toString(Throwable throwable) { final ByteArrayOutputStream stream = new ByteArrayOutputStream(); throwable.printStackTrace(new PrintStream(stream)); @@ -80,17 +132,6 @@ public static Function wrap(IThrowConsumer1 cons }; } - public static Supplier wrap(IThrowRunnable runnable) { - return () -> { - try { - runnable.run(); - } catch (Throwable throwable) { - return throwable; - } - return null; - }; - } - public static Function> wrap(IThrowFunction1 function) { return i -> { try { @@ -101,46 +142,14 @@ public static Function> wrap(IThrowFunction1 Collector collector(Supplier supplier, boolean allowPartial) { - return new SimpleCollector, Void>(ArrayList::new, List::add, (left, right) -> { - left.addAll(right); - return left; - }, list -> { - if (allowPartial && list.contains(null)) return null; - final List throwables = list.stream().filter(Objects::nonNull).collect(Collectors.toList()); - if (!throwables.isEmpty()) HError.throwQuietly(HError.createWithSuppressed(supplier, throwables)); - return null; - }, Collections.emptySet()); - } - - public static Collector, ?, R> collector(Supplier<_T> supplier, boolean allowPartial, Collector collector) { - return new SimpleCollector, List>, R>(ArrayList::new, List::add, (left, right) -> { - left.addAll(right); - return left; - }, list -> { - final Map>> grouped = list.stream().collect(Collectors.groupingBy(OrThrowable::isNotEmpty)); - final List> successes = grouped.get(true); - if (!(allowPartial && (successes != null) && !successes.isEmpty())) { - final List> failures = grouped.get(false); - if ((failures != null) && !failures.isEmpty()) HError.throwQuietly(HError.createWithSuppressed(supplier, failures.stream().map(OrThrowable::getThrowable).collect(Collectors.toList()))); + public static Supplier wrap(IThrowRunnable runnable) { + return () -> { + try { + runnable.run(); + } catch (Throwable throwable) { + return throwable; } - return ((successes == null) ? Stream.empty() : successes.stream().map(OrThrowable::get)).collect(collector); - }, Collections.emptySet()); - } - - public static T createWithSuppressed(Supplier supplier, Iterable throwables) { - return withSuppressed(supplier.get(), throwables); - } - - public static T createWithSuppressed(Supplier supplier, Throwable... throwables) { - return withSuppressed(supplier.get(), throwables); - } - - public static void throwQuietly(Throwable throwable) { - if (throwable instanceof Error) throw (Error) throwable; - if (throwable instanceof RuntimeException) throw (RuntimeException) throwable; - if (throwable instanceof IOException) throw (RuntimeIOException) throwable; - if (throwable instanceof InterruptedException) throw (RuntimeInterruptedException) throwable; - throw new RuntimeWrappingException(throwable); + return null; + }; } }