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.resources.app.action;
35
36 import info.magnolia.commands.CommandsManager;
37 import info.magnolia.context.Context;
38 import info.magnolia.event.EventBus;
39 import info.magnolia.i18nsystem.SimpleTranslator;
40 import info.magnolia.jcr.RuntimeRepositoryException;
41 import info.magnolia.jcr.util.NodeTypes;
42 import info.magnolia.jcr.util.NodeUtil;
43 import info.magnolia.resources.app.utils.ResourceUtils;
44 import info.magnolia.resources.app.workbench.ResourcesContainer;
45 import info.magnolia.ui.api.context.UiContext;
46 import info.magnolia.ui.api.event.AdmincentralEventBus;
47 import info.magnolia.ui.api.event.ContentChangedEvent;
48 import info.magnolia.ui.framework.action.MarkNodeAsDeletedAction;
49 import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter;
50 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
51 import info.magnolia.ui.vaadin.overlay.MessageStyleTypeEnum;
52
53 import java.util.Comparator;
54 import java.util.List;
55
56 import javax.inject.Named;
57 import javax.jcr.Node;
58 import javax.jcr.RepositoryException;
59 import javax.jcr.Session;
60
61 import org.apache.commons.lang3.StringUtils;
62
63 import com.google.common.base.Predicate;
64 import com.google.common.collect.FluentIterable;
65 import com.google.common.collect.Lists;
66 import com.google.common.collect.Ordering;
67 import com.vaadin.data.Item;
68
69
70
71
72
73
74
75
76 public class MarkResourceAsDeletedAction extends MarkNodeAsDeletedAction {
77
78 private final List<JcrItemAdapter> jcrItemAdapters;
79 private final SimpleTranslator i18n;
80 private final boolean isDirectory;
81
82 public MarkResourceAsDeletedAction(MarkResourceAsDeletedActionDefinition definition, List<Item> items, CommandsManager commandsManager, @Named(AdmincentralEventBus.NAME) EventBus eventBus, UiContext uiContext, SimpleTranslator i18n, Context context) {
83 this(definition, ResourceUtils.getJcrItemAdaptersFor(context, items), commandsManager, eventBus, uiContext, i18n, items.get(0));
84 }
85
86 public MarkResourceAsDeletedAction(MarkResourceAsDeletedActionDefinition definition, Item item, CommandsManager commandsManager, @Named(AdmincentralEventBus.NAME) EventBus eventBus, UiContext uiContext, SimpleTranslator i18n, Context context) {
87 this(definition, ResourceUtils.getJcrItemAdaptersFor(context, Lists.newArrayList(item)), commandsManager, eventBus, uiContext, i18n, item);
88 }
89
90 private MarkResourceAsDeletedAction(MarkResourceAsDeletedActionDefinition definition, List<JcrItemAdapter> jcrItemAdapters, CommandsManager commandsManager, EventBus eventBus, UiContext uiContext, SimpleTranslator i18n, Item item) {
91 super(definition, jcrItemAdapters, commandsManager, eventBus, uiContext, i18n);
92 this.isDirectory = ResourceUtils.isDirectory(item);
93 this.jcrItemAdapters = jcrItemAdapters;
94 this.i18n = i18n;
95 }
96
97 @Override
98 protected void onPostExecute() throws Exception {
99 super.onPostExecute();
100 for (JcrItemAdapter itemAdapter : jcrItemAdapters) {
101 javax.jcr.Item jcrItem = itemAdapter.getJcrItem();
102 if (jcrItem != null) {
103 eventBus.fireEvent(new ContentChangedEvent(jcrItem.getPath()));
104 } else {
105 eventBus.fireEvent(new ContentChangedEvent(ResourcesContainer.ROOT_DIRECTORY));
106 }
107 }
108 }
109
110 @Override
111 protected List<JcrItemAdapter> getItems() {
112 List<JcrItemAdapter> items = Lists.newArrayList();
113 for (JcrItemAdapter jcrItemAdapter : jcrItemAdapters) {
114 items.addAll(getItems(jcrItemAdapter));
115 }
116 return items;
117 }
118
119 @Override
120 protected List<JcrItemAdapter> getSortedItems(Comparator<JcrItemAdapter> comparator) {
121 return Ordering.from(comparator).sortedCopy(getItems());
122 }
123
124 @Override
125 protected Comparator<JcrItemAdapter> getItemComparator() {
126 return new Comparator<JcrItemAdapter>() {
127 @Override
128 public int compare(JcrItemAdapter o1, JcrItemAdapter o2) {
129 try {
130 return o2.getJcrItem().getDepth() - o1.getJcrItem().getDepth();
131 } catch (RepositoryException e) {
132 return 0;
133 }
134 }
135 };
136 }
137
138 private List<JcrItemAdapter> getItems(JcrItemAdapter jcrItemAdapter) {
139 List<JcrItemAdapter> items = Lists.newArrayList();
140
141 try {
142 Session jcrSession = jcrItemAdapter.getJcrItem().getSession();
143 Node node = jcrSession.getNode(jcrItemAdapter.getJcrItem().getPath());
144
145 boolean hasSiblings = !getSiblings(node).isEmpty();
146 if (hasSiblings) {
147 items.add(jcrItemAdapter);
148 } else {
149 findNodeAndEmptyAncestorsFromJcr(items, node, null);
150 }
151 } catch (RepositoryException e) {
152 uiContext.openNotification(MessageStyleTypeEnum.ERROR, false, i18n.translate("resources.actions.deleteResource.notification.error"));
153 throw new RuntimeException(e);
154 }
155 return items;
156 }
157
158 private void findNodeAndEmptyAncestorsFromJcr(List<JcrItemAdapter> items, Node node, final Node removedChildNode) throws RepositoryException {
159 if (node.getDepth() == 0) {
160 return;
161 }
162
163 List<Node> siblings = getSiblings(node);
164 List<Node> filteredSiblings = filterSiblings(siblings, removedChildNode);
165
166 boolean hasNoMoreResources = filteredSiblings.size() < 1;
167 if (hasNoMoreResources) {
168 Node parent = node.getParent();
169 items.add(new JcrNodeAdapter(node));
170 findNodeAndEmptyAncestorsFromJcr(items, parent, node);
171 }
172 }
173
174 private List<Node> filterSiblings(List<Node> siblings, final Node removedChildNode) {
175 return FluentIterable
176 .from(siblings)
177 .filter(filterRemovedNode(removedChildNode))
178 .filter(markedAsDeleted())
179 .toList();
180 }
181
182 private List<Node> getSiblings(Node node) throws RepositoryException {
183 List<Node> resources = Lists.newArrayList(NodeUtil.getNodes(node, NodeTypes.Content.NAME));
184 List<Node> folders = Lists.newArrayList(NodeUtil.getNodes(node, NodeTypes.Folder.NAME));
185 resources.addAll(folders);
186
187 return resources;
188 }
189
190 @Override
191 protected String getSuccessMessage() {
192 if (isDirectory) {
193 return i18n.translate("resources.actions.markFolderAsDeleted.notification.success", super.getItems().size());
194 } else {
195 return i18n.translate("resources.actions.markFileAsDeleted.notification.success", super.getItems().size());
196 }
197 }
198
199 @Override
200 protected String getFailureMessage() {
201 if (isDirectory) {
202 return i18n.translate("resources.actions.markFolderAsDeleted.notification.error", super.getItems().size());
203 } else {
204 return i18n.translate("resources.actions.markFileAsDeleted.notification.error", super.getItems().size());
205 }
206 }
207
208 private Predicate<Node> markedAsDeleted() {
209 return new Predicate<Node>() {
210 @Override
211 public boolean apply(Node node) {
212 try {
213 return !node.hasProperty(NodeTypes.Deleted.NAME);
214 } catch (RepositoryException e) {
215 throw new RuntimeRepositoryException(e);
216 }
217 }
218 };
219 }
220
221 private Predicate<Node> filterRemovedNode(final Node removedChildNode) {
222 return new Predicate<Node>() {
223 @Override
224 public boolean apply(Node node) {
225 try {
226 if (StringUtils.equals(node.getPath(), removedChildNode.getPath())) {
227 return false;
228 }
229 } catch (RepositoryException e) {
230 throw new RuntimeRepositoryException(e);
231 }
232 return true;
233 }
234 };
235 }
236 }