/*
 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.beans;

import com.sun.beans.finder.PersistenceDelegateFinder;

import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * An <code>Encoder</code> is a class which can be used to create
 * files or streams that encode the state of a collection of
 * JavaBeans in terms of their public APIs. The <code>Encoder</code>,
 * in conjunction with its persistence delegates, is responsible for
 * breaking the object graph down into a series of <code>Statements</code>s
 * and <code>Expression</code>s which can be used to create it.
 * A subclass typically provides a syntax for these expressions
 * using some human readable form - like Java source code or XML.
 *
 * @since 1.4
 *
 * @author Philip Milne
 */

public class Encoder {
    private final PersistenceDelegateFinder finder = new PersistenceDelegateFinder();
    private Map<Object, Expression> bindings = new IdentityHashMap<>();
    private ExceptionListener exceptionListener;
    boolean executeStatements = true;
    private Map<Object, Object> attributes;

    /**
     * Write the specified object to the output stream.
     * The serialized form will denote a series of
     * expressions, the combined effect of which will create
     * an equivalent object when the input stream is read.
     * By default, the object is assumed to be a <em>JavaBean</em>
     * with a nullary constructor, whose state is defined by
     * the matching pairs of "setter" and "getter" methods
     * returned by the Introspector.
     *
     * @param o The object to be written to the stream.
     *
     * @see XMLDecoder#readObject
     */
    protected void writeObject(Object o) {
        if (o == this) {
            return;
        }
        PersistenceDelegate info = getPersistenceDelegate(o == null ? null : o.getClass());
        info.writeObject(o, this);
    }

    /**
     * Sets the exception handler for this stream to <code>exceptionListener</code>.
     * The exception handler is notified when this stream catches recoverable
     * exceptions.
     *
     * @param exceptionListener The exception handler for this stream;
     *       if <code>null</code> the default exception listener will be used.
     *
     * @see #getExceptionListener
     */
    public void setExceptionListener(ExceptionListener exceptionListener) {
        this.exceptionListener = exceptionListener;
    }

    /**
     * Gets the exception handler for this stream.
     *
     * @return The exception handler for this stream;
     *    Will return the default exception listener if this has not explicitly been set.
     *
     * @see #setExceptionListener
     */
    public ExceptionListener getExceptionListener() {
        return (exceptionListener != null) ? exceptionListener : Statement.defaultExceptionListener;
    }

    Object getValue(Expression exp) {
        try {
            return (exp == null) ? null : exp.getValue();
        }
        catch (Exception e) {
            getExceptionListener().exceptionThrown(e);
            throw new RuntimeException("failed to evaluate: " + exp.toString());
        }
    }

    /**
     * Returns the persistence delegate for the given type.
     * The persistence delegate is calculated by applying
     * the following rules in order:
     * <ol>
     * <li>
     * If a persistence delegate is associated with the given type
     * by using the {@link #setPersistenceDelegate} method
     * it is returned.
     * <li>
     * A persistence delegate is then looked up by the name
     * composed of the the fully qualified name of the given type
     * and the "PersistenceDelegate" postfix.
     * For example, a persistence delegate for the {@code Bean} class
     * should be named {@code BeanPersistenceDelegate}
     * and located in the same package.
     * <pre>
     * public class Bean { ... }
     * public class BeanPersistenceDelegate { ... }</pre>
     * The instance of the {@code BeanPersistenceDelegate} class
     * is returned for the {@code Bean} class.
     * <li>
     * If the type is {@code null},
     * a shared internal persistence delegate is returned
     * that encodes {@code null} value.
     * <li>
     * If the type is a {@code enum} declaration,
     * a shared internal persistence delegate is returned
     * that encodes constants of this enumeration
     * by their names.
     * <li>
     * If the type is a primitive type or the corresponding wrapper,
     * a shared internal persistence delegate is returned
     * that encodes values of the given type.
     * <li>
     * If the type is an array,
     * a shared internal persistence delegate is returned
     * that encodes an array of the appropriate type and length,
     * and each of its elements as if they are properties.
     * <li>
     * If the type is a proxy,
     * a shared internal persistence delegate is returned
     * that encodes a proxy instance by using
     * the {@link java.lang.reflect.Proxy#newProxyInstance} method.
     * <li>
     * If the {@link BeanInfo} for this type has a {@link BeanDescriptor}
     * which defined a "persistenceDelegate" attribute,
     * the value of this named attribute is returned.
     * <li>
     * In all other cases the default persistence delegate is returned.
     * The default persistence delegate assumes the type is a <em>JavaBean</em>,
     * implying that it has a default constructor and that its state
     * may be characterized by the matching pairs of "setter" and "getter"
     * methods returned by the {@link Introspector} class.
     * The default constructor is the constructor with the greatest number
     * of parameters that has the {@link ConstructorProperties} annotation.
     * If none of the constructors has the {@code ConstructorProperties} annotation,
     * then the nullary constructor (constructor with no parameters) will be used.
     * For example, in the following code fragment, the nullary constructor
     * for the {@code Foo} class will be used,
     * while the two-parameter constructor
     * for the {@code Bar} class will be used.
     * <pre>
     * public class Foo {
     *     public Foo() { ... }
     *     public Foo(int x) { ... }
     * }
     * public class Bar {
     *     public Bar() { ... }
     *     &#64;ConstructorProperties({"x"})
     *     public Bar(int x) { ... }
     *     &#64;ConstructorProperties({"x", "y"})
     *     public Bar(int x, int y) { ... }
     * }</pre>
     * </ol>
     *
     * @param type  the class of the objects
     * @return the persistence delegate for the given type
     *
     * @see #setPersistenceDelegate
     * @see java.beans.Introspector#getBeanInfo
     * @see java.beans.BeanInfo#getBeanDescriptor
     */
    public PersistenceDelegate getPersistenceDelegate(Class<?> type) {
        PersistenceDelegate pd = this.finder.find(type);
        if (pd == null) {
            pd = MetaData.getPersistenceDelegate(type);
            if (pd != null) {
                this.finder.register(type, pd);
            }
        }
        return pd;
    }

    /**
     * Associates the specified persistence delegate with the given type.
     *
     * @param type  the class of objects that the specified persistence delegate applies to
     * @param delegate  the persistence delegate for instances of the given type
     *
     * @see #getPersistenceDelegate
     * @see java.beans.Introspector#getBeanInfo
     * @see java.beans.BeanInfo#getBeanDescriptor
     */
    public void setPersistenceDelegate(Class<?> type, PersistenceDelegate delegate) {
        this.finder.register(type, delegate);
    }

    /**
     * Removes the entry for this instance, returning the old entry.
     *
     * @param oldInstance The entry that should be removed.
     * @return The entry that was removed.
     *
     * @see #get
     */
    public Object remove(Object oldInstance) {
        Expression exp = bindings.remove(oldInstance);
        return getValue(exp);
    }

    /**
     * Returns a tentative value for <code>oldInstance</code> in
     * the environment created by this stream. A persistence
     * delegate can use its <code>mutatesTo</code> method to
     * determine whether this value may be initialized to
     * form the equivalent object at the output or whether
     * a new object must be instantiated afresh. If the
     * stream has not yet seen this value, null is returned.
     *
     * @param  oldInstance The instance to be looked up.
     * @return The object, null if the object has not been seen before.
     */
    public Object get(Object oldInstance) {
        if (oldInstance == null || oldInstance == this ||
            oldInstance.getClass() == String.class) {
            return oldInstance;
        }
        Expression exp = bindings.get(oldInstance);
        return getValue(exp);
    }

    private Object writeObject1(Object oldInstance) {
        Object o = get(oldInstance);
        if (o == null) {
            writeObject(oldInstance);
            o = get(oldInstance);
        }
        return o;
    }

    private Statement cloneStatement(Statement oldExp) {
        Object oldTarget = oldExp.getTarget();
        Object newTarget = writeObject1(oldTarget);

        Object[] oldArgs = oldExp.getArguments();
        Object[] newArgs = new Object[oldArgs.length];
        for (int i = 0; i < oldArgs.length; i++) {
            newArgs[i] = writeObject1(oldArgs[i]);
        }
        Statement newExp = Statement.class.equals(oldExp.getClass())
                ? new Statement(newTarget, oldExp.getMethodName(), newArgs)
                : new Expression(newTarget, oldExp.getMethodName(), newArgs);
        newExp.loader = oldExp.loader;
        return newExp;
    }

    /**
     * Writes statement <code>oldStm</code> to the stream.
     * The <code>oldStm</code> should be written entirely
     * in terms of the callers environment, i.e. the
     * target and all arguments should be part of the
     * object graph being written. These expressions
     * represent a series of "what happened" expressions
     * which tell the output stream how to produce an
     * object graph like the original.
     * <p>
     * The implementation of this method will produce
     * a second expression to represent the same expression in
     * an environment that will exist when the stream is read.
     * This is achieved simply by calling <code>writeObject</code>
     * on the target and all the arguments and building a new
     * expression with the results.
     *
     * @param oldStm The expression to be written to the stream.
     */
    public void writeStatement(Statement oldStm) {
        // System.out.println("writeStatement: " + oldExp);
        Statement newStm = cloneStatement(oldStm);
        if (oldStm.getTarget() != this && executeStatements) {
            try {
                newStm.execute();
            } catch (Exception e) {
                getExceptionListener().exceptionThrown(new Exception("Encoder: discarding statement "
                                                                     + newStm, e));
            }
        }
    }

    /**
     * The implementation first checks to see if an
     * expression with this value has already been written.
     * If not, the expression is cloned, using
     * the same procedure as <code>writeStatement</code>,
     * and the value of this expression is reconciled
     * with the value of the cloned expression
     * by calling <code>writeObject</code>.
     *
     * @param oldExp The expression to be written to the stream.
     */
    public void writeExpression(Expression oldExp) {
        // System.out.println("Encoder::writeExpression: " + oldExp);
        Object oldValue = getValue(oldExp);
        if (get(oldValue) != null) {
            return;
        }
        bindings.put(oldValue, (Expression)cloneStatement(oldExp));
        writeObject(oldValue);
    }

    void clear() {
        bindings.clear();
    }

    // Package private method for setting an attributes table for the encoder
    void setAttribute(Object key, Object value) {
        if (attributes == null) {
            attributes = new HashMap<>();
        }
        attributes.put(key, value);
    }

    Object getAttribute(Object key) {
        if (attributes == null) {
            return null;
        }
        return attributes.get(key);
    }
}
