diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java index d210a4f4575f278890277e47b89868ee46f0515a..ada57f4df3f4bd9cf3fe995a7929e562607fbb2a 100644 --- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java +++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java @@ -6,37 +6,44 @@ import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; +import cz.it4i.fiji.haas.ui.UpdatableObservableValue.UpdateStatus; import javafx.beans.value.ObservableValue; public class ObservableValueRegistry<T> { - private Function<T, Boolean> updateFunction; - private Function<T, Boolean> validateFunction; + private Function<T,UpdateStatus> updateFunction; private Consumer<T> removeConsumer; - public ObservableValueRegistry(Function<T, Boolean> validateFunction, Function<T, Boolean> updateFunction, + public ObservableValueRegistry(Function<T, UpdateStatus> updateFunction, Consumer<T> removeConsumer) { super(); - this.validateFunction = validateFunction; this.updateFunction = updateFunction; - this.removeConsumer = removeConsumer; + this.removeConsumer = t-> { + removeConsumer.accept(t); + remove(t); + }; + } private Map<T,UpdatableObservableValue<T>> map = new HashMap<>(); public ObservableValue<T> addIfAbsent(T value) { - UpdatableObservableValue<T> uov = map.computeIfAbsent(value, v-> new UpdatableObservableValue<T>(v, updateFunction, validateFunction)); + UpdatableObservableValue<T> uov = map.computeIfAbsent(value, v-> new UpdatableObservableValue<T>(v, updateFunction)); return uov; } - public ObservableValue<T> remove(T value) { + public ObservableValue<T> get(T value) { + return map.get(value); + } + + private ObservableValue<T> remove(T value) { return map.get(value); } public void update() { for (UpdatableObservableValue<T> value : new LinkedList<>(map.values())) { - if(!value.update()) { + if(value.update() == UpdateStatus.Deleted) { removeConsumer.accept(value.getValue()); } } diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java index 3bd8930da1e6dbe718c8cadeb8bb106210ab947c..41c9dedab6674af2303bd664c8a2f5ec23edb0d1 100644 --- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java +++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java @@ -6,16 +6,21 @@ import javafx.beans.value.ObservableValueBase; public class UpdatableObservableValue<T> extends ObservableValueBase<T>{ + public enum UpdateStatus { + Deleted, + Updated, + NotUpdated + } + private T wrapped; - private Function<T,Boolean> updateFunction; - private Function<T,Boolean> validateFunction; + private Function<T,UpdateStatus> updateFunction; - public UpdatableObservableValue(T wrapped, Function<T, Boolean> updateFunction, Function<T, Boolean> validateFunction) { + public UpdatableObservableValue(T wrapped, Function<T, UpdateStatus> updateFunction) { super(); this.wrapped = wrapped; this.updateFunction = updateFunction; - this.validateFunction = validateFunction; + } @Override @@ -24,14 +29,38 @@ public class UpdatableObservableValue<T> extends ObservableValueBase<T>{ return wrapped; } - public boolean update() { - if(!validateFunction.apply(wrapped)) { - return false; - } - if(updateFunction.apply(wrapped)) { + public UpdateStatus update() { + UpdateStatus status = updateFunction.apply(wrapped); + switch (status) { + case Updated: fireValueChangedEvent(); + default: + return status; } + + } + @Override + public int hashCode() { + return wrapped.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + @SuppressWarnings("unchecked") + UpdatableObservableValue<T> other = (UpdatableObservableValue<T>) obj; + if (wrapped == null) { + if (other.wrapped != null) + return false; + } else if (!wrapped.equals(other.wrapped)) + return false; return true; } + } diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java index ef0058bd2819e88c09a48aeb92023f70794d3b31..eeb218aa001c44cdd7fc7cc0655df445de1c33de 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java @@ -33,7 +33,6 @@ import cz.it4i.fiji.haas_java_client.HaaSClient; import cz.it4i.fiji.haas_java_client.JobState; import cz.it4i.fiji.haas_java_client.Settings; import cz.it4i.fiji.haas_java_client.SynchronizableFileType; -import javafx.beans.value.ObservableValueBase; import net.imagej.updater.util.Progress; public class BenchmarkJobManager { @@ -46,10 +45,9 @@ public class BenchmarkJobManager { private JobManager jobManager; - public final class BenchmarkJob extends ObservableValueBase<BenchmarkJob> implements HaaSOutputSource { + public final class BenchmarkJob implements HaaSOutputSource { private Job job; - private JobState oldState; private HaaSOutputHolder outputOfSnakemake; @@ -67,11 +65,12 @@ public class BenchmarkJobManager { return false; } }; - + + public BenchmarkJob(Job job) { super(); this.job = job; - outputOfSnakemake = new HaaSOutputHolderImpl(getValue(), SynchronizableFileType.StandardErrorFile); + outputOfSnakemake = new HaaSOutputHolderImpl(this, SynchronizableFileType.StandardErrorFile); } public void startJob(Progress progress) throws IOException { @@ -79,12 +78,11 @@ public class BenchmarkJobManager { String outputName = getOutputName(job.openLocalFile(Constants.CONFIG_YAML)); job.submit(); job.setProperty(Constants.SPIM_OUTPUT_FILENAME_PATTERN, outputName); - fireValueChangedEvent(); setDownloaded(false); } public JobState getState() { - return oldState = job.getState(); + return job.getState(); } public void downloadData(Progress progress) throws IOException { @@ -94,13 +92,12 @@ public class BenchmarkJobManager { } else if (job.getState() == JobState.Failed) { job.download(downloadFailedData(), progress); } - fireValueChangedEvent(); + setDownloaded(true); } public void downloadStatistics(Progress progress) throws IOException { job.download(BenchmarkJobManager.downloadStatistics(), progress); - fireValueChangedEvent(); Path resultFile = job.getDirectory().resolve(Constants.BENCHMARK_RESULT_FILE); if (resultFile != null) BenchmarkJobManager.formatResultFile(resultFile); @@ -130,11 +127,6 @@ public class BenchmarkJobManager { return time != null ? time.getTime().toString() : "N/A"; } - @Override - public BenchmarkJob getValue() { - return this; - } - @Override public int hashCode() { return Long.hashCode(job.getId()); @@ -149,11 +141,6 @@ public class BenchmarkJobManager { return false; } - public void update(BenchmarkJob benchmarkJob) { - job = benchmarkJob.job; - if (benchmarkJob.job.getState() != oldState) - fireValueChangedEvent(); - } public boolean downloaded() { return getDownloaded(); @@ -161,11 +148,9 @@ public class BenchmarkJobManager { public BenchmarkJob update() { job.updateInfo(); - if (!job.getState().equals(oldState)) - fireValueChangedEvent(); return this; } - + public Path getDirectory() { return job.getDirectory(); } diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java index cd35978fd422aa0ba1ec822de5d6d31faae4e110..7606d57caa4eba642e00cdd97fab09108ea5665a 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java @@ -5,9 +5,9 @@ import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; +import java.util.Collection; import java.util.EnumSet; import java.util.HashSet; -import java.util.Map; import java.util.Set; import java.util.Timer; import java.util.TimerTask; @@ -17,7 +17,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Collectors; import javax.swing.WindowConstants; @@ -34,22 +33,23 @@ import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager; import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.BenchmarkJob; import cz.it4i.fiji.haas_spim_benchmark.core.Constants; import cz.it4i.fiji.haas_spim_benchmark.core.FXFrameExecutorService; +import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.scene.control.TableView; import net.imagej.updater.util.Progress; public class BenchmarkSPIMController implements FXFrame.Controller { - private static boolean notNullValue(BenchmarkJob j, Predicate<BenchmarkJob> pred) { - if (j == null) { + private static boolean notNullValue(ObservableValue<BenchmarkJob> j, Predicate<BenchmarkJob> pred) { + if (j == null || j.getValue() == null) { return false; } else { - return pred.test(j); + return pred.test(j.getValue()); } } @FXML - private TableView<BenchmarkJob> jobs; + private TableView<ObservableValue<BenchmarkJob>> jobs; private BenchmarkJobManager manager; @@ -60,6 +60,7 @@ public class BenchmarkSPIMController implements FXFrame.Controller { private Executor executorServiceFX = new FXFrameExecutorService(); private Timer timer; + private ObservableBenchmarkJobRegistry registry; private static Logger log = LoggerFactory .getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.BenchmarkSPIMController.class); @@ -94,15 +95,15 @@ public class BenchmarkSPIMController implements FXFrame.Controller { } private void initMenu() { - TableViewContextMenu<BenchmarkJob> menu = new TableViewContextMenu<>(jobs); + TableViewContextMenu<ObservableValue<BenchmarkJob>> menu = new TableViewContextMenu<>(jobs); menu.addItem("Create job", x -> executeWSCallAsync("Creating job", p -> manager.createJob()), j -> true); - menu.addItem("Start job", job -> executeWSCallAsync("Starting job", p -> job.startJob(p)), + menu.addItem("Start job", job -> executeWSCallAsync("Starting job", p -> job.getValue().startJob(p)), job -> notNullValue(job, j -> j.getState() == JobState.Configuring || j.getState() == JobState.Finished)); menu.addItem("Show progress", job -> { try { - new SPIMPipelineProgressViewWindow(root, job).setVisible(true); + new SPIMPipelineProgressViewWindow(root, job.getValue()).setVisible(true); } catch (IOException e) { // TODO Auto-generated catch block log.error(e.getMessage(), e); @@ -110,17 +111,19 @@ public class BenchmarkSPIMController implements FXFrame.Controller { }, job -> notNullValue(job, j -> j.getState() == JobState.Running || j.getState() == JobState.Finished || j.getState() == JobState.Failed)); - menu.addItem("Download result", job -> executeWSCallAsync("Downloading data", p -> job.downloadData(p)), + menu.addItem("Download result", + job -> executeWSCallAsync("Downloading data", p -> job.getValue().downloadData(p)), job -> notNullValue(job, j -> EnumSet.of(JobState.Failed, JobState.Finished).contains(j.getState()) && !j.downloaded())); menu.addItem("Download statistics", - job -> executeWSCallAsync("Downloading data", p -> job.downloadStatistics(p)), + job -> executeWSCallAsync("Downloading data", p -> job.getValue().downloadStatistics(p)), job -> notNullValue(job, j -> j.getState() == JobState.Finished)); - menu.addItem("Show output", j -> new JobOutputView(root, executorServiceUI, j, Constants.HAAS_UPDATE_TIMEOUT), + menu.addItem("Show output", + j -> new JobOutputView(root, executorServiceUI, j.getValue(), Constants.HAAS_UPDATE_TIMEOUT), job -> notNullValue(job, j -> EnumSet.of(JobState.Failed, JobState.Finished, JobState.Running).contains(j.getState()))); - menu.addItem("Open", j -> open(j), x -> true); + menu.addItem("Open", j -> open(j.getValue()), x -> true); menu.addItem("Update table", job -> updateJobs(), j -> true); } @@ -158,46 +161,36 @@ public class BenchmarkSPIMController implements FXFrame.Controller { } private void updateJobs(boolean showProgress) { - executorServiceUI.execute(() -> { - Progress progress = showProgress - ? ModalDialogs.doModal(new ProgressDialog(root, "Updating jobs"), - WindowConstants.DO_NOTHING_ON_CLOSE) - : new DummyProgress(); - try { - manager.getJobs().forEach(job -> job.update()); - } catch (IOException e1) { - throw new RuntimeException(e1); - } + executorServiceWS.execute(() -> { + + registry.update(); executorServiceUI.execute(() -> { + Progress progress = showProgress + ? ModalDialogs.doModal(new ProgressDialog(root, "Updating jobs"), + WindowConstants.DO_NOTHING_ON_CLOSE) + : new DummyProgress(); - Set<BenchmarkJob> old = new HashSet<BenchmarkJob>(jobs.getItems()); - Map<BenchmarkJob, BenchmarkJob> actual; try { - actual = manager.getJobs().stream().collect(Collectors.toMap(job -> job, job -> job)); - } catch (IOException e) { - throw new RuntimeException(e); - } - for (BenchmarkJob job : old) { - if (!actual.containsKey(job)) { - jobs.getItems().remove(job); - } else { - job.update(actual.get(job)); + Collection<BenchmarkJob> jobs = manager.getJobs(); + Set<ObservableValue<BenchmarkJob>> actual = new HashSet<>(this.jobs.getItems()); + for (BenchmarkJob bj : jobs) { + ObservableValue<BenchmarkJob> value = registry.addIfAbsent(bj); + if (!actual.contains(value)) { + this.jobs.getItems().add(value); + } } + } catch (IOException e) { + log.error(e.getMessage(), e); } + progress.done(); - executorServiceFX.execute(() -> { - for (BenchmarkJob job : actual.keySet()) { - if (!old.contains(job)) { - jobs.getItems().add(job); - } - } - }); + }); }); - } private void initTable() { + registry = new ObservableBenchmarkJobRegistry(bj -> jobs.getItems().remove(registry.get(bj))); setCellValueFactory(0, j -> j.getId() + ""); setCellValueFactory(1, j -> j.getState().toString()); setCellValueFactory(2, j -> j.getCreationTime().toString()); diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableBenchmarkJobRegistry.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableBenchmarkJobRegistry.java new file mode 100644 index 0000000000000000000000000000000000000000..93a0664514d743387e4a45486315ae69ed27221b --- /dev/null +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableBenchmarkJobRegistry.java @@ -0,0 +1,26 @@ +package cz.it4i.fiji.haas_spim_benchmark.ui; + +import java.nio.file.Files; +import java.util.function.Consumer; + +import cz.it4i.fiji.haas.ui.ObservableValueRegistry; +import cz.it4i.fiji.haas.ui.UpdatableObservableValue.UpdateStatus; +import cz.it4i.fiji.haas_java_client.JobState; +import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.BenchmarkJob; + +public class ObservableBenchmarkJobRegistry extends ObservableValueRegistry<BenchmarkJob> { + + public ObservableBenchmarkJobRegistry(Consumer<BenchmarkJob> removeConsumer) { + super(t -> update(t), removeConsumer); + } + + private static UpdateStatus update(BenchmarkJob t) { + JobState oldState = t.getState(); + t.update(); + if (!Files.isDirectory(t.getDirectory())) { + return UpdateStatus.Deleted; + } + return oldState != t.getState() ? UpdateStatus.Updated : UpdateStatus.NotUpdated; + } + +} diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableTaskRegistry.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableTaskRegistry.java index 71876913b7daa56044916f17b844330e6f216967..595a057f5640d53d22c6d10745169da585a5e0ea 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableTaskRegistry.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableTaskRegistry.java @@ -3,26 +3,26 @@ package cz.it4i.fiji.haas_spim_benchmark.ui; import java.util.function.Consumer; import cz.it4i.fiji.haas.ui.ObservableValueRegistry; +import cz.it4i.fiji.haas.ui.UpdatableObservableValue.UpdateStatus; import cz.it4i.fiji.haas_java_client.JobState; import cz.it4i.fiji.haas_spim_benchmark.core.Task; import cz.it4i.fiji.haas_spim_benchmark.core.TaskComputation; -public class ObservableTaskRegistry extends ObservableValueRegistry<Task>{ +public class ObservableTaskRegistry extends ObservableValueRegistry<Task> { - public ObservableTaskRegistry( - Consumer<Task> removeConsumer) { - super(x->true, t->update(t), removeConsumer); + public ObservableTaskRegistry(Consumer<Task> removeConsumer) { + super(t -> update(t), removeConsumer); } - private static boolean update(Task t) { - boolean result = true; + private static UpdateStatus update(Task t) { + boolean updated = false; t.update(); - for(TaskComputation tc: t.getComputations()) { + for (TaskComputation tc : t.getComputations()) { JobState oldState = tc.getState(); tc.update(); - result &= oldState == tc.getState(); + updated |= oldState != tc.getState(); } - return result; + return updated ? UpdateStatus.Updated : UpdateStatus.NotUpdated; } diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java index 90cb1147eb28b679ca5014d879bd64d0ab87155a..d71b0839026caea333c10a89a34d110837ac87fc 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java @@ -43,7 +43,7 @@ public class SPIMPipelineProgressViewController implements FXFrame.Controller { public void setBenchmarkJob(BenchmarkJob job) { this.job = job; - registry = new ObservableTaskRegistry(task -> tasks.getItems().remove(registry.remove(task))); + registry = new ObservableTaskRegistry(task -> tasks.getItems().remove(registry.get(task))); fillTable(); }