// Module    : $RCSfile: KeyboardMap.java,v $
// Version   : $Revision: 0.0 $  $Author: patrick $  $Date: 11.07.2012 $
// Project   : KeyboardMaps
// Creation  : 2012 by patrick
// Copyright : Patrick Harms, 2012

package de.ugoe.cs.tasktree.keyboardmaps;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * TODO comment
 * 
 * @version $Revision: $ $Date: 11.07.2012$
 * @author 2012, last modified by $Author: patrick$
 */
public class KeyboardMap {

    /** */
    private static Logger LOG = Logger.getLogger(KeyboardMap.class.getName());

    /** */
    private Locale locale;

    /** */
    private String fileName;

    /** */
    private Map<VirtualKey, List<KeyStroke>> keyStrokes =
        new HashMap<VirtualKey, List<KeyStroke>>();

    /** TODO: remove this stuff */
    private List<Object[]> mKeyIds = new ArrayList<Object[]>();

    /**
     * TODO: comment
     * 
     * @param locale
     */
    KeyboardMap(Locale locale) {
        this.locale = locale;

        if ((this.locale == Locale.ENGLISH) || (this.locale == Locale.US) ||
            (this.locale == Locale.CANADA))
        {
            fileName = "en-us";
        }
        else if (locale == Locale.UK) {
            fileName = "en-gb";
        }
        else {
            fileName = locale.getLanguage();
        }
    }

    /**
     * TODO: comment
     * 
     * @param digit1
     * @param b
     * @param c
     * @param d
     * @param e
     * @param f
     * @return
     */
    public char getCharacterFor(VirtualKey key,
                                boolean    numlock,
                                boolean    shift,
                                boolean    altgr,
                                boolean    inhibit)
        throws IllegalArgumentException
    {
        List<KeyStroke> candidates = keyStrokes.get(key);

        if (candidates == null) {
            return Character.UNASSIGNED;
        }

        // try to find the key stroke
        for (KeyStroke keyStroke : candidates) {
            if ((numlock == keyStroke.getNumlock()) && (!keyStroke.getLocalstate()) &&
                (shift == keyStroke.getShift()) && (altgr == keyStroke.getAltgr()) &&
                (inhibit == keyStroke.getInhibit()))
            {
                return keyStroke.getCharacter();
            }
        }

        // try to find the key stroke with a local state ignoring the other keys
        for (KeyStroke keyStroke : candidates) {
            if ((numlock == keyStroke.getNumlock()) && (keyStroke.getLocalstate()) &&
                (inhibit == keyStroke.getInhibit()))
            {
                return keyStroke.getCharacter();
            }
        }

        return Character.UNASSIGNED;
    }

    /**
     * TODO: comment
     * 
     */
    void init() throws IllegalArgumentException {
        LOG.info("initializing keymap for locale " + locale);

        List<String[]> deadKeySequences = new ArrayList<String[]>();
        List<String[]> keyStrokes = new ArrayList<String[]>();
        readStream(getStream(fileName), deadKeySequences, keyStrokes);

        LOG.info("read " + keyStrokes.size() + " key strokes and " + deadKeySequences.size() +
                 " dead key sequences");

        VirtualKeySynonyms virtualKeySynonyms = determineVirtualKeySynonyms(keyStrokes);
        processKeyStrokes(keyStrokes, virtualKeySynonyms);
        processDeadKeySequences(deadKeySequences);

        for (Object[] keyId : mKeyIds) {
            System.out.println(Integer.toHexString((Integer) keyId[0]) + "  " + keyId[1]);
        }
    }

    /**
     * TODO: comment
     * 
     * @param fileName
     * @return
     */
    private InputStream getStream(String name) {
        LOG.info("reading keymap for locale " + locale + " from resource keymaps/" + name);

        InputStream stream =
            this.getClass().getClassLoader().getResourceAsStream("keymaps/" + name);

        if (stream == null) {
            throw new IllegalArgumentException("no keyboard map available for locale " + locale);
        }

        return stream;
    }

    /**
     * TODO: comment
     * 
     * @param stream
     * @param virtualKeySynonyms
     * @param deadKeySequences
     */
    private void readStream(InputStream    stream,
                            List<String[]> deadKeySequences,
                            List<String[]> keyStrokes)
        throws IllegalArgumentException
    {
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
        }
        catch (UnsupportedEncodingException e) {
            LOG.log(Level.WARNING, "no keyboard map available for locale " + locale, e);
            throw new IllegalArgumentException
                ("provided stream can not be read due to invalid encoding", e);
        }

        try {
            String line;
            while ((line = in.readLine()) != null) {
                if (!"".equals(line)) {
                    processLine(line, deadKeySequences, keyStrokes);
                }
            }
        }
        catch (IOException e) {
            LOG.log(Level.WARNING, "no keyboard map available for locale " + locale, e);
            throw new IllegalArgumentException("no keyboard map available for locale " + locale, e);
        }
        finally {
            try {
                in.close();
            }
            catch (IOException e) {
                LOG.warning("could not close input stream for reading keyboard map");
            }
        }
    }

    /**
     * TODO: comment
     * 
     * @param line
     * @param deadKeySequences
     */
    private void processLine(String         line,
                             List<String[]> deadKeySequences,
                             List<String[]> keyStrokes)
    {
        String[] values = line.split(" ");

        if (values.length <= 0) {
            return;
        }

        // ignore comments
        if (values[0].startsWith("#")) {
            return;
        }

        if ("map".equals(values[0])) {
            // this is the map id. Ignore it.
        }
        else if ("include".equals(values[0])) {
            // process all includes
            for (int i = 1; i < values.length; i++) {
                if (!values[i].startsWith("#")) {
                    readStream(getStream(values[i]), deadKeySequences, keyStrokes);
                }
                else {
                    break;
                }
            }
        }
        else if ("sequence".equals(values[0])) {
            deadKeySequences.add(values);
        }
        else {
            boolean alreadyAdded = false;

            // check, if there is a replacement
            for (int i = 0; i < keyStrokes.size(); i++) {
                if (keyStrokes.get(i)[0].equals(values[0])) {
                    LOG.finest("replacing key stroke " + values[0] + " with former keyid " +
                               keyStrokes.get(i)[1] + " with new key id " + values[1]);
                    keyStrokes.set(i, values);
                    alreadyAdded = true;
                    break;
                }
            }

            if (!alreadyAdded) {
                keyStrokes.add(values);
            }
        }
    }

    /**
     * TODO: comment
     * 
     * @param keyStrokes
     * @return
     */
    private VirtualKeySynonyms determineVirtualKeySynonyms(List<String[]> keyStrokes) {
        LOG.info("determining virtual keys and synonyms for the keymap");

        VirtualKeySynonyms virtualKeySynonyms = new VirtualKeySynonyms();

        // for debugging purposes, determine which key strokes are not matched to virtual keys.
        List<String[]> unmatchedKeyStrokes = new ArrayList<String[]>();

        for (String[] keyStroke : keyStrokes) {
            String keyStrokeName = keyStroke[0];
            int keyId = getKeyId(keyStroke[1]);
            // System.err.println(keyStrokeName + "  0x" + Integer.toHexString(keyId));

            VirtualKey virtualKey = determineVirtualKey(keyStrokeName);

            if (virtualKey != null) {
                virtualKeySynonyms.add(keyId, virtualKey);
            }
            else {
                unmatchedKeyStrokes.add(keyStroke);
            }
        }

        for (String[] unmatchedKeyStroke : unmatchedKeyStrokes) {
            if (!virtualKeySynonyms.containsKey(getKeyId(unmatchedKeyStroke[1]))) {
                LOG.finest("no virtual key mapped to key stroke " + unmatchedKeyStroke[0] + "(" +
                           unmatchedKeyStroke[1] + ") of keyboard map for locale " + locale);
            }
        }

        return virtualKeySynonyms;
    }

    /**
     * TODO: comment
     * 
     * @param string
     * @return
     */
    private int getKeyId(String keyIdString) {
        if (keyIdString.startsWith("0x")) {
            keyIdString = keyIdString.substring(2);
        }

        return Integer.parseInt(keyIdString, 16);
    }

    /**
     * TODO: comment
     * 
     * @param keyStrokes
     * @param virtualKeySynonyms
     */
    private void processKeyStrokes(List<String[]> keyStrokes, VirtualKeySynonyms virtualKeySynonyms)
    {
        for (String[] keyStroke : keyStrokes) {
            handleKeyStroke(keyStroke, virtualKeySynonyms);
        }

        addKeyStrokesIndependentOfNumLock();
    }

    /**
     * TODO: comment
     * 
     * @param values
     */
    private void handleKeyStroke(String[] values, VirtualKeySynonyms virtualKeySynonyms) {
        String keyStrokeName = values[0];
        String keyIdString = values[1];
        if (keyIdString.startsWith("0x")) {
            keyIdString = keyIdString.substring(2);
        }

        int keyId = Integer.parseInt(keyIdString, 16);

        // parse the conditions
        boolean numlock = false;
        boolean localstate = false;
        boolean shift = false;
        boolean altgr = false;
        boolean addupper = false;
        boolean inhibit = false;

        for (int i = 2; i < values.length; i++) {
            if (!values[i].startsWith("#")) {
                if ("numlock".equals(values[i])) {
                    numlock = true;
                }
                else if ("localstate".equals(values[i])) {
                    localstate = true;
                }
                else if ("shift".equals(values[i])) {
                    shift = true;
                }
                else if ("altgr".equals(values[i])) {
                    altgr = true;
                }
                else if ("addupper".equals(values[i])) {
                    addupper = true;
                }
                else if ("inhibit".equals(values[i])) {
                    inhibit = true;
                }
                else {
                    LOG.severe("unknown condition " + values[i] + " specified for key stroke " +
                               keyStrokeName + " through keyboard map for locale " + locale);
                    throw new IllegalArgumentException
                        ("no keyboard map available for locale " + locale);
                }
            }
            else {
                break;
            }
        }

        addAllRepresentedKeyStrokes(keyStrokeName, keyId, numlock, localstate, shift, altgr,
                                    addupper, inhibit, virtualKeySynonyms);
    }

    /**
     * TODO: comment
     * 
     * @param keyStrokeName
     * @param keyId
     * @param numlock
     * @param localstate
     * @param shift
     * @param altgr
     * @param addupper
     * @param inhibit
     */
    private void addAllRepresentedKeyStrokes(String             keyStrokeName,
                                             int                keyId,
                                             boolean            numlock,
                                             boolean            localstate,
                                             boolean            shift,
                                             boolean            altgr,
                                             boolean            addupper,
                                             boolean            inhibit,
                                             VirtualKeySynonyms virtualKeySynonyms)
    {
        VirtualKey[] virtualKeys = virtualKeySynonyms.getVirtualKeySynonyms(keyId);

        if (virtualKeys == null) {
            LOG.severe("no virtual key mapped to key stroke " + keyStrokeName +
                       " of keyboard map for locale " + locale);
            // throw new IllegalArgumentException("no keyboard map available for locale " +
            // mLocale);
            return;
        }

        for (VirtualKey virtualKey : virtualKeys) {
            if (addupper) {
                char c = determineCharacter(keyStrokeName, true);
                addKeyStroke
                  (keyStrokeName, virtualKey, numlock, localstate, true, altgr, inhibit, c);

                c = determineCharacter(keyStrokeName, false);
                addKeyStroke
                  (keyStrokeName, virtualKey, numlock, localstate, false, altgr, inhibit, c);
            }
            else {
                char c = determineCharacter(keyStrokeName, false);
                addKeyStroke
                  (keyStrokeName, virtualKey, numlock, localstate, shift, altgr, inhibit, c);
            }
        }
    }

    /**
     * TODO: comment
     * 
     * @param keyStroke
     */
    private void addKeyStroke(String     keyStrokeName,
                              VirtualKey virtualKey,
                              boolean    numlock,
                              boolean    localstate,
                              boolean    shift,
                              boolean    altgr,
                              boolean    inhibit,
                              char       character)
    {
        KeyStroke keyStroke = new KeyStroke
            (keyStrokeName, virtualKey, numlock, localstate, shift, altgr, inhibit, character);

        List<KeyStroke> keyStrokeList = keyStrokes.get(keyStroke.getVirtualKey());

        if (keyStrokeList == null) {
            keyStrokeList = new ArrayList<KeyStroke>();
            keyStrokes.put(keyStroke.getVirtualKey(), keyStrokeList);
        }

        keyStrokeList.add(keyStroke);
    }

    /**
     * TODO: comment
     * 
     */
    private void addKeyStrokesIndependentOfNumLock() {
        for (Map.Entry<VirtualKey, List<KeyStroke>> entry : keyStrokes.entrySet()) {
            List<KeyStroke> keyStrokesToAdd = new ArrayList<KeyStroke>();
            for (KeyStroke keyStroke : entry.getValue()) {
                if (!keyStroke.getNumlock()) {
                    boolean foundPositiveNumlockVariant = false;
                    for (KeyStroke candidate : entry.getValue()) {
                        if ((candidate.getShift() == keyStroke.getShift()) &&
                            (candidate.getAltgr() == keyStroke.getAltgr()) &&
                            (candidate.getLocalstate() == keyStroke.getLocalstate()) &&
                            (candidate.getInhibit() == keyStroke.getInhibit()) &&
                            (candidate.getNumlock()))
                        {
                            foundPositiveNumlockVariant = true;
                            break;
                        }
                    }

                    if (!foundPositiveNumlockVariant) {
                        keyStrokesToAdd.add(keyStroke);
                    }
                }
            }

            for (KeyStroke keyStroke : keyStrokesToAdd) {
                addKeyStroke(keyStroke.getKeyStrokeName(), keyStroke.getVirtualKey(), true,
                             keyStroke.getLocalstate(), keyStroke.getShift(), keyStroke.getAltgr(),
                             keyStroke.getInhibit(), keyStroke.getCharacter());
            }
        }
    }

    /**
     * TODO: comment
     * 
     * @param deadKeySequences
     */
    private void processDeadKeySequences(List<String[]> deadKeySequences) {
        // TODO Auto-generated method stub
        // System.out.println("PATRICK: KeyboardMap.processDeadKeySequences ");
    }

    /**
     * TODO: comment
     * 
     * @param keyStrokeName
     * @param shift
     * @return
     */
    private VirtualKey determineVirtualKey(String keyStrokeName) {
        if ("Shift_R".equals(keyStrokeName)) {
            return VirtualKey.SHIFT;
        }
        else if ("Shift_L".equals(keyStrokeName)) {
            return VirtualKey.SHIFT;
        }
        else if ("Alt_R".equals(keyStrokeName)) {
            return VirtualKey.ALT_GRAPH;
        }
        else if ("Mode_switch".equals(keyStrokeName)) {
            return VirtualKey.MODECHANGE;
        }
        else if ("ISO_Level3_Shift".equals(keyStrokeName)) {
            return VirtualKey.SHIFT;
        }
        else if ("Alt_L".equals(keyStrokeName)) {
            return VirtualKey.ALT;
        }
        else if ("Control_R".equals(keyStrokeName)) {
            return VirtualKey.CONTROL;
        }
        else if ("Control_L".equals(keyStrokeName)) {
            return VirtualKey.CONTROL;
        }
        else if ("Menu".equals(keyStrokeName)) {
            return VirtualKey.WINDOWS;
        }
        else if ("1".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_1;
        }
        else if ("2".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_2;
        }
        else if ("3".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_3;
        }
        else if ("4".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_4;
        }
        else if ("5".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_5;
        }
        else if ("6".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_6;
        }
        else if ("7".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_7;
        }
        else if ("8".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_8;
        }
        else if ("9".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_9;
        }
        else if ("0".equals(keyStrokeName)) {
            return VirtualKey.DIGIT_0;
        }
        else if ("BackSpace".equals(keyStrokeName)) {
            return VirtualKey.BACK_SPACE;
        }
        else if ("Tab".equals(keyStrokeName)) {
            return VirtualKey.TAB;
        }
        else if ("q".equals(keyStrokeName)) {
            return VirtualKey.LETTER_Q;
        }
        else if ("w".equals(keyStrokeName)) {
            return VirtualKey.LETTER_W;
        }
        else if ("e".equals(keyStrokeName)) {
            return VirtualKey.LETTER_E;
        }
        else if ("r".equals(keyStrokeName)) {
            return VirtualKey.LETTER_R;
        }
        else if ("t".equals(keyStrokeName)) {
            return VirtualKey.LETTER_T;
        }
        else if ("y".equals(keyStrokeName)) {
            return VirtualKey.LETTER_Y;
        }
        else if ("u".equals(keyStrokeName)) {
            return VirtualKey.LETTER_U;
        }
        else if ("i".equals(keyStrokeName)) {
            return VirtualKey.LETTER_I;
        }
        else if ("o".equals(keyStrokeName)) {
            return VirtualKey.LETTER_O;
        }
        else if ("p".equals(keyStrokeName)) {
            return VirtualKey.LETTER_P;
        }
        else if ("a".equals(keyStrokeName)) {
            return VirtualKey.LETTER_A;
        }
        else if ("s".equals(keyStrokeName)) {
            return VirtualKey.LETTER_S;
        }
        else if ("d".equals(keyStrokeName)) {
            return VirtualKey.LETTER_D;
        }
        else if ("f".equals(keyStrokeName)) {
            return VirtualKey.LETTER_F;
        }
        else if ("g".equals(keyStrokeName)) {
            return VirtualKey.LETTER_G;
        }
        else if ("h".equals(keyStrokeName)) {
            return VirtualKey.LETTER_H;
        }
        else if ("j".equals(keyStrokeName)) {
            return VirtualKey.LETTER_J;
        }
        else if ("k".equals(keyStrokeName)) {
            return VirtualKey.LETTER_K;
        }
        else if ("l".equals(keyStrokeName)) {
            return VirtualKey.LETTER_L;
        }
        else if ("Return".equals(keyStrokeName)) {
            return VirtualKey.ENTER;
        }
        else if ("z".equals(keyStrokeName)) {
            return VirtualKey.LETTER_Z;
        }
        else if ("x".equals(keyStrokeName)) {
            return VirtualKey.LETTER_X;
        }
        else if ("c".equals(keyStrokeName)) {
            return VirtualKey.LETTER_C;
        }
        else if ("v".equals(keyStrokeName)) {
            return VirtualKey.LETTER_V;
        }
        else if ("b".equals(keyStrokeName)) {
            return VirtualKey.LETTER_B;
        }
        else if ("n".equals(keyStrokeName)) {
            return VirtualKey.LETTER_N;
        }
        else if ("m".equals(keyStrokeName)) {
            return VirtualKey.LETTER_M;
        }
        else if ("space".equals(keyStrokeName)) {
            return VirtualKey.SPACE;
        }
        else if ("less".equals(keyStrokeName)) {
            return VirtualKey.LESS;
        }
        else if ("greater".equals(keyStrokeName)) {
            return VirtualKey.GREATER;
        }
        else if ("Escape".equals(keyStrokeName)) {
            return VirtualKey.ESCAPE;
        }
        else if ("F1".equals(keyStrokeName)) {
            return VirtualKey.F1;
        }
        else if ("F2".equals(keyStrokeName)) {
            return VirtualKey.F2;
        }
        else if ("F3".equals(keyStrokeName)) {
            return VirtualKey.F3;
        }
        else if ("F4".equals(keyStrokeName)) {
            return VirtualKey.F4;
        }
        else if ("F5".equals(keyStrokeName)) {
            return VirtualKey.F5;
        }
        else if ("F6".equals(keyStrokeName)) {
            return VirtualKey.F6;
        }
        else if ("F7".equals(keyStrokeName)) {
            return VirtualKey.F7;
        }
        else if ("F8".equals(keyStrokeName)) {
            return VirtualKey.F8;
        }
        else if ("F9".equals(keyStrokeName)) {
            return VirtualKey.F9;
        }
        else if ("F10".equals(keyStrokeName)) {
            return VirtualKey.F10;
        }
        else if ("F11".equals(keyStrokeName)) {
            return VirtualKey.F11;
        }
        else if ("F12".equals(keyStrokeName)) {
            return VirtualKey.F12;
        }
        else if ("F13".equals(keyStrokeName)) {
            return VirtualKey.F13;
        }
        else if ("F14".equals(keyStrokeName)) {
            return VirtualKey.F14;
        }
        else if ("F15".equals(keyStrokeName)) {
            return VirtualKey.F15;
        }
        else if ("F16".equals(keyStrokeName)) {
            return VirtualKey.F16;
        }
        else if ("F17".equals(keyStrokeName)) {
            return VirtualKey.F17;
        }
        else if ("F18".equals(keyStrokeName)) {
            return VirtualKey.F18;
        }
        else if ("F19".equals(keyStrokeName)) {
            return VirtualKey.F19;
        }
        else if ("F20".equals(keyStrokeName)) {
            return VirtualKey.F20;
        }
        else if ("F21".equals(keyStrokeName)) {
            return VirtualKey.F21;
        }
        else if ("F22".equals(keyStrokeName)) {
            return VirtualKey.F22;
        }
        else if ("F23".equals(keyStrokeName)) {
            return VirtualKey.F23;
        }
        else if ("F24".equals(keyStrokeName)) {
            return VirtualKey.F24;
        }
        else if ("Print".equals(keyStrokeName)) {
            return VirtualKey.PRINTSCREEN;
        }
        else if ("Scroll_Lock".equals(keyStrokeName)) {
            return VirtualKey.SCROLL_LOCK;
        }
        else if ("Insert".equals(keyStrokeName)) {
            return VirtualKey.INSERT;
        }
        else if ("Delete".equals(keyStrokeName)) {
            return VirtualKey.DELETE;
        }
        else if ("Home".equals(keyStrokeName)) {
            return VirtualKey.HOME;
        }
        else if ("End".equals(keyStrokeName)) {
            return VirtualKey.END;
        }
        else if ("Page_Up".equals(keyStrokeName)) {
            return VirtualKey.PAGE_UP;
        }
        else if ("Page_Down".equals(keyStrokeName)) {
            return VirtualKey.PAGE_DOWN;
        }
        else if ("Left".equals(keyStrokeName)) {
            return VirtualKey.LEFT;
        }
        else if ("Up".equals(keyStrokeName)) {
            return VirtualKey.UP;
        }
        else if ("Down".equals(keyStrokeName)) {
            return VirtualKey.DOWN;
        }
        else if ("Right".equals(keyStrokeName)) {
            return VirtualKey.RIGHT;
        }
        else if ("Num_Lock".equals(keyStrokeName)) {
            return VirtualKey.NUM_LOCK;
        }
        else if ("KP_Divide".equals(keyStrokeName)) {
            return VirtualKey.SLASH;
        }
        else if ("KP_Multiply".equals(keyStrokeName)) {
            return VirtualKey.ASTERISK;
        }
        else if ("KP_Subtract".equals(keyStrokeName)) {
            return VirtualKey.MINUS;
        }
        else if ("KP_Add".equals(keyStrokeName)) {
            return VirtualKey.PLUS;
        }
        else if ("KP_Enter".equals(keyStrokeName)) {
            return VirtualKey.ENTER;
        }
        else if ("KP_Decimal".equals(keyStrokeName)) {
            return VirtualKey.DECIMAL;
        }
        else if ("KP_Separator".equals(keyStrokeName)) {
            return VirtualKey.SEPARATOR;
        }
        else if ("KP_Delete".equals(keyStrokeName)) {
            return VirtualKey.DELETE;
        }
        else if ("KP_0".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_0;
        }
        else if ("KP_Insert".equals(keyStrokeName)) {
            return VirtualKey.INSERT;
        }
        else if ("KP_1".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_1;
        }
        else if ("KP_End".equals(keyStrokeName)) {
            return VirtualKey.END;
        }
        else if ("KP_2".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_2;
        }
        else if ("KP_Down".equals(keyStrokeName)) {
            return VirtualKey.KP_DOWN;
        }
        else if ("KP_3".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_3;
        }
        else if ("KP_Next".equals(keyStrokeName)) {
            return VirtualKey.PAGE_DOWN;
        }
        else if ("KP_4".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_4;
        }
        else if ("KP_Left".equals(keyStrokeName)) {
            return VirtualKey.KP_LEFT;
        }
        else if ("KP_5".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_5;
        }
        else if ("KP_Begin".equals(keyStrokeName)) {
            return VirtualKey.BEGIN;
        }
        else if ("KP_6".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_6;
        }
        else if ("KP_Right".equals(keyStrokeName)) {
            return VirtualKey.KP_RIGHT;
        }
        else if ("KP_7".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_7;
        }
        else if ("KP_Home".equals(keyStrokeName)) {
            return VirtualKey.HOME;
        }
        else if ("KP_8".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_8;
        }
        else if ("KP_Up".equals(keyStrokeName)) {
            return VirtualKey.KP_UP;
        }
        else if ("KP_9".equals(keyStrokeName)) {
            return VirtualKey.NUMPAD_9;
        }
        else if ("KP_Prior".equals(keyStrokeName)) {
            return VirtualKey.PAGE_UP;
        }
        else if ("Caps_Lock".equals(keyStrokeName)) {
            return VirtualKey.CAPS_LOCK;
        }
        else if ("exclam".equals(keyStrokeName)) {
            return VirtualKey.EXCLAMATION_MARK;
        }
        else if ("exclamdown".equals(keyStrokeName)) {
            return VirtualKey.INVERTED_EXCLAMATION_MARK;
        }
        else if ("quotedbl".equals(keyStrokeName)) {
            return VirtualKey.QUOTEDBL;
        }
        else if ("slash".equals(keyStrokeName)) {
            return VirtualKey.SLASH;
        }
        else if ("backslash".equals(keyStrokeName)) {
            return VirtualKey.BACK_SLASH;
        }
        else if ("dead_acute".equals(keyStrokeName)) {
            return VirtualKey.DEAD_ACUTE;
        }
        else if ("dead_diaresis".equals(keyStrokeName)) {
            return VirtualKey.DEAD_DIAERESIS;
        }
        else if ("dead_abovering".equals(keyStrokeName)) {
            return VirtualKey.DEAD_ABOVERING;
        }
        else if ("plus".equals(keyStrokeName)) {
            return VirtualKey.PLUS;
        }
        else if ("asterisk".equals(keyStrokeName)) {
            return VirtualKey.ASTERISK;
        }
        else if ("dead_tilde".equals(keyStrokeName)) {
            return VirtualKey.DEAD_TILDE;
        }
        else if ("dead_doubleacute".equals(keyStrokeName)) {
            return VirtualKey.DEAD_DOUBLEACUTE;
        }
        else if ("dead_caron".equals(keyStrokeName)) {
            return VirtualKey.DEAD_CARON;
        }
        else if ("dead_circumflex".equals(keyStrokeName)) {
            return VirtualKey.DEAD_CIRCUMFLEX;
        }
        else if ("comma".equals(keyStrokeName)) {
            return VirtualKey.COMMA;
        }
        else if ("semicolon".equals(keyStrokeName)) {
            return VirtualKey.SEMICOLON;
        }
        else if ("multiply".equals(keyStrokeName)) {
            return VirtualKey.MULTIPLY;
        }
        else if ("period".equals(keyStrokeName)) {
            return VirtualKey.PERIOD;
        }
        else if ("colon".equals(keyStrokeName)) {
            return VirtualKey.COLON;
        }
        else if ("dead_breve".equals(keyStrokeName)) {
            return VirtualKey.DEAD_BREVE;
        }
        else if ("division".equals(keyStrokeName)) {
            return VirtualKey.DIVIDE;
        }
        else if ("minus".equals(keyStrokeName)) {
            return VirtualKey.MINUS;
        }
        else if ("underscore".equals(keyStrokeName)) {
            return VirtualKey.UNDERSCORE;
        }
        else if ("dead_abovedot".equals(keyStrokeName)) {
            return VirtualKey.DEAD_ABOVEDOT;
        }
        else if ("bracketleft".equals(keyStrokeName)) {
            return VirtualKey.OPEN_BRACKET;
        }
        else if ("bracketright".equals(keyStrokeName)) {
            return VirtualKey.CLOSE_BRACKET;
        }
        else if ("grave".equals(keyStrokeName)) {
            return VirtualKey.DEAD_GRAVE;
        }
        else if ("equal".equals(keyStrokeName)) {
            return VirtualKey.EQUALS;
        }
        else if ("dead_macron".equals(keyStrokeName)) {
            return VirtualKey.DEAD_MACRON;
        }
        else if ("dead_ogonek".equals(keyStrokeName)) {
            return VirtualKey.DEAD_OGONEK;
        }
        else if ("dead_cedilla".equals(keyStrokeName)) {
            return VirtualKey.DEAD_CEDILLA;
        }
        else if ("ampersand".equals(keyStrokeName)) {
            return VirtualKey.AMPERSAND;
        }
        else if ("parenleft".equals(keyStrokeName)) {
            return VirtualKey.LEFT_PARENTHESIS;
        }
        else if ("parenright".equals(keyStrokeName)) {
            return VirtualKey.RIGHT_PARENTHESIS;
        }
        else if ("braceleft".equals(keyStrokeName)) {
            return VirtualKey.BRACELEFT;
        }
        else if ("braceright".equals(keyStrokeName)) {
            return VirtualKey.BRACERIGHT;
        }
        else if ("at".equals(keyStrokeName)) {
            return VirtualKey.AT;
        }
        else if ("dollar".equals(keyStrokeName)) {
            return VirtualKey.DOLLAR;
        }
        else if ("EuroSign".equals(keyStrokeName)) {
            return VirtualKey.EURO_SIGN;
        }
        else if ("Begin".equals(keyStrokeName)) {
            return VirtualKey.BEGIN;
        }
        else if ("numbersign".equals(keyStrokeName)) {
            return VirtualKey.NUMBER_SIGN;
        }
        else if ("asciicircum".equals(keyStrokeName)) {
            return VirtualKey.CIRCUMFLEX;
        }
        else if ("Kanji".equals(keyStrokeName)) {
            return VirtualKey.KANJI;
        }
        else if ("Katakana".equals(keyStrokeName)) {
            return VirtualKey.KATAKANA;
        }
        else if ("Hiragana_Katakana".equals(keyStrokeName)) {
            return VirtualKey.HIRAGANA;
        }
        else if ("Muhenkan".equals(keyStrokeName)) {
            // I found this in the KeyEvent description
            return VirtualKey.NONCONVERT;
        }
        else if ("kan".equals(keyStrokeName)) {
            // I found this in the KeyEvent description
            return VirtualKey.NONCONVERT;
        }
        else if ("Henkan_Mode".equals(keyStrokeName)) {
            // I found this in the key event description
            return VirtualKey.CONVERT;
        }
        else if ("voicedsound".equals(keyStrokeName)) {
            return VirtualKey.DEAD_VOICED_SOUND;
        }
        else if ("semivoicedsound".equals(keyStrokeName)) {
            return VirtualKey.DEAD_SEMIVOICED_SOUND;
        }
        else if ("Menu".equals(keyStrokeName)) {
            return VirtualKey.CONTEXT_MENU;
        }
        else {
            LOG.finest("unknown virtual key for key stroke " + keyStrokeName +
                       " specified through " + "keyboard map for locale " + locale);

            return null;
        }

        // for the following virtual keys no key stroke names are provided in the key maps
        /*
         * CANCEL(KeyEvent.VK_CANCEL), CLEAR(KeyEvent.VK_CLEAR), PAUSE(KeyEvent.VK_PAUSE),
         * HELP(KeyEvent.VK_HELP), META(KeyEvent.VK_META),
         * 
         * BACK_QUOTE(KeyEvent.VK_BACK_QUOTE), QUOTE(KeyEvent.VK_QUOTE),
         * 
         * DEAD_IOTA(KeyEvent.VK_DEAD_IOTA),
         * 
         * FINAL(KeyEvent.VK_FINAL), CONVERT(KeyEvent.VK_CONVERT),
         * NONCONVERT(KeyEvent.VK_NONCONVERT), ACCEPT(KeyEvent.VK_ACCEPT), KANA(KeyEvent.VK_KANA),
         * ALPHANUMERIC(KeyEvent.VK_ALPHANUMERIC), FULL_WIDTH(KeyEvent.VK_FULL_WIDTH),
         * HALF_WIDTH(KeyEvent.VK_HALF_WIDTH), ROMAN_CHARACTERS(KeyEvent.VK_ROMAN_CHARACTERS),
         * ALL_CANDIDATES(KeyEvent.VK_ALL_CANDIDATES),
         * PREVIOUS_CANDIDATE(KeyEvent.VK_PREVIOUS_CANDIDATE), CODE_INPUT(KeyEvent.VK_CODE_INPUT),
         * JAPANESE_KATAKANA(KeyEvent.VK_JAPANESE_KATAKANA),
         * JAPANESE_HIRAGANA(KeyEvent.VK_JAPANESE_HIRAGANA),
         * JAPANESE_ROMAN(KeyEvent.VK_JAPANESE_ROMAN), KANA_LOCK(KeyEvent.VK_KANA_LOCK),
         * INPUT_METHOD_ON_OFF(KeyEvent.VK_INPUT_METHOD_ON_OFF),
         * 
         * CUT(KeyEvent.VK_CUT), COPY(KeyEvent.VK_COPY), PASTE(KeyEvent.VK_PASTE),
         * UNDO(KeyEvent.VK_UNDO), AGAIN(KeyEvent.VK_AGAIN), FIND(KeyEvent.VK_FIND),
         * PROPS(KeyEvent.VK_PROPS), STOP(KeyEvent.VK_STOP), COMPOSE(KeyEvent.VK_COMPOSE),
         */
    }

    /**
     * TODO: comment
     * 
     * @param keyStrokeName
     * @param shift
     * @return
     */
    private char determineCharacter(String keyStrokeName, boolean getUpper) {
        if ("Shift_R".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Shift_L".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Alt_R".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Mode_switch".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("ISO_Level3_Shift".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Alt_L".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Control_R".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Control_L".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Menu".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("1".equals(keyStrokeName)) {
            return '1';
        }
        else if ("2".equals(keyStrokeName)) {
            return '2';
        }
        else if ("3".equals(keyStrokeName)) {
            return '3';
        }
        else if ("4".equals(keyStrokeName)) {
            return '4';
        }
        else if ("5".equals(keyStrokeName)) {
            return '5';
        }
        else if ("6".equals(keyStrokeName)) {
            return '6';
        }
        else if ("7".equals(keyStrokeName)) {
            return '7';
        }
        else if ("8".equals(keyStrokeName)) {
            return '8';
        }
        else if ("9".equals(keyStrokeName)) {
            return '9';
        }
        else if ("0".equals(keyStrokeName)) {
            return '0';
        }
        else if ("BackSpace".equals(keyStrokeName)) {
            return '\b';
        }
        else if ("Tab".equals(keyStrokeName)) {
            return '\t';
        }
        else if ("ISO_Left_Tab".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("q".equals(keyStrokeName)) {
            return getUpper ? 'Q' : 'q';
        }
        else if ("w".equals(keyStrokeName)) {
            return getUpper ? 'W' : 'w';
        }
        else if ("e".equals(keyStrokeName)) {
            return getUpper ? 'E' : 'e';
        }
        else if ("r".equals(keyStrokeName)) {
            return getUpper ? 'R' : 'r';
        }
        else if ("t".equals(keyStrokeName)) {
            return getUpper ? 'T' : 't';
        }
        else if ("y".equals(keyStrokeName)) {
            return getUpper ? 'Y' : 'y';
        }
        else if ("u".equals(keyStrokeName)) {
            return getUpper ? 'U' : 'u';
        }
        else if ("i".equals(keyStrokeName)) {
            return getUpper ? 'I' : 'i';
        }
        else if ("o".equals(keyStrokeName)) {
            return getUpper ? 'O' : 'o';
        }
        else if ("p".equals(keyStrokeName)) {
            return getUpper ? 'P' : 'p';
        }
        else if ("a".equals(keyStrokeName)) {
            return getUpper ? 'A' : 'a';
        }
        else if ("s".equals(keyStrokeName)) {
            return getUpper ? 'S' : 's';
        }
        else if ("d".equals(keyStrokeName)) {
            return getUpper ? 'D' : 'd';
        }
        else if ("f".equals(keyStrokeName)) {
            return getUpper ? 'F' : 'f';
        }
        else if ("g".equals(keyStrokeName)) {
            return getUpper ? 'G' : 'g';
        }
        else if ("h".equals(keyStrokeName)) {
            return getUpper ? 'H' : 'h';
        }
        else if ("j".equals(keyStrokeName)) {
            return getUpper ? 'J' : 'j';
        }
        else if ("k".equals(keyStrokeName)) {
            return getUpper ? 'K' : 'k';
        }
        else if ("l".equals(keyStrokeName)) {
            return getUpper ? 'L' : 'l';
        }
        else if ("Return".equals(keyStrokeName)) {
            return '\n';
        }
        else if ("z".equals(keyStrokeName)) {
            return getUpper ? 'Z' : 'z';
        }
        else if ("x".equals(keyStrokeName)) {
            return getUpper ? 'X' : 'x';
        }
        else if ("c".equals(keyStrokeName)) {
            return getUpper ? 'C' : 'c';
        }
        else if ("v".equals(keyStrokeName)) {
            return getUpper ? 'V' : 'v';
        }
        else if ("b".equals(keyStrokeName)) {
            return getUpper ? 'B' : 'b';
        }
        else if ("n".equals(keyStrokeName)) {
            return getUpper ? 'N' : 'n';
        }
        else if ("m".equals(keyStrokeName)) {
            return getUpper ? 'M' : 'm';
        }
        else if ("space".equals(keyStrokeName)) {
            return ' ';
        }
        else if ("less".equals(keyStrokeName)) {
            return '<';
        }
        else if ("greater".equals(keyStrokeName)) {
            return '>';
        }
        else if ("bar".equals(keyStrokeName)) {
            return '|';
        }
        else if ("brokenbar".equals(keyStrokeName)) {
            return '¦';
        }
        else if ("Escape".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F1".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F2".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F3".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F4".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F5".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F6".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F7".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F8".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F9".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F10".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F11".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("SunF36".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F12".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("SunF37".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Print".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Sys_Req".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Execute".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F22".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Scroll_Lock".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F23".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Insert".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Delete".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Home".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("End".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Page_Up".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Page_Down".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Left".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Up".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Down".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Right".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Num_Lock".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_Divide".equals(keyStrokeName)) {
            return '/';
        }
        else if ("KP_Multiply".equals(keyStrokeName)) {
            return '*';
        }
        else if ("KP_Subtract".equals(keyStrokeName)) {
            return '-';
        }
        else if ("KP_Add".equals(keyStrokeName)) {
            return '+';
        }
        else if ("KP_Enter".equals(keyStrokeName)) {
            return '\n';
        }
        else if ("KP_Decimal".equals(keyStrokeName)) {
            return ',';
        }
        else if ("KP_Separator".equals(keyStrokeName)) {
            return ',';
        }
        else if ("KP_Delete".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_0".equals(keyStrokeName)) {
            return '0';
        }
        else if ("KP_Insert".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_1".equals(keyStrokeName)) {
            return '1';
        }
        else if ("KP_End".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_2".equals(keyStrokeName)) {
            return '2';
        }
        else if ("KP_Down".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_3".equals(keyStrokeName)) {
            return '3';
        }
        else if ("KP_Next".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_4".equals(keyStrokeName)) {
            return '4';
        }
        else if ("KP_Left".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_5".equals(keyStrokeName)) {
            return '5';
        }
        else if ("KP_Begin".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_6".equals(keyStrokeName)) {
            return '6';
        }
        else if ("KP_Right".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_7".equals(keyStrokeName)) {
            return '7';
        }
        else if ("KP_Home".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_8".equals(keyStrokeName)) {
            return '8';
        }
        else if ("KP_Up".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("KP_9".equals(keyStrokeName)) {
            return '9';
        }
        else if ("KP_Prior".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Caps_Lock".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Multi_key".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("exclam".equals(keyStrokeName)) {
            return '!';
        }
        else if ("onesuperior".equals(keyStrokeName)) {
            return '¹';
        }
        else if ("exclamdown".equals(keyStrokeName)) {
            return '¡';
        }
        else if ("quotedbl".equals(keyStrokeName)) {
            return '"';
        }
        else if ("twosuperior".equals(keyStrokeName)) {
            return '²';
        }
        else if ("oneeighth".equals(keyStrokeName)) {
            return '⅛';
        }
        else if ("section".equals(keyStrokeName)) {
            return '§';
        }
        else if ("threesuperior".equals(keyStrokeName)) {
            return '³';
        }
        else if ("sterling".equals(keyStrokeName)) {
            return '£';
        }
        else if ("dollar".equals(keyStrokeName)) {
            return '$';
        }
        else if ("onequarter".equals(keyStrokeName)) {
            return '¼';
        }
        else if ("currency".equals(keyStrokeName)) {
            return '¤';
        }
        else if ("percent".equals(keyStrokeName)) {
            return '%';
        }
        else if ("onehalf".equals(keyStrokeName)) {
            return '½';
        }
        else if ("threeeighths".equals(keyStrokeName)) {
            return '⅜';
        }
        else if ("ampersand".equals(keyStrokeName)) {
            return '&';
        }
        else if ("threequarters".equals(keyStrokeName)) {
            return '¾';
        }
        else if ("fiveeighths".equals(keyStrokeName)) {
            return '⅝';
        }
        else if ("slash".equals(keyStrokeName)) {
            return '/';
        }
        else if ("braceleft".equals(keyStrokeName)) {
            return '{';
        }
        else if ("seveneighths".equals(keyStrokeName)) {
            return '⅞';
        }
        else if ("parenleft".equals(keyStrokeName)) {
            return '(';
        }
        else if ("bracketleft".equals(keyStrokeName)) {
            return '[';
        }
        else if ("trademark".equals(keyStrokeName)) {
            return '™';
        }
        else if ("parenright".equals(keyStrokeName)) {
            return ')';
        }
        else if ("bracketright".equals(keyStrokeName)) {
            return ']';
        }
        else if ("plusminus".equals(keyStrokeName)) {
            return '±';
        }
        else if ("equal".equals(keyStrokeName)) {
            return '=';
        }
        else if ("braceright".equals(keyStrokeName)) {
            return '}';
        }
        else if ("ssharp".equals(keyStrokeName)) {
            return 'ß';
        }
        else if ("question".equals(keyStrokeName)) {
            return '?';
        }
        else if ("backslash".equals(keyStrokeName)) {
            return '\\';
        }
        else if ("questiondown".equals(keyStrokeName)) {
            return '¿';
        }
        else if ("acute".equals(keyStrokeName)) {
            return '´';
        }
        else if ("dead_acute".equals(keyStrokeName)) {
            return 0x0301;
        }
        else if ("grave".equals(keyStrokeName)) {
            return '`';
        }
        else if ("dead_grave".equals(keyStrokeName)) {
            return 0x0300;
        }
        else if ("dead_cedilla".equals(keyStrokeName)) {
            return 0x0327;
        }
        else if ("dead_ogonek".equals(keyStrokeName)) {
            return 0x0328;
        }
        else if ("at".equals(keyStrokeName)) {
            return '@';
        }
        else if ("Greek_OMEGA".equals(keyStrokeName)) {
            return 'Ω';
        }
        else if ("EuroSign".equals(keyStrokeName)) {
            return '€';
        }
        else if ("paragraph".equals(keyStrokeName)) {
            return 0x2029;
        }
        else if ("registered".equals(keyStrokeName)) {
            return '®';
        }
        else if ("tslash".equals(keyStrokeName)) {
            return 'ŧ';
        }
        else if ("Tslash".equals(keyStrokeName)) {
            return 'Ŧ';
        }
        else if ("z".equals(keyStrokeName)) {
            return getUpper ? 'Z' : 'z';
        }
        else if ("leftarrow".equals(keyStrokeName)) {
            return '←';
        }
        else if ("yen".equals(keyStrokeName)) {
            return '¥';
        }
        else if ("downarrow".equals(keyStrokeName)) {
            return '↓';
        }
        else if ("uparrow".equals(keyStrokeName)) {
            return '↑';
        }
        else if ("rightarrow".equals(keyStrokeName)) {
            return '→';
        }
        else if ("idotless".equals(keyStrokeName)) {
            return 'ı';
        }
        else if ("oslash".equals(keyStrokeName)) {
            return 'ø';
        }
        else if ("Ooblique".equals(keyStrokeName)) {
            return 'Ø';
        }
        else if ("thorn".equals(keyStrokeName)) {
            return 'þ';
        }
        else if ("THORN".equals(keyStrokeName)) {
            return 'Þ';
        }
        else if ("udiaeresis".equals(keyStrokeName)) {
            return getUpper ? 'Ü' : 'ü';
        }
        else if ("Udiaeresis".equals(keyStrokeName)) {
            return getUpper ? 'Ü' : 'ü';
        }
        else if ("dead_diaeresis".equals(keyStrokeName)) {
            return 0x0308;
        }
        else if ("dead_abovering".equals(keyStrokeName)) {
            return 0x030A;
        }
        else if ("plus".equals(keyStrokeName)) {
            return '+';
        }
        else if ("asterisk".equals(keyStrokeName)) {
            return '*';
        }
        else if ("asciitilde".equals(keyStrokeName)) {
            return '~';
        }
        else if ("dead_tilde".equals(keyStrokeName)) {
            return 0x0303;
        }
        else if ("dead_macron".equals(keyStrokeName)) {
            return 0x0304;
        }
        else if ("ae".equals(keyStrokeName)) {
            return 'æ';
        }
        else if ("AE".equals(keyStrokeName)) {
            return 'Æ';
        }
        else if ("eth".equals(keyStrokeName)) {
            return 'ð';
        }
        else if ("ETH".equals(keyStrokeName)) {
            return 'Ð';
        }
        else if ("dstroke".equals(keyStrokeName)) {
            return getUpper ? 'Đ' : 'đ';
        }
        else if ("ordfeminine".equals(keyStrokeName)) {
            return 'ª';
        }
        else if ("eng".equals(keyStrokeName)) {
            return 'ŋ';
        }
        else if ("ENG".equals(keyStrokeName)) {
            return 'Ŋ';
        }
        else if ("hstroke".equals(keyStrokeName)) {
            return 'ħ';
        }
        else if ("Hstroke".equals(keyStrokeName)) {
            return 'Ħ';
        }
        else if ("kra".equals(keyStrokeName)) {
            return 'ĸ';
        }
        else if ("odiaeresis".equals(keyStrokeName)) {
            return 'ö';
        }
        else if ("Odiaeresis".equals(keyStrokeName)) {
            return 'Ö';
        }
        else if ("dead_doubleacute".equals(keyStrokeName)) {
            return 0x030B;
        }
        else if ("adiaeresis".equals(keyStrokeName)) {
            return 'ä';
        }
        else if ("Adiaeresis".equals(keyStrokeName)) {
            return 'Ä';
        }
        else if ("dead_caron".equals(keyStrokeName)) {
            return 0x030C;
        }
        else if ("asciicircum".equals(keyStrokeName)) {
            return '^';
        }
        else if ("dead_circumflex".equals(keyStrokeName)) {
            return 0x0302;
        }
        else if ("degree".equals(keyStrokeName)) {
            return '°';
        }
        else if ("notsign".equals(keyStrokeName)) {
            return '¬';
        }
        else if ("numbersign".equals(keyStrokeName)) {
            return '#';
        }
        else if ("apostrophe".equals(keyStrokeName)) {
            return '\'';
        }
        else if ("dead_breve".equals(keyStrokeName)) {
            return 0x0306;
        }
        else if ("y".equals(keyStrokeName)) {
            return getUpper ? 'Y' : 'y';
        }
        else if ("guillemotleft".equals(keyStrokeName)) {
            return '»';
        }
        else if ("guillemotright".equals(keyStrokeName)) {
            return '«';
        }
        else if ("cent".equals(keyStrokeName)) {
            return '¢';
        }
        else if ("copyright".equals(keyStrokeName)) {
            return '©';
        }
        else if ("leftdoublequotemark".equals(keyStrokeName)) {
            return '„';
        }
        else if ("rightdoublequotemark".equals(keyStrokeName)) {
            return '“';
        }
        else if ("mu".equals(keyStrokeName)) {
            return 'µ';
        }
        else if ("masculine".equals(keyStrokeName)) {
            return 'º';
        }
        else if ("comma".equals(keyStrokeName)) {
            return ',';
        }
        else if ("semicolon".equals(keyStrokeName)) {
            return ';';
        }
        else if ("horizconnector".equals(keyStrokeName)) {
            return '·';
        }
        else if ("multiply".equals(keyStrokeName)) {
            return '×';
        }
        else if ("period".equals(keyStrokeName)) {
            return '.';
        }
        else if ("colon".equals(keyStrokeName)) {
            return ':';
        }
        else if ("periodcentered".equals(keyStrokeName)) {
            return '…';
        }
        else if ("division".equals(keyStrokeName)) {
            return '÷';
        }
        else if ("minus".equals(keyStrokeName)) {
            return '-';
        }
        else if ("underscore".equals(keyStrokeName)) {
            return '_';
        }
        else if ("dead_belowdot".equals(keyStrokeName)) {
            return 0x0323;
        }
        else if ("dead_abovedot".equals(keyStrokeName)) {
            return 0x0307;
        }
        else if ("eacute".equals(keyStrokeName)) {
            return getUpper ? 'É' : 'é';
        }
        else if ("Eacute".equals(keyStrokeName)) {
            return getUpper ? 'É' : 'é';
        }
        else if ("egrave".equals(keyStrokeName)) {
            return getUpper ? 'È' : 'è';
        }
        else if ("Egrave".equals(keyStrokeName)) {
            return getUpper ? 'È' : 'è';
        }
        else if ("ccedilla".equals(keyStrokeName)) {
            return getUpper ? 'Ç' : 'ç';
        }
        else if ("Ccedilla".equals(keyStrokeName)) {
            return getUpper ? 'Ç' : 'ç';
        }
        else if ("agrave".equals(keyStrokeName)) {
            return getUpper ? 'À' : 'à';
        }
        else if ("Agrave".equals(keyStrokeName)) {
            return getUpper ? 'À' : 'à';
        }
        else if ("lstroke".equals(keyStrokeName)) {
            return getUpper ? 'Ł' : 'ł';
        }
        else if ("Lstroke".equals(keyStrokeName)) {
            return getUpper ? 'Ł' : 'ł';
        }
        else if ("ugrave".equals(keyStrokeName)) {
            return getUpper ? 'Ù' : 'ù';
        }
        else if ("Ugrave".equals(keyStrokeName)) {
            return getUpper ? 'Ù' : 'ù';
        }
        else if ("igrave".equals(keyStrokeName)) {
            return getUpper ? 'Ì' : 'ì';
        }
        else if ("Igrave".equals(keyStrokeName)) {
            return getUpper ? 'Ì' : 'ì';
        }
        else if ("ograve".equals(keyStrokeName)) {
            return getUpper ? 'Ò' : 'ò';
        }
        else if ("ograve".equals(keyStrokeName)) {
            return getUpper ? 'Ò' : 'ò';
        }
        else if ("keyboard_type".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("keyboard_subtype".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("keyboard_functionkeys".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("kana_NU".equals(keyStrokeName)) {
            return 'ヌ';
        }
        else if ("kana_FU".equals(keyStrokeName)) {
            return 'フ';
        }
        else if ("kana_A".equals(keyStrokeName)) {
            return 'ア';
        }
        else if ("kana_a".equals(keyStrokeName)) {
            return 'ァ';
        }
        else if ("kana_U".equals(keyStrokeName)) {
            return 'ウ';
        }
        else if ("kana_u".equals(keyStrokeName)) {
            return 'ゥ';
        }
        else if ("kana_E".equals(keyStrokeName)) {
            return 'エ';
        }
        else if ("kana_e".equals(keyStrokeName)) {
            return 'ェ';
        }
        else if ("kana_O".equals(keyStrokeName)) {
            return 'オ';
        }
        else if ("kana_o".equals(keyStrokeName)) {
            return 'ォ';
        }
        else if ("kana_YA".equals(keyStrokeName)) {
            return 'ヤ';
        }
        else if ("kana_ya".equals(keyStrokeName)) {
            return 'ャ';
        }
        else if ("kana_YU".equals(keyStrokeName)) {
            return 'ユ';
        }
        else if ("kana_yu".equals(keyStrokeName)) {
            return 'ュ';
        }
        else if ("kana_YO".equals(keyStrokeName)) {
            return 'ヨ';
        }
        else if ("kana_yo".equals(keyStrokeName)) {
            return 'ョ';
        }
        else if ("kana_WA".equals(keyStrokeName)) {
            return 'ワ';
        }
        else if ("kana_WO".equals(keyStrokeName)) {
            return 'ヲ';
        }
        else if ("kana_HO".equals(keyStrokeName)) {
            return 'ホ';
        }
        else if ("kana_HE".equals(keyStrokeName)) {
            return 'ヘ';
        }
        else if ("kana_TA".equals(keyStrokeName)) {
            return 'タ';
        }
        else if ("kana_TE".equals(keyStrokeName)) {
            return 'テ';
        }
        else if ("kana_I".equals(keyStrokeName)) {
            return 'イ';
        }
        else if ("kana_i".equals(keyStrokeName)) {
            return 'ィ';
        }
        else if ("kana_SU".equals(keyStrokeName)) {
            return 'ス';
        }
        else if ("kana_KA".equals(keyStrokeName)) {
            return 'カ';
        }
        else if ("kana_N".equals(keyStrokeName)) {
            return 'ン';
        }
        else if ("kana_NA".equals(keyStrokeName)) {
            return 'ナ';
        }
        else if ("kana_NI".equals(keyStrokeName)) {
            return 'ニ';
        }
        else if ("kana_RA".equals(keyStrokeName)) {
            return 'ラ';
        }
        else if ("kana_SE".equals(keyStrokeName)) {
            return 'セ';
        }
        else if ("voicedsound".equals(keyStrokeName)) {
            return 0x3099;
        }
        else if ("semivoicedsound".equals(keyStrokeName)) {
            return 0x309A;
        }
        else if ("kana_openingbracket".equals(keyStrokeName)) {
            return 0x04A2;
        }
        else if ("kana_closingbracket".equals(keyStrokeName)) {
            return 0x04A3;
        }
        else if ("kana_CHI".equals(keyStrokeName)) {
            return 'チ';
        }
        else if ("kana_TO".equals(keyStrokeName)) {
            return 'ト';
        }
        else if ("kana_SHI".equals(keyStrokeName)) {
            return 'シ';
        }
        else if ("kana_HA".equals(keyStrokeName)) {
            return 'ハ';
        }
        else if ("kana_KI".equals(keyStrokeName)) {
            return 'キ';
        }
        else if ("kana_KU".equals(keyStrokeName)) {
            return 'ク';
        }
        else if ("kana_MA".equals(keyStrokeName)) {
            return 'マ';
        }
        else if ("kana_NO".equals(keyStrokeName)) {
            return 'ノ';
        }
        else if ("kana_RI".equals(keyStrokeName)) {
            return 'リ';
        }
        else if ("kana_RE".equals(keyStrokeName)) {
            return 'レ';
        }
        else if ("kana_KE".equals(keyStrokeName)) {
            return 'ケ';
        }
        else if ("Zenkaku_Hankaku".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Kanji".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("kana_MU".equals(keyStrokeName)) {
            return 'ム';
        }
        else if ("kana_TSU".equals(keyStrokeName)) {
            return 'ツ';
        }
        else if ("kana_tsu".equals(keyStrokeName)) {
            return 'ッ';
        }
        else if ("kana_SA".equals(keyStrokeName)) {
            return 'サ';
        }
        else if ("kana_SO".equals(keyStrokeName)) {
            return 'ソ';
        }
        else if ("kana_HI".equals(keyStrokeName)) {
            return 'ヒ';
        }
        else if ("kana_KO".equals(keyStrokeName)) {
            return 'コ';
        }
        else if ("kana_MI".equals(keyStrokeName)) {
            return 'ミ';
        }
        else if ("kana_MO".equals(keyStrokeName)) {
            return 'モ';
        }
        else if ("kana_NE".equals(keyStrokeName)) {
            return 'ネ';
        }
        else if ("kana_comma".equals(keyStrokeName)) {
            return '､';
        }
        else if ("kana_RU".equals(keyStrokeName)) {
            return 'ル';
        }
        else if ("kana_fullstop".equals(keyStrokeName)) {
            return '｡';
        }
        else if ("kana_ME".equals(keyStrokeName)) {
            return 'メ';
        }
        else if ("kana_conjunctive".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Henkan_Mode".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Hiragana_Katakana".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Katakana".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Romaji".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Muhenkan".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Eisu_toggle".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Eisu_toggle".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("F13".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Hangul".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else if ("Hangul_Hanja".equals(keyStrokeName)) {
            return Character.UNASSIGNED;
        }
        else {
            LOG.severe("unknown key stroke name " + keyStrokeName +
                       " specified through keyboard map " + "for locale " + locale);

            // if (shift)
            // {
            // System.err.println("    else if (\"" + keyStrokeName + "\".equals(keyStrokeName))");
            // System.err.println("    {");
            // System.err.println("      return shift ? '" +
            // Character.toUpperCase(keyStrokeName.charAt(0)) +
            // "' : '" + Character.toLowerCase(keyStrokeName.charAt(0)) + "';");
            // System.err.println("    }");
            // }
            // else
            // {
            // System.err.println("    else if (\"" + keyStrokeName + "\".equals(keyStrokeName))");
            // System.err.println("    {");
            // System.err.println("      return '" + keyStrokeName + "';");
            // System.err.println("    }");
            // }
            //
            // return 0x0;
            throw new IllegalArgumentException("no keyboard map available for locale " + locale);
        }
    }

    /**
     * this is a former implementation
     * 
     * @param keyId
     * @return
     */
    /*
     * private VirtualKey[] mapKeyIdToVirtualKeys(int keyId, String keyStrokeName) {
     * 
     * Set<String> names = null;
     * 
     * for (int i = 0; i < mKeyIds.size(); i++) { if (((Integer) mKeyIds.get(i)[0]) == keyId) {
     * names = (Set<String>) mKeyIds.get(i)[1]; break; } }
     * 
     * if (names == null) { names = new HashSet<String>(); boolean added = false;
     * 
     * for (int i = 0; i < mKeyIds.size(); i++) { if (((Integer) mKeyIds.get(i)[0]) > keyId) {
     * mKeyIds.add(i, new Object[] { keyId, names }); added = true; break; } }
     * 
     * if (!added) { mKeyIds.add(new Object[] { keyId, names }); } }
     * 
     * names.add(keyStrokeName);
     * 
     * 
     * switch(keyId) { case 0x36: case 0x2a: return new VirtualKey[] { VirtualKey.SHIFT }; case
     * 0xb8: return new VirtualKey[] { VirtualKey.ALT_GRAPH }; case 0x38: return new VirtualKey[] {
     * VirtualKey.ALT }; case 0x9d: case 0x1d: return new VirtualKey[] { VirtualKey.CONTROL }; case
     * 0xdd: return new VirtualKey[] { VirtualKey.WINDOWS }; case 0x2: return new VirtualKey[] {
     * VirtualKey.DIGIT_1 }; case 0x3: return new VirtualKey[] { VirtualKey.DIGIT_2 }; case 0x4:
     * return new VirtualKey[] { VirtualKey.DIGIT_3 }; case 0x5: return new VirtualKey[] {
     * VirtualKey.DIGIT_4 }; case 0x6: return new VirtualKey[] { VirtualKey.DIGIT_5 }; case 0x7:
     * return new VirtualKey[] { VirtualKey.DIGIT_6 }; case 0x8: return new VirtualKey[] {
     * VirtualKey.DIGIT_7 }; case 0x9: return new VirtualKey[] { VirtualKey.DIGIT_8 }; case 0xa:
     * return new VirtualKey[] { VirtualKey.DIGIT_9 }; case 0xb: return new VirtualKey[] {
     * VirtualKey.DIGIT_0 }; case 0xe: return new VirtualKey[] { VirtualKey.BACK_SPACE }; case 0xf:
     * return new VirtualKey[] { VirtualKey.TAB }; case 0x10: return new VirtualKey[] {
     * VirtualKey.LETTER_Q }; case 0x11: return new VirtualKey[] { VirtualKey.LETTER_W }; case 0x12:
     * return new VirtualKey[] { VirtualKey.LETTER_E }; case 0x13: return new VirtualKey[] {
     * VirtualKey.LETTER_R }; case 0x14: return new VirtualKey[] { VirtualKey.LETTER_T }; case 0x15:
     * return new VirtualKey[] { VirtualKey.LETTER_Y }; case 0x16: return new VirtualKey[] {
     * VirtualKey.LETTER_U }; case 0x17: return new VirtualKey[] { VirtualKey.LETTER_I }; case 0x18:
     * return new VirtualKey[] { VirtualKey.LETTER_O }; case 0x19: return new VirtualKey[] {
     * VirtualKey.LETTER_P }; case 0x1e: return new VirtualKey[] { VirtualKey.LETTER_A }; case 0x1f:
     * return new VirtualKey[] { VirtualKey.LETTER_S }; case 0x20: return new VirtualKey[] {
     * VirtualKey.LETTER_D }; case 0x21: return new VirtualKey[] { VirtualKey.LETTER_F }; case 0x22:
     * return new VirtualKey[] { VirtualKey.LETTER_G }; case 0x23: return new VirtualKey[] {
     * VirtualKey.LETTER_H }; case 0x24: return new VirtualKey[] { VirtualKey.LETTER_J }; case 0x25:
     * return new VirtualKey[] { VirtualKey.LETTER_K }; case 0x26: return new VirtualKey[] {
     * VirtualKey.LETTER_L }; case 0x1c: return new VirtualKey[] { VirtualKey.ENTER }; case 0x2c:
     * return new VirtualKey[] { VirtualKey.LETTER_Z }; case 0x2d: return new VirtualKey[] {
     * VirtualKey.LETTER_X }; case 0x2e: return new VirtualKey[] { VirtualKey.LETTER_C }; case 0x2f:
     * return new VirtualKey[] { VirtualKey.LETTER_V }; case 0x30: return new VirtualKey[] {
     * VirtualKey.LETTER_B }; case 0x31: return new VirtualKey[] { VirtualKey.LETTER_N }; case 0x32:
     * return new VirtualKey[] { VirtualKey.LETTER_M }; case 0x39: return new VirtualKey[] {
     * VirtualKey.SPACE }; case 0x56: return new VirtualKey[] { VirtualKey.LESS }; case 0x1: return
     * new VirtualKey[] { VirtualKey.ESCAPE }; case 0x3b: return new VirtualKey[] { VirtualKey.F1 };
     * case 0x3c: return new VirtualKey[] { VirtualKey.F2 }; case 0x3d: return new VirtualKey[] {
     * VirtualKey.F3 }; case 0x3e: return new VirtualKey[] { VirtualKey.F4 }; case 0x3f: return new
     * VirtualKey[] { VirtualKey.F5 }; case 0x40: return new VirtualKey[] { VirtualKey.F6 }; case
     * 0x41: return new VirtualKey[] { VirtualKey.F7 }; case 0x42: return new VirtualKey[] {
     * VirtualKey.F8 }; case 0x43: return new VirtualKey[] { VirtualKey.F9 }; case 0x44: return new
     * VirtualKey[] { VirtualKey.F10 }; case 0x57: return new VirtualKey[] { VirtualKey.F11 }; case
     * 0x58: return new VirtualKey[] { VirtualKey.F12 }; case 0xb7: return new VirtualKey[] {
     * VirtualKey.PRINTSCREEN }; case 0x46: return new VirtualKey[] { VirtualKey.SCROLL_LOCK }; case
     * 0xd2: return new VirtualKey[] { VirtualKey.INSERT }; case 0xd3: return new VirtualKey[] {
     * VirtualKey.DELETE }; case 0xc7: return new VirtualKey[] { VirtualKey.HOME }; case 0xcf:
     * return new VirtualKey[] { VirtualKey.END }; case 0xc9: return new VirtualKey[] {
     * VirtualKey.PAGE_UP }; case 0xd1: return new VirtualKey[] { VirtualKey.PAGE_DOWN }; case 0xcb:
     * return new VirtualKey[] { VirtualKey.LEFT }; case 0xc8: return new VirtualKey[] {
     * VirtualKey.UP }; case 0xd0: return new VirtualKey[] { VirtualKey.DOWN }; case 0xcd: return
     * new VirtualKey[] { VirtualKey.RIGHT }; case 0x45: return new VirtualKey[] {
     * VirtualKey.NUM_LOCK }; case 0xb5: return new VirtualKey[] { VirtualKey.DIVIDE }; case 0x37:
     * return new VirtualKey[] { VirtualKey.MULTIPLY }; case 0x4a: return new VirtualKey[] {
     * VirtualKey.SUBTRACT }; case 0x4e: return new VirtualKey[] { VirtualKey.ADD }; case 0x9c:
     * return new VirtualKey[] { VirtualKey.ENTER }; case 0x53: return new VirtualKey[] {
     * VirtualKey.DECIMAL, VirtualKey.DELETE }; case 0x52: return new VirtualKey[] {
     * VirtualKey.NUMPAD_0, VirtualKey.INSERT }; case 0x4f: return new VirtualKey[] {
     * VirtualKey.NUMPAD_1, VirtualKey.END }; case 0x50: return new VirtualKey[] {
     * VirtualKey.NUMPAD_2, VirtualKey.KP_DOWN }; case 0x51: return new VirtualKey[] {
     * VirtualKey.NUMPAD_3, VirtualKey.PAGE_UP }; case 0x4b: return new VirtualKey[] {
     * VirtualKey.NUMPAD_4, VirtualKey.KP_LEFT }; case 0x4c: return new VirtualKey[] {
     * VirtualKey.NUMPAD_5, VirtualKey.BEGIN }; case 0x4d: return new VirtualKey[] {
     * VirtualKey.NUMPAD_6, VirtualKey.KP_RIGHT }; case 0x47: return new VirtualKey[] {
     * VirtualKey.NUMPAD_7, VirtualKey.HOME }; case 0x48: return new VirtualKey[] {
     * VirtualKey.NUMPAD_8, VirtualKey.KP_UP }; case 0x49: return new VirtualKey[] {
     * VirtualKey.NUMPAD_9, VirtualKey.PAGE_DOWN }; case 0x0: return new VirtualKey[] {
     * VirtualKey.CAPS_LOCK }; case 0xc: return new VirtualKey[] { VirtualKey.MINUS,
     * VirtualKey.UNDERSCORE }; case 0xd: return new VirtualKey[] { VirtualKey.EQUALS,
     * VirtualKey.PLUS }; case 0x1a: return new VirtualKey[] { VirtualKey.OPEN_BRACKET,
     * VirtualKey.BRACELEFT }; case 0x1b: return new VirtualKey[] { VirtualKey.CLOSE_BRACKET,
     * VirtualKey.BRACERIGHT }; case 0x27: return new VirtualKey[] { VirtualKey.SEMICOLON,
     * VirtualKey.COLON }; /* case 0x28: return new VirtualKey[] { VirtualKey.APOSTROPHE,
     * VirtualKey.QUOTEDBL }; case 0x29: return new VirtualKey[] { VirtualKey.DEAD_GRAVE,
     * VirtualKey.DEAD_TILDE }; case 0x2b: return new VirtualKey[] { VirtualKey.BACK_SLASH,
     * VirtualKey.BAR }; case 0x33: return new VirtualKey[] { VirtualKey.COMMA, VirtualKey.LESS };
     * case 0x34: return new VirtualKey[] { VirtualKey.PERIOD, VirtualKey.GREATER }; case 0x35:
     * return new VirtualKey[] { VirtualKey.SLASH, VirtualKey.QUESTIONMARK }; case 0x73: return new
     * VirtualKey[] { VirtualKey.BACK_SLASH, VirtualKey.DEGREE, VirtualKey.QUESTIONMARK,
     * VirtualKey.UNDERSCORE }; case 0x7d: return new VirtualKey[] { VirtualKey.BAR }; case 0x79:
     * return new VirtualKey[] { VirtualKey.HENKAN_MODE }; case 0x70: return new VirtualKey[] {
     * VirtualKey.KATAKANA }; case 0x7b: return new VirtualKey[] { VirtualKey.MUHENKAN }; case 0x3a:
     * return new VirtualKey[] { VirtualKey.EISU_TOGGLE, VirtualKey.CAPS_LOCK }; case 0xdc: return
     * new VirtualKey[] { VirtualKey.F13 }; case 0xf2: return new VirtualKey[] { VirtualKey.HANGUL
     * }; case 0xf1: return new VirtualKey[] { VirtualKey.HANGUL_HANJA }; case 0x54: return new
     * VirtualKey[] { VirtualKey.EXECUTE }; default: LOG.severe("unknown key id 0x" +
     * Integer.toHexString(keyId) + " specified for key stroke " + keyStrokeName +
     * " through keyboard map for locale " + mLocale); throw new
     * IllegalArgumentException("no keyboard map available for locale " + mLocale); } }
     */

}
