1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.inputmethod.latin;
18
19import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
20import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
21import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
22import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
23
24import android.os.Build;
25import android.text.TextUtils;
26import android.view.inputmethod.InputMethodSubtype;
27
28import java.util.ArrayList;
29
30public final class AdditionalSubtype {
31    private static final InputMethodSubtype[] EMPTY_SUBTYPE_ARRAY = new InputMethodSubtype[0];
32
33    private AdditionalSubtype() {
34        // This utility class is not publicly instantiable.
35    }
36
37    public static boolean isAdditionalSubtype(final InputMethodSubtype subtype) {
38        return subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE);
39    }
40
41    private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":";
42    private static final String PREF_SUBTYPE_SEPARATOR = ";";
43
44    public static InputMethodSubtype createAdditionalSubtype(final String localeString,
45            final String keyboardLayoutSetName, final String extraValue) {
46        final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
47        final String layoutDisplayNameExtraValue;
48        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
49                && SubtypeLocale.isExceptionalLocale(localeString)) {
50            final String layoutDisplayName = SubtypeLocale.getKeyboardLayoutSetDisplayName(
51                    keyboardLayoutSetName);
52            layoutDisplayNameExtraValue = StringUtils.appendToCsvIfNotExists(
53                    UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME + "=" + layoutDisplayName, extraValue);
54        } else {
55            layoutDisplayNameExtraValue = extraValue;
56        }
57        final String additionalSubtypeExtraValue = StringUtils.appendToCsvIfNotExists(
58                IS_ADDITIONAL_SUBTYPE, layoutDisplayNameExtraValue);
59        final int nameId = SubtypeLocale.getSubtypeNameId(localeString, keyboardLayoutSetName);
60        return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard,
61                localeString, KEYBOARD_MODE,
62                layoutExtraValue + "," + additionalSubtypeExtraValue, false, false);
63    }
64
65    public static String getPrefSubtype(final InputMethodSubtype subtype) {
66        final String localeString = subtype.getLocale();
67        final String keyboardLayoutSetName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
68        final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
69        final String extraValue = StringUtils.removeFromCsvIfExists(layoutExtraValue,
70                StringUtils.removeFromCsvIfExists(IS_ADDITIONAL_SUBTYPE, subtype.getExtraValue()));
71        final String basePrefSubtype = localeString + LOCALE_AND_LAYOUT_SEPARATOR
72                + keyboardLayoutSetName;
73        return extraValue.isEmpty() ? basePrefSubtype
74                : basePrefSubtype + LOCALE_AND_LAYOUT_SEPARATOR + extraValue;
75    }
76
77    public static InputMethodSubtype createAdditionalSubtype(final String prefSubtype) {
78        final String elems[] = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR);
79        if (elems.length < 2 || elems.length > 3) {
80            throw new RuntimeException("Unknown additional subtype specified: " + prefSubtype);
81        }
82        final String localeString = elems[0];
83        final String keyboardLayoutSetName = elems[1];
84        final String extraValue = (elems.length == 3) ? elems[2] : null;
85        return createAdditionalSubtype(localeString, keyboardLayoutSetName, extraValue);
86    }
87
88    public static InputMethodSubtype[] createAdditionalSubtypesArray(final String prefSubtypes) {
89        if (TextUtils.isEmpty(prefSubtypes)) {
90            return EMPTY_SUBTYPE_ARRAY;
91        }
92        final String[] prefSubtypeArray = prefSubtypes.split(PREF_SUBTYPE_SEPARATOR);
93        final ArrayList<InputMethodSubtype> subtypesList =
94                CollectionUtils.newArrayList(prefSubtypeArray.length);
95        for (final String prefSubtype : prefSubtypeArray) {
96            final InputMethodSubtype subtype = createAdditionalSubtype(prefSubtype);
97            if (subtype.getNameResId() == SubtypeLocale.UNKNOWN_KEYBOARD_LAYOUT) {
98                // Skip unknown keyboard layout subtype. This may happen when predefined keyboard
99                // layout has been removed.
100                continue;
101            }
102            subtypesList.add(subtype);
103        }
104        return subtypesList.toArray(new InputMethodSubtype[subtypesList.size()]);
105    }
106
107    public static String createPrefSubtypes(final InputMethodSubtype[] subtypes) {
108        if (subtypes == null || subtypes.length == 0) {
109            return "";
110        }
111        final StringBuilder sb = new StringBuilder();
112        for (final InputMethodSubtype subtype : subtypes) {
113            if (sb.length() > 0) {
114                sb.append(PREF_SUBTYPE_SEPARATOR);
115            }
116            sb.append(getPrefSubtype(subtype));
117        }
118        return sb.toString();
119    }
120
121    public static String createPrefSubtypes(final String[] prefSubtypes) {
122        if (prefSubtypes == null || prefSubtypes.length == 0) {
123            return "";
124        }
125        final StringBuilder sb = new StringBuilder();
126        for (final String prefSubtype : prefSubtypes) {
127            if (sb.length() > 0) {
128                sb.append(PREF_SUBTYPE_SEPARATOR);
129            }
130            sb.append(prefSubtype);
131        }
132        return sb.toString();
133    }
134}
135