From ed66b016db06a7ad788dec5be4a28e6259e93c07 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Sun, 24 Feb 2019 10:47:44 +0800 Subject: [PATCH] Rename then-series functions --- .../jackhuang/hmcl/game/LauncherHelper.java | 10 +- .../jackhuang/hmcl/game/ModpackHelper.java | 6 +- .../jackhuang/hmcl/ui/LeftPaneController.java | 5 +- .../hmcl/ui/account/AccountLoginPane.java | 2 +- .../hmcl/ui/account/AddAccountPane.java | 2 +- .../account/AddAuthlibInjectorServerPane.java | 2 +- .../ui/download/InstallerWizardProvider.java | 6 +- .../hmcl/ui/download/ModpackPage.java | 4 +- .../VanillaInstallWizardProvider.java | 2 +- .../hmcl/ui/download/VersionsPage.java | 2 +- .../hmcl/ui/versions/ModListPage.java | 2 +- .../hmcl/ui/versions/VersionSettingsPage.java | 4 +- .../hmcl/ui/versions/WorldListPage.java | 6 +- .../download/DefaultDependencyManager.java | 8 +- .../hmcl/download/DefaultGameBuilder.java | 15 +- .../hmcl/mod/MultiMCModpackInstallTask.java | 2 +- .../jackhuang/hmcl/task/FinalizedTask.java | 71 -------- .../java/org/jackhuang/hmcl/task/Task.java | 124 ++++++++++--- .../org/jackhuang/hmcl/task/TaskExecutor.java | 3 +- .../org/jackhuang/hmcl/task/TaskResult.java | 167 ++++++++++++++---- 20 files changed, 275 insertions(+), 168 deletions(-) delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index c980ee78a..93e5b34e4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -141,7 +141,7 @@ public final class LauncherHelper { } }) .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN))) - .thenTaskResult(() -> Task.ofResult(i18n("account.methods"), () -> { + .thenCompose(() -> Task.ofResult(i18n("account.methods"), () -> { try { return account.logIn(); } catch (CredentialExpiredException e) { @@ -152,11 +152,11 @@ public final class LauncherHelper { return account.playOffline().orElseThrow(() -> e); } })) - .thenResult(Schedulers.javafx(), authInfo -> { + .thenApply(Schedulers.javafx(), authInfo -> { emitStatus(LoadingState.LAUNCHING); return authInfo; }) - .thenResult(authInfo -> new HMCLGameLauncher( + .thenApply(authInfo -> new HMCLGameLauncher( repository, selectedVersion, authInfo, @@ -165,7 +165,7 @@ public final class LauncherHelper { ? null // Unnecessary to start listening to game process output when close launcher immediately after game launched. : new HMCLProcessListener(authInfo, setting, gameVersion.isPresent()) )) - .thenTaskResult(launcher -> { // launcher is prev task's result + .thenCompose(launcher -> { // launcher is prev task's result if (scriptFile == null) { return new LaunchTask<>(launcher::launch).setName(i18n("version.launch")); } else { @@ -175,7 +175,7 @@ public final class LauncherHelper { }).setName(i18n("version.launch_script")); } }) - .thenVoid(process -> { // process is LaunchTask's result + .thenAccept(process -> { // process is LaunchTask's result if (scriptFile == null) { PROCESSES.add(process); if (launcherVisibility == LauncherVisibility.CLOSE) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index c4bfdac61..3b256d044 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -110,13 +110,13 @@ public final class ModpackHelper { if (modpack.getManifest() instanceof CurseManifest) return new CurseInstallTask(profile.getDependency(), zipFile, modpack, ((CurseManifest) modpack.getManifest()), name) - .finalized(Schedulers.defaultScheduler(), success, failure); + .whenComplete(Schedulers.defaultScheduler(), success, failure); else if (modpack.getManifest() instanceof HMCLModpackManifest) return new HMCLModpackInstallTask(profile, zipFile, modpack, name) - .finalized(Schedulers.defaultScheduler(), success, failure); + .whenComplete(Schedulers.defaultScheduler(), success, failure); else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration) return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, ((MultiMCInstanceConfiguration) modpack.getManifest()), name) - .finalized(Schedulers.defaultScheduler(), success, failure) + .whenComplete(Schedulers.defaultScheduler(), success, failure) .then(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)); else throw new IllegalStateException("Unrecognized modpack: " + modpack); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java index 0479f27d0..ad0160dee 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -25,7 +25,6 @@ import org.jackhuang.hmcl.event.EventBus; import org.jackhuang.hmcl.event.RefreshedVersionsEvent; import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.game.ModpackHelper; -import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.setting.Accounts; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.Profiles; @@ -120,8 +119,8 @@ public final class LeftPaneController extends AdvancedListBox { File modpackFile = new File("modpack.zip").getAbsoluteFile(); if (modpackFile.exists()) { Task.ofResult(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath())) - .thenResult(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding)) - .thenVoid(modpack -> { + .thenApply(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding)) + .thenAccept(modpack -> { AtomicReference region = new AtomicReference<>(); TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack) .with(Task.of(Schedulers.javafx(), this::checkAccount)).executor(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java index 01b6ae552..00646b113 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountLoginPane.java @@ -62,7 +62,7 @@ public class AccountLoginPane extends StackPane { progressBar.setVisible(true); lblCreationWarning.setText(""); Task.ofResult(() -> oldAccount.logInWithPassword(password)) - .finalized(Schedulers.javafx(), authInfo -> { + .whenComplete(Schedulers.javafx(), authInfo -> { success.accept(authInfo); fireEvent(new DialogCloseEvent()); progressBar.setVisible(false); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 32c76b49f..579548f80 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -196,7 +196,7 @@ public class AddAccountPane extends StackPane { Object additionalData = getAuthAdditionalData(); Task.ofResult(() -> factory.create(new Selector(), username, password, additionalData)) - .finalized(Schedulers.javafx(), account -> { + .whenComplete(Schedulers.javafx(), account -> { int oldIndex = Accounts.getAccounts().indexOf(account); if (oldIndex == -1) { Accounts.getAccounts().add(account); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java index 85ec12ba1..18b3b2970 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAuthlibInjectorServerPane.java @@ -106,7 +106,7 @@ public class AddAuthlibInjectorServerPane extends StackPane implements DialogAwa Task.of(() -> { serverBeingAdded = AuthlibInjectorServer.locateServer(url); - }).finalized(Schedulers.javafx(), (isDependentsSucceeded, exception) -> { + }).whenComplete(Schedulers.javafx(), (isDependentsSucceeded, exception) -> { addServerPane.setDisable(false); nextPane.hideSpinner(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java index fe5f651c5..6f826a1a9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java @@ -93,13 +93,13 @@ public final class InstallerWizardProvider implements WizardProvider { TaskResult ret = Task.ofResult(() -> version); if (settings.containsKey("forge")) - ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge"))); + ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge"))); if (settings.containsKey("liteloader")) - ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("liteloader"))); + ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("liteloader"))); if (settings.containsKey("optifine")) - ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine"))); + ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine"))); return ret.then(profile.getRepository().refreshVersionsAsync()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java index 0149028f2..7a762498b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackPage.java @@ -110,8 +110,8 @@ public final class ModpackPage extends StackPane implements WizardPage { spinnerPane.showSpinner(); Task.ofResult(() -> CompressingUtils.findSuitableEncoding(selectedFile.toPath())) - .thenResult(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding)) - .finalized(Schedulers.javafx(), manifest -> { + .thenApply(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding)) + .whenComplete(Schedulers.javafx(), manifest -> { spinnerPane.hideSpinner(); controller.getSettings().put(MODPACK_MANIFEST, manifest); lblName.setText(manifest.getName()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index 9a3e6bcbf..e64696b2c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -59,7 +59,7 @@ public final class VanillaInstallWizardProvider implements WizardProvider { if (settings.containsKey("optifine")) builder.version((RemoteVersion) settings.get("optifine")); - return builder.buildAsync().finalized((a, b) -> profile.getRepository().refreshVersions()) + return builder.buildAsync().whenComplete((a, b) -> profile.getRepository().refreshVersions()) .then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name))); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index 1787606c3..dfe82d5d4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -128,7 +128,7 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres @Override public void refresh() { transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer()); - executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((isDependentsSucceeded, exception) -> { + executor = versionList.refreshAsync(gameVersion, downloadProvider).whenComplete((isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { List items = loadVersions(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index c420c5d5d..39e3d269e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -91,7 +91,7 @@ public final class ModListPage extends Control { modManager.refreshMods(); return new LinkedList<>(modManager.getMods()); } - }).finalized(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> { + }).whenComplete(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> { loadingProperty().set(false); if (isDependentsSucceeded) FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index be654a339..17619e040 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -118,7 +118,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag FXUtils.smoothScrolling(scroll); - Task.ofResult(JavaVersion::getJavas).thenVoid(Schedulers.javafx(), list -> { + Task.ofResult(JavaVersion::getJavas).thenAccept(Schedulers.javafx(), list -> { javaItem.loadChildren(list.stream() .map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit", javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion)) @@ -274,7 +274,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag if (versionSetting == null) return; Task.ofResult(versionSetting::getJavaVersion) - .thenVoid(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion) + .thenAccept(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion) .map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Path"))) .start(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index 195da3bd7..cf7b62a8f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -51,7 +51,7 @@ public class WorldListPage extends ListPage { setLoading(true); Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) - .finalized(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> { + .whenComplete(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> { setLoading(false); if (isDependentsSucceeded) itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList())); @@ -73,10 +73,10 @@ public class WorldListPage extends ListPage { // Only accept one world file because user is required to confirm the new world name // Or too many input dialogs are popped. Task.ofResult(() -> new World(zipFile.toPath())) - .finalized(Schedulers.javafx(), world -> { + .whenComplete(Schedulers.javafx(), world -> { Controllers.inputDialog(i18n("world.name.enter"), (name, resolve, reject) -> { Task.of(() -> world.install(savesDir, name)) - .finalized(Schedulers.javafx(), () -> { + .whenComplete(Schedulers.javafx(), () -> { itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name)))); resolve.run(); }, e -> { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index c094c719c..ac656d9fc 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -91,7 +91,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager { public TaskResult installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) { VersionList versionList = getVersionList(libraryId); return versionList.loadAsync(gameVersion, getDownloadProvider()) - .thenTaskResult(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion) + .thenCompose(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion) .orElseThrow(() -> new IllegalStateException("Remote library " + libraryId + " has no version " + libraryVersion)))); } @@ -107,9 +107,9 @@ public class DefaultDependencyManager extends AbstractDependencyManager { else throw new IllegalArgumentException("Remote library " + libraryVersion + " is unrecognized."); return task - .thenTaskResult(LibrariesUniqueTask::new) - .thenTaskResult(MaintainTask::new) - .thenTaskResult(newVersion -> new VersionJsonSaveTask(repository, newVersion)); + .thenCompose(LibrariesUniqueTask::new) + .thenCompose(MaintainTask::new) + .thenCompose(newVersion -> new VersionJsonSaveTask(repository, newVersion)); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java index 885517422..4791266f7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -22,7 +22,6 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.ParallelTask; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskResult; -import org.jackhuang.hmcl.util.AutoTypingMap; import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.gson.JsonUtils; @@ -50,7 +49,7 @@ public class DefaultGameBuilder extends GameBuilder { @Override public Task buildAsync() { - return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenTaskResult(rawJson -> { + return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenCompose(rawJson -> { Version original = JsonUtils.GSON.fromJson(rawJson, Version.class); Version version = original.setId(name).setJar(null); Task vanillaTask = downloadGameAsync(gameVersion, version).then(new ParallelTask( @@ -58,20 +57,20 @@ public class DefaultGameBuilder extends GameBuilder { new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries. ).with(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version))); // using [with] because download failure here are tolerant. - TaskResult libraryTask = vanillaTask.thenResult(() -> version); + TaskResult libraryTask = vanillaTask.thenSupply(() -> version); if (toolVersions.containsKey("forge")) - libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "forge")); + libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "forge")); if (toolVersions.containsKey("liteloader")) - libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "liteloader")); + libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "liteloader")); if (toolVersions.containsKey("optifine")) - libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "optifine")); + libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "optifine")); for (RemoteVersion remoteVersion : remoteVersions) - libraryTask = libraryTask.thenTaskResult(dependencyManager.installLibraryAsync(remoteVersion)); + libraryTask = libraryTask.thenCompose(dependencyManager.installLibraryAsync(remoteVersion)); return libraryTask; - }).finalized((isDependentsSucceeded, exception) -> { + }).whenComplete((isDependentsSucceeded, exception) -> { if (!isDependentsSucceeded) dependencyManager.getGameRepository().getVersionRoot(name).delete(); }); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java index c453ce859..6095604ec 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/MultiMCModpackInstallTask.java @@ -156,7 +156,7 @@ public final class MultiMCModpackInstallTask extends Task { } } - dependencies.add(new MaintainTask(version).thenTaskResult(maintainedVersion -> new VersionJsonSaveTask(repository, maintainedVersion))); + dependencies.add(new MaintainTask(version).thenCompose(maintainedVersion -> new VersionJsonSaveTask(repository, maintainedVersion))); dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name))); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java deleted file mode 100644 index a060d0d7c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.jackhuang.hmcl.task; - -import java.util.Collection; -import java.util.Collections; - -/** - * A task that combines two tasks and make sure [pred] runs before succ. - * - * @author huangyuhui - */ -final class FinalizedTask extends Task { - - private final Task pred; - private final FinalizedCallback callback; - private final Scheduler scheduler; - - /** - * A task that combines two tasks and make sure pred runs before succ. - * - * @param pred the task that runs before succ. - * @param callback a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. - */ - public FinalizedTask(Task pred, Scheduler scheduler, FinalizedCallback callback) { - this.pred = pred; - this.scheduler = scheduler; - this.callback = callback; - - setSignificance(TaskSignificance.MODERATE); - } - - @Override - public Scheduler getScheduler() { - return scheduler; - } - - @Override - public void execute() throws Exception { - callback.execute(isDependentsSucceeded(), pred.getLastException()); - - if (!isDependentsSucceeded()) - throw new SilentException(); - } - - @Override - public Collection getDependents() { - return Collections.singleton(pred); - } - - @Override - public boolean isRelyingOnDependents() { - return false; - } -} - diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java index cede8eebc..3f7d3204b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -265,18 +265,6 @@ public abstract class Task { return executor().test(); } - public final void subscribe(Task subscriber) { - new TaskExecutor(then(subscriber)).start(); - } - - public final void subscribe(Scheduler scheduler, ExceptionalRunnable closure) { - subscribe(of(scheduler, closure)); - } - - public final void subscribe(ExceptionalRunnable closure) { - subscribe(of(closure)); - } - public final Task then(Task b) { return then(convert(b)); } @@ -285,13 +273,29 @@ public abstract class Task { return new CoupleTask(this, b, true); } - public final TaskResult thenResult(Callable supplier) { - return thenTaskResult(() -> Task.ofResult(supplier)); + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed using the default Scheduler. + * + * @param fn the function to use to compute the value of the returned TaskResult + * @param the function's return type + * @return the new TaskResult + */ + public final TaskResult thenSupply(Callable fn) { + return thenCompose(() -> Task.ofResult(fn)); } - public final TaskResult thenTaskResult(ExceptionalSupplier, ?> taskSupplier) { - return new TaskResult() { - TaskResult then; + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed. + * + * @param fn the function returning a new TaskResult + * @param the type of the returned TaskResult's result + * @return the TaskResult + */ + public final TaskResult thenCompose(ExceptionalSupplier, ?> fn) { + return new TaskResult() { + TaskResult then; @Override public Collection getDependents() { @@ -300,7 +304,7 @@ public abstract class Task { @Override public void execute() throws Exception { - then = taskSupplier.get().storeTo(this::setResult); + then = fn.get().storeTo(this::setResult); } @Override @@ -318,17 +322,87 @@ public abstract class Task { return new CoupleTask(this, b, false); } - public final Task finalized(FinalizedCallback b) { - return finalized(Schedulers.defaultScheduler(), b); + /** + * Returns a new Task with the same exception as this task, that executes + * the given action when this task completes. + * + *

When this task is complete, the given action is invoked, a boolean + * value represents the execution status of this task, and the exception + * (or {@code null} if none) of this task as arguments. The returned task + * is completed when the action returns. If the supplied action itself + * encounters an exception, then the returned task exceptionally completes + * with this exception unless this task also completed exceptionally. + * + * @param action the action to perform + * @return the new Task + */ + public final Task whenComplete(FinalizedCallback action) { + return whenComplete(Schedulers.defaultScheduler(), action); } - public final Task finalized(Scheduler scheduler, FinalizedCallback b) { - return new FinalizedTask(this, scheduler, b).setName(getCaller()); + /** + * Returns a new Task with the same exception as this task, that executes + * the given action when this task completes. + * + *

When this task is complete, the given action is invoked, a boolean + * value represents the execution status of this task, and the exception + * (or {@code null} if none) of this task as arguments. The returned task + * is completed when the action returns. If the supplied action itself + * encounters an exception, then the returned task exceptionally completes + * with this exception unless this task also completed exceptionally. + * + * @param action the action to perform + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public final Task whenComplete(Scheduler scheduler, FinalizedCallback action) { + return new Task() { + { + setSignificance(TaskSignificance.MODERATE); + } + + @Override + public Scheduler getScheduler() { + return scheduler; + } + + @Override + public void execute() throws Exception { + action.execute(isDependentsSucceeded(), Task.this.getLastException()); + + if (!isDependentsSucceeded()) + throw new SilentException(); + } + + @Override + public Collection getDependents() { + return Collections.singleton(Task.this); + } + + @Override + public boolean isRelyingOnDependents() { + return false; + } + }.setName(getCaller()); } - // T, K here is necessary, or javac cannot infer type of failure - public final Task finalized(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { - return finalized(scheduler, (isDependentsSucceeded, exception) -> { + /** + * Returns a new Task with the same exception as this task, that executes + * the given actions when this task completes. + * + *

When this task is complete, the given success action is invoked, the + * given failure action is invoked with the exception of this task. The + * returned task is completed when the action returns. If the supplied + * action itself encounters an exception, then the returned task exceptionally + * completes with this exception unless this task also + * completed exceptionally. + * + * @param success the action to perform when this task successfully completed + * @param failure the action to perform when this task exceptionally returned + * @return the new Task + */ + public final Task whenComplete(Scheduler scheduler, ExceptionalRunnable success, ExceptionalConsumer failure) { + return whenComplete(scheduler, (isDependentsSucceeded, exception) -> { if (isDependentsSucceeded) { if (success != null) try { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java index 12587b715..82d48f36b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -133,6 +133,7 @@ public final class TaskExecutor { private boolean executeTask(Task task) { if (canceled) { task.setState(Task.TaskState.FAILED); + task.setLastException(new CancellationException()); return false; } @@ -221,7 +222,7 @@ public final class TaskExecutor { task.onDone().fireEvent(new TaskEvent(this, task, true)); taskListeners.forEach(it -> it.onFailed(task, e)); } catch (SilentException | RejectedExecutionException e) { - // do nothing + task.setLastException(e); } catch (Exception e) { task.setLastException(e); lastException = e; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java index 5f9185ae0..342a1ab2e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskResult.java @@ -29,35 +29,55 @@ import java.util.function.Consumer; * * @author huangyuhui */ -public abstract class TaskResult extends Task { +public abstract class TaskResult extends Task { - private V result; - private Consumer resultConsumer; + private T result; + private Consumer resultConsumer; @Override - public TaskResult setName(String name) { + public TaskResult setName(String name) { super.setName(name); return this; } - public V getResult() { + /** + * Returns the result of this task. + * + * The result will be generated only if the execution is completed. + */ + public T getResult() { return result; } - public void setResult(V result) { + protected void setResult(T result) { this.result = result; if (resultConsumer != null) resultConsumer.accept(result); } - public TaskResult storeTo(Consumer resultConsumer) { - this.resultConsumer = resultConsumer; + /** + * Sync the result of this task by given action. + * + * @param action the action to perform when result of this task changed + * @return this TaskResult + */ + public TaskResult storeTo(Consumer action) { + this.resultConsumer = action; return this; } - public TaskResult thenTaskResult(ExceptionalFunction, E> taskSupplier) { - return new TaskResult() { - TaskResult then; + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed with result of this task as the argument + * to the supplied function. + * + * @param fn the function returning a new TaskResult + * @param the type of the returned TaskResult's result + * @return the TaskResult + */ + public TaskResult thenCompose(ExceptionalFunction, E> fn) { + return new TaskResult() { + TaskResult then; @Override public Collection getDependents() { @@ -66,7 +86,7 @@ public abstract class TaskResult extends Task { @Override public void execute() throws Exception { - then = taskSupplier.apply(TaskResult.this.getResult()).storeTo(this::setResult); + then = fn.apply(TaskResult.this.getResult()).storeTo(this::setResult); } @Override @@ -76,44 +96,129 @@ public abstract class TaskResult extends Task { }; } - public Task then(ExceptionalFunction taskSupplier) { - return new CoupleTask(this, () -> taskSupplier.apply(getResult()), true); + /** + * Returns a new Task that, when this task completes + * normally, is executed with this task as the argument + * to the supplied function. + * + * @param fn the function returning a new Task + * @return the Task + */ + public Task then(ExceptionalFunction fn) { + return new CoupleTask(this, () -> fn.apply(getResult()), true); } - public TaskResult thenResult(ExceptionalFunction task) { - return thenResult(Schedulers.defaultScheduler(), task); + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed using the default Scheduler, with this + * task's result as the argument to the supplied function. + * + * @param fn the function to use to compute the value of the returned TaskResult + * @param the function's return type + * @return the new TaskResult + */ + public TaskResult thenApply(ExceptionalFunction fn) { + return thenApply(Schedulers.defaultScheduler(), fn); } - public TaskResult thenResult(Scheduler scheduler, ExceptionalFunction task) { - return thenResult(getCaller(), scheduler, task); + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied function. + * + * @param scheduler the executor to use for asynchronous execution + * @param fn the function to use to compute the value of the returned TaskResult + * @param the function's return type + * @return the new TaskResult + */ + public TaskResult thenApply(Scheduler scheduler, ExceptionalFunction fn) { + return thenApply(getCaller(), scheduler, fn); } - public TaskResult thenResult(String name, Scheduler scheduler, ExceptionalFunction task) { - return new Subtask<>(name, scheduler, task); + /** + * Returns a new TaskResult that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied function. + * + * @param name the name of this new TaskResult for displaying + * @param scheduler the executor to use for asynchronous execution + * @param fn the function to use to compute the value of the returned TaskResult + * @param the function's return type + * @return the new TaskResult + */ + public TaskResult thenApply(String name, Scheduler scheduler, ExceptionalFunction fn) { + return new Subtask<>(name, scheduler, fn); } - // stupid javac stop us from renaming thenVoid to thenResult - public Task thenVoid(ExceptionalConsumer task) { - return thenVoid(Schedulers.defaultScheduler(), task); + /** + * Returns a new Task that, when this task completes + * normally, is executed using the default Scheduler, with this + * task's result as the argument to the supplied action. + * + * @param action the action to perform before completing the + * returned Task + * @return the new Task + */ + public Task thenAccept(ExceptionalConsumer action) { + return thenAccept(Schedulers.defaultScheduler(), action); } - public Task thenVoid(Scheduler scheduler, ExceptionalConsumer task) { - return new CoupleTask(this, () -> Task.of(scheduler, () -> task.accept(getResult())), true); + /** + * Returns a new Task that, when this task completes + * normally, is executed using the supplied Scheduler, with this + * task's result as the argument to the supplied action. + * + * @param action the action to perform before completing the returned Task + * @param scheduler the executor to use for asynchronous execution + * @return the new Task + */ + public Task thenAccept(Scheduler scheduler, ExceptionalConsumer action) { + return new CoupleTask(this, () -> Task.of(scheduler, () -> action.accept(getResult())), true); } - public Task finalized(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { - return finalized(scheduler, () -> success.accept(getResult()), failure); + /** + * Returns a new Task with the same exception as this task, that executes + * the given actions when this task completes. + * + *

When this task is complete, the given success action is invoked with + * the result, the given failure action is invoked with the exception of + * this task. The returned task is completed when the action returns. If + * the supplied action itself encounters an exception, then the returned + * task exceptionally completes with this exception unless this task also + * completed exceptionally. + * + * @param success the action to perform when this task successfully completed + * @param failure the action to perform when this task exceptionally returned + * @return the new Task + */ + public Task whenComplete(Scheduler scheduler, ExceptionalConsumer success, ExceptionalConsumer failure) { + return whenComplete(scheduler, () -> success.accept(getResult()), failure); } - public Task finalized(Scheduler scheduler, FinalizedCallback callback) { - return finalized(scheduler, ((isDependentsSucceeded, exception) -> callback.execute(getResult(), isDependentsSucceeded, exception))); + /** + * Returns a new Task with the same exception as this task, that executes + * the given action when this task completes. + * + *

When this task is complete, the given action is invoked with the + * result (or {@code null} if none), a boolean value represents the + * execution status of this task, and the exception (or {@code null} + * if none) of this task as arguments. The returned task is completed + * when the action returns. If the supplied action itself encounters an + * exception, then the returned task exceptionally completes with this + * exception unless this task also completed exceptionally. + * + * @param action the action to perform + * @return the new Task + */ + public Task whenComplete(Scheduler scheduler, FinalizedCallback action) { + return whenComplete(scheduler, ((isDependentsSucceeded, exception) -> action.execute(getResult(), isDependentsSucceeded, exception))); } private class Subtask extends TaskResult { private final Scheduler scheduler; - private final ExceptionalFunction callable; + private final ExceptionalFunction callable; - public Subtask(String name, Scheduler scheduler, ExceptionalFunction callable) { + public Subtask(String name, Scheduler scheduler, ExceptionalFunction callable) { this.scheduler = scheduler; this.callable = callable;