/*
 * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.yangtools.util.concurrent;

import static java.util.Objects.requireNonNull;

import com.google.common.base.Function;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import org.gaul.modernizer_maven_annotations.SuppressModernizer;

/**
 * Utility exception mapper which translates an Exception to a specified type of
 * Exception.
 *
 * <p>
 * This mapper is intended to be used with
 * {@link com.google.common.util.concurrent.Futures#makeChecked(
 * com.google.common.util.concurrent.ListenableFuture, Function)}
 * <ul>
 * <li>if exception is the specified type or one of its subclasses, it returns
 * original exception.
 * <li>if exception is {@link ExecutionException} and the cause is of the
 * specified type, it returns the cause
 * <li>otherwise returns an instance of the specified exception type with
 * original exception as the cause.
 * </ul>
 *
 * @param <X> the exception type
 * @author Thomas Pantelis
 */
@SuppressModernizer
public abstract class ExceptionMapper<X extends Exception> implements Function<Exception, X> {

    private final Class<X> exceptionType;
    private final String opName;

    /**
     * Constructor.
     *
     * @param opName the String prefix for exception messages.
     * @param exceptionType the exception type to which to translate.
     */
    public ExceptionMapper(final String opName, final Class<X> exceptionType) {
        this.exceptionType = requireNonNull(exceptionType);
        this.opName = requireNonNull(opName);
    }

    /**
     * Return the exception class produced by this instance.
     *
     * @return Exception class.
     */
    protected final Class<X> getExceptionType() {
        return exceptionType;
    }

    /**
     * Invoked to create a new exception instance of the specified type.
     *
     * @param message the message for the new exception.
     * @param cause the cause for the new exception.
     *
     * @return an instance of the exception type.
     */
    protected abstract X newWithCause(String message, Throwable cause);

    @Override
    @SuppressWarnings("unchecked")
    @SuppressFBWarnings({"BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", "NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE"})
    public X apply(final Exception input) {

        // If exception is of the specified type,return it.
        if (exceptionType.isAssignableFrom(input.getClass())) {
            return (X) input;
        }

        // If exception is ExecutionException whose cause is of the specified
        // type, return the cause.
        if (input instanceof ExecutionException && input.getCause() != null) {
            if (exceptionType.isAssignableFrom(input.getCause().getClass())) {
                return (X) input.getCause();
            }
            return newWithCause(opName + " execution failed", input.getCause());
        }

        // Otherwise return an instance of the specified type with the original
        // cause.

        if (input instanceof InterruptedException) {
            return newWithCause(opName + " was interupted.", input);
        }

        if (input instanceof CancellationException) {
            return newWithCause(opName + " was cancelled.", input);
        }

        // We really shouldn't get here but need to cover it anyway for completeness.
        return newWithCause(opName + " encountered an unexpected failure", input);
    }
}

@@ -769,19 +769,16 @@
  type of
-%0A *
  Excepti
@@ -784,21 +784,8 @@
 ion.
-%0A *%0A * %3Cp%3E%0A *
  Thi
@@ -811,31 +811,41 @@
 d to
+%0A *
  be 
-used with%0A * %7B@link
+primarily used with %7B@code
  com
@@ -886,9 +886,9 @@
 ures
-#
+.
 make
@@ -899,72 +899,8 @@
 ked(
-%0A * com.google.common.util.concurrent.ListenableFuture, Function
 )%7D%0A 
@@ -908,16 +908,18 @@
  %3Cul%3E%0A *
+  
  %3Cli%3Eif 
@@ -986,19 +986,16 @@
  returns
-%0A *
  origina
@@ -1009,16 +1009,18 @@
 tion.%0A *
+  
  %3Cli%3Eif 
@@ -1082,19 +1082,16 @@
 s of the
-%0A *
  specifi
@@ -1122,16 +1122,18 @@
 cause%0A *
+  
  %3Cli%3Eoth
@@ -1195,19 +1195,16 @@
 ype with
-%0A *
  origina

Update ExceptionMapper documentation