001package com.identityworksllc.iiq.common;
002
003import java.io.PrintStream;
004import java.io.PrintWriter;
005import java.util.Objects;
006import java.util.StringJoiner;
007
008/**
009 * This exception is to be used whenever an exception is caught inside of a catch
010 * block. It will display details of both exceptions on printStackTrace and other
011 * methods.
012 *
013 * The first exception will be treated like any other "cause" passed to an
014 * exception, so it will be returned by {@link Throwable#getCause()}, while
015 * the second exception will be stored separately as {@link #t2}.
016 */
017public final class PairedException extends Throwable {
018    /**
019     * The internal second exception
020     */
021    private final Throwable t2;
022
023    /**
024     * Constructs a new {@link PairedException} from the two throwables
025     * @param t1 The first throwable
026     * @param t2 The second throwable
027     */
028    public PairedException(Throwable t1, Throwable t2) {
029        super(t1);
030        Objects.requireNonNull(t2);
031        this.t2 = t2;
032    }
033
034    /**
035     * Constructs a new {@link PairedException} from the two throwables
036     * @param t1 The first throwable
037     * @param t2 The second throwable
038     */
039    public PairedException(String message, Throwable t1, Throwable t2) {
040        super(message, t1);
041        Objects.requireNonNull(t2);
042        this.t2 = t2;
043    }
044
045    @Override
046    public String getLocalizedMessage() {
047        return new StringJoiner(",", PairedException.class.getSimpleName() + "[", "]")
048                .add("m1=" + super.getLocalizedMessage())
049                .add("m2=" + t2.getLocalizedMessage())
050                .toString();
051    }
052
053    @Override
054    public String getMessage() {
055        return new StringJoiner(",", PairedException.class.getSimpleName() + "[", "]")
056                .add("m1=" + super.getMessage())
057                .add("m2=" + t2.getMessage())
058                .toString();
059    }
060
061    public Throwable getSecondCause() {
062        return t2;
063    }
064
065    public StackTraceElement[] getSecondStackTrace() {
066        Objects.requireNonNull(t2);
067        return t2.getStackTrace();
068    }
069
070    @Override
071    public void printStackTrace(PrintWriter s) {
072        super.printStackTrace(s);
073        if (t2 != null) {
074            t2.printStackTrace(s);
075        }
076    }
077
078    @Override
079    public void printStackTrace() {
080        super.printStackTrace();
081        if (t2 != null) {
082            t2.printStackTrace();
083        }
084    }
085
086    @Override
087    public void printStackTrace(PrintStream s) {
088        super.printStackTrace(s);
089        if (t2 != null) {
090            t2.printStackTrace(s);
091        }
092    }
093
094    @Override
095    public String toString() {
096        return new StringJoiner(", ", PairedGeneralException.class.getSimpleName() + "[", "]")
097                .add("t1=" + getCause().toString())
098                .add("t2=" + getSecondCause().toString())
099                .toString();
100    }
101}