1cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka/*
2cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka * Copyright (C) 2014 The Android Open Source Project
3cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka *
4cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License");
5cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka * you may not use this file except in compliance with the License.
6cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka * You may obtain a copy of the License at
7cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka *
8cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka *      http://www.apache.org/licenses/LICENSE-2.0
9cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka *
10cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software
11cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS,
12cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka * See the License for the specific language governing permissions and
14cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka * limitations under the License.
15cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka */
16cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
17cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokapackage com.android.inputmethod.keyboard;
18cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
19cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaimport android.content.res.Resources;
20cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaimport android.text.InputType;
21cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaimport android.view.inputmethod.EditorInfo;
22cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaimport android.view.inputmethod.InputMethodSubtype;
23cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
24cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
25cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaimport com.android.inputmethod.latin.Constants;
26cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaimport com.android.inputmethod.latin.utils.RunInLocale;
27cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaimport com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
28cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
29cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaimport java.util.Locale;
30cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
31cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaokaabstract class KeyboardLayoutSetActionLabelBase extends KeyboardLayoutSetTestsBase {
32cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    public void testActionUnspecified() {
33cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
34cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final String tag = "unspecifiled "
35cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                    + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
36cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_UNSPECIFIED,
37cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                    KeyboardIconsSet.NAME_ENTER_KEY);
38cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        }
39cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    }
40cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
41cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    public void testActionNone() {
42cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
43cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final String tag = "none " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
44cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_NONE,
45cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                    KeyboardIconsSet.NAME_ENTER_KEY);
46cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        }
47cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    }
48cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
49cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    public void testActionSearch() {
50cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
51cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final String tag = "search " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
52cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_SEARCH,
53cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                    KeyboardIconsSet.NAME_SEARCH_KEY);
54cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        }
55cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    }
56cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
57cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    public abstract void testActionGo();
58cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    public abstract void testActionSend();
59cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    public abstract void testActionNext();
60cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    public abstract void testActionDone();
61cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    public abstract void testActionPrevious();
62cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
63cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    public void testActionCustom() {
64cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
65cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final String tag = "custom " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
66cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final CharSequence customLabel = "customLabel";
67cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final EditorInfo editorInfo = new EditorInfo();
68cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            editorInfo.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED;
69cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            editorInfo.actionLabel = customLabel;
70cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            doTestActionKeyLabel(tag, subtype, editorInfo, customLabel);
71cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        }
72cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    }
73cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
74cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    private static void doTestActionKey(final String tag, final KeyboardLayoutSet layoutSet,
75cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final int elementId, final CharSequence label, final int iconId) {
76cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final Keyboard keyboard = layoutSet.getKeyboard(elementId);
77cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final Key enterKey = keyboard.getKey(Constants.CODE_ENTER);
78cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        assertNotNull(tag + " enter key on " + keyboard.mId, enterKey);
79cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        assertEquals(tag + " enter label " + enterKey, label, enterKey.getLabel());
80cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        assertEquals(tag + " enter icon " + enterKey, iconId, enterKey.getIconId());
81cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    }
82cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
83cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    protected void doTestActionKeyLabelResId(final String tag, final InputMethodSubtype subtype,
84cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final int actionId, final int labelResId) {
85cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final Locale labelLocale = subtype.getLocale().equals(SubtypeLocaleUtils.NO_LANGUAGE)
86cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                ? null : SubtypeLocaleUtils.getSubtypeLocale(subtype);
87cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKeyLabelResIdInLocale(tag, subtype, actionId, labelLocale, labelResId);
88cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    }
89cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
90cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    protected void doTestActionKeyLabelResIdInLocale(final String tag,
91cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final InputMethodSubtype subtype, final int actionId, final Locale labelLocale,
92cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final int labelResId) {
93cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final EditorInfo editorInfo = new EditorInfo();
94cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        editorInfo.imeOptions = actionId;
95cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final RunInLocale<String> job = new RunInLocale<String>() {
96cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            @Override
97cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            protected String job(final Resources res) {
98cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                return res.getString(labelResId);
99cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            }
100cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        };
101cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final String label = job.runInLocale(getContext().getResources(), labelLocale);
102cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKeyLabel(tag, subtype, editorInfo, label);
103cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    }
104cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
105cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    protected void doTestActionKeyLabel(final String tag, final InputMethodSubtype subtype,
106cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final EditorInfo editorInfo, final CharSequence label) {
107cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        // Test text layouts.
108cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
109cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
110cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET,
111cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                label, KeyboardIconsSet.ICON_UNDEFINED);
112cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS,
113cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                label, KeyboardIconsSet.ICON_UNDEFINED);
114cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED,
115cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                label, KeyboardIconsSet.ICON_UNDEFINED);
116cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        // Test phone number layouts.
117cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE,
118cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                label, KeyboardIconsSet.ICON_UNDEFINED);
119cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS,
120cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                label, KeyboardIconsSet.ICON_UNDEFINED);
121cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        // Test normal number layout.
122cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER,
123cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                label, KeyboardIconsSet.ICON_UNDEFINED);
124cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        // Test number password layouts.
125cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        editorInfo.inputType =
126cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
127cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
128cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER,
129cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                label, KeyboardIconsSet.ICON_UNDEFINED);
130cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    }
131cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka
132cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    protected void doTestActionKeyIcon(final String tag, final InputMethodSubtype subtype,
133cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka            final int actionId, final String iconName) {
134cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final int iconId = KeyboardIconsSet.getIconId(iconName);
135cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final EditorInfo editorInfo = new EditorInfo();
136cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        editorInfo.imeOptions = actionId;
137cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        // Test text layouts.
138cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
139cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
140cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET, null /* label */, iconId);
141cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS, null /* label */, iconId);
142cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(
143cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED, null /* label */, iconId);
144cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        // Test phone number layouts.
145cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE, null /* label */, iconId);
146cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(
147cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS, null /* label */, iconId);
148cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        // Test normal number layout.
149cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
150cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        // Test number password layout.
151cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        editorInfo.inputType =
152cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
153cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
154cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
155cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka    }
156cd6f5ae5661f67c8598df41a8f2ce6cb46a8ee62Tadashi G. Takaoka}
157