/* Encoder.java
 Copyright (C) 2005, 2006 Free Software Foundation, Inc.

 This file is part of GNU Classpath.

 GNU Classpath is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.

 GNU Classpath 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 for more details.

 You should have received a copy of the GNU General Public License
 along with GNU Classpath; see the file COPYING.  If not, write to the
 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301 USA.

 Linking this library statically or dynamically with other modules is
 making a combined work based on this library.  Thus, the terms and
 conditions of the GNU General Public License cover the whole
 combination.

 As a special exception, the copyright holders of this library give you
 permission to link this library with independent modules to produce an
 executable, regardless of the license terms of these independent
 modules, and to copy and distribute the resulting executable under
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */


package java.beans;

import gnu.java.beans.DefaultExceptionListener;
import gnu.java.beans.encoder.ArrayPersistenceDelegate;
import gnu.java.beans.encoder.ClassPersistenceDelegate;
import gnu.java.beans.encoder.CollectionPersistenceDelegate;
import gnu.java.beans.encoder.MapPersistenceDelegate;
import gnu.java.beans.encoder.PrimitivePersistenceDelegate;

import java.util.AbstractCollection;
import java.util.HashMap;
import java.util.IdentityHashMap;

/**
 * @author Robert Schuster (robertschuster@fsfe.org)
 * @since 1.4
 */
public class Encoder
{

  /**
   * An internal DefaultPersistenceDelegate instance that is used for every
   * class that does not a have a special special PersistenceDelegate.
   */
  private static PersistenceDelegate defaultPersistenceDelegate;

  private static PersistenceDelegate fakePersistenceDelegate;

  /**
   * Stores the relation Class->PersistenceDelegate.
   */
  private static HashMap delegates = new HashMap();

  /**
   * Stores the relation oldInstance->newInstance
   */
  private IdentityHashMap candidates = new IdentityHashMap();

  private ExceptionListener exceptionListener;

  /**
   * A simple number that is used to restrict the access to writeExpression and
   * writeStatement. The rule is that both methods should only be used when an
   * object is written to the stream (= writeObject). Therefore accessCounter is
   * incremented just before the call to writeObject and decremented afterwards.
   * Then writeStatement and writeExpression allow execution only if
   * accessCounter is bigger than zero.
   */
  private int accessCounter = 0;

  public Encoder()
  {
    setupDefaultPersistenceDelegates();

    setExceptionListener(null);
  }

  /**
   * Sets up a bunch of {@link PersistenceDelegate} instances which are needed
   * for the basic working of a {@link Encoder}s.
   */
  private static void setupDefaultPersistenceDelegates()
  {
    synchronized (delegates)
      {
        if (defaultPersistenceDelegate != null)
          return;

        delegates.put(Class.class, new ClassPersistenceDelegate());

        PersistenceDelegate pd = new PrimitivePersistenceDelegate();
        delegates.put(Boolean.class, pd);
        delegates.put(Byte.class, pd);
        delegates.put(Short.class, pd);
        delegates.put(Integer.class, pd);
        delegates.put(Long.class, pd);
        delegates.put(Float.class, pd);
        delegates.put(Double.class, pd);

        delegates.put(Object[].class, new ArrayPersistenceDelegate());

        pd = new CollectionPersistenceDelegate();
        delegates.put(AbstractCollection.class, pd);

        pd = new MapPersistenceDelegate();
        delegates.put(java.util.AbstractMap.class, pd);
        delegates.put(java.util.Hashtable.class, pd);

        defaultPersistenceDelegate = new DefaultPersistenceDelegate();
        delegates.put(Object.class, defaultPersistenceDelegate);

        // Creates a PersistenceDelegate implementation which is
        // returned for 'null'. In practice this instance is
        // not used in any way and is just here to be compatible
        // with the reference implementation which returns a
        // similar instance when calling getPersistenceDelegate(null) .
        fakePersistenceDelegate = new PersistenceDelegate()
        {
          protected Expression instantiate(Object o, Encoder e)
          {
            return null;
          }
        };

      }
  }

  protected void writeObject(Object o)
  {
    // 'null' has no PersistenceDelegate and will not
    // create an Expression which has to be cloned.
    // However subclasses should be aware that writeObject
    // may be called with a 'null' argument and should
    // write the proper representation of it.
    if (o == null)
      return;

    PersistenceDelegate pd = getPersistenceDelegate(o.getClass());

    accessCounter++;
    pd.writeObject(o, this);
    accessCounter--;

  }

  /**
   * Sets the {@link ExceptionListener} instance to be used for reporting
   * recorable exceptions in the instantiation and initialization sequence. If
   * the argument is <code>null</code> a default instance will be used that
   * prints the thrown exception to <code>System.err</code>.
   */
  public void setExceptionListener(ExceptionListener listener)
  {
    exceptionListener = (listener != null)
        ? listener : DefaultExceptionListener.INSTANCE;
  }

  /**
   * Returns the currently active {@link ExceptionListener} instance.
   */
  public ExceptionListener getExceptionListener()
  {
    return exceptionListener;
  }

  public PersistenceDelegate getPersistenceDelegate(Class<?> type)
  {
    // This is not specified but the JDK behaves like this.
    if (type == null)
      return fakePersistenceDelegate;

    // Treats all array classes in the same way and assigns
    // them a shared PersistenceDelegate implementation tailored
    // for array instantation and initialization.
    if (type.isArray())
      return (PersistenceDelegate) delegates.get(Object[].class);

    PersistenceDelegate pd = (PersistenceDelegate) delegates.get(type);

    return (pd != null) ? pd : defaultPersistenceDelegate;
  }

  /**
   * Sets the {@link PersistenceDelegate} instance for the given class.
   * <p>
   * Note: Throws a <code>NullPointerException</code> if the argument is
   * <code>null</code>.
   * </p>
   * <p>
   * Note: Silently ignores PersistenceDelegates for Array types and primitive
   * wrapper classes.
   * </p>
   * <p>
   * Note: Although this method is not declared <code>static</code> changes to
   * the {@link PersistenceDelegate}s affect <strong>all</strong>
   * {@link Encoder} instances. <strong>In this implementation</strong> the
   * access is thread safe.
   * </p>
   */
  public void setPersistenceDelegate(Class<?> type,
                                     PersistenceDelegate delegate)
  {
    // If the argument is null this will cause a NullPointerException
    // which is expected behavior.

    // This makes custom PDs for array, primitive types and their wrappers
    // impossible but this is how the JDK behaves.
    if (type.isArray() || type.isPrimitive() || type == Boolean.class
        || type == Byte.class || type == Short.class || type == Integer.class
        || type == Long.class || type == Float.class || type == Double.class)
      return;

    synchronized (delegates)
      {
        delegates.put(type, delegate);
      }

  }

  public Object remove(Object oldInstance)
  {
    return candidates.remove(oldInstance);
  }

  /**
   * Returns the replacement object which has been created by the encoder during
   * the instantiation sequence or <code>null</code> if the object has not
   * been processed yet.
   * <p>
   * Note: The <code>String</code> class acts as an endpoint for the
   * inherently recursive algorithm of the {@link Encoder}. Therefore instances
   * of <code>String</code> will always be returned by this method. In other
   * words the assertion: <code>
   * assert (anyEncoder.get(anyString) == anyString)
   * </code<
   * will always hold.</p>
   *
   * <p>Note: If <code>null</code> is requested, the result will
   * always be <code>null</code>.</p>
   */
  public Object get(Object oldInstance)
  {
    // String instances are handled in a special way.
    // No one knows why this is not officially specified
    // because this is a rather important design decision.
    return (oldInstance == null) ? null :
             (oldInstance.getClass() == String.class) ?
               oldInstance : candidates.get(oldInstance);
  }

  /**
   * <p>
   * Note: If you call this method not from within an object instantiation and
   * initialization sequence it will be silently ignored.
   * </p>
   */
  public void writeStatement(Statement stmt)
  {
    // Silently ignore out of bounds calls.
    if (accessCounter <= 0)
      return;

    Object target = stmt.getTarget();

    Object newTarget = get(target);
    if (newTarget == null)
      {
        writeObject(target);
        newTarget = get(target);
      }

    Object[] args = stmt.getArguments();
    Object[] newArgs = new Object[args.length];

    for (int i = 0; i < args.length; i++)
      {
        newArgs[i] = get(args[i]);
        if (newArgs[i] == null || isImmutableType(args[i].getClass()))
          {
            writeObject(args[i]);
            newArgs[i] = get(args[i]);
          }
      }

    Statement newStmt = new Statement(newTarget, stmt.getMethodName(), newArgs);

    try
      {
        newStmt.execute();
      }
    catch (Exception e)
      {
        exceptionListener.exceptionThrown(e);
      }

  }

  /**
   * <p>
   * Note: If you call this method not from within an object instantiation and
   * initialization sequence it will be silently ignored.
   * </p>
   */
  public void writeExpression(Expression expr)
  {
    // Silently ignore out of bounds calls.
    if (accessCounter <= 0)
      return;

    Object target = expr.getTarget();
    Object value = null;
    Object newValue = null;

    try
      {
        value = expr.getValue();
      }
    catch (Exception e)
      {
        exceptionListener.exceptionThrown(e);
        return;
      }


    newValue = get(value);

    if (newValue == null)
      {
        Object newTarget = get(target);
        if (newTarget == null)
          {
            writeObject(target);
            newTarget = get(target);

            // May happen if exception was thrown.
            if (newTarget == null)
              {
                return;
              }
          }

        Object[] args = expr.getArguments();
        Object[] newArgs = new Object[args.length];

        for (int i = 0; i < args.length; i++)
          {
            newArgs[i] = get(args[i]);
            if (newArgs[i] == null || isImmutableType(args[i].getClass()))
              {
                writeObject(args[i]);
                newArgs[i] = get(args[i]);
              }
          }

        Expression newExpr = new Expression(newTarget, expr.getMethodName(),
                                            newArgs);

        // Fakes the result of Class.forName(<primitiveType>) to make it possible
        // to hand such a type to the encoding process.
        if (value instanceof Class && ((Class) value).isPrimitive())
          newExpr.setValue(value);

        // Instantiates the new object.
        try
          {
            newValue = newExpr.getValue();

            candidates.put(value, newValue);
          }
        catch (Exception e)
          {
            exceptionListener.exceptionThrown(e);

            return;
          }

        writeObject(value);

      }
    else if(value.getClass() == String.class || value.getClass() == Class.class)
      {
        writeObject(value);
      }

  }

  /** Returns whether the given class is an immutable
   * type which has to be handled differently when serializing it.
   *
   * <p>Immutable objects always have to be instantiated instead of
   * modifying an existing instance.</p>
   *
   * @param type The class to test.
   * @return Whether the first argument is an immutable type.
   */
  boolean isImmutableType(Class type)
  {
    return type == String.class || type == Class.class
      || type == Integer.class || type == Boolean.class
      || type == Byte.class || type == Short.class
      || type == Long.class || type == Float.class
      || type == Double.class;
  }

  /** Sets the stream candidate for a given object.
   *
   * @param oldObject The object given to the encoder.
   * @param newObject The object the encoder generated.
   */
  void putCandidate(Object oldObject, Object newObject)
  {
    candidates.put(oldObject, newObject);
  }

}
