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 org.unicode.cldr.draft.keyboard.KeyboardSettings.FallbackSetting; 7 import org.unicode.cldr.draft.keyboard.KeyboardSettings.TransformFailureSetting; 8 import org.unicode.cldr.draft.keyboard.KeyboardSettings.TransformPartialSetting; 9 10 import com.google.common.base.Functions; 11 import com.google.common.base.Joiner; 12 import com.google.common.base.Objects; 13 import com.google.common.collect.FluentIterable; 14 import com.google.common.collect.ImmutableList; 15 import com.ibm.icu.util.ULocale; 16 17 /** 18 * An object that is used to uniquely identify a particular keyboard. This object can be serialized 19 * as a string. The string has the following format: 20 * {@code <locale>-t-k0-<platform>-<attribute0>-<attribute1>-<attributeN>} 21 * 22 * <p> 23 * The locale and platform tags are mandatory, the attributes are not. 24 * 25 * <p> 26 * The following are all valid keyboard locale strings: 27 * <ul> 28 * <li>bn-t-k0-windows.xml</li> 29 * <li>de-BE-t-k0-windows-var.xml</li> 30 * <li>fi-t-k0-osx-extended-var.xml</li> 31 * <li>es-US-t-k0-android-768dpi.xml</li> 32 * </ul> 33 */ 34 public final class KeyboardId { 35 private final ULocale locale; 36 private final Platform platform; 37 private final ImmutableList<String> attributes; 38 KeyboardId(ULocale locale, Platform platform, ImmutableList<String> attributes)39 private KeyboardId(ULocale locale, Platform platform, ImmutableList<String> attributes) { 40 this.locale = checkNotNull(locale); 41 this.platform = checkNotNull(platform); 42 this.attributes = checkNotNull(attributes); 43 } 44 45 /** Creates a keyboard id from the given locale, platform and attributes. */ of(ULocale locale, Platform platform, ImmutableList<String> attributes)46 public static KeyboardId of(ULocale locale, Platform platform, ImmutableList<String> attributes) { 47 return new KeyboardId(locale, platform, attributes); 48 } 49 50 /** 51 * Creates a keyboard id from the given string. See class documentation for information on the 52 * required format of the string. 53 */ fromString(String keyboardLocale)54 public static KeyboardId fromString(String keyboardLocale) { 55 int tExtensionLocation = keyboardLocale.indexOf("-t-k0-"); 56 checkArgument(tExtensionLocation != -1, keyboardLocale); 57 String localeString = keyboardLocale.substring(0, tExtensionLocation); 58 ULocale locale = ULocale.forLanguageTag(localeString); 59 String[] attributeStrings = keyboardLocale.substring(tExtensionLocation + 6).split("-"); 60 checkArgument(attributeStrings.length > 0, keyboardLocale); 61 Platform platform = Platform.fromString(attributeStrings[0]); 62 ImmutableList<String> attributes = attributeStrings.length > 1 63 ? ImmutableList.copyOf(attributeStrings).subList(1, attributeStrings.length) 64 : ImmutableList.<String> of(); 65 return new KeyboardId(locale, platform, attributes); 66 } 67 68 /** Returns the keyboard's locale. */ locale()69 public ULocale locale() { 70 return locale; 71 } 72 73 /** Returns the keyboard's platform. */ platform()74 public Platform platform() { 75 return platform; 76 } 77 78 /** Returns the list of additional attributes associated with the keyboard (if any). */ attributes()79 public ImmutableList<String> attributes() { 80 return attributes; 81 } 82 83 private static final Joiner DASH_JOINER = Joiner.on("-"); 84 85 @Override toString()86 public String toString() { 87 ImmutableList.Builder<String> components = ImmutableList.builder(); 88 // We want to use dashes within the locale as opposed to underscores. 89 components.add(locale.toString().replace("_", "-")); 90 components.add("t-k0"); 91 components.add(platform.toString()); 92 components.addAll(FluentIterable.from(attributes).transform(Functions.toStringFunction())); 93 return DASH_JOINER.join(components.build()); 94 } 95 96 @Override equals(Object o)97 public boolean equals(Object o) { 98 if (o == this) { 99 return true; 100 } 101 if (o instanceof KeyboardId) { 102 KeyboardId other = (KeyboardId) o; 103 return Objects.equal(locale, other.locale) && Objects.equal(platform, other.platform) 104 && Objects.equal(attributes, other.attributes); 105 } 106 return false; 107 } 108 109 @Override hashCode()110 public int hashCode() { 111 return Objects.hashCode(locale, platform, attributes); 112 } 113 114 /** The current set of platforms supported. */ 115 public enum Platform { 116 ANDROID(4.4f, KeyboardSettings.of(FallbackSetting.NONE, TransformFailureSetting.NONE, 117 TransformPartialSetting.NONE)), CHROMEOS(33f, KeyboardSettings.of(FallbackSetting.BASE, TransformFailureSetting.OMIT, 118 TransformPartialSetting.HIDE)), OSX(10.9f, KeyboardSettings.of(FallbackSetting.BASE, TransformFailureSetting.EMIT, 119 TransformPartialSetting.SHOW)), WINDOWS(10f, KeyboardSettings.of(FallbackSetting.OMIT, TransformFailureSetting.EMIT, 120 TransformPartialSetting.HIDE)); 121 122 private final float version; 123 private final KeyboardSettings settings; 124 Platform(float version, KeyboardSettings settings)125 private Platform(float version, KeyboardSettings settings) { 126 this.version = version; 127 this.settings = checkNotNull(settings); 128 checkArgument(version >= 0); 129 } 130 version()131 public double version() { 132 return version; 133 } 134 settings()135 public KeyboardSettings settings() { 136 return settings; 137 } 138 139 @Override toString()140 public String toString() { 141 return name().toLowerCase(); 142 } 143 144 /** 145 * Retrieves the enum value for the given string. Throws an illegal argument exception if the 146 * given string does not correspond to an enum value. 147 */ fromString(String platform)148 private static Platform fromString(String platform) { 149 Platform value = Platform.valueOf(platform.toUpperCase()); 150 checkArgument(platform != null, platform); 151 return value; 152 } 153 } 154 } 155