1c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka/* 2c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * Copyright (C) 2014 The Android Open Source Project 3c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * 4c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 5c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * you may not use this file except in compliance with the License. 6c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * You may obtain a copy of the License at 7c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * 8c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 9c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * 10c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 11c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 12c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * See the License for the specific language governing permissions and 14c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * limitations under the License. 15c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka */ 16c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 17c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokapackage com.android.inputmethod.keyboard.layout.expected; 18c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 19c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokaimport com.android.inputmethod.keyboard.Key; 20c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.MoreKeySpec; 219342484e8d573a40f470b6a593df31c602fa4076Ken Wakasaimport com.android.inputmethod.latin.common.Constants; 224beeb9253a06482299e0c67467531d30436a02fcJean Chalardimport com.android.inputmethod.latin.common.StringUtils; 23c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 24c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokaimport java.util.Locale; 25c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 26c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka/** 27c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * This class represents an expected output of a key. 28c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * 29c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * There are two types of expected output, an integer code point and a string output text. 30c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka */ 31c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokaabstract class ExpectedKeyOutput { 32c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka static ExpectedKeyOutput newInstance(final int code) { 33c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return new Code(code); 34c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 35c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 36c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka static ExpectedKeyOutput newInstance(final String outputText) { 37c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka // If the <code>outputText</code> is one code point string, use {@link CodePoint} object. 38c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka if (StringUtils.codePointCount(outputText) == 1) { 39c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return new Code(outputText.codePointAt(0)); 40c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 41c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return new Text(outputText); 42c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 43c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 44c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka abstract ExpectedKeyOutput toUpperCase(final Locale locale); 45c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka abstract ExpectedKeyOutput preserveCase(); 4651333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka abstract boolean hasSameKeyOutput(final String text); 4751333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka abstract boolean hasSameKeyOutput(final Key key); 4851333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka abstract boolean hasSameKeyOutput(final MoreKeySpec moreKeySpec); 4951333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka abstract boolean hasSameKeyOutput(final ExpectedKeyOutput output); 50c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 51c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka /** 52c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * This class represents an integer code point. 53c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka */ 54c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka private static class Code extends ExpectedKeyOutput { 55c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka // UNICODE code point or a special negative value defined in {@link Constants}. 56c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka private final int mCode; 57c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 58c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka Code(final int code) { mCode = code; } 59c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 60c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 61c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka ExpectedKeyOutput toUpperCase(final Locale locale) { 62c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka if (Constants.isLetterCode(mCode)) { 63c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka final String codeString = StringUtils.newSingleCodePointString(mCode); 64c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka // A letter may have an upper case counterpart that consists of multiple code 65c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka // points, for instance the upper case of "ß" is "SS". 666c47403e27fd703ece844f4b1b24632721da1772Tadashi G. Takaoka return newInstance(StringUtils.toTitleCaseOfKeyLabel(codeString, locale)); 67c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 68c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka // A special negative value has no upper case. 69c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return this; 70c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 71c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 72c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 73c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka ExpectedKeyOutput preserveCase() { 74c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka return new CasePreservedCode(mCode); 75c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka } 76c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka 77c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka @Override 7851333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka boolean hasSameKeyOutput(final String text) { 79c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return StringUtils.codePointCount(text) == 1 && text.codePointAt(0) == mCode; 80c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 81c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 82c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 8351333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka boolean hasSameKeyOutput(final Key key) { 84c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return mCode == key.getCode(); 85c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 86c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 87c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 8851333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka boolean hasSameKeyOutput(final MoreKeySpec moreKeySpec) { 89c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return mCode == moreKeySpec.mCode; 90c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 91c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 92c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 9351333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka boolean hasSameKeyOutput(final ExpectedKeyOutput output) { 94c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return (output instanceof Code) && mCode == ((Code)output).mCode; 95c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 96c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 97c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 98c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka public String toString() { 99c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return Constants.isLetterCode(mCode) ? StringUtils.newSingleCodePointString(mCode) 100c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka : Constants.printableCode(mCode); 101c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 102c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka 103c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka private static class CasePreservedCode extends Code { 104c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka CasePreservedCode(final int code) { super(code); } 105c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka 106c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka @Override 107c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka ExpectedKeyOutput toUpperCase(final Locale locale) { return this; } 108c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka 109c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka @Override 110c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka ExpectedKeyOutput preserveCase() { return this; } 111c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka } 112c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 113c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 114c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka /** 115c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * This class represents a string output text. 116c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka */ 117c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka private static class Text extends ExpectedKeyOutput { 118c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka private final String mText; 119c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 120c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka Text(final String text) { mText = text; } 121c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 122c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 123c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka ExpectedKeyOutput toUpperCase(final Locale locale) { 124c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return newInstance(mText.toUpperCase(locale)); 125c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 126c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 127c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 128c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka ExpectedKeyOutput preserveCase() { 129c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka return new CasePreservedText(mText); 130c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka } 131c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka 132c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka @Override 13351333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka boolean hasSameKeyOutput(final String text) { 134c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return text.equals(text); 135c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 136c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 137c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 13851333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka boolean hasSameKeyOutput(final Key key) { 139c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return key.getCode() == Constants.CODE_OUTPUT_TEXT 140c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka && mText.equals(key.getOutputText()); 141c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 142c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 143c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 14451333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka boolean hasSameKeyOutput(final MoreKeySpec moreKeySpec) { 145c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return moreKeySpec.mCode == Constants.CODE_OUTPUT_TEXT 146c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka && mText.equals(moreKeySpec.mOutputText); 147c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 148c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 149c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 15051333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka boolean hasSameKeyOutput(final ExpectedKeyOutput output) { 151c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return (output instanceof Text) && mText == ((Text)output).mText; 152c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 153c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka 154c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka @Override 155c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka public String toString() { 156c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka return mText; 157c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 158c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka 159c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka private static class CasePreservedText extends Text { 160c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka CasePreservedText(final String text) { super(text); } 161c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka 162c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka @Override 163c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka ExpectedKeyOutput toUpperCase(final Locale locale) { return this; } 164c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka 165c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka @Override 166c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka ExpectedKeyOutput preserveCase() { return this; } 167c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka } 168c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka } 169c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka} 170