/* AWTKeyStroke.java -- an immutable key stroke
   Copyright (C) 2002 Free Software Foundation

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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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.awt;

import java.awt.event.KeyEvent;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Map;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.StringTokenizer;

/**
 * This class mirrors KeyEvents, representing both low-level key presses and
 * key releases, and high level key typed inputs. However, this class forms
 * immutable strokes, and can be efficiently reused via the factory methods
 * for creating them.
 *
 * <p>For backwards compatibility with Swing, this supports a way to build
 * instances of a subclass, using reflection, provided the subclass has a
 * no-arg constructor (of any accessibility).
 *
 * @author Eric Blake <ebb9@email.byu.edu>
 * @see #getAWTKeyStroke(char)
 * @since 1.4
 * @status updated to 1.4
 */
public class AWTKeyStroke implements Serializable
{
  /**
   * Compatible with JDK 1.4+.
   */
  private static final long serialVersionUID = -6430539691155161871L;

  /** The mask for modifiers. */
  private static final int MODIFIERS_MASK = 0x3fef;

  /**
   * The cache of recently created keystrokes. This maps KeyStrokes to
   * KeyStrokes in a cache which removes the least recently accessed entry,
   * under the assumption that garbage collection of a new keystroke is
   * easy when we find the old one that it matches in the cache.
   */
  private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true)
  {
    /** The largest the keystroke cache can grow. */
    private static final int MAX_CACHE_SIZE = 2048;

    /** Prune stale entries. */
    protected boolean removeEldestEntry(Map.Entry eldest)
    {	// XXX - FIXME Use Map.Entry, not just Entry  as gcj 3.1 workaround.
      return size() > MAX_CACHE_SIZE;
    }
  };

  /** The most recently generated keystroke, or null. */
  private static AWTKeyStroke recent;

  /**
   * The no-arg constructor of a subclass, or null to use AWTKeyStroke. Note
   * that this will be left accessible, to get around private access; but
   * it should not be a security risk as it is highly unlikely that creating
   * protected instances of the subclass via reflection will do much damage.
   */
  private static Constructor ctor;

  /**
   * A table of keyCode names to values.
   *
   * @see #getAWTKeyStroke(String)
   */
  private static final HashMap vktable = new HashMap();
  static
  {
    // Using reflection saves the hassle of keeping this in sync with KeyEvent,
    // at the price of an expensive initialization.
    AccessController.doPrivileged(new PrivilegedAction()
      {
        public Object run()
        {
          Field[] fields = KeyEvent.class.getFields();
          int i = fields.length;
          try
            {
              while (--i >= 0)
                {
                  Field f = fields[i];
                  String name = f.getName();
                  if (name.startsWith("VK_"))
                    vktable.put(name.substring(3), f.get(null));
                }
            }
          catch (Exception e)
            {
              throw (Error) new InternalError().initCause(e);
            }
          return null;
        }
      });
  }

  /**
   * The typed character, or CHAR_UNDEFINED for key presses and releases.
   *
   * @serial the keyChar
   */
  private char keyChar;

  /**
   * The virtual key code, or VK_UNDEFINED for key typed. Package visible for
   * use by Component.
   *
   * @serial the keyCode
   */
  int keyCode;

  /**
   * The modifiers in effect. To match Sun, this stores the old style masks
   * for shift, control, alt, meta, and alt-graph (but not button1); as well
   * as the new style of extended modifiers for all modifiers.
   *
   * @serial bitwise or of the *_DOWN_MASK modifiers
   */
  private int modifiers;

  /**
   * True if this is a key release; should only be true if keyChar is
   * CHAR_UNDEFINED.
   *
   * @serial true to distinguish key pressed from key released
   */
  private boolean onKeyRelease;

  /**
   * Construct a keystroke with default values: it will be interpreted as a
   * key typed event with an invalid character and no modifiers. Client code
   * should use the factory methods instead.
   *
   * @see #getAWTKeyStroke(char)
   * @see #getAWTKeyStroke(Character, int)
   * @see #getAWTKeyStroke(int, int, boolean)
   * @see #getAWTKeyStroke(int, int)
   * @see #getAWTKeyStrokeForEvent(KeyEvent)
   * @see #getAWTKeyStroke(String)
   */
  protected AWTKeyStroke()
  {
    keyChar = KeyEvent.CHAR_UNDEFINED;
  }

  /**
   * Construct a keystroke with the given values. Client code should use the
   * factory methods instead.
   *
   * @param keyChar the character entered, if this is a key typed
   * @param keyCode the key pressed or released, or VK_UNDEFINED for key typed
   * @param modifiers the modifier keys for the keystroke, in old or new style
   * @param onKeyRelease true if this is a key release instead of a press
   * @see #getAWTKeyStroke(char)
   * @see #getAWTKeyStroke(Character, int)
   * @see #getAWTKeyStroke(int, int, boolean)
   * @see #getAWTKeyStroke(int, int)
   * @see #getAWTKeyStrokeForEvent(KeyEvent)
   * @see #getAWTKeyStroke(String)
   */
  protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
                         boolean onKeyRelease)
  {
    this.keyChar = keyChar;
    this.keyCode = keyCode;
    // No need to call extend(), as only trusted code calls this constructor.
    this.modifiers = modifiers;
    this.onKeyRelease = onKeyRelease;
  }

  /**
   * Registers a new subclass as being the type of keystrokes to generate in
   * the factory methods. This operation flushes the cache of stored keystrokes
   * if the class differs from the current one. The new class must be
   * AWTKeyStroke or a subclass, and must have a no-arg constructor (which may
   * be private).
   *
   * @param subclass the new runtime type of generated keystrokes
   * @throws IllegalArgumentException subclass doesn't have no-arg constructor
   * @throws ClassCastException subclass doesn't extend AWTKeyStroke
   */
  protected static void registerSubclass(final Class subclass)
  {
    if (subclass == null)
      throw new IllegalArgumentException();
    if (subclass.equals(ctor == null ? AWTKeyStroke.class
                        : ctor.getDeclaringClass()))
      return;
    if (subclass.equals(AWTKeyStroke.class))
       {
         cache.clear();
         recent = null;
         ctor = null;
         return;
       }
    try
      {
        ctor = (Constructor) AccessController.doPrivileged
          (new PrivilegedExceptionAction()
            {
              public Object run()
                throws NoSuchMethodException, InstantiationException,
                       IllegalAccessException, InvocationTargetException
              {
                Constructor c = subclass.getDeclaredConstructor(null);
                c.setAccessible(true);
                // Create a new instance, to make sure that we can, and
                // to cause any ClassCastException.
                AWTKeyStroke dummy = (AWTKeyStroke) c.newInstance(null);
                return c;
              }
            });
      }
    catch (PrivilegedActionException e)
      {
        // e.getCause() will not ever be ClassCastException; that should
        // escape on its own.
        throw (RuntimeException)
          new IllegalArgumentException().initCause(e.getCause());
      }
    cache.clear();
    recent = null;
  }

  /**
   * Returns a keystroke representing a typed character.
   *
   * @param keyChar the typed character 
   * @return the specified keystroke
   */
  public static AWTKeyStroke getAWTKeyStroke(char keyChar)
  {
    return getAWTKeyStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
  }

  /**
   * Returns a keystroke representing a typed character with the given
   * modifiers. Note that keyChar is a <code>Character</code> instead of a
   * <code>char</code> to avoid accidental ambiguity with
   * <code>getAWTKeyStroke(int, int)</code>. The modifiers are the bitwise
   * or of the masks found in {@link InputEvent}; the new style (*_DOWN_MASK)
   * is preferred, but the old style will work.
   *
   * @param keyChar the typed character
   * @param modifiers the modifiers, or 0
   * @return the specified keystroke
   * @throws IllegalArgumentException if keyChar is null
   */
  public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers)
  {
    if (keyChar == null)
      throw new IllegalArgumentException();
    return getAWTKeyStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
                           extend(modifiers), false);
  }

  /**
   * Returns a keystroke representing a pressed or released key event, with
   * the given modifiers. The "virtual key" should be one of the VK_*
   * constants in {@link KeyEvent}. The modifiers are the bitwise or of the
   * masks found in {@link InputEvent}; the new style (*_DOWN_MASK) is
   * preferred, but the old style will work.
   *
   * @param keyCode the virtual key
   * @param modifiers the modifiers, or 0
   * @param release true if this is a key release instead of a key press
   * @return the specified keystroke
   */
  public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
                                             boolean release)
  {
    return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
                           extend(modifiers), release);
  }

  /**
   * Returns a keystroke representing a pressed key event, with the given
   * modifiers. The "virtual key" should be one of the VK_* constants in
   * {@link KeyEvent}. The modifiers are the bitwise or of the masks found
   * in {@link InputEvent}; the new style (*_DOWN_MASK) is preferred, but the
   * old style will work.
   *
   * @param keyCode the virtual key
   * @param modifiers the modifiers, or 0
   * @return the specified keystroke
   */
  public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers)
  {
    return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
                           extend(modifiers), false);
  }

  /**
   * Returns a keystroke representing what caused the key event.
   *
   * @param event the key event to convert
   * @return the specified keystroke, or null if the event is invalid
   * @throws NullPointerException if event is null
   */
  public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent event)
  {
    switch (event.id)
      {
      case KeyEvent.KEY_TYPED:
        return getAWTKeyStroke(event.getKeyChar(), KeyEvent.VK_UNDEFINED,
                               extend(event.getModifiersEx()), false);
      case KeyEvent.KEY_PRESSED:
        return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(),
                               extend(event.getModifiersEx()), false);
      case KeyEvent.KEY_RELEASED:
        return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(),
                               extend(event.getModifiersEx()), true);
      default:
        return null;
      }
  }

  /**
   * Parses a string and returns the keystroke that it represents. The syntax
   * for keystrokes is listed below, with tokens separated by an arbitrary
   * number of spaces:
   * <pre>
   * keyStroke := &lt;modifiers&gt;* ( &lt;typedID&gt; | &lt;codeID&gt; )
   * modifiers := ( shift | control | ctrl | meta | alt
   *                | button1 | button2 | button3 )
   * typedID := typed &lt;single Unicode character&gt;
   * codeID := ( pressed | released )? &lt;name&gt;
   * name := &lt;the KeyEvent field name less the leading "VK_"&gt;
   * </pre>
   *
   * <p>Note that the grammar is rather weak, and not all valid keystrokes
   * can be generated in this manner (for example, a typed space, or anything
   * with the alt-graph modifier!). The output of AWTKeyStroke.toString()
   * will not meet the grammar. If pressed or released is not specified,
   * pressed is assumed. Examples:<br>
   * <code>
   * "INSERT" =&gt; getAWTKeyStroke(KeyEvent.VK_INSERT, 0);<br>
   * "control DELETE" =&gt;
   *    getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);<br>
   * "alt shift X" =&gt; getAWTKeyStroke(KeyEvent.VK_X,
   *    InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);<br>
   * "alt shift released X" =&gt; getAWTKeyStroke(KeyEvent.VK_X,
   *    InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);<br>
   * "typed a" =&gt; getAWTKeyStroke('a');
   * </code>      
   *
   * @param s the string to parse
   * @return the specified keystroke
   * @throws NullPointerException if s is null
   * @throws IllegalArgumentException if s cannot be parsed
   */
  public static AWTKeyStroke getAWTKeyStroke(String s)
  {
    StringTokenizer t = new StringTokenizer(s, " ");
    if (! t.hasMoreTokens())
      throw new IllegalArgumentException();
    int modifiers = 0;
    boolean released = false;
    String token = null;
    do
      {
        token = t.nextToken();
        if ("shift".equals(token))
          modifiers |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK;
        else if ("ctrl".equals(token) || "control".equals(token))
          modifiers |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK;
        else if ("meta".equals(token))
          modifiers |= KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK;
        else if ("alt".equals(token))
          modifiers |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK;
        else if ("button1".equals(token))
          modifiers |= KeyEvent.BUTTON1_DOWN_MASK;
        else if ("button2".equals(token))
          modifiers |= KeyEvent.BUTTON2_DOWN_MASK;
        else if ("button3".equals(token))
          modifiers |= KeyEvent.BUTTON3_DOWN_MASK;
        else if ("typed".equals(token))
          {
            if (t.hasMoreTokens())
              {
                token = t.nextToken();
                if (! t.hasMoreTokens() && token.length() == 1)
                  return getAWTKeyStroke(token.charAt(0),
                                         KeyEvent.VK_UNDEFINED, modifiers,
                                         false);
              }
            throw new IllegalArgumentException();
          }
        else if ("pressed".equals(token))
          {
            if (t.hasMoreTokens())
              token = t.nextToken();
            break;
          }
        else if ("released".equals(token))
          {
            released = true;
            if (t.hasMoreTokens())
              token = t.nextToken();
            break;
          }
        else
          break;
      }
    while (t.hasMoreTokens());
    // Now token contains the VK name we must parse.
    Integer code = (Integer) vktable.get(token);
    if (code == null || t.hasMoreTokens())
      throw new IllegalArgumentException();
    return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, code.intValue(),
                           modifiers, released);
  }

  /**
   * Returns the character of this keystroke, if it was typed.
   *
   * @return the character value, or CHAR_UNDEFINED
   * @see #getAWTKeyStroke(char)
   */
  public final char getKeyChar()
  {
    return keyChar;
  }

  /**
   * Returns the virtual key code of this keystroke, if it was pressed or
   * released. This will be a VK_* constant from KeyEvent.
   *
   * @return the virtual key code value, or VK_UNDEFINED
   * @see #getAWTKeyStroke(int, int)
   */
  public final int getKeyCode()
  {
    return keyCode;
  }

  /**
   * Returns the modifiers for this keystroke. This will be a bitwise or of
   * constants from InputEvent; it includes the old style masks for shift,
   * control, alt, meta, and alt-graph (but not button1); as well as the new
   * style of extended modifiers for all modifiers.
   *
   * @return the modifiers
   * @see #getAWTKeyStroke(Character, int)
   * @see #getAWTKeyStroke(int, int)
   */
  public final int getModifiers()
  {
    return modifiers;
  }

  /**
   * Tests if this keystroke is a key release.
   *
   * @return true if this is a key release
   * @see #getAWTKeyStroke(int, int, boolean)
   */
  public final boolean isOnKeyRelease()
  {
    return onKeyRelease;
  }

  /**
   * Returns the AWT event type of this keystroke. This is one of
   * {@link KeyEvent#KEY_TYPED}, {@link KeyEvent#KEY_PRESSED}, or
   * {@link KeyEvent#KEY_RELEASED}.
   *
   * @return the key event type
   */
  public final int getKeyEventType()
  {
    return keyCode == KeyEvent.VK_UNDEFINED ? KeyEvent.KEY_TYPED
      : onKeyRelease ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED;
  }

  /**
   * Returns a hashcode for this key event. It is not documented, but appears
   * to be: <code>(getKeyChar() + 1) * (getKeyCode() + 1)
   * * (getModifiers() + 1) * 2 + (isOnKeyRelease() ? 1 : 2)</code>.
   *
   * @return the hashcode
   */
  public int hashCode()
  {
    return (keyChar + 1) * (keyCode + 1) * (modifiers + 1) * 2
      + (onKeyRelease ? 1 : 2);
  }

  /**
   * Tests two keystrokes for equality.
   *
   * @param o the object to test
   * @return true if it is equal
   */
  public final boolean equals(Object o)
  {
    if (! (o instanceof AWTKeyStroke))
      return false;
    AWTKeyStroke s = (AWTKeyStroke) o;
    return this == o || (keyChar == s.keyChar && keyCode == s.keyCode
                         && modifiers == s.modifiers
                         && onKeyRelease == s.onKeyRelease);
  }

  /**
   * Returns a string representation of this keystroke. For typed keystrokes,
   * this is <code>"keyChar " + KeyEvent.getKeyModifiersText(getModifiers())
   + getKeyChar()</code>; for pressed and released keystrokes, this is
   * <code>"keyCode " + KeyEvent.getKeyModifiersText(getModifiers())
   * + KeyEvent.getKeyText(getKeyCode())
   * + (isOnKeyRelease() ? "-R" : "-P")</code>.
   *
   * @return a string representation
   */
  public String toString()
  {
    if (keyCode == KeyEvent.VK_UNDEFINED)
      return "keyChar " + KeyEvent.getKeyModifiersText(modifiers) + keyChar;
    return "keyCode " + KeyEvent.getKeyModifiersText(modifiers)
      + KeyEvent.getKeyText(keyCode) + (onKeyRelease ? "-R" : "-P");
  }

  /**
   * Returns a cached version of the deserialized keystroke, if available.
   *
   * @return a cached replacement
   * @throws ObjectStreamException if something goes wrong
   */
  protected Object readResolve() throws ObjectStreamException
  {
    AWTKeyStroke s = (AWTKeyStroke) cache.get(this);
    if (s != null)
      return s;
    cache.put(this, this);
    return this;
  }

  /**
   * Gets the appropriate keystroke, creating one if necessary.
   *
   * @param keyChar the keyChar
   * @param keyCode the keyCode
   * @param modifiers the modifiers
   * @param release true for key release
   * @return the specified keystroke
   */
  private static AWTKeyStroke getAWTKeyStroke(char keyChar, int keyCode,
                                              int modifiers, boolean release)
  {
    // Check level 0 cache.
    AWTKeyStroke stroke = recent; // Avoid thread races.
    if (stroke != null && stroke.keyChar == keyChar
        && stroke.keyCode == keyCode && stroke.modifiers == modifiers
        && stroke.onKeyRelease == release)
      return stroke;
    // Create a new object, on the assumption that if it has a match in the
    // cache, the VM can easily garbage collect it as it is temporary.
    Constructor c = ctor; // Avoid thread races.
    if (c == null)
      stroke = new AWTKeyStroke(keyChar, keyCode, modifiers, release);
    else
      try
        {
          stroke = (AWTKeyStroke) c.newInstance(null);
          stroke.keyChar = keyChar;
          stroke.keyCode = keyCode;
          stroke.modifiers = modifiers;
          stroke.onKeyRelease = release;
        }
      catch (Exception e)
        {
          throw (Error) new InternalError().initCause(e);
        }
    // Check level 1 cache.
    AWTKeyStroke cached = (AWTKeyStroke) cache.get(stroke);
    if (cached == null)
      cache.put(stroke, stroke);
    else
      stroke = cached;
    return recent = stroke;
  }

  /**
   * Converts the modifiers to the appropriate format.
   *
   * @param mod the modifiers to convert
   * @return the adjusted modifiers
   */
  private static int extend(int mod)
  {
    if ((mod & (KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK)) != 0)
      mod |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK;
    if ((mod & (KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK)) != 0)
      mod |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK;
    if ((mod & (KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK)) != 0)
      mod |= KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK;
    if ((mod & (KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK)) != 0)
      mod |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK;
    if ((mod & (KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK)) != 0)
      mod |= KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK;
    if ((mod & KeyEvent.BUTTON1_MASK) != 0)
      mod |= KeyEvent.BUTTON1_DOWN_MASK;
    return mod & MODIFIERS_MASK;
  }
} // class AWTKeyStroke
