/**
 * Copyright 2014 Netflix, Inc.
 * 
 * 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 rx.exceptions;

/**
 * Represents a {@code Throwable} that an {@code Observable} might notify its subscribers of, but that then can
 * be handled by an operator that is designed to recover from or react appropriately to such an error. You can
 * recover more information from an {@code OnErrorThrowable} than is found in a typical {@code Throwable}, such
 * as the item the {@code Observable} was trying to emit at the time the error was encountered.
 */
public final class OnErrorThrowable extends RuntimeException {

    private static final long serialVersionUID = -569558213262703934L;

    private final boolean hasValue;
    private final Object value;

    private OnErrorThrowable(Throwable exception) {
        super(exception);
        hasValue = false;
        this.value = null;
    }

    private OnErrorThrowable(Throwable exception, Object value) {
        super(exception);
        hasValue = true;
        this.value = value;
    }

    /**
     * Get the value associated with this {@code OnErrorThrowable}
     *
     * @return the value associated with this {@code OnErrorThrowable} (or {@code null} if there is none)
     */
    public Object getValue() {
        return value;
    }

    /**
     * Indicates whether or not there is a value associated with this {@code OnErrorThrowable}
     *
     * @return {@code true} if there is a value associated with this {@code OnErrorThrowable}, otherwise
     *         {@code false}
     */
    public boolean isValueNull() {
        return hasValue;
    }

    /**
     * Converts a {@link Throwable} into an {@link OnErrorThrowable}.
     *
     * @param t
     *          the {@code Throwable} to convert
     * @return an {@code OnErrorThrowable} representation of {@code t}
     */
    public static OnErrorThrowable from(Throwable t) {
        Throwable cause = Exceptions.getFinalCause(t);
        if (cause instanceof OnErrorThrowable.OnNextValue) {
            return new OnErrorThrowable(t, ((OnNextValue) cause).getValue());
        } else {
            return new OnErrorThrowable(t);
        }
    }

    /**
     * Adds the given item as the final cause of the given {@code Throwable}, wrapped in {@code OnNextValue}
     * (which extends {@code RuntimeException}).
     * 
     * @param e
     *          the {@link Throwable} to which you want to add a cause
     * @param value
     *          the item you want to add to {@code e} as the cause of the {@code Throwable}
     * @return the same {@code Throwable} ({@code e}) that was passed in, with {@code value} added to it as a
     *         cause
     */
    public static Throwable addValueAsLastCause(Throwable e, Object value) {
        Throwable lastCause = Exceptions.getFinalCause(e);
        if (lastCause != null && lastCause instanceof OnNextValue) {
            // purposefully using == for object reference check
            if (((OnNextValue) lastCause).getValue() == value) {
                // don't add another
                return e;
            }
        }
        Exceptions.addCause(e, new OnNextValue(value));
        return e;
    }

    /**
     * Represents an exception that was encountered while trying to emit an item from an Observable, and
     * tries to preserve that item for future use and/or reporting.
     */
    public static class OnNextValue extends RuntimeException {

        private static final long serialVersionUID = -3454462756050397899L;
        private final Object value;

        /**
         * Create an {@code OnNextValue} exception and include in its error message a string representation of
         * the item that was intended to be emitted at the time the exception was handled.
         *
         * @param value
         *         the item that the Observable was trying to emit at the time of the exception
         */
        public OnNextValue(Object value) {
            super("OnError while emitting onNext value: " + renderValue(value));
            this.value = value;
        }

        /**
         * Retrieve the item that the Observable was trying to emit at the time this exception occurred.
         *
         * @return the item that the Observable was trying to emit at the time of the exception
         */
        public Object getValue() {
            return value;
        }

        /**
         * Render the object if it is a basic type. This avoids the library making potentially expensive
         * or calls to toString() which may throw exceptions. See PR #1401 for details.
         *
         * @param value
         *        the item that the Observable was trying to emit at the time of the exception
         * @return a string version of the object if primitive, otherwise the classname of the object
         */
        private static String renderValue(Object value){
            if(value == null){
                return "null";
            }
            if(value.getClass().isPrimitive()){
                return value.toString();
            }
            if(value instanceof String){
                return (String)value;
            }
            return value.getClass().getSimpleName() + ".class";
        }
    }
}

@@ -5407,24 +5407,25 @@
           if
+ 
 (value == nu
@@ -5427,16 +5427,17 @@
 == null)
+ 
 %7B%0A      
@@ -5485,24 +5485,25 @@
           if
+ 
 (value.getCl
@@ -5522,16 +5522,17 @@
 itive())
+ 
 %7B%0A      
@@ -5594,16 +5594,17 @@
       if
+ 
 (value i
@@ -5620,16 +5620,17 @@
  String)
+ 
 %7B%0A      
@@ -5654,16 +5654,17 @@
 (String)
+ 
 value;%0A 
@@ -5668,32 +5668,133 @@
 ;%0A            %7D%0A
+            if (value instanceof Enum) %7B%0A                return ((Enum) value).name();%0A            %7D%0A
             retu
@@ -5820,14 +5820,8 @@
 .get
-Simple
 Name

Print full classname (inner class support) and fix enum output