diff --git a/app/alarm/ui/doc/images/configuration_editor.png b/app/alarm/ui/doc/images/configuration_editor.png index e78308aa00..7c92761d3c 100644 Binary files a/app/alarm/ui/doc/images/configuration_editor.png and b/app/alarm/ui/doc/images/configuration_editor.png differ diff --git a/app/alarm/ui/doc/images/configuration_editor_dialogs.png b/app/alarm/ui/doc/images/configuration_editor_dialogs.png index adb12ecc53..e6feca7bf1 100644 Binary files a/app/alarm/ui/doc/images/configuration_editor_dialogs.png and b/app/alarm/ui/doc/images/configuration_editor_dialogs.png differ diff --git a/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/Messages.java b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/Messages.java index 19a8c1f2c0..13272352db 100644 --- a/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/Messages.java +++ b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/Messages.java @@ -24,8 +24,11 @@ public class Messages public static String disableAlarmFailed; public static String disableAlarms; public static String disabled; + public static String disabledIndefinitely; public static String disableMenu; public static String disabledUntil; + public static String disabledCommonEnableDate; + public static String disabledVaryingEnableDate; public static String displays; public static String enableAlarmFailed; public static String enableAlarms; @@ -37,12 +40,10 @@ public class Messages public static String headerConfirmEnable; public static String indefinitely; public static String moveItemFailed; - public static String partlyDisabled; public static String promptTitle; - public static String promptContent; public static String removeComponentFailed; public static String renameItemFailed; - public static String timer; + public static String totalPVs; public static String unacknowledgeFailed; public static String withEnableDate; @@ -52,7 +53,7 @@ public class Messages NLS.initializeMessages(Messages.class); } - private Messages() + private Messages() { // prevent instantiation } diff --git a/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeHelper.java b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeHelper.java index afbd673d48..25e77114a6 100644 --- a/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeHelper.java +++ b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeHelper.java @@ -7,16 +7,22 @@ *******************************************************************************/ package org.phoebus.applications.alarm.ui.tree; -import java.util.List; +import java.text.MessageFormat; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.phoebus.applications.alarm.client.AlarmClient; import org.phoebus.applications.alarm.client.AlarmClientLeaf; import org.phoebus.applications.alarm.model.AlarmTreeItem; import org.phoebus.applications.alarm.model.AlarmTreePath; +import org.phoebus.applications.alarm.ui.Messages; import org.phoebus.ui.dialog.DialogHelper; import javafx.scene.control.TextInputDialog; import javafx.scene.control.TreeView; +import org.phoebus.util.time.TimestampFormats; /** @author Evan Smith */ @@ -104,18 +110,111 @@ public static boolean validateNewPath(String path, AlarmTreeItem root) item = item.getChild(path_elems[i]); if (null == item) { - // System.out.println("Path element " + path_elems[i] + " does not exist in the tree at that location."); return false; } // Make sure the path does not contain a PV. // PV cannot have children. if (item instanceof AlarmClientLeaf) { - // System.out.println("Path element " + path_elems[i] + " is a leaf."); return false; } } return true; } + + /** + * Collects {@link AlarmClientLeaf}s items. + * @param items A {@link List} of {@link AlarmTreeItem}s, typically selected by user in the tree view. This could + * be a mix of leaf and non-leaf nodes. Moreover, leaf nodes could be child nodes of non-leaf nodes + * in the {@link List}. + * @return A {@link Set} of only {@link AlarmClientLeaf}s, i.e. no duplicates even id user selection would indicate it. + */ + protected static Set getLeafItems(List> items){ + return items.stream().flatMap(item -> streamLeafItems(item)).collect(Collectors.toSet()); + } + + /** + * Collects {@link AlarmClientLeaf}s items. + * @param root The start node from where to get {@link AlarmClientLeaf}s. If this is an {@link AlarmClientLeaf}, it + * will be returned as the sole item in the {@link Set} + * @return A {@link Set} of only {@link AlarmClientLeaf}s. + */ + protected static Set getLeafItems(final AlarmTreeItem root) { + return streamLeafItems(root).collect(Collectors.toSet()); + } + + private static Stream streamLeafItems(final AlarmTreeItem alarmTreeItem){ + if (alarmTreeItem instanceof AlarmClientLeaf alarmClientLeaf){ + return Stream.of(alarmClientLeaf); + } + else { + return alarmTreeItem.getChildren().stream().flatMap(child -> streamLeafItems(child)); + } + } + + /** + * + * @param items {@link List} of {@link AlarmTreeItem}s that may be a mix of leaves and non-leaves, e.g. a user + * selection in the alarm tree view. + * @return A {@link TreeNodeInfo} object. + */ + public static TreeNodeInfo getTreeNodeInfo(List> items){ + Set leaves = getLeafItems(items); + int disabledIndefinitely = 0; + int disabledWithEnableDate = 0; + Optional localDateTime = Optional.empty(); + + for(AlarmClientLeaf leaf : leaves){ + if(!leaf.isEnabled()){ + LocalDateTime enableDate = leaf.getEnabledDate(); + if(enableDate != null){ + if(localDateTime.isPresent() && !localDateTime.get().equals(enableDate)){ + localDateTime = Optional.empty(); + } + else{ + localDateTime = Optional.of(enableDate); + } + disabledWithEnableDate++; + } + else{ + disabledIndefinitely++; + } + } + } + return new TreeNodeInfo(leaves, disabledIndefinitely, disabledWithEnableDate, localDateTime); + } + + /** + * + * @param item A {@link AlarmTreeItem}, can be either a leaf or non-leaf in the alarm tree view. + * @return A {@link TreeNodeInfo} object. + */ + public static TreeNodeInfo getTreeNodeInfo(AlarmTreeItem item){ + return getTreeNodeInfo(List.of(item)); + } + + /** + * Formats a {@link TreeNodeInfo} object based on its content. + * @param treeNodeInfo A {@link TreeNodeInfo} + * @return A string describing total number of leaves, disabled leaves (if any) and an enable date where applicable. + */ + public static String treeNodeInfoToString(TreeNodeInfo treeNodeInfo){ + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(MessageFormat.format(Messages.totalPVs, treeNodeInfo.leaves().size())); + if(treeNodeInfo.disabled() > 0){ + stringBuilder.append(", ").append(MessageFormat.format(Messages.disabledIndefinitely, treeNodeInfo.disabled())); + } + int disabledWithEnableDate = treeNodeInfo.disabledWithEnableDate(); + if(disabledWithEnableDate > 0){ + stringBuilder.append(", "); + if(treeNodeInfo.commonEnableDate().isPresent()){ + stringBuilder.append(MessageFormat.format(Messages.disabledCommonEnableDate, TimestampFormats.SECONDS_FORMAT.format(treeNodeInfo.commonEnableDate().get()), disabledWithEnableDate)); + } + else{ + stringBuilder.append(MessageFormat.format(Messages.disabledVaryingEnableDate, disabledWithEnableDate)); + } + } + return stringBuilder.toString(); + } } diff --git a/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeViewCell.java b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeViewCell.java index a2646d2e10..3b5d89e1f5 100644 --- a/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeViewCell.java +++ b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeViewCell.java @@ -7,6 +7,7 @@ *******************************************************************************/ package org.phoebus.applications.alarm.ui.tree; +import javafx.application.Platform; import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.TreeCell; @@ -15,20 +16,16 @@ import javafx.scene.layout.HBox; import javafx.scene.paint.Color; -import javafx.util.Pair; import org.phoebus.applications.alarm.client.AlarmClientLeaf; -import org.phoebus.applications.alarm.client.AlarmClientNode; import org.phoebus.applications.alarm.client.ClientState; import org.phoebus.applications.alarm.model.AlarmTreeItem; import org.phoebus.applications.alarm.model.SeverityLevel; import org.phoebus.applications.alarm.ui.AlarmUI; import org.phoebus.applications.alarm.ui.Messages; +import org.phoebus.framework.jobs.JobManager; +import org.phoebus.util.time.TimestampFormats; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; /** TreeCell for AlarmTreeItem * @author Kay Kasemir @@ -82,10 +79,8 @@ protected void updateItem(final AlarmTreeItem item, final boolean empty) setGraphic(null); else { - final SeverityLevel severity; - if (item instanceof AlarmClientLeaf) + if (item instanceof AlarmClientLeaf leaf) { - final AlarmClientLeaf leaf = (AlarmClientLeaf) item; final ClientState state = leaf.getState(); final StringBuilder text = new StringBuilder(); @@ -111,7 +106,7 @@ protected void updateItem(final AlarmTreeItem item, final boolean empty) } else { if (leaf.getEnabled().enabled_date != null) { LocalDateTime enabledDate = leaf.getEnabled().enabled_date; - String enabledDateString = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(enabledDate); + String enabledDateString = TimestampFormats.SECONDS_FORMAT.format(enabledDate); disabledTimerIndicator.setText("(" + Messages.disabledUntil + " " + enabledDateString + ")"); } else { disabledTimerIndicator.setText("(" + Messages.disabled + ")"); @@ -126,45 +121,25 @@ protected void updateItem(final AlarmTreeItem item, final boolean empty) } else { - final AlarmClientNode node = (AlarmClientNode) item; - - Optional> maybeLeavesDisabledStatusBooleanPair = leavesDisabledStatus(node); - if (maybeLeavesDisabledStatusBooleanPair.isPresent() && !maybeLeavesDisabledStatusBooleanPair.get().getKey().equals(LeavesDisabledStatus.AllEnabled)) { - Pair leavesDisabledStatusBooleanPair = maybeLeavesDisabledStatusBooleanPair.get(); - - if (leavesDisabledStatusBooleanPair.getKey().equals(LeavesDisabledStatus.AllDisabled)) { - if (leavesDisabledStatusBooleanPair.getValue()) { - disabledTimerIndicator.setText("(" + Messages.disabled + "; " + Messages.timer + ")"); - } - else { - disabledTimerIndicator.setText("(" + Messages.disabled + ")"); - } - } - else if (leavesDisabledStatusBooleanPair.getKey().equals(LeavesDisabledStatus.SomeEnabledSomeDisabled)) { - if (leavesDisabledStatusBooleanPair.getValue()) { - disabledTimerIndicator.setText("(" + Messages.partlyDisabled + "; " + Messages.timer + ")"); + // To get the information to display on non-leaf nodes one will need to walk a potentially deep + // tree structure, so this is done off the UI thread. + JobManager.schedule("Get Tree Node Info", monitor -> { + TreeNodeInfo info = AlarmTreeHelper.getTreeNodeInfo(item); + Platform.runLater(() -> { + String labelText = item.getName(); + label.setText(labelText); + SeverityLevel severityLevel = item.getState().severity; + disabledTimerIndicator.setText(AlarmTreeHelper.treeNodeInfoToString(info)); + if(info.disabled() + info.disabledWithEnableDate() == info.leaves().size()){ + label.setTextFill(Color.GRAY); } - else { - disabledTimerIndicator.setText("(" + Messages.partlyDisabled + ")"); + else{ + label.setTextFill(AlarmUI.getColor(severityLevel)); } - } - } - else { - disabledTimerIndicator.setText(""); - } - - String labelText = item.getName(); - label.setText(labelText); - - severity = node.getState().severity; - if (maybeLeavesDisabledStatusBooleanPair.isPresent() && maybeLeavesDisabledStatusBooleanPair.get().getKey().equals(LeavesDisabledStatus.AllDisabled)) { - label.setTextFill(Color.GRAY); - } - else { - label.setTextFill(AlarmUI.getColor(severity)); - } - label.setBackground(AlarmUI.getBackground(severity)); - image.setImage(AlarmUI.getIcon(severity)); + label.setBackground(AlarmUI.getBackground(severityLevel)); + image.setImage(AlarmUI.getIcon(severityLevel)); + }); + }); } // Profiler showed small advantage when skipping redundant 'setGraphic' call if (getGraphic() != content) @@ -175,61 +150,4 @@ else if (leavesDisabledStatusBooleanPair.getKey().equals(LeavesDisabledStatus.So private boolean isLeafDisabled(AlarmClientLeaf alarmClientLeaf) { return !alarmClientLeaf.isEnabled() || alarmClientLeaf.getState().isDynamicallyDisabled(); } - - private enum LeavesDisabledStatus { - AllEnabled, - SomeEnabledSomeDisabled, - AllDisabled, - } - - // leavesDisabledStatus() optionally returns a pair. - // - // If a pair is _not_ returned, it means that there exist no leaves - // in 'alarmClientNode', and the disabled status is undefined. - // - // When a pair _is_ returned, the first component describes - // whether all leaves are disabled, all leaves are enabled, or whether - // some leaves are enabled and some are disabled, and the second component - // indicates whether one or more disabled leaves have a timer associated - // with them ('true'), at the end of which they will automatically become - // enabled again. When the second component is 'false' there is no - // associated timer. - private Optional> leavesDisabledStatus(AlarmClientNode alarmClientNode) { - List> leavesDisabledStatusList = new LinkedList<>(); - for (var child : alarmClientNode.getChildren()) { - if (child instanceof AlarmClientLeaf alarmClientLeaf) { - - if (isLeafDisabled(alarmClientLeaf)) { - boolean timer = alarmClientLeaf.getEnabled().enabled_date != null; - leavesDisabledStatusList.add(new Pair<>(LeavesDisabledStatus.AllDisabled, timer)); - } - else { - leavesDisabledStatusList.add(new Pair<>(LeavesDisabledStatus.AllEnabled, false)); - } - } - else if (child instanceof AlarmClientNode alarmClientNode1 && !alarmClientNode1.getChildren().isEmpty()) { - if (leavesDisabledStatus(alarmClientNode1).isPresent()) { - leavesDisabledStatusList.add(leavesDisabledStatus(alarmClientNode1).get()); - } - // If leavesDisabledStatus(alarmClientNode1).isPresent() evaluates to false, there are no leaves and therefore no result. - } - else if (child instanceof AlarmClientNode alarmClientNode1 && alarmClientNode1.getChildren().isEmpty()) { - // Don't add any LeavesDisabledStatus, since there are no leaves - } - else { - throw new RuntimeException("Missing case: " + child.getClass().getName()); - } - } - - Optional> leavesDisabledStatus = leavesDisabledStatusList.stream().reduce((status1, status2) -> { - if (status1.getKey().equals(status2.getKey())) { - return new Pair<>(status1.getKey(), status1.getValue() || status2.getValue()); - } - else { - return new Pair<>(LeavesDisabledStatus.SomeEnabledSomeDisabled, status1.getValue() || status2.getValue()); - } - }); - - return leavesDisabledStatus; - } } diff --git a/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/DisableAction.java b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/DisableAction.java index 01445f4d9f..6bcc61d255 100644 --- a/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/DisableAction.java +++ b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/DisableAction.java @@ -23,11 +23,11 @@ import java.text.MessageFormat; import java.time.LocalDateTime; import java.util.*; -import java.util.stream.Collectors; +import java.util.concurrent.atomic.AtomicReference; public class DisableAction extends Menu { - private AlarmClient alarmClient; + private final AlarmClient alarmClient; public DisableAction(final Node node, final AlarmClient model, final List> items) { this.alarmClient = model; @@ -37,19 +37,13 @@ public DisableAction(final Node node, final AlarmClient model, final List totalLeafItems = new HashSet<>(); - Set leafItemsWithEnableDate = new HashSet<>(); - setOnShowing(e -> { - - new Thread(() -> { - if (checkEnableDates(items, totalLeafItems, leafItemsWithEnableDate)) { - Platform.runLater(() -> disableUntil.setDisable(false)); - } - - }).start(); - - - }); + AtomicReference treeNodeInfo = new AtomicReference<>(); + setOnShowing(e -> JobManager.schedule("Get Tree Node Info", monitor -> { + treeNodeInfo.set(AlarmTreeHelper.getTreeNodeInfo(items)); + if(treeNodeInfo.get().disabledWithEnableDate() == 0 || treeNodeInfo.get().commonEnableDate().isPresent()) { + Platform.runLater(() -> disableUntil.setDisable(false)); + } + })); disableUntil.setOnAction(e -> { final FXMLLoader fxmlLoader = new FXMLLoader(); fxmlLoader.setResources(NLS.getMessages(Messages.class)); @@ -64,13 +58,10 @@ public DisableAction(final Node node, final AlarmClient model, final List dlg = new Dialog<>(); dlg.setTitle("Disable until"); dlg.getDialogPane().setContent(root); @@ -82,75 +73,12 @@ public DisableAction(final Node node, final AlarmClient model, final List localDateTime = dlg.showAndWait(); - if (localDateTime.isPresent()) { - updateEnablement(localDateTime.get(), totalLeafItems); - System.out.println(localDateTime.get()); - } - + localDateTime.ifPresent(dateTime -> updateEnablement(dateTime, treeNodeInfo.get().leaves())); }); getItems().addAll(disable, disableUntil); } - /** - * Divides items the user clicked on in leaf items and non leaf items - * Returns true when all leaf items of the same structure either have no enable dates or all the same - * Returns false if the enable dates differ - * - * @param items Root item - * @param totalLeafItems {@link Set} that will hold all leaf nodes - * @param leafItemsWithEnableDate {@link Set} that will hold all leaf nodes with non-null enable date - * - */ - - public static boolean checkEnableDates(final List> items, Set totalLeafItems, Set leafItemsWithEnableDate) { - Set> nonLeafItems = - items.stream().filter(i -> !(i instanceof AlarmClientLeaf)).collect(Collectors.toSet()); - Set> leafItems = - items.stream().filter(i -> (i instanceof AlarmClientLeaf)).collect(Collectors.toSet()); - nonLeafItems.forEach(i -> findAffectedPVs(i, totalLeafItems, leafItemsWithEnableDate)); - leafItems.forEach(i -> findAffectedPVs(i, totalLeafItems, leafItemsWithEnableDate)); - if (leafItemsWithEnableDate.isEmpty()) { - return true; - } else if (totalLeafItems.size() != leafItemsWithEnableDate.size()) { - return false; - } else { - LocalDateTime firstDate = leafItemsWithEnableDate.iterator().next().getEnabledDate(); - for (AlarmClientLeaf alarmClientLeaf : totalLeafItems) { - LocalDateTime currDate = alarmClientLeaf.getEnabledDate(); - if (!firstDate.equals(currDate)) { - return false; - } - } - return true; - } - } - - - /** - * Recursively counts alarm tree items in a subtree to find total number and - * number of disabled with enable date. - * - * @param item Root item - * @param total {@link Set} that will hold all leaf nodes - * @param withEnableDate {@link Set} that will hold all leaf nodes with non-null enable date - * - */ - public static void findAffectedPVs(final AlarmTreeItem item, final Set total, final Set withEnableDate) { - if (item instanceof AlarmClientLeaf) { - final AlarmClientLeaf pv = (AlarmClientLeaf) item; - total.add(pv); - if (pv.getEnabledDate() != null) { - withEnableDate.add(pv); - } - } else { - for (AlarmTreeItem sub : item.getChildren()) { - findAffectedPVs(sub, total, withEnableDate); - } - } - } - - /** * Updates a component to disable a hierarchy of PVs with an enable date. * diff --git a/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/TreeNodeInfo.java b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/TreeNodeInfo.java new file mode 100644 index 0000000000..5ce8a2cd13 --- /dev/null +++ b/app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/TreeNodeInfo.java @@ -0,0 +1,18 @@ +package org.phoebus.applications.alarm.ui.tree; + +import org.phoebus.applications.alarm.client.AlarmClientLeaf; + +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.Set; + +/** + * Data object defining a set of properties for the leaves + * @param leaves A {@link Set} of {@link AlarmClientLeaf}s. Note that the elements do not necessarily share the same parent node. + * @param disabled Number of {@link AlarmClientLeaf}s in {@link #leaves} disabled indefinitely, i.e. disabled with no enable date set. + * @param disabledWithEnableDate Number of {@link AlarmClientLeaf}s disabled with an enable date set. + * @param commonEnableDate Non-empty {@link Optional} if all the {@link AlarmClientLeaf}s counted by {@link #disabledWithEnableDate} + * have the same enable date. + */ +public record TreeNodeInfo(Set leaves, int disabled, int disabledWithEnableDate, Optional commonEnableDate) { +} diff --git a/app/alarm/ui/src/main/resources/org/phoebus/applications/alarm/ui/messages.properties b/app/alarm/ui/src/main/resources/org/phoebus/applications/alarm/ui/messages.properties index a66ace171d..83b48427d4 100644 --- a/app/alarm/ui/src/main/resources/org/phoebus/applications/alarm/ui/messages.properties +++ b/app/alarm/ui/src/main/resources/org/phoebus/applications/alarm/ui/messages.properties @@ -40,9 +40,12 @@ detail=Detail disabled=Disabled disableAlarmFailed=Failed to disable alarm disableAlarms=Disable Alarms +disabledIndefinitely=Disabled: {0} disableMenu=Disable... disabledUntil=Disabled until disableUntil=Disable until: +disabledCommonEnableDate=Disabled until {0}: {1} +disabledVaryingEnableDate=Disabled (varying enable date): {0} displays=Displays: enabled=Enabled enablingFilter=Enabling Filter: @@ -63,11 +66,9 @@ latch=Latch latchTooltip=Latch alarm until acknowledged? moveItemFailed=Failed to move item option=Option -partlyDisabled=Partly disabled partlyDisabled2=(Partly disabled) path=Path: promptTitle=Absolute Date is set to a point in time in the past -promptContent=The option 'disable until' must be set to a point in time in the future. relativeDateLabel=Relative Date: relativeDateTooltip=Select a predefined duration for disabling the alarm removeComponentFailed=Failed to remove component @@ -79,5 +80,6 @@ tooltipDeleteSelectedItems=Delete selected table items tooltipMoveEditDetail=Edit the detail field of table item tooltipMoveTableItemDown=Move table item down tooltipMoveTableItemUp=Move table item up +totalPVs=PVs: {0} unacknowledgeFailed=Failed to unacknowledge alarm(s) withEnableDate=With Enable Date diff --git a/app/alarm/ui/src/main/resources/org/phoebus/applications/alarm/ui/messages_fr.properties b/app/alarm/ui/src/main/resources/org/phoebus/applications/alarm/ui/messages_fr.properties index 6c42024745..b02cbfa9dd 100644 --- a/app/alarm/ui/src/main/resources/org/phoebus/applications/alarm/ui/messages_fr.properties +++ b/app/alarm/ui/src/main/resources/org/phoebus/applications/alarm/ui/messages_fr.properties @@ -49,7 +49,6 @@ partlyDisabled=Partiellement désactivé partlyDisabled2=(Partiellement désactivé) path=Chemin : promptTitle=La date absolue est définie à un moment situé dans le passé -promptContent=L'option 'désactiver jusqu'à' doit être définie à un moment situé dans le futur. relativeDateLabel=Date relative : relativeDateTooltip=Sélectionner une durée prédéfinie pour la désactivation de l'alarme removeComponentFailed=Échec de la suppression du composant diff --git a/app/alarm/ui/src/test/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeHelperTest.java b/app/alarm/ui/src/test/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeHelperTest.java new file mode 100644 index 0000000000..eb6e3f3fcf --- /dev/null +++ b/app/alarm/ui/src/test/java/org/phoebus/applications/alarm/ui/tree/AlarmTreeHelperTest.java @@ -0,0 +1,152 @@ +package org.phoebus.applications.alarm.ui.tree; + +import org.junit.jupiter.api.Test; +import org.phoebus.applications.alarm.client.AlarmClientLeaf; +import org.phoebus.applications.alarm.client.AlarmClientNode; +import org.phoebus.applications.alarm.model.AlarmTreeItem; +import org.phoebus.applications.alarm.model.BasicState; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +public class AlarmTreeHelperTest { + + @Test + public void testGetAlarmLeaves1() { + AlarmClientLeaf leaf0 = new AlarmClientLeaf("test/path/0", "testName0"); + AlarmClientLeaf leaf1 = new AlarmClientLeaf("test/path/1", "testName1"); + AlarmClientLeaf leaf2 = new AlarmClientLeaf("test/path/2", "testName2"); + + assertEquals(3, AlarmTreeHelper.getLeafItems(List.of(leaf0, leaf1, leaf2)).size()); + } + + @Test + public void testGetAlarmLeaves2() { + AlarmTreeItem parent1 = new AlarmClientNode("/root", "parent1"); + AlarmTreeItem parent2 = new AlarmClientNode("/parent", "parent2"); + AlarmClientLeaf child1 = new AlarmClientLeaf("/paren1", "child1"); + parent2.addToParent(parent1); + child1.addToParent(parent1); + AlarmClientLeaf child2 = new AlarmClientLeaf("/parent2", "child2"); + child2.addToParent(parent1); + + assertEquals(2, AlarmTreeHelper.getLeafItems(List.of(parent1, parent2)).size()); + } + + @Test + public void testGetAlarmLeaves3() { + AlarmTreeItem parent1 = new AlarmClientNode("/root", "parent1"); + AlarmTreeItem parent2 = new AlarmClientNode("/parent", "parent2"); + AlarmClientLeaf child1 = new AlarmClientLeaf("/parent1", "child1"); + parent2.addToParent(parent1); + child1.addToParent(parent1); + AlarmClientLeaf child2 = new AlarmClientLeaf("/parent2", "child2"); + child2.addToParent(parent2); + + assertEquals(2, AlarmTreeHelper.getLeafItems(parent1).size()); + } + + @Test + public void testGetAlarmLeaves4() { + AlarmTreeItem parent1 = new AlarmClientNode("/root", "parent1"); + AlarmTreeItem parent2 = new AlarmClientNode("/parent", "parent2"); + AlarmClientLeaf child1 = new AlarmClientLeaf("/paren1", "child1"); + parent2.addToParent(parent1); + child1.addToParent(parent1); + AlarmClientLeaf child2 = new AlarmClientLeaf("/parent2", "child2"); + child2.addToParent(parent2); + AlarmClientLeaf child3 = new AlarmClientLeaf("/parent2", "child3"); + child3.setEnabled(false); + child3.addToParent(parent2); + + Set leaves = AlarmTreeHelper.getLeafItems(List.of(parent1, child3, new AlarmClientLeaf("/none", "child4"))); + + assertEquals(4, leaves.size()); + } + + @Test + public void testGetAlarmNodeInfo1() { + AlarmTreeItem parent1 = new AlarmClientNode("/root", "parent1"); + AlarmClientLeaf leaf0 = new AlarmClientLeaf("test/path/0", "testName0"); + leaf0.addToParent(parent1); + AlarmClientLeaf leaf1 = new AlarmClientLeaf("test/path/1", "testName1"); + leaf1.addToParent(parent1); + AlarmClientLeaf leaf2 = new AlarmClientLeaf("test/path/2", "testName2"); + leaf2.addToParent(parent1); + + TreeNodeInfo treeNodeInfo = AlarmTreeHelper.getTreeNodeInfo(parent1); + + assertEquals(3, treeNodeInfo.leaves().size()); + assertEquals(0, treeNodeInfo.disabled()); + assertEquals(0, treeNodeInfo.disabledWithEnableDate()); + assertTrue(treeNodeInfo.commonEnableDate().isEmpty()); + } + + @Test + public void testGetAlarmNodeContent2() { + AlarmTreeItem parent1 = new AlarmClientNode("/root", "parent1"); + AlarmClientLeaf leaf0 = new AlarmClientLeaf("test/path/0", "testName0"); + leaf0.setEnabled(false); + leaf0.addToParent(parent1); + AlarmClientLeaf leaf1 = new AlarmClientLeaf("test/path/1", "testName1"); + leaf1.addToParent(parent1); + AlarmClientLeaf leaf2 = new AlarmClientLeaf("test/path/2", "testName2"); + leaf2.addToParent(parent1); + + TreeNodeInfo treeNodeInfo = AlarmTreeHelper.getTreeNodeInfo(parent1); + + assertEquals(3, treeNodeInfo.leaves().size()); + assertEquals(1, treeNodeInfo.disabled()); + assertEquals(0, treeNodeInfo.disabledWithEnableDate()); + assertTrue(treeNodeInfo.commonEnableDate().isEmpty()); + + } + + @Test + public void testGetAlarmNodeContent3() { + AlarmTreeItem parent1 = new AlarmClientNode("/root", "parent1"); + LocalDateTime localDateTime1 = LocalDateTime.now().plusDays(1); + LocalDateTime localDateTime2 = localDateTime1.plusDays(2); + AlarmClientLeaf leaf0 = new AlarmClientLeaf("test/path/0", "testName0"); + leaf0.setEnabledDate(localDateTime1); + leaf0.addToParent(parent1); + AlarmClientLeaf leaf1 = new AlarmClientLeaf("test/path/1", "testName1"); + leaf1.setEnabledDate(localDateTime2); + leaf1.addToParent(parent1); + AlarmClientLeaf leaf2 = new AlarmClientLeaf("test/path/2", "testName2"); + leaf2.addToParent(parent1); + + TreeNodeInfo treeNodeInfo = AlarmTreeHelper.getTreeNodeInfo(parent1); + + assertEquals(3, treeNodeInfo.leaves().size()); + assertEquals(0, treeNodeInfo.disabled()); + assertEquals(2, treeNodeInfo.disabledWithEnableDate()); + assertTrue(treeNodeInfo.commonEnableDate().isEmpty()); + } + + @Test + public void testGetAlarmNodeContent4() { + AlarmTreeItem parent1 = new AlarmClientNode("/root", "parent1"); + LocalDateTime localDateTime1 = LocalDateTime.now().plusDays(1); + AlarmClientLeaf leaf0 = new AlarmClientLeaf("test/path/0", "testName0"); + leaf0.setEnabledDate(localDateTime1); + leaf0.addToParent(parent1); + AlarmClientLeaf leaf1 = new AlarmClientLeaf("test/path/1", "testName1"); + leaf1.setEnabledDate(localDateTime1); + leaf1.addToParent(parent1); + AlarmClientLeaf leaf2 = new AlarmClientLeaf("test/path/2", "testName2"); + leaf2.setEnabled(false); + leaf2.addToParent(parent1); + + TreeNodeInfo treeNodeInfo = AlarmTreeHelper.getTreeNodeInfo(parent1); + + assertEquals(3, treeNodeInfo.leaves().size()); + assertEquals(1, treeNodeInfo.disabled()); + assertEquals(2, treeNodeInfo.disabledWithEnableDate()); + assertTrue(treeNodeInfo.commonEnableDate().isPresent()); + assertEquals(localDateTime1, treeNodeInfo.commonEnableDate().get()); + } +} diff --git a/app/alarm/ui/src/test/java/org/phoebus/applications/alarm/ui/tree/CheckEnableDatesTest.java b/app/alarm/ui/src/test/java/org/phoebus/applications/alarm/ui/tree/CheckEnableDatesTest.java deleted file mode 100644 index edba2cef87..0000000000 --- a/app/alarm/ui/src/test/java/org/phoebus/applications/alarm/ui/tree/CheckEnableDatesTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.phoebus.applications.alarm.ui.tree; - -import org.junit.jupiter.api.Test; -import org.phoebus.applications.alarm.client.AlarmClientLeaf; -import org.phoebus.applications.alarm.model.AlarmTreeItem; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class CheckEnableDatesTest { - - AlarmClientLeaf leaf0 = new AlarmClientLeaf("test/path/0", "testName0"); - AlarmClientLeaf leaf1 = new AlarmClientLeaf("test/path/1", "testName1"); - AlarmClientLeaf leaf2 = new AlarmClientLeaf("test/path/2", "testName2"); - - List> items = new ArrayList<>(); - Set totalLeafItems = new HashSet<>(); - Set leavesWithEnableDate = new HashSet<>(); - - LocalDateTime testTime = LocalDateTime.now().plusDays(3); - - @Test - public void noEnableDates(){ - items.add(leaf0); - items.add(leaf1); - items.add(leaf2); - - assertTrue(DisableAction.checkEnableDates(items, totalLeafItems, leavesWithEnableDate)); - } - - @Test - public void identicalEnableDates(){ - leaf0.setEnabledDate(testTime); - leaf1.setEnabledDate(testTime); - leaf2.setEnabledDate(testTime); - - items.add(leaf0); - items.add(leaf1); - items.add(leaf2); - - assertTrue(DisableAction.checkEnableDates(items, totalLeafItems, leavesWithEnableDate)); - } - - @Test - public void differentEnableDates(){ - leaf0.setEnabledDate(testTime); - leaf1.setEnabledDate(testTime.plusDays(1)); - leaf2.setEnabledDate(testTime); - - items.add(leaf0); - items.add(leaf1); - items.add(leaf2); - - assertFalse(DisableAction.checkEnableDates(items, totalLeafItems, leavesWithEnableDate)); - } - - @Test - public void sameSize(){ - leaf0.setEnabledDate(testTime); - leaf1.setEnabledDate(testTime); - - items.add(leaf0); - items.add(leaf1); - items.add(leaf2); - - assertFalse(DisableAction.checkEnableDates(items, totalLeafItems, leavesWithEnableDate)); - } -} diff --git a/app/alarm/ui/src/test/java/org/phoebus/applications/alarm/ui/tree/DisableActionTest.java b/app/alarm/ui/src/test/java/org/phoebus/applications/alarm/ui/tree/DisableActionTest.java deleted file mode 100644 index f87e77fb30..0000000000 --- a/app/alarm/ui/src/test/java/org/phoebus/applications/alarm/ui/tree/DisableActionTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2025 European Spallation Source ERIC. - */ - -package org.phoebus.applications.alarm.ui.tree; - -import org.junit.jupiter.api.Test; -import org.phoebus.applications.alarm.client.AlarmClientLeaf; -import org.phoebus.applications.alarm.client.AlarmClientNode; -import org.phoebus.applications.alarm.model.AlarmTreeItem; -import org.phoebus.applications.alarm.model.BasicState; -import org.phoebus.applications.alarm.model.EnabledState; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class DisableActionTest { - - @Test - public void testFindAffectedPvs_5() { - AlarmTreeItem parent1 = new AlarmClientNode("/root", "parent1"); - AlarmTreeItem parent2 = new AlarmClientNode("/parent", "parent2"); - AlarmClientLeaf child1 = new AlarmClientLeaf("/paren1", "child1"); - parent2.addToParent(parent1); - child1.setEnabled(false); - child1.addToParent(parent1); - AlarmClientLeaf child2 = new AlarmClientLeaf("/parent2", "child2"); - child2.addToParent(parent2); - AlarmClientLeaf child3 = new AlarmClientLeaf("/parent2", "child3"); - child3.setEnabled(new EnabledState(LocalDateTime.now())); - child3.addToParent(parent2); - - Set total = new HashSet<>(); - Set withEnableDate = new HashSet<>(); - - DisableAction.findAffectedPVs(parent1, total, withEnableDate); - - assertEquals(3, total.size()); - assertEquals(1, withEnableDate.size()); - } -}