Browse Source

Bind countOfWarnSeverity and countOfCritSeverity to list

Sebastian Stenzel 3 years ago
parent
commit
f85f953668

+ 27 - 61
main/ui/src/main/java/org/cryptomator/ui/health/CheckDetailController.java

@@ -1,31 +1,27 @@
 package org.cryptomator.ui.health;
 
 import com.tobiasdiez.easybind.EasyBind;
+import com.tobiasdiez.easybind.EasyObservableList;
+import com.tobiasdiez.easybind.Subscription;
 import com.tobiasdiez.easybind.optional.OptionalBinding;
 import org.cryptomator.cryptofs.health.api.DiagnosticResult;
 import org.cryptomator.ui.common.FxController;
 
 import javax.inject.Inject;
 import javafx.beans.binding.Binding;
-import javafx.beans.property.LongProperty;
 import javafx.beans.property.ObjectProperty;
-import javafx.beans.property.SimpleLongProperty;
 import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
-import javafx.collections.ListChangeListener;
-import javafx.collections.ObservableList;
 import javafx.concurrent.Worker;
 import javafx.fxml.FXML;
 import javafx.scene.control.ListView;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
 
 @HealthCheckScoped
 public class CheckDetailController implements FxController {
 
-	private final Map<ObservableList<DiagnosticResult>, WarnAndErrorEntry> cachedWarnAndCritCounts;
-	private final Binding<ObservableList<DiagnosticResult>> results;
+	private final EasyObservableList<DiagnosticResult> results;
 	private final OptionalBinding<Worker.State> taskState;
 	private final Binding<String> taskName;
 	private final Binding<Number> taskDuration;
@@ -37,15 +33,15 @@ public class CheckDetailController implements FxController {
 	private final Binding<Boolean> taskSucceeded;
 	private final Binding<Boolean> taskFailed;
 	private final Binding<Boolean> taskCancelled;
-	private final LongProperty countOfWarnSeverity;
-	private final LongProperty countOfCritSeverity;
+	private final Binding<Number> countOfWarnSeverity;
+	private final Binding<Number> countOfCritSeverity;
 
 	public ListView<DiagnosticResult> resultsListView;
+	private Subscription resultSubscription;
 
 	@Inject
 	public CheckDetailController(ObjectProperty<HealthCheckTask> selectedTask, ResultListCellFactory resultListCellFactory) {
-		selectedTask.addListener(this::rebindWarnAndCritProperties);
-		this.results = EasyBind.wrapNullable(selectedTask).map(HealthCheckTask::results).orElse(FXCollections.emptyObservableList());
+		this.results = EasyBind.wrapList(FXCollections.observableArrayList());
 		this.taskState = EasyBind.wrapNullable(selectedTask).mapObservable(HealthCheckTask::stateProperty);
 		this.taskName = EasyBind.wrapNullable(selectedTask).map(HealthCheckTask::getTitle).orElse("");
 		this.taskDuration = EasyBind.wrapNullable(selectedTask).mapObservable(HealthCheckTask::durationInMillisProperty).orElse(-1L);
@@ -57,46 +53,27 @@ public class CheckDetailController implements FxController {
 		this.taskFailed = taskState.map(Worker.State.FAILED::equals).orElse(false);
 		this.taskCancelled = taskState.map(Worker.State.CANCELLED::equals).orElse(false);
 		this.taskFinished = EasyBind.combine(taskSucceeded, taskFailed, taskCancelled, (a, b, c) -> a || b || c);
-		this.countOfWarnSeverity = new SimpleLongProperty(0);
-		this.countOfCritSeverity = new SimpleLongProperty(0);
-		this.cachedWarnAndCritCounts = new IdentityHashMap<>(); //important to use an identity hashmap, because collections violate the immnutable hashkey contract
-	}
-
-	private synchronized void rebindWarnAndCritProperties(ObservableValue<? extends HealthCheckTask> observable, HealthCheckTask oldVal, HealthCheckTask newVal) {
-		//create and cache properites for the newList, if not already present
-		final var listToUpdate = newVal.results();
-		cachedWarnAndCritCounts.computeIfAbsent(listToUpdate, key -> {
-			var warnProperty = new SimpleLongProperty(countSeverityInList(listToUpdate, DiagnosticResult.Severity.WARN));
-			var errProperty = new SimpleLongProperty(countSeverityInList(listToUpdate, DiagnosticResult.Severity.CRITICAL));
-			return new WarnAndErrorEntry(warnProperty, errProperty);
-		});
-		listToUpdate.addListener(this::updateListSpecificWarnAndCritCount);
-
-		//updateBindings
-		countOfCritSeverity.bind(cachedWarnAndCritCounts.get(listToUpdate).errorCount);
-		countOfWarnSeverity.bind(cachedWarnAndCritCounts.get(listToUpdate).warningCount);
-	}
-
-	private synchronized void updateListSpecificWarnAndCritCount(ListChangeListener.Change<? extends DiagnosticResult> c) {
-		long tmpErr = cachedWarnAndCritCounts.get(c.getList()).errorCount.get();
-		long tmpWarn = cachedWarnAndCritCounts.get(c.getList()).warningCount.get();
-		while (c.next()) {
-			if (c.wasAdded()) {
-				tmpWarn += countSeverityInList(c.getAddedSubList(), DiagnosticResult.Severity.WARN);
-				tmpErr += countSeverityInList(c.getAddedSubList(), DiagnosticResult.Severity.CRITICAL);
-			}
+		this.countOfWarnSeverity = results.reduce(countSeverity(DiagnosticResult.Severity.WARN));
+		this.countOfCritSeverity = results.reduce(countSeverity(DiagnosticResult.Severity.CRITICAL));
+		selectedTask.addListener(this::selectedTaskChanged);
+	}
+
+	private void selectedTaskChanged(ObservableValue<? extends HealthCheckTask> observable, HealthCheckTask oldValue, HealthCheckTask newValue) {
+		if (resultSubscription != null) {
+			resultSubscription.unsubscribe();
+		}
+		if (newValue != null) {
+			resultSubscription = EasyBind.bindContent(results, newValue.results());
 		}
-		cachedWarnAndCritCounts.get(c.getList()).errorCount.set(tmpErr);
-		cachedWarnAndCritCounts.get(c.getList()).warningCount.set(tmpWarn);
 	}
 
-	private long countSeverityInList(List<? extends DiagnosticResult> list, DiagnosticResult.Severity severityToCount) {
-		return list.stream().map(DiagnosticResult::getServerity).filter(severityToCount::equals).count();
+	private Function<Stream<? extends DiagnosticResult>, Long> countSeverity(DiagnosticResult.Severity severity) {
+		return stream -> stream.filter(item -> severity.equals(item.getServerity())).count();
 	}
 
 	@FXML
 	public void initialize() {
-		resultsListView.itemsProperty().bind(results);
+		resultsListView.setItems(results);
 		resultsListView.setCellFactory(resultListCellFactory);
 	}
 
@@ -119,18 +96,18 @@ public class CheckDetailController implements FxController {
 	}
 
 	public long getCountOfWarnSeverity() {
-		return countOfWarnSeverity.get();
+		return countOfWarnSeverity.getValue().longValue();
 	}
 
-	public LongProperty countOfWarnSeverityProperty() {
+	public Binding<Number> countOfWarnSeverityProperty() {
 		return countOfWarnSeverity;
 	}
 
 	public long getCountOfCritSeverity() {
-		return countOfCritSeverity.get();
+		return countOfCritSeverity.getValue().longValue();
 	}
 
-	public LongProperty countOfCritSeverityProperty() {
+	public Binding<Number> countOfCritSeverityProperty() {
 		return countOfCritSeverity;
 	}
 
@@ -190,15 +167,4 @@ public class CheckDetailController implements FxController {
 		return taskCancelled;
 	}
 
-	private static class WarnAndErrorEntry {
-
-		WarnAndErrorEntry(LongProperty warningCount, LongProperty errorCount) {
-			this.warningCount = warningCount;
-			this.errorCount = errorCount;
-		}
-
-		final LongProperty warningCount;
-		final LongProperty errorCount;
-	}
-
 }