package throwing.bridge;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.IntStream;

abstract class CheckedBridge<D, X extends Throwable> extends AbstractBridge<D> {
    private final FunctionBridge<X> bridge;
    
    CheckedBridge(D delegate, FunctionBridge<X> bridge) {
        super(delegate);
        this.bridge = bridge;
    }
    
    protected FunctionBridge<X> getBridge() {
        return bridge;
    }
    
    protected void filterBridgeException(Runnable runnable) throws X {
        filterBridgeException(() -> {
            runnable.run();
            return null;
        });
    }
    
    protected <R> R filterBridgeException(Supplier<R> supplier) throws X {
        try {
            return supplier.get();
        } catch (Throwable t) {
            if (t instanceof BridgeException) {
                Throwable cause = t.getCause();
                if (getBridge().getExceptionClass().isInstance(cause)) {
                    // filter out bridge lines from the exception. They can get
                    // rather verbose.
                    List<StackTraceElement> ste = Arrays.asList(cause.getStackTrace());
                    IntSummaryStatistics stats = IntStream.range(0, ste.size())
                            .filter(i -> ste.get(i).getClassName().startsWith("throwing.bridge"))
                            .summaryStatistics();
                    if (stats.getCount() > 0) {
                        List<StackTraceElement> filtered = new ArrayList<>(ste.size()
                                - (stats.getMax() - stats.getMin()));
                        for (int x = 0; x < stats.getMin(); x++) {
                            filtered.add(ste.get(x));
                        }
                        for (int x = stats.getMax() + 1; x < ste.size(); x++) {
                            filtered.add(ste.get(x));
                        }
                        cause.setStackTrace(filtered.toArray(new StackTraceElement[filtered.size()]));
                    }
                    
                    throw getBridge().getExceptionClass().cast(cause);
                } else {
                    throw t;
                }
            } else if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else if (t instanceof Error) {
                throw (Error) t;
            } else {
                throw new AssertionError(t);
            }
        }
    }
}

@@ -283,24 +283,224 @@
 Bridge%3CD%3E %7B%0A
+    private static final String PACKAGE = CheckedBridge.class.getPackage().getName();%0A    // it might be useful to have a way to turn this off%0A    public static volatile boolean FILTER_STACK = true;%0A%0A
     private 
@@ -531,20 +531,16 @@
 bridge;%0A
-    
 %0A    Che
@@ -643,37 +643,33 @@
 = bridge;%0A    %7D%0A
-    
 %0A
+
     protected Fu
@@ -719,37 +719,33 @@
 n bridge;%0A    %7D%0A
-    
 %0A
+
     protected vo
@@ -908,21 +908,17 @@
 ;%0A    %7D%0A
-    
 %0A
+
     prot
@@ -1377,571 +1377,24 @@
     
-List%3CStackTraceElement%3E ste = Arrays.asList(cause.getStackTrace());%0A                    IntSummaryStatistics stats = IntStream.range(0, ste.size())%0A                            .filter(i -%3E ste.get(i).getClassName().startsWith(%22throwing.bridge%22))%0A                            .summaryStatistics();%0A                    if (stats.getCount() %3E 0) %7B%0A                        List%3CStackTraceElement%3E filtered = new ArrayList%3C%3E(ste.size()%0A                                - (stats.getMax() - stats.getMin()));%0A                        for (int x = 0; x %3C stats.getMin(); x++
+if (FILTER_STACK
 ) %7B%0A
@@ -1421,324 +1421,30 @@
     
-  
-  
 filter
-ed.add(ste.get(x));%0A                        %7D%0A                        for (int x = stats.getMax() + 1; x %3C ste.size(); x++) %7B%0A                            filtered.add(ste.get(x));%0A                        %7D%0A                        cause.setStackTrace(filtered.toArray(new StackTraceElement%5Bfiltered.size()%5D)
+StackTrace(cause
 );%0A 
@@ -1468,29 +1468,9 @@
   %7D%0A
-                    
 %0A
+
     
@@ -1852,16 +1852,16 @@
 ror(t);%0A
-
         
@@ -1881,11 +1881,877 @@
  %7D%0A    %7D
+%0A%0A    // this method also filters out a lot of the java.util.stream trace elements%0A    private void filterStackTrace(Throwable cause) %7B%0A        List%3CStackTraceElement%3E ste = Arrays.asList(cause.getStackTrace());%0A        IntSummaryStatistics stats = IntStream.range(0, ste.size()).filter(%0A                i -%3E ste.get(i).getClassName().startsWith(PACKAGE)).summaryStatistics();%0A        if (stats.getCount() %3E 0) %7B%0A            List%3CStackTraceElement%3E filtered = new ArrayList%3C%3E(ste.size() - (stats.getMax() - stats.getMin()));%0A            for (int x = 0; x %3C stats.getMin(); x++) %7B%0A                filtered.add(ste.get(x));%0A            %7D%0A            for (int x = stats.getMax() + 1; x %3C ste.size(); x++) %7B%0A                filtered.add(ste.get(x));%0A            %7D%0A            cause.setStackTrace(filtered.toArray(new StackTraceElement%5Bfiltered.size()%5D));%0A        %7D%0A    %7D
 %0A%7D%0A

Make the stack trace filtering a bit more flexible