InputMethodSubtype.java revision 9c4cc03a354922df08efacfc486ef0e80144d3ea
1ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok/*
2ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * Copyright (C) 2010 The Android Open Source Project
3ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok *
4ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * Licensed under the Apache License, Version 2.0 (the "License");
5ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * you may not use this file except in compliance with the License.
6ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * You may obtain a copy of the License at
7ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok *
8ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok *      http://www.apache.org/licenses/LICENSE-2.0
9ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok *
10ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * Unless required by applicable law or agreed to in writing, software
11ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * distributed under the License is distributed on an "AS IS" BASIS,
12ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * See the License for the specific language governing permissions and
14ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok * limitations under the License.
15ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok */
16ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
17ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokpackage android.view.inputmethod;
18ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
197265d9bd6d80c5bedaa6de2b80f6619a301a07c8satokimport android.content.Context;
20ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.os.Parcel;
21ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.os.Parcelable;
229c4cc03a354922df08efacfc486ef0e80144d3easatokimport android.util.Slog;
23ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
247265d9bd6d80c5bedaa6de2b80f6619a301a07c8satokimport java.util.ArrayList;
25ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport java.util.Arrays;
269c4cc03a354922df08efacfc486ef0e80144d3easatokimport java.util.HashMap;
277265d9bd6d80c5bedaa6de2b80f6619a301a07c8satokimport java.util.HashSet;
287265d9bd6d80c5bedaa6de2b80f6619a301a07c8satokimport java.util.List;
29ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
30ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok/**
31e31e9424554d5f032f578830556913b4ba78f7f9Ken Wakasa * This class is used to specify meta information of a subtype contained in an input method.
32e31e9424554d5f032f578830556913b4ba78f7f9Ken Wakasa * Subtype can describe locale (e.g. en_US, fr_FR...) and mode (e.g. voice, keyboard...), and is
33e31e9424554d5f032f578830556913b4ba78f7f9Ken Wakasa * used for IME switch and settings. The input method subtype allows the system to bring up the
34e31e9424554d5f032f578830556913b4ba78f7f9Ken Wakasa * specified subtype of the designated input method directly.
35ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok */
36ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokpublic final class InputMethodSubtype implements Parcelable {
379c4cc03a354922df08efacfc486ef0e80144d3easatok    private static final String TAG = InputMethodSubtype.class.getSimpleName();
389c4cc03a354922df08efacfc486ef0e80144d3easatok    private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
399c4cc03a354922df08efacfc486ef0e80144d3easatok    private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
409c4cc03a354922df08efacfc486ef0e80144d3easatok
41ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final int mSubtypeNameResId;
42ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final int mSubtypeIconResId;
43ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final String mSubtypeLocale;
449ef0283bdcd9534cc09ae37eb2b78771b95247b5satok    private final String mSubtypeMode;
45ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final String mSubtypeExtraValue;
46ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private final int mSubtypeHashCode;
479c4cc03a354922df08efacfc486ef0e80144d3easatok    private HashMap<String, String> mExtraValueHashMapCache;
48ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
49ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
50ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * Constructor
51ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param nameId The name of the subtype
52ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param iconId The icon of the subtype
53ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param locale The locale supported by the subtype
54ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param modeId The mode supported by the subtype
55ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @param extraValue The extra value of the subtype
56ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
579ef0283bdcd9534cc09ae37eb2b78771b95247b5satok    InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue) {
58ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeNameResId = nameId;
59ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeIconResId = iconId;
60af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeLocale = locale != null ? locale : "";
61af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeMode = mode != null ? mode : "";
62af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeExtraValue = extraValue != null ? extraValue : "";
63ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
649ef0283bdcd9534cc09ae37eb2b78771b95247b5satok                mSubtypeMode, mSubtypeExtraValue);
65ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
66ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
67ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    InputMethodSubtype(Parcel source) {
68af4bf400abab86baee44dacbcdf13444d06ee46esatok        String s;
69ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeNameResId = source.readInt();
70ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeIconResId = source.readInt();
71af4bf400abab86baee44dacbcdf13444d06ee46esatok        s = source.readString();
72af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeLocale = s != null ? s : "";
73af4bf400abab86baee44dacbcdf13444d06ee46esatok        s = source.readString();
74af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeMode = s != null ? s : "";
75af4bf400abab86baee44dacbcdf13444d06ee46esatok        s = source.readString();
76af4bf400abab86baee44dacbcdf13444d06ee46esatok        mSubtypeExtraValue = s != null ? s : "";
77ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
789ef0283bdcd9534cc09ae37eb2b78771b95247b5satok                mSubtypeMode, mSubtypeExtraValue);
79ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
80ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
81ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
82ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the name of the subtype
83ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
84ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int getNameResId() {
85ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeNameResId;
86ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
87ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
88ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
89ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the icon of the subtype
90ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
91ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int getIconResId() {
92ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeIconResId;
93ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
94ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
95ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
96ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the locale of the subtype
97ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
98ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public String getLocale() {
99ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeLocale;
100ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
101ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
102ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
103ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the mode of the subtype
104ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
1059ef0283bdcd9534cc09ae37eb2b78771b95247b5satok    public String getMode() {
1069ef0283bdcd9534cc09ae37eb2b78771b95247b5satok        return mSubtypeMode;
107ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
108ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
109ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
110ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return the extra value of the subtype
111ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
112ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public String getExtraValue() {
113ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeExtraValue;
114ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
115ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
1169c4cc03a354922df08efacfc486ef0e80144d3easatok    private HashMap<String, String> getExtraValueHashMap() {
1179c4cc03a354922df08efacfc486ef0e80144d3easatok        if (mExtraValueHashMapCache == null) {
1189c4cc03a354922df08efacfc486ef0e80144d3easatok            mExtraValueHashMapCache = new HashMap<String, String>();
1199c4cc03a354922df08efacfc486ef0e80144d3easatok            final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR);
1209c4cc03a354922df08efacfc486ef0e80144d3easatok            final int N = pairs.length;
1219c4cc03a354922df08efacfc486ef0e80144d3easatok            for (int i = 0; i < N; ++i) {
1229c4cc03a354922df08efacfc486ef0e80144d3easatok                final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR);
1239c4cc03a354922df08efacfc486ef0e80144d3easatok                if (pair.length == 1) {
1249c4cc03a354922df08efacfc486ef0e80144d3easatok                    mExtraValueHashMapCache.put(pair[0], null);
1259c4cc03a354922df08efacfc486ef0e80144d3easatok                } else if (pair.length > 1) {
1269c4cc03a354922df08efacfc486ef0e80144d3easatok                    if (pair.length > 2) {
1279c4cc03a354922df08efacfc486ef0e80144d3easatok                        Slog.w(TAG, "ExtraValue has two or more '='s");
1289c4cc03a354922df08efacfc486ef0e80144d3easatok                    }
1299c4cc03a354922df08efacfc486ef0e80144d3easatok                    mExtraValueHashMapCache.put(pair[0], pair[1]);
1309c4cc03a354922df08efacfc486ef0e80144d3easatok                }
1319c4cc03a354922df08efacfc486ef0e80144d3easatok            }
1329c4cc03a354922df08efacfc486ef0e80144d3easatok        }
1339c4cc03a354922df08efacfc486ef0e80144d3easatok        return mExtraValueHashMapCache;
1349c4cc03a354922df08efacfc486ef0e80144d3easatok    }
1359c4cc03a354922df08efacfc486ef0e80144d3easatok
1369c4cc03a354922df08efacfc486ef0e80144d3easatok    /**
1379c4cc03a354922df08efacfc486ef0e80144d3easatok     * The string of ExtraValue in subtype should be defined as follows:
1389c4cc03a354922df08efacfc486ef0e80144d3easatok     * example: key0,key1=value1,key2,key3,key4=value4
1399c4cc03a354922df08efacfc486ef0e80144d3easatok     * @param key the key of extra value
1409c4cc03a354922df08efacfc486ef0e80144d3easatok     * @return the subtype contains specified the extra value
1419c4cc03a354922df08efacfc486ef0e80144d3easatok     */
1429c4cc03a354922df08efacfc486ef0e80144d3easatok    public boolean containsExtraValueKey(String key) {
1439c4cc03a354922df08efacfc486ef0e80144d3easatok        return getExtraValueHashMap().containsKey(key);
1449c4cc03a354922df08efacfc486ef0e80144d3easatok    }
1459c4cc03a354922df08efacfc486ef0e80144d3easatok
1469c4cc03a354922df08efacfc486ef0e80144d3easatok    /**
1479c4cc03a354922df08efacfc486ef0e80144d3easatok     * The string of ExtraValue in subtype should be defined as follows:
1489c4cc03a354922df08efacfc486ef0e80144d3easatok     * example: key0,key1=value1,key2,key3,key4=value4
1499c4cc03a354922df08efacfc486ef0e80144d3easatok     * @param key the key of extra value
1509c4cc03a354922df08efacfc486ef0e80144d3easatok     * @return the value of the specified key
1519c4cc03a354922df08efacfc486ef0e80144d3easatok     */
1529c4cc03a354922df08efacfc486ef0e80144d3easatok    public String getExtraValueOf(String key) {
1539c4cc03a354922df08efacfc486ef0e80144d3easatok        return getExtraValueHashMap().get(key);
1549c4cc03a354922df08efacfc486ef0e80144d3easatok    }
1559c4cc03a354922df08efacfc486ef0e80144d3easatok
156ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
157ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int hashCode() {
158ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return mSubtypeHashCode;
159ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
160ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
161ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    @Override
162ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public boolean equals(Object o) {
163ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        if (o instanceof InputMethodSubtype) {
164ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            InputMethodSubtype subtype = (InputMethodSubtype) o;
165af4bf400abab86baee44dacbcdf13444d06ee46esatok            return (subtype.hashCode() == hashCode())
166af4bf400abab86baee44dacbcdf13444d06ee46esatok                && (subtype.getNameResId() == getNameResId())
167af4bf400abab86baee44dacbcdf13444d06ee46esatok                && (subtype.getMode().equals(getMode()))
168ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                && (subtype.getIconResId() == getIconResId())
169ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                && (subtype.getLocale().equals(getLocale()))
170ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                && (subtype.getExtraValue().equals(getExtraValue()));
171ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
172ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return false;
173ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
174ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
175ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public int describeContents() {
176ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        return 0;
177ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
178ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
179ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public void writeToParcel(Parcel dest, int parcelableFlags) {
180ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeInt(mSubtypeNameResId);
181ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeInt(mSubtypeIconResId);
182ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeString(mSubtypeLocale);
1839ef0283bdcd9534cc09ae37eb2b78771b95247b5satok        dest.writeString(mSubtypeMode);
184ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        dest.writeString(mSubtypeExtraValue);
185ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
186ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
187ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public static final Parcelable.Creator<InputMethodSubtype> CREATOR
188ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            = new Parcelable.Creator<InputMethodSubtype>() {
189ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        public InputMethodSubtype createFromParcel(Parcel source) {
190ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            return new InputMethodSubtype(source);
191ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
192ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
193ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        public InputMethodSubtype[] newArray(int size) {
194ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            return new InputMethodSubtype[size];
195ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
196ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    };
197ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
198ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private static int hashCodeInternal(int nameResId, int iconResId, String locale,
1999ef0283bdcd9534cc09ae37eb2b78771b95247b5satok            String mode, String extraValue) {
2009ef0283bdcd9534cc09ae37eb2b78771b95247b5satok        return Arrays.hashCode(new Object[] {nameResId, iconResId, locale, mode, extraValue});
201ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2027265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok
2037265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok    /**
2047265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * Sort the list of InputMethodSubtype
2057265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param context Context will be used for getting localized strings from IME
2067265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param flags Flags for the sort order
2077265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param imi InputMethodInfo of which subtypes are subject to be sorted
2087265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @param subtypeList List of InputMethodSubtype which will be sorted
2097265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @return Sorted list of subtypes
2107265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     * @hide
2117265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok     */
2127265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok    public static List<InputMethodSubtype> sort(Context context, int flags, InputMethodInfo imi,
2137265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            List<InputMethodSubtype> subtypeList) {
2147265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        if (imi == null) return subtypeList;
2157265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        final HashSet<InputMethodSubtype> inputSubtypesSet = new HashSet<InputMethodSubtype>(
2167265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok                subtypeList);
2177265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        final ArrayList<InputMethodSubtype> sortedList = new ArrayList<InputMethodSubtype>();
2187265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        int N = imi.getSubtypeCount();
2197265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        for (int i = 0; i < N; ++i) {
2207265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            InputMethodSubtype subtype = imi.getSubtypeAt(i);
2217265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            if (inputSubtypesSet.contains(subtype)) {
2227265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok                sortedList.add(subtype);
2237265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok                inputSubtypesSet.remove(subtype);
2247265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            }
2257265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        }
2267265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        // If subtypes in inputSubtypesSet remain, that means these subtypes are not
2277265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        // contained in imi, so the remaining subtypes will be appended.
2287265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        for (InputMethodSubtype subtype: inputSubtypesSet) {
2297265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok            sortedList.add(subtype);
2307265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        }
2317265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok        return sortedList;
2327265d9bd6d80c5bedaa6de2b80f6619a301a07c8satok    }
233af4bf400abab86baee44dacbcdf13444d06ee46esatok}
234