class CompareModeIcu4J extends CompareMode {

    private final Comparator<String> collator;

    protected CompareModeIcu4J(String name, int strength, boolean binaryUnsigned) {
        super(name, strength, binaryUnsigned);
        collator = getIcu4jCollator(name, strength);
    }

    @Override
    public int compareString(String a, String b, boolean ignoreCase) {
        if (ignoreCase) {
            a = a.toUpperCase();
            b = b.toUpperCase();
        }
        return collator.compare(a, b);
    }

    @Override
    public boolean equalsChars(String a, int ai, String b, int bi, boolean ignoreCase) {<FILL_FUNCTION_BODY>}

    @SuppressWarnings("unchecked")
    private static Comparator<String> getIcu4jCollator(String name, int strength) {
        try {
            Comparator<String> result = null;
            Class<?> collatorClass = Utils.loadUserClass("com.ibm.icu.text.Collator");
            Method getInstanceMethod = collatorClass.getMethod("getInstance", Locale.class);
            if (name.length() == 2) {
                Locale locale = new Locale(StringUtils.toLowerEnglish(name), "");
                if (compareLocaleNames(locale, name)) {
                    result = (Comparator<String>) getInstanceMethod.invoke(null, locale);
                }
            } else if (name.length() == 5) {
                // LL_CC (language_country)
                int idx = name.indexOf('_');
                if (idx >= 0) {
                    String language = StringUtils.toLowerEnglish(name.substring(0, idx));
                    String country = name.substring(idx + 1);
                    Locale locale = new Locale(language, country);
                    if (compareLocaleNames(locale, name)) {
                        result = (Comparator<String>) getInstanceMethod.invoke(null, locale);
                    }
                }
            }
            if (result == null) {
                for (Locale locale : (Locale[]) collatorClass.getMethod("getAvailableLocales")
                        .invoke(null)) {
                    if (compareLocaleNames(locale, name)) {
                        result = (Comparator<String>) getInstanceMethod.invoke(null, locale);
                        break;
                    }
                }
            }
            if (result == null) {
                throw DbException.getInvalidValueException("collator", name);
            }
            collatorClass.getMethod("setStrength", int.class).invoke(result, strength);
            return result;
        } catch (Exception e) {
            throw DbException.convert(e);
        }
    }
}

        return compareString(a.substring(ai, ai + 1), b.substring(bi, bi + 1), ignoreCase) == 0;
    
<methods>public int compareString(java.lang.String, java.lang.String, boolean) ,public boolean equalsChars(java.lang.String, int, java.lang.String, int, boolean) ,public static java.text.Collator getCollator(java.lang.String) ,public static synchronized com.lealone.db.value.CompareMode getInstance(java.lang.String, int, boolean) ,public static java.lang.String getName(java.util.Locale) ,public java.lang.String getName() ,public int getStrength() ,public boolean isBinaryUnsigned() <variables>private static final non-sealed boolean CAN_USE_ICU4J,public static final java.lang.String DEFAULT,public static final java.lang.String ICU4J,public static final java.lang.String OFF,public static final java.lang.String SIGNED,public static final java.lang.String UNSIGNED,private final non-sealed boolean binaryUnsigned,private static com.lealone.db.value.CompareMode lastUsed,private final non-sealed java.lang.String name,private final non-sealed int strength