1 package org.argeo.connect.e4.resources.parts;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.jcr.Node;
7 import javax.jcr.Property;
8 import javax.jcr.PropertyType;
9 import javax.jcr.Repository;
10 import javax.jcr.RepositoryException;
11 import javax.jcr.Session;
12
13 import org.argeo.cms.e4.PrivilegedJob;
14 import org.argeo.connect.ConnectException;
15 import org.argeo.connect.resources.ResourcesNames;
16 import org.argeo.connect.resources.ResourcesService;
17 import org.argeo.connect.ui.ConnectColumnDefinition;
18 import org.argeo.connect.ui.SystemWorkbenchService;
19 import org.argeo.connect.ui.util.TitleIconRowLP;
20 import org.argeo.connect.ui.util.VirtualJcrTableViewer;
21 import org.argeo.connect.ui.widgets.SimpleJcrTableComposite;
22 import org.argeo.connect.util.ConnectJcrUtils;
23 import org.argeo.eclipse.ui.EclipseJcrMonitor;
24 import org.argeo.eclipse.ui.EclipseUiUtils;
25 import org.argeo.eclipse.ui.jcr.lists.JcrColumnDefinition;
26 import org.argeo.jcr.JcrMonitor;
27 import org.argeo.jcr.JcrUtils;
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.core.runtime.IStatus;
30 import org.eclipse.core.runtime.Status;
31 import org.eclipse.jface.dialogs.MessageDialog;
32 import org.eclipse.jface.viewers.DoubleClickEvent;
33 import org.eclipse.jface.viewers.IDoubleClickListener;
34 import org.eclipse.jface.viewers.ILazyContentProvider;
35 import org.eclipse.jface.viewers.ISelectionChangedListener;
36 import org.eclipse.jface.viewers.IStructuredSelection;
37 import org.eclipse.jface.viewers.SelectionChangedEvent;
38 import org.eclipse.jface.viewers.TableViewer;
39 import org.eclipse.jface.viewers.Viewer;
40 import org.eclipse.jface.wizard.Wizard;
41 import org.eclipse.jface.wizard.WizardPage;
42 import org.eclipse.swt.SWT;
43 import org.eclipse.swt.layout.GridData;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Display;
46
47
48
49
50
51
52
53
54
55 public class TagOrUntagInstancesWizard extends Wizard {
56
57
58
59 public final static int TYPE_ADD = 1;
60 public final static int TYPE_REMOVE = 2;
61
62
63 private SystemWorkbenchService systemWorkbenchService;
64
65
66 private Display callingDisplay;
67
68 private String tagId;
69 private Node tagInstance;
70
71 private String tagPropName;
72
73 private Object[] elements;
74 private final String selectorName;
75 private final int actionType;
76
77
78 private Session session;
79 private ResourcesService resourcesService;
80 private Node tagParent;
81 private String tagInstanceType;
82
83
84
85
86
87
88
89
90
91
92
93 public TagOrUntagInstancesWizard(Display callingDisplay, int actionType, Session session,
94 ResourcesService resourcesService, SystemWorkbenchService systemWorkbenchService, Object[] elements,
95 String selectorName, String tagId, String tagPropName) {
96
97 this.callingDisplay = callingDisplay;
98 this.session = session;
99 this.resourcesService = resourcesService;
100 this.systemWorkbenchService = systemWorkbenchService;
101 this.tagId = tagId;
102 this.tagPropName = tagPropName;
103
104 this.elements = elements;
105 this.selectorName = selectorName;
106
107 this.actionType = actionType;
108
109 tagParent = resourcesService.getTagLikeResourceParent(session, tagId);
110 tagInstanceType = ConnectJcrUtils.get(tagParent, ResourcesNames.RESOURCES_TAG_INSTANCE_TYPE);
111 }
112
113 @Override
114 public void addPages() {
115 try {
116
117 String title = "Batch " + (actionType == TYPE_ADD ? "addition" : "remove");
118 setWindowTitle(title);
119 MainInfoPage inputPage = new MainInfoPage("Configure");
120 addPage(inputPage);
121 RecapPage recapPage = new RecapPage("Validate and launch");
122 addPage(recapPage);
123 } catch (Exception e) {
124 throw new ConnectException("Cannot add page to wizard", e);
125 }
126 }
127
128
129
130
131
132 @Override
133 public boolean performFinish() {
134
135
136 String errMsg = null;
137 if (tagInstance == null)
138 errMsg = "Please choose the tag to use";
139
140 if (errMsg != null) {
141 MessageDialog.openError(getShell(), "Unvalid information", errMsg);
142 return false;
143 }
144 new UpdateTagAndInstancesJob(callingDisplay, actionType, tagInstance, elements, selectorName, tagPropName)
145 .schedule();
146 return true;
147 }
148
149 @Override
150 public boolean performCancel() {
151 return true;
152 }
153
154 @Override
155 public boolean canFinish() {
156 return tagInstance != null && getContainer().getCurrentPage().getNextPage() == null;
157 }
158
159 protected class MainInfoPage extends WizardPage {
160 private static final long serialVersionUID = 1L;
161
162 private SimpleJcrTableComposite tableCmp;
163
164 private List<JcrColumnDefinition> colDefs = new ArrayList<JcrColumnDefinition>();
165 {
166 colDefs.add(new JcrColumnDefinition(null, Property.JCR_TITLE, PropertyType.STRING, "Label", 420));
167 };
168
169 public MainInfoPage(String pageName) {
170 super(pageName);
171 setTitle("Select a tag");
172 setMessage("Choose the value that will be " + (actionType == TYPE_ADD ? "added to " : "removed from ")
173 + "the previously selected items.");
174 }
175
176 public void createControl(Composite parent) {
177 Composite body = new Composite(parent, SWT.NONE);
178 body.setLayout(EclipseUiUtils.noSpaceGridLayout());
179 Node tagParent = resourcesService.getTagLikeResourceParent(session, tagId);
180 int style = SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL;
181 tableCmp = new SimpleJcrTableComposite(body, style, session, ConnectJcrUtils.getPath(tagParent),
182 tagInstanceType, colDefs, true, false);
183 GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
184 gd.heightHint = 400;
185 tableCmp.setLayoutData(gd);
186
187
188 tableCmp.getTableViewer().addDoubleClickListener(new MyDoubleClickListener());
189 tableCmp.getTableViewer().addSelectionChangedListener(new MySelectionChangedListener());
190
191 setControl(body);
192 tableCmp.setFocus();
193 }
194
195 class MySelectionChangedListener implements ISelectionChangedListener {
196 @Override
197 public void selectionChanged(SelectionChangedEvent event) {
198 if (event.getSelection().isEmpty())
199 tagInstance = null;
200 else {
201 Object obj = ((IStructuredSelection) event.getSelection()).getFirstElement();
202 if (obj instanceof Node) {
203 tagInstance = (Node) obj;
204 }
205 }
206 }
207 }
208
209 class MyDoubleClickListener implements IDoubleClickListener {
210 public void doubleClick(DoubleClickEvent evt) {
211 if (evt.getSelection().isEmpty()) {
212 tagInstance = null;
213 return;
214 } else {
215 Object obj = ((IStructuredSelection) evt.getSelection()).getFirstElement();
216 if (obj instanceof Node) {
217 tagInstance = (Node) obj;
218 getContainer().showPage(getNextPage());
219 }
220 }
221 }
222 }
223 }
224
225 protected class RecapPage extends WizardPage {
226 private static final long serialVersionUID = 1L;
227
228 public RecapPage(String pageName) {
229 super(pageName);
230 setTitle("Check and confirm");
231 }
232
233 public void setVisible(boolean visible) {
234 super.setVisible(visible);
235
236 if (visible == true) {
237 if (tagInstance == null)
238 setErrorMessage("Please choose a tag value to be used");
239 else {
240 setErrorMessage(null);
241 String name = ConnectJcrUtils.get(tagInstance, Property.JCR_TITLE);
242 if (actionType == TYPE_ADD)
243 setMessage("Your are about to add [" + name + "] to the below listed " + elements.length
244 + " items. " + "Are you sure you want to proceed ?");
245 else
246 setMessage("Your are about to remove [" + name + "] from the below listed " + elements.length
247 + " items. " + "Are you sure you want to proceed ?");
248 }
249 }
250 }
251
252 public void createControl(Composite parent) {
253 Composite body = new Composite(parent, SWT.NONE);
254 body.setLayout(EclipseUiUtils.noSpaceGridLayout());
255 ArrayList<ConnectColumnDefinition> colDefs = new ArrayList<ConnectColumnDefinition>();
256 colDefs.add(new ConnectColumnDefinition("Display Name",
257 new TitleIconRowLP(systemWorkbenchService, selectorName, Property.JCR_TITLE), 300));
258
259 VirtualJcrTableViewer tableCmp = new VirtualJcrTableViewer(body, SWT.READ_ONLY, colDefs);
260 TableViewer membersViewer = tableCmp.getTableViewer();
261 membersViewer.setContentProvider(new MyLazyContentProvider(membersViewer));
262 setViewerInput(membersViewer, elements);
263 GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
264 gd.heightHint = 400;
265 tableCmp.setLayoutData(gd);
266 setControl(body);
267 }
268 }
269
270
271 protected void setViewerInput(TableViewer membersViewer, Object[] elements) {
272 membersViewer.setInput(elements);
273
274 membersViewer.setItemCount(elements.length);
275 membersViewer.refresh();
276 }
277
278 private class MyLazyContentProvider implements ILazyContentProvider {
279 private static final long serialVersionUID = 1L;
280 private TableViewer viewer;
281 private Object[] elements;
282
283 public MyLazyContentProvider(TableViewer viewer) {
284 this.viewer = viewer;
285 }
286
287 public void dispose() {
288 }
289
290 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
291
292
293 viewer.setSelection(null);
294 this.elements = (Object[]) newInput;
295 }
296
297 public void updateElement(int index) {
298 viewer.replace(elements[index], index);
299 }
300 }
301
302
303 private class UpdateTagAndInstancesJob extends PrivilegedJob {
304
305 private int actionType;
306 private Repository repository;
307 private String tagPath;
308 private String tagPropName;
309 private List<String> pathes = new ArrayList<String>();
310 private Display display;
311
312 public UpdateTagAndInstancesJob(Display display, int actionType, Node taginstance, Object[] toUpdateElements,
313 String selectorName, String tagPropName) {
314 super("Updating");
315
316 this.display = display;
317 this.actionType = actionType;
318 this.tagPropName = tagPropName;
319
320 try {
321 this.tagPath = tagInstance.getPath();
322 repository = tagInstance.getSession().getRepository();
323 for (Object element : toUpdateElements) {
324 Node currNode = ConnectJcrUtils.getNodeFromElement(element, selectorName);
325 pathes.add(currNode.getPath());
326 }
327 } catch (RepositoryException e) {
328 throw new ConnectException("Unable to init " + "tag instance batch update for " + tagInstance, e);
329 }
330 }
331
332 protected IStatus doRun(IProgressMonitor progressMonitor) {
333 Session session = null;
334 try {
335 JcrMonitor monitor = new EclipseJcrMonitor(progressMonitor);
336 if (monitor != null && !monitor.isCanceled()) {
337 monitor.beginTask("Updating objects", -1);
338
339 session = repository.login();
340 Node targetTagInstance = session.getNode(tagPath);
341
342
343
344 ConnectJcrUtils.checkCOStatusBeforeUpdate(tagInstance);
345
346
347 String value = targetTagInstance.getProperty(Property.JCR_TITLE).getString();
348
349 for (String currPath : pathes) {
350 Node currNode = session.getNode(currPath);
351 ConnectJcrUtils.checkCOStatusBeforeUpdate(currNode);
352 if (actionType == TYPE_ADD) {
353
354
355 ConnectJcrUtils.addStringToMultiValuedProp(currNode, tagPropName, value);
356 } else if (actionType == TYPE_REMOVE) {
357
358
359 ConnectJcrUtils.removeStringFromMultiValuedProp(currNode, tagPropName, value);
360 }
361 ConnectJcrUtils.saveAndPublish(currNode, true);
362 }
363 monitor.worked(1);
364
365
366 display.asyncExec(new Runnable() {
367 @Override
368 public void run() {
369
370 }
371 });
372 }
373 } catch (Exception e) {
374 return new Status(IStatus.ERROR, "", "Unable to perform batch update on " + tagPath + " for "
375 + (selectorName == null ? "single node " : selectorName) + " row list with " + tagInstanceType,
376 e);
377 } finally {
378 JcrUtils.logoutQuietly(session);
379 }
380 return Status.OK_STATUS;
381 }
382 }
383 }