summaryrefslogtreecommitdiffstats
path: root/jack-api/src/com/android/jack/api/brest/ChainedException.java
diff options
context:
space:
mode:
Diffstat (limited to 'jack-api/src/com/android/jack/api/brest/ChainedException.java')
-rw-r--r--jack-api/src/com/android/jack/api/brest/ChainedException.java152
1 files changed, 152 insertions, 0 deletions
diff --git a/jack-api/src/com/android/jack/api/brest/ChainedException.java b/jack-api/src/com/android/jack/api/brest/ChainedException.java
new file mode 100644
index 0000000..7a8a01c
--- /dev/null
+++ b/jack-api/src/com/android/jack/api/brest/ChainedException.java
@@ -0,0 +1,152 @@
+/*
+ * 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.brest;
+
+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;
+ }
+ }
+}