diff options
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.java | 152 |
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; + } + } +} |