1 package org.unicode.cldr.draft.keyboard;
2 
3 import static com.google.common.base.Preconditions.checkArgument;
4 import static com.google.common.base.Preconditions.checkNotNull;
5 
6 import java.io.IOException;
7 import java.util.List;
8 
9 import com.google.common.base.Charsets;
10 import com.google.common.base.Splitter;
11 import com.google.common.collect.ImmutableSortedMap;
12 import com.google.common.collect.Iterables;
13 import com.google.common.io.Resources;
14 
15 /**
16  * An class which maps a hardware key code (the value that is sent from keyboard driver to the
17  * application) to its actual iso layout position.
18  */
19 public final class KeycodeMap {
20     private final ImmutableSortedMap<Integer, IsoLayoutPosition> keycodeToIsoLayout;
21 
KeycodeMap(ImmutableSortedMap<Integer, IsoLayoutPosition> keycodeToIsoLayout)22     private KeycodeMap(ImmutableSortedMap<Integer, IsoLayoutPosition> keycodeToIsoLayout) {
23         this.keycodeToIsoLayout = checkNotNull(keycodeToIsoLayout);
24     }
25 
26     private static final Splitter LINE_SPLITTER = Splitter.on("\n").omitEmptyStrings();
27     private static final Splitter COMMA_SPLITTER = Splitter.on(",");
28 
29     /**
30      * Creates the mapping from csv contents. The first line must contain the column headers
31      * "keycode,iso".
32      */
fromCsv(String csv)33     public static KeycodeMap fromCsv(String csv) {
34         checkArgument(!csv.isEmpty());
35         List<String> lines = LINE_SPLITTER.splitToList(csv);
36         checkArgument(lines.get(0).equals("keycode,iso"), "Missing csv headers");
37         ImmutableSortedMap.Builder<Integer, IsoLayoutPosition> builder = ImmutableSortedMap.naturalOrder();
38         for (String line : Iterables.skip(lines, 1)) {
39             // No fancy CSV parsing required since there are no strings.
40             List<String> components = COMMA_SPLITTER.splitToList(line);
41             builder.put(Integer.valueOf(components.get(0)), IsoLayoutPosition.valueOf(components.get(1)));
42         }
43         return new KeycodeMap(builder.build());
44     }
45 
46     /** Retrieves the csv file relative to the class given. */
fromResource(Class<?> clazz, String fileName)47     public static KeycodeMap fromResource(Class<?> clazz, String fileName) {
48         try {
49             String csv = Resources.toString(Resources.getResource(clazz, fileName),
50                 Charsets.UTF_8);
51             return fromCsv(csv);
52         } catch (IOException e) {
53             throw new IllegalArgumentException(e);
54         }
55     }
56 
hasIsoLayoutPosition(Integer keycode)57     public boolean hasIsoLayoutPosition(Integer keycode) {
58         return keycodeToIsoLayout.containsKey(keycode);
59     }
60 
getIsoLayoutPosition(Integer keycode)61     public IsoLayoutPosition getIsoLayoutPosition(Integer keycode) {
62         return checkNotNull(keycodeToIsoLayout.get(keycode), "No keycode for %s [%s]", keycode,
63             keycodeToIsoLayout);
64     }
65 
keycodeToIsoLayout()66     public ImmutableSortedMap<Integer, IsoLayoutPosition> keycodeToIsoLayout() {
67         return keycodeToIsoLayout;
68     }
69 }
70