/* AWTKeyStroke.java -- an immutable key stroke
   Copyright (C) 2002, 2004, 2005, 2006 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., 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.awt;

import java.awt.event.InputEvent;
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.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
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)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @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<AWTKeyStroke,AWTKeyStroke> cache =
    new LinkedHashMap<AWTKeyStroke,AWTKeyStroke>(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<AWTKeyStroke,AWTKeyStroke>
                                        eldest)
    {
      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.  This is package-private to
   * avoid an accessor method.
   *
   * @see #getAWTKeyStroke(String)
   */
  static final HashMap<String,Object> vktable = new HashMap<String,Object>();
  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((Class<?>[])null);
                c.setAccessible(true);
                // Create a new instance, to make sure that we can, and
                // to cause any ClassCastException.
                AWTKeyStroke dummy = (AWTKeyStroke) c.newInstance();
                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
   * @throws IllegalArgumentException if s is null or cannot be parsed
   * @return the specified keystroke
   */
  public static AWTKeyStroke getAWTKeyStroke(String s)
  {
    if (s == null)
      throw new IllegalArgumentException("null argument");
    StringTokenizer t = new StringTokenizer(s, " ");
    if (! t.hasMoreTokens())
      throw new IllegalArgumentException("no tokens '" + s + "'");
    int modifiers = 0;
    boolean released = false;
    String token = null;
    do
      {
        token = t.nextToken();
        if ("shift".equals(token))
          {
            modifiers |= KeyEvent.SHIFT_MASK;
            modifiers |= KeyEvent.SHIFT_DOWN_MASK;
          }
        else if ("ctrl".equals(token) || "control".equals(token))
          {
            modifiers |= KeyEvent.CTRL_MASK;
            modifiers |= KeyEvent.CTRL_DOWN_MASK;
          }
        else if ("meta".equals(token))
          {
            modifiers |= KeyEvent.META_MASK;
            modifiers |= KeyEvent.META_DOWN_MASK;
          }
        else if ("alt".equals(token))
          {
            modifiers |= KeyEvent.ALT_MASK;
            modifiers |= 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("Invalid 'typed' argument '"
                                               + s + "'");
          }
        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)
      throw new IllegalArgumentException("Unknown token '" + token
                                         + "' in '" + s + "'");
    if (t.hasMoreTokens())
      throw new IllegalArgumentException("Too many tokens: " + s);
    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 = 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();
          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 = 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
