package org.unicode.cldr.draft.keyboard; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Collection; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.HashBasedTable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ListMultimap; import com.google.common.collect.Maps; import com.google.common.collect.Table; import com.ibm.icu.text.Collator; /** Builder class to assist in constructing a keyboard object. */ public final class KeyboardBuilder { private final ImmutableSet.Builder keyboardIds; private final ImmutableList.Builder names; private final Map transformSequenceToOutput; private final Table modifierAndPositionToCharacter; public KeyboardBuilder() { keyboardIds = ImmutableSet.builder(); names = ImmutableList.builder(); transformSequenceToOutput = Maps.newHashMap(); modifierAndPositionToCharacter = HashBasedTable.create(); } public KeyboardBuilder addKeyboardIds(Iterable keyboardIds) { this.keyboardIds.addAll(keyboardIds); return this; } public KeyboardBuilder addName(String name) { names.add(name); return this; } public KeyboardBuilder addTransform(String sequence, String output) { if (transformSequenceToOutput.containsKey(sequence) && !transformSequenceToOutput.get(sequence).equals(output)) { String errorMessage = String.format("Duplicate entry for [%s:%s]", sequence, output); throw new IllegalArgumentException(errorMessage); } transformSequenceToOutput.put(sequence, output); return this; } public KeyboardBuilder addCharacterMap( ModifierKeyCombination combination, CharacterMap characterMap) { checkNotNull(combination); if (modifierAndPositionToCharacter.contains(combination, characterMap.position())) { CharacterMap existing = modifierAndPositionToCharacter.get(combination, characterMap.position()); checkArgument( existing.equals(characterMap), "Duplicate entry for [%s:%s:%s]", combination, characterMap, existing); } modifierAndPositionToCharacter.put(combination, characterMap.position(), characterMap); return this; } public KeyboardBuilder addCharacterMap( Collection combinations, CharacterMap characterMap) { for (ModifierKeyCombination combination : combinations) { addCharacterMap(combination, characterMap); } return this; } public ImmutableList build() { ImmutableSet keyboardIds = this.keyboardIds.build(); checkArgument(keyboardIds.size() > 0, "KeyboardIds must contain at least one element"); // See if key map consolidation is possible. ListMultimap, ModifierKeyCombination> charactersToCombinations = ArrayListMultimap.create(); for (ModifierKeyCombination combination : modifierAndPositionToCharacter.rowKeySet()) { Collection characterMaps = modifierAndPositionToCharacter.row(combination).values(); charactersToCombinations.put(ImmutableSet.copyOf(characterMaps), combination); } // Build the key maps. KeyboardId id = keyboardIds.iterator().next(); ImmutableSortedSet.Builder keyMaps = ImmutableSortedSet.naturalOrder(); for (ImmutableSet characterMaps : charactersToCombinations.keySet()) { List combinations = charactersToCombinations.get(characterMaps); ModifierKeyCombinationSet combinationSet = ModifierKeyCombinationSet.of(ImmutableSet.copyOf(combinations)); keyMaps.add(KeyMap.of(combinationSet, characterMaps)); } // Add the transforms. ImmutableSortedSet.Builder transforms = ImmutableSortedSet.orderedBy(collatorComparator(Collator.getInstance(id.locale()))); for (Entry transformEntry : transformSequenceToOutput.entrySet()) { transforms.add(Transform.of(transformEntry.getKey(), transformEntry.getValue())); } ImmutableList.Builder keyboards = ImmutableList.builder(); for (KeyboardId keyboardId : keyboardIds) { keyboards.add(Keyboard.of(keyboardId, names.build(), keyMaps.build(), transforms.build())); } return keyboards.build(); } public Set transformSequences() { return transformSequenceToOutput.keySet(); } private static Comparator collatorComparator(final Collator collator) { return new Comparator() { @Override public int compare(Transform o1, Transform o2) { return collator.compare(o1.sequence(), o2.sequence()); } }; } }