/* DefaultPersistenceDelegate.java
 Copyright (C) 2005 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 java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/** <p><code>DefaultPersistenceDelegate</code> is a {@link PersistenceDelegate}
 * implementation that can be used to serialize objects which adhere to the
 * Java Beans naming convention.</p>
 *
 * @author Robert Schuster (robertschuster@fsfe.org)
 * @since 1.4
 */
public class DefaultPersistenceDelegate extends PersistenceDelegate
{

  private String[] constructorPropertyNames;

  /** Using this constructor the object to be serialized will be instantiated
   * with the default non-argument constructor.
   */
  public DefaultPersistenceDelegate()
  {
  }

  /** This constructor allows to specify which Bean properties appear
   * in the constructor.
   *
   * <p>The implementation reads the mentioned properties from the Bean
   * instance and applies it in the given order to a corresponding
   * constructor.</p>
   *
   * @param constructorPropertyNames The properties the Bean's constructor
   * should be given to.
   */
  public DefaultPersistenceDelegate(String[] constructorPropertyNames)
  {
    this.constructorPropertyNames = constructorPropertyNames;
  }

  protected boolean mutatesTo(Object oldInstance, Object newInstance)
  {
    try
      {

        return (constructorPropertyNames != null
               && constructorPropertyNames.length > 0
               && oldInstance.getClass()
               .getDeclaredMethod("equals",
                                  new Class[] { Object.class }) != null)
                                  ? oldInstance.equals(newInstance)
                                  : super.mutatesTo(oldInstance, newInstance);
      }
    catch (NoSuchMethodException nsme)
      {
        return super.mutatesTo(oldInstance, newInstance);
      }
  }

  protected Expression instantiate(Object oldInstance, Encoder out)
  {
    Object[] args = null;

    try
      {
        // If there are property names in the array, then we create
        // a corresponding argument array and store every
        // argument in it. To retrieve an argument object we have
        // dig up the right property in the bean class' BeanInfo
        // object.
        // This is so costly in terms of execution time I better
        // not think twice about it ...
        if (constructorPropertyNames != null)
          {
            args = new Object[constructorPropertyNames.length];

            // Look up the properties of oldInstance's class to find matches for
            // the
            // names given in the constructor.
            PropertyDescriptor[] propertyDescs = Introspector.getBeanInfo(
                                                                          oldInstance.getClass()).getPropertyDescriptors();

            for (int i = 0; i < constructorPropertyNames.length; i++)
              {
                // Scan the property descriptions for a matching name.
                for (int j = 0; j < propertyDescs.length; j++)
                  {
                    if (propertyDescs[i].getName().equals(
                                                          constructorPropertyNames[i]))
                      {
                        Method readMethod = propertyDescs[i].getReadMethod();

                        args[i] = readMethod.invoke(oldInstance);
                      }
                  }
              }
          }

      }
    catch (IllegalAccessException iae)
      {
        out.getExceptionListener().exceptionThrown(iae);
      }
    catch (IllegalArgumentException iarge)
      {
        out.getExceptionListener().exceptionThrown(iarge);
      }
    catch (InvocationTargetException ite)
      {
        out.getExceptionListener().exceptionThrown(ite);
      }
    catch (IntrospectionException ie)
      {
        out.getExceptionListener().exceptionThrown(ie);
      }

    return new Expression(oldInstance, oldInstance.getClass(), "new", args);
  }

  protected void initialize(Class<?> type, Object oldInstance,
                            Object newInstance, Encoder out)
  {
    // Calling the supertype's implementation of initialize makes it
    // possible that descendants of classes like AbstractHashMap
    // or Hashtable are serialized correctly. This mechanism grounds on
    // two other facts:
    // * Each class which has not registered a special purpose
    //   PersistenceDelegate is handled by a DefaultPersistenceDelegate
    //   instance.
    // * PersistenceDelegate.initialize() is implemented in a way that it
    //   calls the initialize method of the superclass' persistence delegate.
    super.initialize(type, oldInstance, newInstance, out);

    // Suppresses the writing of property setting statements when this delegate
    // is not used for the exact instance type. By doing so the following code
    // is called only once per object.
    if (type != oldInstance.getClass())
      return;

    try
      {
        PropertyDescriptor[] propertyDescs = Introspector.getBeanInfo(
                                                                      oldInstance.getClass()).getPropertyDescriptors();

        for (int i = 0; i < propertyDescs.length; i++)
          {
            Method readMethod = propertyDescs[i].getReadMethod();
            Method writeMethod = propertyDescs[i].getWriteMethod();

            if (readMethod != null && writeMethod != null)
              {
                Object oldValue = readMethod.invoke(oldInstance);

                if (oldValue != null)
                  out.writeStatement(new Statement(oldInstance,
                                                   writeMethod.getName(),
                                                   new Object[] { oldValue }));
              }
          }
      }
    catch (IntrospectionException ie)
      {
        out.getExceptionListener().exceptionThrown(ie);
      }
    catch (IllegalAccessException iae)
      {
        out.getExceptionListener().exceptionThrown(iae);
      }
    catch (InvocationTargetException ite)
      {
        out.getExceptionListener().exceptionThrown(ite);
      }
  }
}
