1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.contentapp.action;
35
36 import info.magnolia.i18nsystem.SimpleTranslator;
37 import info.magnolia.jcr.predicate.AbstractPredicate;
38 import info.magnolia.jcr.util.NodeTypes;
39 import info.magnolia.jcr.util.NodeUtil;
40 import info.magnolia.ui.api.context.UiContext;
41 import info.magnolia.ui.contentapp.browser.ActionExecutionService;
42 import info.magnolia.ui.contentapp.browser.context.ValueContext;
43 import info.magnolia.ui.datasource.jcr.JcrDatasourceDefinition;
44 import info.magnolia.ui.framework.datasource.DatasourceComponent;
45 import info.magnolia.ui.framework.datasource.components.SelectedItems;
46
47 import java.util.List;
48
49 import javax.inject.Inject;
50 import javax.jcr.Node;
51 import javax.jcr.RepositoryException;
52
53 import org.apache.commons.lang3.StringUtils;
54
55 import lombok.AllArgsConstructor;
56 import lombok.SneakyThrows;
57
58
59
60
61
62
63 public class DeleteNodesConfirmationAction<D extends DeleteNodesConfirmationActionDefinition> extends ConfirmationAction<D, Node> {
64
65 private static final String NL = "<br />";
66
67 private boolean warningAlreadySet = false;
68
69 private final ModifiedSubNodesWithNodeTypePredicate predicate;
70
71 @Inject
72 public DeleteNodesConfirmationAction(D definition, UiContext uiContext, ActionExecutionService actionExecutionService, SimpleTranslator i18n, ValueContext valueContext, @DatasourceComponent JcrDatasourceDefinition datasourceDefinition) {
73 super(definition, uiContext, actionExecutionService, i18n, valueContext);
74 this.predicate = new ModifiedSubNodesWithNodeTypePredicate(datasourceDefinition.getAllowedNodeTypes());
75 }
76
77 @Override
78 protected String getConfirmationMessage() {
79 if (predicate == null) {
80 return super.getConfirmationMessage();
81 }
82 StringBuilder label = new StringBuilder();
83
84
85 label.append(super.getConfirmationMessage());
86
87 getValueContext().current().value().map(SelectedItems::stream).ifPresent(nodeStream -> nodeStream.forEach(node -> {
88 String modifiedSubNodesPaths = getModifiedSubNodesMessage(node);
89 if (StringUtils.isNotEmpty(modifiedSubNodesPaths)) {
90 if (!warningAlreadySet) {
91 label.append(NL).append(NL);
92 label.append(getSimpleTranslator().translate("confirmation.delete.modified.message"));
93 label.append(NL);
94 warningAlreadySet = true;
95 }
96 label.append(modifiedSubNodesPaths);
97 }
98 }));
99 return label.toString();
100 }
101
102 @SneakyThrows(RepositoryException.class)
103 private String getModifiedSubNodesMessage(Node parent) {
104 StringBuilder stringBuilder = new StringBuilder();
105 Iterable<Node> nodes = NodeUtil.collectAllChildren(parent, predicate);
106 for (Node node : nodes) {
107 stringBuilder.append(node.getPath());
108 stringBuilder.append(NL);
109 }
110 return stringBuilder.toString();
111 }
112
113 @AllArgsConstructor
114 private class ModifiedSubNodesWithNodeTypePredicate extends AbstractPredicate<Node> {
115
116 private final List<String> nodeTypes;
117
118 @SneakyThrows(RepositoryException.class)
119 @Override
120 public boolean evaluateTyped(Node node) {
121 for (String nodeType : nodeTypes) {
122 if (node.isNodeType(nodeType)) {
123 return NodeTypes.Activatable.ACTIVATION_STATUS_MODIFIED == NodeTypes.Activatable.getActivationStatus(node);
124 }
125 }
126 return false;
127 }
128 }
129 }