/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.jack.api.v01; import java.util.ArrayList; import java.util.Iterator; import javax.annotation.CheckForNull; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; /** * Abstract class to easily chain exceptions together. * * The exception can be managed like any other exception. In this case, the first one will be the * only one used. * * Special management can use the {@link #iterator()} or the {@link #getNextException()} to browse * all chained exceptions and dispatch them. * * See {@link ChainedExceptionBuilder} to build the chain of exceptions. */ public abstract class ChainedException extends Exception implements Iterable<ChainedException> { private static final long serialVersionUID = 1L; @Nonnull private String message; @Nonnegative private int count = 1; @Nonnull private ChainedException tail = this; @CheckForNull private ChainedException next = null; public ChainedException(@Nonnull String message) { super(""); this.message = message; } public ChainedException(@Nonnull String message, @Nonnull Throwable cause) { super("", cause); this.message = message; } public ChainedException(@Nonnull Throwable cause) { super(cause); this.message = cause.getMessage(); } @Override @Nonnull public String getMessage() { return message; } @Override @Nonnull public String getLocalizedMessage() { return message; } public void setMessage(@Nonnull String message) { this.message = message; } @Nonnull protected ChainedException putAsLastExceptionOf( @CheckForNull ChainedException head) { if (head == null) { this.tail = this; this.next = null; this.count = 1; return this; } else { head.tail.next = this; head.tail = this; head.count++; return head; } } @CheckForNull public ChainedException getNextException() { return next; } @Nonnegative public int getNextExceptionCount() { return count; } @Override @Nonnull public Iterator<ChainedException> iterator() { ArrayList<ChainedException> list = new ArrayList<ChainedException>(count); ChainedException exception = this; do { list.add(exception); exception = exception.next; } while (exception != null); return list.iterator(); } /** * Builder to construct a chain of exceptions. */ public static class ChainedExceptionBuilder<T extends ChainedException> { @CheckForNull private T head = null; @SuppressWarnings("unchecked") public void appendException(@Nonnull T exceptions) { for (ChainedException exception : exceptions) { head = (T) exception.putAsLastExceptionOf(head); } } public void throwIfNecessary() throws T { if (head != null) { throw head; } } @Nonnull public T getException() { assert head != null; return head; } } }