diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java index e12700207..26aaf5ce8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -64,7 +64,7 @@ public final class Accounts { } public static boolean hasCurrentCharacter(Account account) { - return Lang.get(account.getProperties(), "character", String.class, null) != null; + return Lang.get(account.getProperties(), "character", String.class).isPresent(); } public static String getCurrentCharacter(Account account) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index 65d139940..30d90acf9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -69,7 +69,7 @@ public class Settings { { for (Map settings : SETTINGS.getAccounts()) { Optional characterName = Accounts.getCurrentCharacter(settings); - AccountFactory factory = Accounts.ACCOUNT_FACTORY.get(Lang.get(settings, "type", String.class, "")); + AccountFactory factory = Accounts.ACCOUNT_FACTORY.get(Lang.get(settings, "type", String.class).orElse("")); if (factory == null || !characterName.isPresent()) { // unrecognized account type, so remove it. SETTINGS.getAccounts().remove(settings); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index 85978c49e..32928e3c7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -114,7 +114,7 @@ public final class FXUtils { } public static void removeListener(Node node, String key) { - Lang.convert(node.getProperties().get(key), ListenerPair.class) + Lang.cast(node.getProperties().get(key), ListenerPair.class) .ifPresent(info -> { info.unbind(); node.getProperties().remove(key); @@ -329,7 +329,7 @@ public final class FXUtils { } public static void unbindEnum(JFXComboBox comboBox) { - ChangeListener listener = Lang.get(comboBox.getProperties(), "listener", ChangeListener.class, null); + ChangeListener listener = Lang.get(comboBox.getProperties(), "listener", ChangeListener.class).orElse(null); if (listener == null) return; comboBox.getSelectionModel().selectedIndexProperty().removeListener(listener); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java index a639e45d3..3062478f3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java @@ -66,9 +66,9 @@ public final class DownloadWizardProvider implements WizardProvider { if (!settings.containsKey(ModpackPage.MODPACK_FILE)) return null; - File selected = Lang.get(settings, ModpackPage.MODPACK_FILE, File.class, null); - Modpack modpack = Lang.get(settings, ModpackPage.MODPACK_CURSEFORGE_MANIFEST, Modpack.class, null); - String name = Lang.get(settings, ModpackPage.MODPACK_NAME, String.class, null); + File selected = Lang.get(settings, ModpackPage.MODPACK_FILE, File.class).orElse(null); + Modpack modpack = Lang.get(settings, ModpackPage.MODPACK_CURSEFORGE_MANIFEST, Modpack.class).orElse(null); + String name = Lang.get(settings, ModpackPage.MODPACK_NAME, String.class).orElse(null); if (selected == null || modpack == null || name == null) return null; return ModpackHelper.getInstallTask(profile, selected, name, modpack); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountFactory.java index 502dfb01e..096a54a01 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountFactory.java @@ -41,7 +41,7 @@ public abstract class AccountFactory { public final T fromStorage(Map storage) { T account = fromStorageImpl(storage); - Map properties = Lang.get(storage, "properties", Map.class, null); + Map properties = Lang.get(storage, "properties", Map.class).orElse(null); if (properties == null) return account; account.getProperties().putAll(properties); return account; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/AuthlibInjectorAccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/AuthlibInjectorAccountFactory.java index 95cff3d9f..c106a4cd9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/AuthlibInjectorAccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/AuthlibInjectorAccountFactory.java @@ -39,8 +39,8 @@ public class AuthlibInjectorAccountFactory extends AccountFactory new IllegalArgumentException("storage does not have key " + STORAGE_KEY_SERVER_BASE_URL)); AuthlibInjectorAccount account = new AuthlibInjectorAccount(injectorJarPathSupplier, serverBaseURL, username); - account.setUserId(Lang.get(storage, STORAGE_KEY_USER_ID, String.class, username)); - account.setAccessToken(Lang.get(storage, STORAGE_KEY_ACCESS_TOKEN, String.class, null)); + account.setUserId(Lang.get(storage, STORAGE_KEY_USER_ID, String.class).orElse(username)); + account.setAccessToken(Lang.get(storage, STORAGE_KEY_ACCESS_TOKEN, String.class).orElse(null)); account.setClientToken(Lang.get(storage, STORAGE_KEY_CLIENT_TOKEN, String.class) .orElseThrow(() -> new IllegalArgumentException("storage does not have key " + STORAGE_KEY_CLIENT_TOKEN))); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccountFactory.java index f7c7a714f..302e493fb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccountFactory.java @@ -58,8 +58,8 @@ public class YggdrasilAccountFactory extends AccountFactory { .orElseThrow(() -> new IllegalArgumentException("storage does not have key " + STORAGE_KEY_USER_NAME)); YggdrasilAccount account = new YggdrasilAccount(baseAuthServer, baseSessionServer, username); - account.setUserId(Lang.get(storage, STORAGE_KEY_USER_ID, String.class, username)); - account.setAccessToken(Lang.get(storage, STORAGE_KEY_ACCESS_TOKEN, String.class, null)); + account.setUserId(Lang.get(storage, STORAGE_KEY_USER_ID, String.class).orElse(username)); + account.setAccessToken(Lang.get(storage, STORAGE_KEY_ACCESS_TOKEN, String.class).orElse(null)); account.setClientToken(Lang.get(storage, STORAGE_KEY_CLIENT_TOKEN, String.class) .orElseThrow(() -> new IllegalArgumentException("storage does not have key " + STORAGE_KEY_CLIENT_TOKEN))); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java index 3beebeeec..f96ec0dc9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java @@ -20,6 +20,13 @@ public final class Lang { private Lang() { } + /** + * Construct a mutable map by given key-value pairs. + * @param pairs entries in the new map + * @param the type of keys + * @param the type of values + * @return the map which contains data in {@code pairs}. + */ @SafeVarargs public static Map mapOf(Pair... pairs) { HashMap map = new HashMap<>(); @@ -38,7 +45,8 @@ public final class Lang { return value; } - public static void throwable(Throwable exception) throws E { + @SuppressWarnings("unchecked") + private static void throwable(Throwable exception) throws E { throw (E) exception; } @@ -108,7 +116,6 @@ public final class Lang { * * @param type of result. * @param consumer your method. - * @return the result of the method to invoke. */ public static void invokeConsumer(ExceptionalConsumer consumer, T t) { try { @@ -175,7 +182,7 @@ public final class Lang { public static T ignoringException(ExceptionalSupplier supplier, T defaultValue) { try { return supplier.get(); - } catch (Exception e) { + } catch (Exception ignore) { return defaultValue; } } @@ -183,24 +190,32 @@ public final class Lang { public static void ignoringException(ExceptionalRunnable runnable) { try { runnable.run(); - } catch (Exception e) { + } catch (Exception ignore) { } } - public static Optional convert(Object o, Class clazz) { - if (o == null || !ReflectionHelper.isInstance(clazz, o)) + /** + * Cast {@code obj} to V dynamically. + * @param obj the object reference to be cast. + * @param clazz the class reference of {@code V}. + * @param the type that {@code obj} is being cast to. + * @return {@code obj} in the type of {@code V}. + */ + @SuppressWarnings("unchecked") + public static Optional cast(Object obj, Class clazz) { + if (obj == null || !ReflectionHelper.isInstance(clazz, obj)) return Optional.empty(); else - return Optional.of((V) o); - } - - public static V convert(Object o, Class clazz, V defaultValue) { - if (o == null || !ReflectionHelper.isInstance(clazz, o)) - return defaultValue; - else - return (V) o; + return Optional.of((V) obj); } + /** + * Get the element at the specific position {@code index} in {@code list}. + * + * @param index the index of element to be return + * @param the type of elements in {@code list} + * @return the element at the specific position, null if index is out of bound. + */ public static Optional get(List list, int index) { if (index < 0 || index >= list.size()) return Optional.empty(); @@ -208,14 +223,28 @@ public final class Lang { return Optional.ofNullable(list.get(index)); } + /** + * Get the value to which the specific key is mapped, + * or {@code null} if {@code map} has no mapping for the key + * or the value is not in the type of {@code clazz}. + * + * @param map the map + * @param key the key for finding the associate value. + * @param the type of values in {@code map} + * @return the value to which the specific key is mapped, or {@code null} if {@code map} has no mapping for the key or the type is not correct. + */ public static Optional get(Map map, Object key, Class clazz) { - return convert(map.get(key), clazz); - } - - public static V get(Map map, Object key, Class clazz, V defaultValue) { - return convert(map.get(key), clazz, defaultValue); + return cast(map.get(key), clazz); } + /** + * Join two collections into one list. + * + * @param a one collection, to be joined. + * @param b another collection to be joined. + * @param the super type of elements in {@code a} and {@code b} + * @return the joint collection + */ public static List merge(Collection a, Collection b) { List result = new ArrayList<>(); if (a != null) @@ -236,14 +265,32 @@ public final class Lang { }, null, isDaemon); } + /** + * Start a thread invoking {@code runnable} immediately. + * @param runnable code to run. + * @return the reference of the started thread + */ public static Thread thread(Runnable runnable) { return thread(runnable, null); } + /** + * Start a thread invoking {@code runnable} immediately. + * @param runnable code to run + * @param name the name of thread + * @return the reference of the started thread + */ public static Thread thread(Runnable runnable, String name) { return thread(runnable, name, false); } + /** + * Start a thread invoking {@code runnable} immediately. + * @param runnable code to run + * @param name the name of thread + * @param isDaemon true if thread will be terminated when only daemon threads are running. + * @return the reference of the started thread + */ public static Thread thread(Runnable runnable, String name, boolean isDaemon) { Thread thread = new Thread(runnable); if (isDaemon) @@ -297,6 +344,12 @@ public final class Lang { } } + /** + * Find the first non-null reference in given list. + * @param t nullable references list. + * @param the type of nullable references + * @return the first non-null reference. + */ @SafeVarargs public static T nonNull(T... t) { for (T a : t) if (a != null) return a;