/* java.beans.EventHandler
   Copyright (C) 2004, 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.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * <p>EventHandler forms a bridge between dynamically created listeners and
 * arbitrary properties and methods.</p>
 * 
 * <p>You can use this class to easily create listener implementations for
 * some basic interactions between an event source and its target. Using
 * the three static methods named <code>create</code> you can create
 * these listener implementations.</p>
 * 
 * <p>See the documentation of each method for usage examples.</p>
 *  
 * @author Jerry Quinn (jlquinn@optonline.net)
 * @author Robert Schuster (thebohemian@gmx.net)
 * @since 1.4
 */
public class EventHandler implements InvocationHandler
{
  // The name of the method that will be implemented.  If null, any method.
  private String listenerMethod;

  // The object to call action on.
  private Object target;

  // The name of the method or property setter in target.
  private String action;

  // The property to extract from an event passed to listenerMethod.
  private String property;

  // The target objects Class.
  private Class targetClass;
  
  // String class doesn't already have a capitalize routine.
  private String capitalize(String s)
  {
    return s.substring(0, 1).toUpperCase() + s.substring(1);
  }

  /**
   * Creates a new <code>EventHandler</code> instance.
   *
   * <p>Typical creation is done with the create method, not by knewing an
   * EventHandler.</p>
   *
   * <p>This constructs an EventHandler that will connect the method
   * listenerMethodName to target.action, extracting eventPropertyName from
   * the first argument of listenerMethodName. and sending it to action.</p>
   * 
   * <p>Throws a <code>NullPointerException</code> if the <code>target</code>
   * argument is <code>null</code>. 
   *
   * @param target Object that will perform the action.
   * @param action A property or method of the target.
   * @param eventPropertyName A readable property of the inbound event.
   * @param listenerMethodName The listener method name triggering the action.
   */
  public EventHandler(Object target, String action, String eventPropertyName,
		      String listenerMethodName)
  {
    this.target = target;
    
    // Retrieving the class is done for two reasons:
    // 1) The class object is needed very frequently in the invoke() method.
    // 2) The constructor should throw a NullPointerException if target is null.
    targetClass = target.getClass();
    
    this.action = action;	// Turn this into a method or do we wait till
    		// runtime
    property = eventPropertyName;
    listenerMethod = listenerMethodName;
  }

  /**
   * Returns the event property name.
   */
  public String getEventPropertyName()
  {
    return property;
  }

  /**
   * Returns the listener's method name.
   */
  public String getListenerMethodName()
  {
    return listenerMethod;
  }

  /**
   * Returns the target object.
   */
  public Object getTarget()
  {
    return target;
  }

  /**
   * Returns the action method name.
   */
  public String getAction()
  {
    return action;
  }

  // Fetch a qualified property like a.b.c from object o.  The properties can
  // be boolean isProp or object getProp properties.
  //
  // Returns a length 2 array with the first entry containing the value
  // extracted from the property, and the second entry contains the class of
  // the method return type.
  //
  // We play this game because if the method returns a native type, the return
  // value will be a wrapper.  If we then take the type of the wrapper and use
  // it to locate the action method that takes the native type, it won't match.
  private Object[] getProperty(Object o, String prop)
  {
    // Isolate the first property name from a.b.c.
    int pos;
    String rest = null;
    if ((pos = prop.indexOf('.')) != -1)
      {
	rest = prop.substring(pos + 1);
	prop = prop.substring(0, pos);
      }

    // Find a method named getProp.  It could be isProp instead.
    Method getter;
    try
      {
	// Look for boolean property getter isProperty
	getter = o.getClass().getMethod("is" + capitalize(prop),
						 null);
      }
    catch (NoSuchMethodException nsme1)
      {
        try {
          // Look for regular property getter getProperty
          getter = o.getClass().getMethod("get" + capitalize(prop),
						 null);
        } catch(NoSuchMethodException nsme2) {
            try {
            // Finally look for a method of the name prop
            getter = o.getClass().getMethod(prop, null);
            } catch(NoSuchMethodException nsme3) {
                // Ok, give up with an intelligent hint for the user.
                throw new RuntimeException("Method not called: Could not find a property or method '" + prop
                        + "' in " + o.getClass() + " while following the property argument '" + property + "'.");
            }
        }
      }
    try {
      Object val = getter.invoke(o, null);

      if (rest != null)
        return getProperty(val, rest);

      return new Object[] {val, getter.getReturnType()};
    } catch(InvocationTargetException ite) {
        throw new RuntimeException("Method not called: Property or method '" + prop + "' has thrown an exception.", ite);
    } catch(IllegalAccessException iae) {
        // This cannot happen because we looked up method with Class.getMethod()
        // which returns public methods only.
        throw (InternalError) new InternalError("Non-public method was invoked.").initCause(iae);
    }
  }

  /**
   * Invokes the <code>EventHandler</code>.
   * 
   * <p>This method is normally called by the listener's proxy implementation.</p>
   * 
   * @param proxy The listener interface that is implemented using
   * the proxy mechanism.
   * @param method The method that was called on the proxy instance.
   * @param arguments The arguments which where given to the method.
   * @throws Throwable <code>NoSuchMethodException</code> is thrown when the EventHandler's
   * action method or property cannot be found.
   */
  public Object invoke(Object proxy, Method method, Object[] arguments)
  {
      try {
      // The method instance of the target object. We have to find out which
      // one we have to invoke.
      Method actionMethod = null;

    // Listener methods that weren't specified are ignored.  If listenerMethod
    // is null, then all listener methods are processed.
    if (listenerMethod != null && !method.getName().equals(listenerMethod))
      return null;

    // If a property is defined we definitely need a valid object at
    // arguments[0] that can be used to retrieve a value to which the
    // property of the target gets set.
    if(property != null) {
      // Extracts the argument. We will let it fail with a NullPointerException
      // the caller used a listener method that has no arguments.
      Object event = arguments[0];

      // Obtains the property XXX propertyType keeps showing up null - why?
      // because the object inside getProperty changes, but the ref variable
      // can't change this way, dolt!  need a better way to get both values out
      // - need method and object to do the invoke and get return type
      Object v[] = getProperty(event, property);
      Object[] args = new Object[] { v[0] };
      
      // Changes the class array that controls which method signature we are going
      // to look up in the target object.
      Class[] argTypes = new Class[] { initClass((Class) v[1]) };
    
      // Tries to  find a setter method to which we can apply the
      while(argTypes[0] != null) {
      try
      {
        // Look for a property setter for action.
        actionMethod = targetClass.getMethod("set" + capitalize(action), argTypes);

        return actionMethod.invoke(target, args);
      }
    catch (NoSuchMethodException e)
      {
        // If action as property didn't work, try as method later.
      }
    
      argTypes[0] = nextClass(argTypes[0]);
      }
      
      // We could not find a suitable setter method. Now we try again interpreting
      // action as the method name itself.
      // Since we probably have changed the block local argTypes array 
      // we need to rebuild it.
      argTypes = new Class[] { initClass((Class) v[1]) };
    
      // Tries to  find a setter method to which we can apply the
      while(argTypes[0] != null) {
        try
        {
          actionMethod = targetClass.getMethod(action, argTypes);

          return actionMethod.invoke(target, args);
        }
        catch (NoSuchMethodException e)
        {
        }
        
        argTypes[0] = nextClass(argTypes[0]);
      }
        
        throw new RuntimeException("Method not called: Could not find a public method named '"
                + action + "' in target " + targetClass + " which takes a '"
                + v[1] + "' argument or a property of this type.");
      }      
  
    // If property was null we will search for a no-argument method here.
    // Note: The ordering of method lookups is important because we want to prefer no-argument
    // calls like the JDK does. This means if we have actionMethod() and actionMethod(Event) we will
    // call the first *EVEN* if we have a valid argument for the second method. This is behavior compliant
    // to the JDK.
    // If actionMethod() is not available but there is a actionMethod(Event) we take this. That makes us
    // more specification compliant than the JDK itself because this one will fail in such a case.
    try
      {
      actionMethod = targetClass.getMethod(action, null);
      }
    catch(NoSuchMethodException nsme)
      {
        // Note: If we want to be really strict the specification says that a no-argument method should
        // accept an EventObject (or subclass I guess). However since the official implementation is broken
        // anyways, it's more flexible without the EventObject restriction and we are compatible on everything
        // else this can stay this way.
        if(arguments != null && arguments.length >= 1/* && arguments[0] instanceof EventObject*/) {
            Class[] targetArgTypes = new Class[] { initClass(arguments[0].getClass()) };
            
            while(targetArgTypes[0] != null) {
                try
                {
                  // If no property exists we expect the first element of the arguments to be
                  // an EventObject which is then applied to the target method.
      
                  actionMethod = targetClass.getMethod(action, targetArgTypes);
              
                  return actionMethod.invoke(target, new Object[] { arguments[0] });
                }
                catch(NoSuchMethodException nsme2)
                {
                    
                }
                
                targetArgTypes[0] = nextClass(targetArgTypes[0]);
            }
          
        }
      }

    // If we do not have a Method instance at this point this means that all our tries
    // failed. The JDK throws an ArrayIndexOutOfBoundsException in this case.
    if(actionMethod == null)
      throw new ArrayIndexOutOfBoundsException(0);
    
    // Invoke target.action(property)
    return actionMethod.invoke(target, null);
      } catch(InvocationTargetException ite) {
         throw new RuntimeException(ite.getCause());
      } catch(IllegalAccessException iae) {
          // Cannot happen because we always use getMethod() which returns public
          // methods only. Otherwise there is something seriously broken in
          // GNU Classpath.
          throw (InternalError) new InternalError("Non-public method was invoked.").initCause(iae);
      }
  }
  
  /**
   * <p>Returns the primitive type for every wrapper class or the
   * class itself if it is no wrapper class.</p>
   * 
   * <p>This is needed because to be able to find both kinds of methods:
   * One that takes a wrapper class as the first argument and one that
   * accepts a primitive instead.</p>
   */
  private Class initClass(Class klass) {
   if(klass == Boolean.class) {
    return Boolean.TYPE;    
   } else if(klass == Byte.class) {
    return Byte.TYPE;   
   } else if(klass == Short.class) {
    return Short.TYPE;   
   } else if(klass == Integer.class) {
    return Integer.TYPE;   
   } else if(klass == Long.class) {
    return Long.TYPE;   
   } else if(klass == Float.class) {
    return Float.TYPE;   
   } else if(klass == Double.class) {
    return Double.TYPE;   
   } else {
    return klass;   
   }
  }

  /**
   * 
   * 
   * @param klass
   * @return
   */
  private Class nextClass(Class klass) {
    if(klass == Boolean.TYPE) {
    return Boolean.class;    
   } else if(klass == Byte.TYPE) {
    return Byte.class;   
   } else if(klass == Short.TYPE) {
    return Short.class;   
   } else if(klass == Integer.TYPE) {
    return Integer.class;   
   } else if(klass == Long.TYPE) {
    return Long.class;   
   } else if(klass == Float.TYPE) {
    return Float.class;   
   } else if(klass == Double.TYPE) {
    return Double.class;   
   } else {
    return klass.getSuperclass();
   }
   }
  
  /**
   * <p>Constructs an implementation of <code>listenerInterface</code>
   * to dispatch events.</p>
   * 
   * <p>You can use such an implementation to simply call a public
   * no-argument method of an arbitrary target object or to forward
   * the first argument of the listener method to the target method.</p>
   * 
   * <p>Call this method like:</p>
   * <code>
   * button.addActionListener((ActionListener)
   *    EventHandler.create(ActionListener.class, target, "dispose"));
   * </code>
   * 
   * <p>to achieve the following behavior:</p>
   * <code>
   * button.addActionListener(new ActionListener() {
   *    public void actionPerformed(ActionEvent ae) {
   *        target.dispose();
   *    }
   * });
   * </code>
   * 
   * <p>That means if you need a listener implementation that simply calls a
   * a no-argument method on a given instance for <strong>each</strong>
   * method of the listener interface.</p>
   * 
   * <p>Note: The <code>action</code> is interpreted as a method name. If your target object
   * has no no-argument method of the given name the EventHandler tries to find
   * a method with the same name but which can accept the first argument of the
   * listener method. Usually this will be an event object but any other object
   * will be forwarded, too. Keep in mind that using a property name instead of a
   * real method here is wrong and will throw an <code>ArrayIndexOutOfBoundsException</code>
   * whenever one of the listener methods is called.<p/>
   *
   * <p>The <code>EventHandler</code> will automatically convert primitives
   * to their wrapper class and vice versa. Furthermore it will call
   * a target method if it accepts a superclass of the type of the
   * first argument of the listener method.</p>
   * 
   * <p>In case that the method of the target object throws an exception
   * it will be wrapped in a <code>RuntimeException</code> and thrown out
   * of the listener method.</p>
   * 
   * <p>In case that the method of the target object cannot be found an
   * <code>ArrayIndexOutOfBoundsException</code> will be thrown when the
   * listener method is invoked.</p>
   * 
   * <p>A call to this method is equivalent to:
   * <code>create(listenerInterface, target, action, null, null)</code></p>
   *
   * @param listenerInterface Listener interface to implement.
   * @param target Object to invoke action on.
   * @param action Target property or method to invoke.
   * @return A constructed proxy object.
   */
  public static Object create(Class listenerInterface, Object target, String action)
  {
    return create(listenerInterface, target, action, null, null);
  }

  /**
   * <p>Constructs an implementation of <code>listenerInterface</code>
   * to dispatch events.</p>
   *
   * <p>Use this method if you want to create an implementation that retrieves
   * a property value from the <b>first</b> argument of the listener method
   * and applies it to the target's property or method. This first argument
   * of the listener is usually an event object but any other object is
   * valid, too.</p>
   * 
   * <p>You can set the value of <code>eventPropertyName</code> to "prop"
   * to denote the retrieval of a property named "prop" from the event
   * object. In case that no such property exists the <code>EventHandler</code>
   * will try to find a method with that name.</p>
   * 
   * <p>If you set <code>eventPropertyName</code> to a value like this "a.b.c"
   * <code>EventHandler</code> will recursively evaluate the properties "a", "b"
   * and "c". Again if no property can be found the <code>EventHandler</code>
   * tries a method name instead. This allows mixing the names, too: "a.toString"
   * will retrieve the property "a" from the event object and will then call
   * the method "toString" on it.</p>
   * 
   * <p>An exception thrown in any of these methods will provoke a
   * <code>RuntimeException</code> to be thrown which contains an
   * <code>InvocationTargetException</code> containing the triggering exception.</p>
   * 
   * <p>If you set <code>eventPropertyName</code> to a non-null value the
   * <code>action</code> parameter will be interpreted as a property name
   * or a method name of the target object.</p>
   *   
   * <p>Any object retrieved from the event object and applied to the
   * target will converted from primitives to their wrapper class or
   * vice versa or applied to a method that accepts a superclass
   * of the object.</p>
   *
   * <p>Examples:</p>
   * <p>The following code:</p><code>
   * button.addActionListener(
   *    new ActionListener() {
   *        public void actionPerformed(ActionEvent ae) {
   *            Object o = ae.getSource().getClass().getName();
   *            textField.setText((String) o);
   *        }
   *    });
   * </code>
   * 
   * <p>Can be expressed using the <code>EventHandler</code> like this:</p>
   * <p>
   * <code>button.addActionListener((ActionListener)
   *    EventHandler.create(ActionListener.class, textField, "text", "source.class.name");
   * <code>
   * </p>
   * 
   * <p>As said above you can specify the target as a method, too:</p>
   * <p>
   * <code>button.addActionListener((ActionListener)
   *    EventHandler.create(ActionListener.class, textField, "setText", "source.class.name");
   * <code>
   * </p>
   * 
   * <p>Furthermore you can use method names in the property:</p>
   * <p>
   * <code>button.addActionListener((ActionListener)
   *    EventHandler.create(ActionListener.class, textField, "setText", "getSource.getClass.getName");
   * <code>
   * </p>
   * 
   * <p>Finally you can mix names:</p>
   * <p>
   * <code>button.addActionListener((ActionListener)
   *    EventHandler.create(ActionListener.class, textField, "setText", "source.getClass.name");
   * <code>
   * </p>
   * 
   * <p>A call to this method is equivalent to:
   * <code>create(listenerInterface, target, action, null, null)</code>
   * </p>
   *
   * @param listenerInterface Listener interface to implement.
   * @param target Object to invoke action on.
   * @param action Target property or method to invoke.
   * @param eventPropertyName Name of property to extract from event.
   * @return A constructed proxy object.
   */
  public static Object create(Class listenerInterface, Object target,
			      String action, String eventPropertyName)
  {
    return create(listenerInterface, target, action, eventPropertyName, null);
  }

  /**
   * <p>Constructs an implementation of <code>listenerInterface</code>
   * to dispatch events.</p>
   *
   * <p>Besides the functionality described for {@link create(Class, Object, String)}
   * and {@link create(Class, Object, String, String)} this method allows you
   * to filter the listener method that should have an effect. Look at these
   * method's documentation for more information about the <code>EventHandler</code>'s
   * usage.</p>
   * 
   * <p>If you want to call <code>dispose</code> on a <code>JFrame</code> instance
   * when the <code>WindowListener.windowClosing()</code> method was invoked use
   * the following code:</p>
   * <p>
   * <code>
   * EventHandler.create(WindowListener.class, jframeInstance, "dispose", null, "windowClosing");
   * </code>
   * </p>
   * 
   * <p>A <code>NullPointerException</code> is thrown if the <code>listenerInterface</code>
   * or <code>target</code> argument are <code>null</code>.
   * 
   * @param listenerInterface Listener interface to implement.
   * @param target Object to invoke action on.
   * @param action Target method name to invoke.
   * @param eventPropertyName Name of property to extract from event.
   * @param listenerMethodName Listener method to implement.
   * @return A constructed proxy object.
   */
  public static Object create(Class listenerInterface, Object target,
			      String action, String eventPropertyName,
			      String listenerMethodName)
  {
    // Create EventHandler instance
    EventHandler eh = new EventHandler(target, action, eventPropertyName,
				       listenerMethodName);

    // Create proxy object passing in the event handler
    Object proxy = Proxy.newProxyInstance(listenerInterface.getClassLoader(),
					  new Class[] {listenerInterface},
					  eh);

    return proxy;
  }

}
