package cn.yiiguxing.plugin.translate; import cn.yiiguxing.plugin.translate.model.QueryResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.LinkedHashSet; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 辅助工具类 */ @SuppressWarnings("WeakerAccess") public final class Utils { private static final Pattern PATTERN_EXPLAIN = Pattern.compile("(^(a|adj|prep|pron|n|v|conj|s|sc|o|oc|vi|vt|aux|ad|adv|art|num|int|u|c|pl|abbr)\\.)(.+)"); private static final int GROUP_CLASS = 1; private static final int GROUP_EXPLAIN = 3; private Utils() { } /** * 从翻译结果中获取错误信息 * * @param result 翻译结果 * @return 错误信息 */ public static String getErrorMessage(QueryResult result) { if (result == null) return "Nothing to show"; if (result.getErrorCode() == QueryResult.ERROR_CODE_NONE) return null; String error; switch (result.getErrorCode()) { case QueryResult.ERROR_CODE_RESTRICTED: error = "请求过于频繁,请尝试<a href=\"" + Constants.HTML_DESCRIPTION_SETTINGS + "\">更换API KEY</a>"; break; case QueryResult.ERROR_CODE_INVALID_KEY: error = "无效的API KEY,请<a href=\"" + Constants.HTML_DESCRIPTION_SETTINGS + "\">更换API KEY</a>"; break; case QueryResult.ERROR_CODE_QUERY_TOO_LONG: error = "Query too long"; break; case QueryResult.ERROR_CODE_UNSUPPORTED_LANG: error = "Unsupported lang"; break; case QueryResult.ERROR_CODE_NO_RESULT: default: error = isEmptyOrBlankString(result.getMessage()) ? "Nothing to show" : result.getMessage(); break; } return error; } /** * 测试目标字符串是否是空字符串或者空白字符串 */ public static boolean isEmptyOrBlankString(String str) { return null == str || str.trim().isEmpty(); } /** * 单词拆分 */ public static String splitWord(String input) { if (isEmptyOrBlankString(input)) return input; return input.replaceAll("[_*\\s]+", " ") .replaceAll("([A-Z][a-z]+)|([0-9\\W]+)", " $0 ") .replaceAll("[A-Z]{2,}", " $0") .replaceAll("\\s{2,}", " ") .trim(); } /** * 拆分单词解释。例如:将 "vt. 分离; 使分离" 拆分为 ['vt.', '分离; 使分离'] * * @return 一个长度为2的数组,数组第一个元素为单词词性,如果解释中不存在词性则为<code>null</code>。数组第二个元素为单词解释。 */ @NotNull public static String[] splitExplain(@NotNull String input) { String[] result = new String[2]; Matcher explainMatcher = PATTERN_EXPLAIN.matcher(input); if (explainMatcher.find()) { result[0] = explainMatcher.group(GROUP_CLASS); result[1] = explainMatcher.group(GROUP_EXPLAIN).trim(); } else { result[1] = input; } return result; } /** * 展开像 'Hello; Hi' 这样的解释 */ @Nullable public static String[] expandExplain(@Nullable String[] explains) { if (explains == null || explains.length == 0) return explains; final LinkedHashSet<String> result = new LinkedHashSet<String>(explains.length); final Pattern pattern = Pattern.compile("[;;]"); for (String explain : explains) { Collections.addAll(result, pattern.split(explain)); } return result.toArray(new String[result.size()]); } /** * Checks that the specified object reference is not {@code null}. This * method is designed primarily for doing parameter validation in methods * and constructors, as demonstrated below: * <blockquote><pre> * public Foo(Bar bar) { * this.bar = Utils.requireNonNull(bar); * } * </pre></blockquote> * * @param obj the object reference to check for nullity * @param <T> the type of the reference * @return {@code obj} if not {@code null} * @throws NullPointerException if {@code obj} is {@code null} */ @NotNull public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; } /** * Checks that the specified object reference is not {@code null} and * throws a customized {@link NullPointerException} if it is. This method * is designed primarily for doing parameter validation in methods and * constructors with multiple parameters, as demonstrated below: * <blockquote><pre> * public Foo(Bar bar, Baz baz) { * this.bar = Utils.requireNonNull(bar, "bar must not be null"); * this.baz = Utils.requireNonNull(baz, "baz must not be null"); * } * </pre></blockquote> * * @param obj the object reference to check for nullity * @param message detail message to be used in the event that a {@code * NullPointerException} is thrown * @param <T> the type of the reference * @return {@code obj} if not {@code null} * @throws NullPointerException if {@code obj} is {@code null} */ @SuppressWarnings("SameParameterValue") @NotNull public static <T> T requireNonNull(T obj, String message) { if (obj == null) throw new NullPointerException(message); return obj; } }