• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.util.Collection;
7 import java.util.Comparator;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Map.Entry;
11 import java.util.Set;
12 
13 import com.google.common.collect.ArrayListMultimap;
14 import com.google.common.collect.HashBasedTable;
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.collect.ImmutableSet;
17 import com.google.common.collect.ImmutableSortedSet;
18 import com.google.common.collect.ListMultimap;
19 import com.google.common.collect.Maps;
20 import com.google.common.collect.Table;
21 import com.ibm.icu.text.Collator;
22 
23 /** Builder class to assist in constructing a keyboard object. */
24 public final class KeyboardBuilder {
25     private final ImmutableSet.Builder<KeyboardId> keyboardIds;
26     private final ImmutableList.Builder<String> names;
27     private final Map<String, String> transformSequenceToOutput;
28     private final Table<ModifierKeyCombination, IsoLayoutPosition, CharacterMap> modifierAndPositionToCharacter;
29 
KeyboardBuilder()30     public KeyboardBuilder() {
31         keyboardIds = ImmutableSet.builder();
32         names = ImmutableList.builder();
33         transformSequenceToOutput = Maps.newHashMap();
34         modifierAndPositionToCharacter = HashBasedTable.create();
35     }
36 
addKeyboardIds(Iterable<KeyboardId> keyboardIds)37     public KeyboardBuilder addKeyboardIds(Iterable<KeyboardId> keyboardIds) {
38         this.keyboardIds.addAll(keyboardIds);
39         return this;
40     }
41 
addName(String name)42     public KeyboardBuilder addName(String name) {
43         names.add(name);
44         return this;
45     }
46 
addTransform(String sequence, String output)47     public KeyboardBuilder addTransform(String sequence, String output) {
48         if (transformSequenceToOutput.containsKey(sequence)
49             && !transformSequenceToOutput.get(sequence).equals(output)) {
50             String errorMessage = String.format("Duplicate entry for [%s:%s]", sequence, output);
51             throw new IllegalArgumentException(errorMessage);
52         }
53         transformSequenceToOutput.put(sequence, output);
54         return this;
55     }
56 
addCharacterMap( ModifierKeyCombination combination, CharacterMap characterMap)57     public KeyboardBuilder addCharacterMap(
58         ModifierKeyCombination combination, CharacterMap characterMap) {
59         checkNotNull(combination);
60         if (modifierAndPositionToCharacter.contains(combination, characterMap.position())) {
61             CharacterMap existing = modifierAndPositionToCharacter.get(combination, characterMap.position());
62             checkArgument(
63                 existing.equals(characterMap),
64                 "Duplicate entry for [%s:%s:%s]",
65                 combination,
66                 characterMap,
67                 existing);
68         }
69         modifierAndPositionToCharacter.put(combination, characterMap.position(), characterMap);
70         return this;
71     }
72 
addCharacterMap( Collection<ModifierKeyCombination> combinations, CharacterMap characterMap)73     public KeyboardBuilder addCharacterMap(
74         Collection<ModifierKeyCombination> combinations, CharacterMap characterMap) {
75         for (ModifierKeyCombination combination : combinations) {
76             addCharacterMap(combination, characterMap);
77         }
78         return this;
79     }
80 
build()81     public ImmutableList<Keyboard> build() {
82         ImmutableSet<KeyboardId> keyboardIds = this.keyboardIds.build();
83         checkArgument(keyboardIds.size() > 0, "KeyboardIds must contain at least one element");
84         // See if key map consolidation is possible.
85         ListMultimap<ImmutableSet<CharacterMap>, ModifierKeyCombination> charactersToCombinations = ArrayListMultimap.create();
86         for (ModifierKeyCombination combination : modifierAndPositionToCharacter.rowKeySet()) {
87             Collection<CharacterMap> characterMaps = modifierAndPositionToCharacter.row(combination).values();
88             charactersToCombinations.put(ImmutableSet.copyOf(characterMaps), combination);
89         }
90         // Build the key maps.
91         KeyboardId id = keyboardIds.iterator().next();
92         ImmutableSortedSet.Builder<KeyMap> keyMaps = ImmutableSortedSet.naturalOrder();
93         for (ImmutableSet<CharacterMap> characterMaps : charactersToCombinations.keySet()) {
94             List<ModifierKeyCombination> combinations = charactersToCombinations.get(characterMaps);
95             ModifierKeyCombinationSet combinationSet = ModifierKeyCombinationSet.of(ImmutableSet.copyOf(combinations));
96             keyMaps.add(KeyMap.of(combinationSet, characterMaps));
97         }
98         // Add the transforms.
99         ImmutableSortedSet.Builder<Transform> transforms = ImmutableSortedSet.orderedBy(collatorComparator(Collator.getInstance(id.locale())));
100         for (Entry<String, String> transformEntry : transformSequenceToOutput.entrySet()) {
101             transforms.add(Transform.of(transformEntry.getKey(), transformEntry.getValue()));
102         }
103         ImmutableList.Builder<Keyboard> keyboards = ImmutableList.builder();
104         for (KeyboardId keyboardId : keyboardIds) {
105             keyboards.add(Keyboard.of(keyboardId, names.build(), keyMaps.build(), transforms.build()));
106         }
107         return keyboards.build();
108     }
109 
transformSequences()110     public Set<String> transformSequences() {
111         return transformSequenceToOutput.keySet();
112     }
113 
collatorComparator(final Collator collator)114     private static Comparator<Transform> collatorComparator(final Collator collator) {
115         return new Comparator<Transform>() {
116             @Override
117             public int compare(Transform o1, Transform o2) {
118                 return collator.compare(o1.sequence(), o2.sequence());
119             }
120         };
121     }
122 }
123