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.util.NodeTypes;
41 import info.magnolia.jcr.util.NodeUtil;
42 import info.magnolia.resources.app.utils.ResourceUtils;
43 import info.magnolia.resources.app.workbench.ResourcesContainer;
44 import info.magnolia.ui.api.app.SubAppContext;
45 import info.magnolia.ui.api.event.AdmincentralEventBus;
46 import info.magnolia.ui.api.event.ContentChangedEvent;
47 import info.magnolia.ui.framework.action.ActivationAction;
48 import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter;
49 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
50
51 import java.util.Collections;
52 import java.util.Comparator;
53 import java.util.List;
54
55 import javax.inject.Named;
56 import javax.jcr.Node;
57 import javax.jcr.RepositoryException;
58
59 import org.apache.commons.lang3.StringUtils;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 import com.google.common.collect.Lists;
64 import com.google.common.collect.Ordering;
65 import com.vaadin.data.Item;
66
67
68
69
70
71
72
73
74
75 public class ResourceActivationAction extends ActivationAction<ResourceActivationActionDefinition> {
76
77 private static final Logger log = LoggerFactory.getLogger(ResourceActivationAction.class);
78
79 private final List<Item> resourceItems;
80 private final ResourceActivationActionDefinition definition;
81 private final EventBus eventBus;
82 private final Context context;
83 private String closestAffectedAncestor;
84
85 public ResourceActivationAction(ResourceActivationActionDefinition definition, Item item, CommandsManager commandsManager, @Named(AdmincentralEventBus.NAME) EventBus eventBus, SubAppContext uiContext, SimpleTranslator i18n, Context context) {
86 this(definition, Lists.newArrayList(item), commandsManager, eventBus, uiContext, i18n, context);
87 }
88
89 public ResourceActivationAction(ResourceActivationActionDefinition definition, List<Item> items, CommandsManager commandsManager, @Named(AdmincentralEventBus.NAME) EventBus eventBus, SubAppContext uiContext, SimpleTranslator i18n, Context context) {
90 super(definition, Collections.EMPTY_LIST, commandsManager, eventBus, uiContext, i18n);
91 this.definition = definition;
92 this.resourceItems = items;
93 this.eventBus = eventBus;
94 this.context = context;
95 this.closestAffectedAncestor = StringUtils.EMPTY;
96 }
97
98 @Override
99 protected Comparator<JcrItemAdapter> getItemComparator() {
100 return new Comparator<JcrItemAdapter>() {
101 @Override
102 public int compare(JcrItemAdapter o1, JcrItemAdapter o2) {
103 try {
104 if (getDefinition().isDeletionActivation()) {
105 return o2.getJcrItem().getDepth() - o1.getJcrItem().getDepth();
106 }
107 return o1.getJcrItem().getDepth() - o2.getJcrItem().getDepth();
108 } catch (RepositoryException e) {
109 return 0;
110 }
111 }
112 };
113 }
114
115 @Override
116 protected List<JcrItemAdapter> getItems() {
117 final List<JcrItemAdapter> allItems = Lists.newLinkedList();
118
119 for (Item resourceItem : resourceItems) {
120 allItems.addAll(resolveJcrItemsToPublish(resourceItem));
121 }
122
123 this.closestAffectedAncestor = resolveClosestAffectedAncestor(allItems);
124 return allItems;
125 }
126
127 private String resolveClosestAffectedAncestor(List<JcrItemAdapter> resourcePaths) {
128 String commonPath = "";
129 String[][] directories = new String[resourcePaths.size()][];
130
131 for (int i = 0; i < resourcePaths.size(); i++) {
132 try {
133 directories[i] = resourcePaths.get(i).getJcrItem().getPath().split("/");
134 } catch (RepositoryException e) {
135 log.error("JcrItem is not being found", e);
136 }
137 }
138
139 for (int j = 0; j < directories[0].length; j++) {
140 String nextDirectory = directories[0][j];
141 for (int i = 1; i < resourcePaths.size(); i++) {
142 if (!nextDirectory.equals(directories[i][j])) {
143
144 return commonPath;
145 }
146 }
147 commonPath += nextDirectory + "/";
148 }
149 return commonPath;
150 }
151
152 private List<JcrItemAdapter> resolveJcrItemsToPublish(Item resourceItem) {
153 JcrNodeAdapter jcrItemAdapter = ResourceUtils.getJcrNodeAdapterFor(context, resourceItem);
154
155 List<JcrItemAdapter> items = Lists.newLinkedList();
156 try {
157 if (!StringUtils.equals(definition.getCommand(), "deactivate") || !definition.isRecursive()) {
158 int depth = jcrItemAdapter.getJcrItem().getDepth();
159 for (int i = 1; i < depth + 1; i++) {
160 Node ancestor = (Node) jcrItemAdapter.getJcrItem().getAncestor(i);
161 if (!definition.isDeletionActivation() && isNodeNotActivated(ancestor)) {
162 items.add(new JcrNodeAdapter(ancestor));
163 } else if (definition.isDeletionActivation() && isNodeDeleted(ancestor)) {
164 items.add(new JcrNodeAdapter(ancestor));
165 }
166 }
167 }
168 } catch (RepositoryException e) {
169 log.error("Resource cannot be resolved", e);
170 }
171
172
173 if (items.isEmpty()) {
174 items.add(new JcrNodeAdapter(jcrItemAdapter.getJcrItem()));
175 }
176
177 return items;
178 }
179
180
181
182
183 private boolean isNodeDeleted(Node ancestor) {
184 try {
185 return NodeUtil.hasMixin(ancestor, NodeTypes.Deleted.NAME);
186 } catch (RepositoryException e) {
187 log.error("Node is not being found.", e);
188 return false;
189 }
190 }
191
192
193
194
195 private boolean isNodeNotActivated(Node node) {
196 try {
197 return !NodeTypes.Activatable.isActivated(node);
198 } catch (RepositoryException e) {
199 log.error("Node is not being found.", e);
200 return false;
201 }
202 }
203
204 @Override
205 protected List<JcrItemAdapter> getSortedItems(Comparator<JcrItemAdapter> comparator) {
206 return Ordering.from(comparator).sortedCopy(getItems());
207 }
208
209
210
211 @Override
212 protected void onPostExecute() throws Exception {
213 super.onPostExecute();
214
215 String sanitizedPath;
216
217 if (StringUtils.equals(closestAffectedAncestor, ResourcesContainer.ROOT_DIRECTORY)) {
218 sanitizedPath = closestAffectedAncestor;
219 } else if (definition.isDeletionActivation()) {
220 String removedLastSlash = StringUtils.removeEnd(closestAffectedAncestor, "/");
221 sanitizedPath = StringUtils.substringBeforeLast(removedLastSlash, "/");
222 if (StringUtils.equals(sanitizedPath, "")) {
223 sanitizedPath = ResourcesContainer.ROOT_DIRECTORY;
224 }
225 } else {
226 sanitizedPath = StringUtils.removeEnd(closestAffectedAncestor, "/");
227 }
228
229 eventBus.fireEvent(new ContentChangedEvent(sanitizedPath));
230 }
231 }