]> git.argeo.org Git - gpl/argeo-slc.git/blob - plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrResultTreeView.java
e1a5759eff3d92d3257a9998ad409893838e999d
[gpl/argeo-slc.git] / plugins / org.argeo.slc.client.ui / src / main / java / org / argeo / slc / client / ui / views / JcrResultTreeView.java
1 package org.argeo.slc.client.ui.views;
2
3 import java.awt.Window;
4 import java.util.ArrayList;
5 import java.util.Calendar;
6 import java.util.List;
7
8 import javax.jcr.Node;
9 import javax.jcr.NodeIterator;
10 import javax.jcr.Property;
11 import javax.jcr.PropertyIterator;
12 import javax.jcr.PropertyType;
13 import javax.jcr.RepositoryException;
14 import javax.jcr.Session;
15 import javax.jcr.Value;
16 import javax.jcr.nodetype.NodeType;
17 import javax.jcr.observation.Event;
18 import javax.jcr.observation.EventListener;
19 import javax.jcr.observation.ObservationManager;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.argeo.ArgeoException;
24 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
25 import org.argeo.eclipse.ui.utils.CommandUtils;
26 import org.argeo.jcr.JcrUtils;
27 import org.argeo.jcr.UserJcrUtils;
28 import org.argeo.slc.SlcException;
29 import org.argeo.slc.client.ui.ClientUiPlugin;
30 import org.argeo.slc.client.ui.SlcUiConstants;
31 import org.argeo.slc.client.ui.commands.AddResultFolder;
32 import org.argeo.slc.client.ui.commands.RenameResultFolder;
33 import org.argeo.slc.client.ui.commands.RenameResultNode;
34 import org.argeo.slc.client.ui.editors.ProcessEditor;
35 import org.argeo.slc.client.ui.editors.ProcessEditorInput;
36 import org.argeo.slc.client.ui.model.ParentNodeFolder;
37 import org.argeo.slc.client.ui.model.ResultFolder;
38 import org.argeo.slc.client.ui.model.ResultParent;
39 import org.argeo.slc.client.ui.model.ResultParentUtils;
40 import org.argeo.slc.client.ui.model.SingleResultNode;
41 import org.argeo.slc.client.ui.model.VirtualFolder;
42 import org.argeo.slc.client.ui.providers.ResultTreeContentProvider;
43 import org.argeo.slc.client.ui.providers.ResultTreeLabelProvider;
44 import org.argeo.slc.client.ui.wizards.ConfirmOverwriteWizard;
45 import org.argeo.slc.jcr.SlcJcrResultUtils;
46 import org.argeo.slc.jcr.SlcNames;
47 import org.argeo.slc.jcr.SlcTypes;
48 import org.eclipse.jface.action.IMenuListener;
49 import org.eclipse.jface.action.IMenuManager;
50 import org.eclipse.jface.action.MenuManager;
51 import org.eclipse.jface.viewers.ColumnLabelProvider;
52 import org.eclipse.jface.viewers.DecoratingLabelProvider;
53 import org.eclipse.jface.viewers.DoubleClickEvent;
54 import org.eclipse.jface.viewers.IDoubleClickListener;
55 import org.eclipse.jface.viewers.ILabelDecorator;
56 import org.eclipse.jface.viewers.ISelectionChangedListener;
57 import org.eclipse.jface.viewers.IStructuredContentProvider;
58 import org.eclipse.jface.viewers.IStructuredSelection;
59 import org.eclipse.jface.viewers.SelectionChangedEvent;
60 import org.eclipse.jface.viewers.TableViewer;
61 import org.eclipse.jface.viewers.TableViewerColumn;
62 import org.eclipse.jface.viewers.TreePath;
63 import org.eclipse.jface.viewers.TreeViewer;
64 import org.eclipse.jface.viewers.Viewer;
65 import org.eclipse.jface.viewers.ViewerDropAdapter;
66 import org.eclipse.jface.wizard.WizardDialog;
67 import org.eclipse.swt.SWT;
68 import org.eclipse.swt.custom.SashForm;
69 import org.eclipse.swt.dnd.DND;
70 import org.eclipse.swt.dnd.DragSourceEvent;
71 import org.eclipse.swt.dnd.DragSourceListener;
72 import org.eclipse.swt.dnd.TextTransfer;
73 import org.eclipse.swt.dnd.Transfer;
74 import org.eclipse.swt.dnd.TransferData;
75 import org.eclipse.swt.layout.FillLayout;
76 import org.eclipse.swt.layout.GridData;
77 import org.eclipse.swt.layout.GridLayout;
78 import org.eclipse.swt.widgets.Composite;
79 import org.eclipse.swt.widgets.Display;
80 import org.eclipse.swt.widgets.Menu;
81 import org.eclipse.ui.ISharedImages;
82 import org.eclipse.ui.IWorkbenchPage;
83 import org.eclipse.ui.IWorkbenchWindow;
84 import org.eclipse.ui.PlatformUI;
85 import org.eclipse.ui.part.ViewPart;
86
87 /** SLC generic JCR Result tree view. */
88 public class JcrResultTreeView extends ViewPart {
89 public final static String ID = ClientUiPlugin.ID + ".jcrResultTreeView";
90
91 private final static Log log = LogFactory.getLog(JcrResultTreeView.class);
92
93 /* DEPENDENCY INJECTION */
94 private Session session;
95
96 // This page widgets
97 private TreeViewer resultTreeViewer;
98 private TableViewer propertiesViewer;
99
100 private EventListener resultsObserver = null;
101
102 private final static String[] observedNodeTypes = {
103 SlcTypes.SLC_TEST_RESULT, SlcTypes.SLC_RESULT_FOLDER,
104 NodeType.NT_UNSTRUCTURED };
105
106 // FIXME cache to ease D&D
107 private boolean isActionUnderMyResult = false;
108 private ResultParent lastSelectedTargetElement;
109 private ResultParent lastSelectedSourceElement;
110 private ResultParent lastSelectedSourceElementParent;
111 private boolean isResultFolder = false;
112
113 // FIXME we cache the fact that we are moving a node to avoid exception
114 // triggered by the "Add Node" event while moving
115 // boolean isMoveInProgress = false;
116
117 /**
118 * To be overridden to adapt size of form and result frames.
119 */
120 protected int[] getWeights() {
121 return new int[] { 70, 30 };
122 }
123
124 @Override
125 public void createPartControl(Composite parent) {
126 parent.setLayout(new FillLayout());
127 // Main layout
128 SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
129 sashForm.setSashWidth(4);
130 sashForm.setLayout(new FillLayout());
131
132 // Create the tree on top of the view
133 Composite top = new Composite(sashForm, SWT.NONE);
134 GridLayout gl = new GridLayout(1, false);
135 top.setLayout(gl);
136 resultTreeViewer = createResultsTreeViewer(top);
137
138 // Create the property viewer on the bottom
139 Composite bottom = new Composite(sashForm, SWT.NONE);
140 bottom.setLayout(new GridLayout(1, false));
141 propertiesViewer = createPropertiesViewer(bottom);
142
143 sashForm.setWeights(getWeights());
144
145 try {
146 ObservationManager observationManager = session.getWorkspace()
147 .getObservationManager();
148 resultsObserver = new ResultObserver(resultTreeViewer.getTree()
149 .getDisplay());
150 observationManager.addEventListener(resultsObserver,
151 Event.NODE_MOVED | Event.NODE_ADDED | Event.NODE_REMOVED,
152 UserJcrUtils.getUserHome(session).getPath(), true, null,
153 observedNodeTypes, false);
154 } catch (RepositoryException e) {
155 throw new SlcException("Cannot register listeners", e);
156 }
157
158 // Refresh the view to initialize it
159 refresh(null);
160 }
161
162 // The main tree viewer
163 protected TreeViewer createResultsTreeViewer(Composite parent) {
164 int style = SWT.BORDER | SWT.MULTI;
165
166 TreeViewer viewer = new TreeViewer(parent, style);
167 viewer.getTree().setLayoutData(
168 new GridData(SWT.FILL, SWT.FILL, true, true));
169
170 viewer.setContentProvider(new ResultTreeContentProvider());
171
172 // Add label provider with label decorator
173 ResultTreeLabelProvider rtLblProvider = new ResultTreeLabelProvider();
174 ILabelDecorator decorator = ClientUiPlugin.getDefault().getWorkbench()
175 .getDecoratorManager().getLabelDecorator();
176 viewer.setLabelProvider(new DecoratingLabelProvider(rtLblProvider,
177 decorator));
178 viewer.addDoubleClickListener(new ViewDoubleClickListener());
179
180 // viewer.setLabelProvider(rtLblProvider);
181 getSite().setSelectionProvider(viewer);
182
183 // add drag & drop support
184 int operations = DND.DROP_COPY | DND.DROP_MOVE;
185 Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
186 viewer.addDragSupport(operations, tt, new ViewDragListener());
187 viewer.addDropSupport(operations, tt, new ViewDropListener(viewer));
188
189 // add context menu
190 MenuManager menuManager = new MenuManager();
191 Menu menu = menuManager.createContextMenu(viewer.getTree());
192 menuManager.addMenuListener(new IMenuListener() {
193 public void menuAboutToShow(IMenuManager manager) {
194 contextMenuAboutToShow(manager);
195 }
196 });
197 viewer.getTree().setMenu(menu);
198 getSite().registerContextMenu(menuManager, viewer);
199
200 // add change listener to display TestResult information in the property
201 // viewer
202 viewer.addSelectionChangedListener(new MySelectionChangedListener());
203 return viewer;
204 }
205
206 // Detailed property viewer
207 protected TableViewer createPropertiesViewer(Composite parent) {
208 propertiesViewer = new TableViewer(parent);
209 propertiesViewer.getTable().setLayoutData(
210 new GridData(SWT.FILL, SWT.FILL, true, true));
211 propertiesViewer.getTable().setHeaderVisible(true);
212 propertiesViewer.setContentProvider(new PropertiesContentProvider());
213 TableViewerColumn col = new TableViewerColumn(propertiesViewer,
214 SWT.NONE);
215 col.getColumn().setText("Name");
216 col.getColumn().setWidth(200);
217 col.setLabelProvider(new ColumnLabelProvider() {
218 public String getText(Object element) {
219 try {
220 return ((Property) element).getName();
221 } catch (RepositoryException e) {
222 throw new ArgeoException(
223 "Unexpected exception in label provider", e);
224 }
225 }
226 });
227 col = new TableViewerColumn(propertiesViewer, SWT.NONE);
228 col.getColumn().setText("Value");
229 col.getColumn().setWidth(400);
230 col.setLabelProvider(new ColumnLabelProvider() {
231 public String getText(Object element) {
232 try {
233 Property property = (Property) element;
234 if (property.getType() == PropertyType.BINARY)
235 return "<binary>";
236 else if (property.isMultiple()) {
237 StringBuffer buf = new StringBuffer("[");
238 Value[] values = property.getValues();
239 for (int i = 0; i < values.length; i++) {
240 if (i != 0)
241 buf.append(", ");
242 buf.append(values[i].getString());
243 }
244 buf.append(']');
245 return buf.toString();
246 } else
247 return property.getValue().getString();
248 } catch (RepositoryException e) {
249 throw new ArgeoException(
250 "Unexpected exception in label provider", e);
251 }
252 }
253 });
254 col = new TableViewerColumn(propertiesViewer, SWT.NONE);
255 col.getColumn().setText("Type");
256 col.getColumn().setWidth(200);
257 col.setLabelProvider(new ColumnLabelProvider() {
258 public String getText(Object element) {
259 try {
260 return PropertyType.nameFromValue(((Property) element)
261 .getType());
262 } catch (RepositoryException e) {
263 throw new ArgeoException(
264 "Unexpected exception in label provider", e);
265 }
266 }
267 });
268 propertiesViewer.setInput(getViewSite());
269 return propertiesViewer;
270 }
271
272 /**
273 * Override to provide specific behaviour. Typically to enable the display
274 * of a result file.
275 *
276 * @param evt
277 */
278 protected void processDoubleClick(DoubleClickEvent evt) {
279 Object obj = ((IStructuredSelection) evt.getSelection())
280 .getFirstElement();
281 try {
282 if (obj instanceof SingleResultNode) {
283 SingleResultNode srNode = (SingleResultNode) obj;
284 Node node = srNode.getNode();
285 // FIXME: open a default result editor
286 if (node.isNodeType(SlcTypes.SLC_PROCESS)) {
287 IWorkbenchPage activePage = PlatformUI.getWorkbench()
288 .getActiveWorkbenchWindow().getActivePage();
289 activePage.openEditor(
290 new ProcessEditorInput(node.getPath()),
291 ProcessEditor.ID);
292 }
293 }
294 } catch (Exception e) {
295 throw new SlcException("Cannot open " + obj, e);
296 }
297 }
298
299 @Override
300 public void setFocus() {
301 }
302
303 /**
304 * refreshes the passed resultParent and its corresponding subtree. It
305 * refreshes the whole viewer if null is passed.
306 *
307 * @param ResultParent
308 *
309 */
310 public void refresh(ResultParent resultParent) {
311 if (log.isDebugEnabled())
312 log.debug("Refreshing '" + resultParent + "'...");
313 // Thread.dumpStack();
314 if (resultParent == null) {
315 resultTreeViewer.setInput(initializeResultTree());
316 } else {
317 if (resultParent instanceof ParentNodeFolder) {
318 ParentNodeFolder currFolder = (ParentNodeFolder) resultParent;
319 jcrRefresh(currFolder.getNode());
320 currFolder.forceFullRefresh();
321 }
322 // FIXME: specific refresh does not work
323 // resultTreeViewer.refresh(currFolder, true);
324 TreePath[] tps = resultTreeViewer.getExpandedTreePaths();
325 resultTreeViewer.setInput(initializeResultTree());
326 resultTreeViewer.setExpandedTreePaths(tps);
327 }
328 }
329
330 /**
331 * refreshes the passed node and its corresponding subtree.
332 *
333 * @param node
334 * cannot be null
335 *
336 */
337 public boolean jcrRefresh(Node node) {
338 if (log.isDebugEnabled())
339 log.debug(" JCR refreshing " + node + "...");
340 boolean isPassed = true;
341 try {
342 if (node.isNodeType(SlcTypes.SLC_TEST_RESULT)) {
343 isPassed = node.getNode(SlcNames.SLC_STATUS)
344 .getProperty(SlcNames.SLC_SUCCESS).getBoolean();
345 } else if (node.isNodeType(SlcTypes.SLC_RESULT_FOLDER)) {
346 NodeIterator ni = node.getNodes();
347 // quicker but wrong : refresh will stop as soon as a failed
348 // test is found and the whole tree won't be refreshed
349 // while (isPassed && ni.hasNext()){
350 while (ni.hasNext()) {
351 Node currChild = ni.nextNode();
352 isPassed = isPassed & jcrRefresh(currChild);
353 }
354 if (isPassed != node.getNode(SlcNames.SLC_STATUS)
355 .getProperty(SlcNames.SLC_SUCCESS).getBoolean()) {
356 node.getNode(SlcNames.SLC_STATUS).setProperty(
357 SlcNames.SLC_SUCCESS, isPassed);
358 node.getSession().save();
359 return isPassed;
360 }
361 } else
362 ; // do nothing
363 } catch (RepositoryException e) {
364 throw new SlcException("Cannot register listeners", e);
365 }
366 return isPassed;
367 }
368
369 private ResultParent[] initializeResultTree() {
370 try {
371 if (session.nodeExists(SlcJcrResultUtils
372 .getSlcResultsBasePath(session))) {
373 ResultParent[] roots = new ResultParent[5];
374
375 // My results
376 roots[0] = new ParentNodeFolder(null,
377 SlcJcrResultUtils.getMyResultParentNode(session),
378 SlcUiConstants.DEFAULT_MY_RESULTS_FOLDER_LABEL);
379
380 // today
381 Calendar cal = Calendar.getInstance();
382 String relPath = JcrUtils.dateAsPath(cal);
383 List<String> datePathes = new ArrayList<String>();
384 datePathes.add(relPath);
385 roots[1] = new VirtualFolder(null,
386 ResultParentUtils.getResultsForDates(session,
387 datePathes), "Today");
388
389 // Yesterday
390 cal = Calendar.getInstance();
391 cal.add(Calendar.DAY_OF_YEAR, -1);
392 relPath = JcrUtils.dateAsPath(cal);
393 datePathes = new ArrayList<String>();
394 datePathes.add(relPath);
395 roots[2] = new VirtualFolder(null,
396 ResultParentUtils.getResultsForDates(session,
397 datePathes), "Yesterday");
398 // Last 7 days
399
400 cal = Calendar.getInstance();
401 datePathes = new ArrayList<String>();
402
403 for (int i = 0; i < 7; i++) {
404 cal.add(Calendar.DAY_OF_YEAR, -i);
405 relPath = JcrUtils.dateAsPath(cal);
406 datePathes.add(relPath);
407 }
408 roots[3] = new VirtualFolder(null,
409 ResultParentUtils.getResultsForDates(session,
410 datePathes), "Last 7 days");
411
412 // All results
413 Node otherResultsPar = session.getNode(SlcJcrResultUtils
414 .getSlcResultsBasePath(session));
415 roots[4] = new ParentNodeFolder(null, otherResultsPar,
416 "All results");
417 return roots;
418 } else
419 // no test has yet been processed, we leave the viewer blank
420 return null;
421 } catch (RepositoryException re) {
422 throw new ArgeoException(
423 "Unexpected error while initializing ResultTree.", re);
424 }
425 }
426
427 // Manage context menu
428 /**
429 * Defines the commands that will pop up in the context menu.
430 **/
431 protected void contextMenuAboutToShow(IMenuManager menuManager) {
432 IWorkbenchWindow window = ClientUiPlugin.getDefault().getWorkbench()
433 .getActiveWorkbenchWindow();
434
435 // Building conditions
436 IStructuredSelection selection = (IStructuredSelection) resultTreeViewer
437 .getSelection();
438 boolean canAddSubfolder = false;
439 boolean isSingleResultNode = false;
440 if (selection.size() == 1) {
441 Object obj = selection.getFirstElement();
442 try {
443 // if (obj instanceof ResultFolder
444 // && (((ResultFolder) obj).getNode())
445 // .isNodeType(SlcTypes.SLC_RESULT_FOLDER))
446 if (isResultFolder)
447 canAddSubfolder = true;
448 else if (obj instanceof SingleResultNode)
449 isSingleResultNode = true;
450 else if (obj instanceof ParentNodeFolder
451 && (((ParentNodeFolder) obj).getNode().getPath()
452 .startsWith(SlcJcrResultUtils
453 .getMyResultsBasePath(session))))
454 canAddSubfolder = true;
455
456 } catch (RepositoryException re) {
457 throw new SlcException(
458 "unexpected error while building condition for context menu",
459 re);
460 }
461 }
462 // Effective Refresh
463 CommandUtils.refreshCommand(menuManager, window, AddResultFolder.ID,
464 AddResultFolder.DEFAULT_LABEL,
465 ClientUiPlugin.getDefault().getWorkbench().getSharedImages()
466 .getImageDescriptor(ISharedImages.IMG_OBJ_ADD),
467 canAddSubfolder);
468
469 CommandUtils.refreshCommand(menuManager, window, RenameResultFolder.ID,
470 RenameResultFolder.DEFAULT_LABEL,
471 RenameResultFolder.DEFAULT_IMG_DESCRIPTOR, canAddSubfolder);
472
473 CommandUtils.refreshCommand(menuManager, window, RenameResultNode.ID,
474 RenameResultNode.DEFAULT_LABEL,
475 RenameResultNode.DEFAULT_IMG_DESCRIPTOR, isSingleResultNode);
476 }
477
478 /* INNER CLASSES */
479 class ViewDragListener implements DragSourceListener {
480
481 public void dragStart(DragSourceEvent event) {
482 // Check if the drag action should start.
483 IStructuredSelection selection = (IStructuredSelection) resultTreeViewer
484 .getSelection();
485 boolean doIt = false;
486 // only one node at a time for the time being.
487 if (selection.size() == 1) {
488 try {
489 Object obj = selection.getFirstElement();
490 if (obj instanceof SingleResultNode) {
491 Node tNode = ((SingleResultNode) obj).getNode();
492 if (tNode.getPrimaryNodeType().isNodeType(
493 SlcTypes.SLC_TEST_RESULT)) {
494 doIt = true;
495 isResultFolder = false;
496 }
497 } else if (obj instanceof ResultFolder) {
498 Node tNode = ((ResultFolder) obj).getNode();
499 if (tNode.getPrimaryNodeType().isNodeType(
500 SlcTypes.SLC_RESULT_FOLDER)) {
501 doIt = true;
502 isResultFolder = true;
503 }
504 }
505 } catch (RepositoryException re) {
506 throw new SlcException(
507 "unexpected error while validating drag source", re);
508 }
509 }
510 event.doit = doIt;
511 }
512
513 public void dragSetData(DragSourceEvent event) {
514 IStructuredSelection selection = (IStructuredSelection) resultTreeViewer
515 .getSelection();
516 Object obj = selection.getFirstElement();
517 try {
518 Node first;
519 if (obj instanceof SingleResultNode) {
520 first = ((SingleResultNode) obj).getNode();
521 event.data = first.getIdentifier();
522 } else if (obj instanceof ResultFolder) {
523 first = ((ResultFolder) obj).getNode();
524 event.data = first.getIdentifier();
525 }
526 } catch (RepositoryException re) {
527 throw new SlcException("unexpected error while setting data",
528 re);
529 }
530 }
531
532 public void dragFinished(DragSourceEvent event) {
533 // refresh is done via observer
534 }
535 }
536
537 // Implementation of the Drop Listener
538 protected class ViewDropListener extends ViewerDropAdapter {
539 private Node targetParentNode = null;
540
541 public ViewDropListener(Viewer viewer) {
542 super(viewer);
543 }
544
545 @Override
546 public boolean validateDrop(Object target, int operation,
547 TransferData transferType) {
548
549 boolean validDrop = false;
550 try {
551 // We can only drop under myResults
552 Node tpNode = null;
553 if (target instanceof ResultFolder) {
554 tpNode = ((ResultFolder) target).getNode();
555 } else if (target instanceof ParentNodeFolder) {
556 if ((((ParentNodeFolder) target).getNode().getPath()
557 .startsWith(SlcJcrResultUtils
558 .getMyResultsBasePath(session))))
559 tpNode = ((ParentNodeFolder) target).getNode();
560 } else if (target instanceof SingleResultNode) {
561 Node currNode = ((SingleResultNode) target).getNode();
562 if (currNode
563 .getParent()
564 .getPath()
565 .startsWith(
566 SlcJcrResultUtils
567 .getMyResultsBasePath(session)))
568 tpNode = currNode.getParent();
569 }
570
571 if (tpNode != null) {
572 // Sanity check : we cannot move a folder to one of its sub
573 // folder
574 boolean doit = true;
575 if (isResultFolder) {
576 Node source = ((ParentNodeFolder) lastSelectedSourceElement)
577 .getNode();
578 String sourcePath = source.getPath();
579 String targetPath = tpNode.getPath();
580 if (targetPath.startsWith(sourcePath))
581 doit = false;
582 }
583 if (doit) {
584 targetParentNode = tpNode;
585 validDrop = true;
586 lastSelectedTargetElement = (ResultParent) target;
587 }
588 }
589
590 } catch (RepositoryException re) {
591 throw new SlcException(
592 "unexpected error while validating drop target", re);
593 }
594 return validDrop;
595 }
596
597 @Override
598 public boolean performDrop(Object data) {
599 // clear selection to prevent unwanted scrolling of the UI
600 resultTreeViewer.setSelection(null);
601 try {
602 Node source = session.getNodeByIdentifier((String) data);
603
604 // Check is a node with same name already exists at destination
605 String name;
606 if (source.hasProperty(Property.JCR_TITLE))
607 name = source.getProperty(Property.JCR_TITLE).getString();
608 else if (source.hasProperty(SlcNames.SLC_TEST_CASE))
609 name = source.getProperty(SlcNames.SLC_TEST_CASE)
610 .getString();
611 else
612 name = source.getName();
613
614 if (targetParentNode.hasNode(name)) {
615 ConfirmOverwriteWizard wizard = new ConfirmOverwriteWizard(
616 name, targetParentNode);
617 WizardDialog dialog = new WizardDialog(Display.getDefault()
618 .getActiveShell(), wizard);
619
620 if (dialog.open() == WizardDialog.CANCEL)
621 return true;
622
623 if (wizard.overwrite()) {
624 targetParentNode.getNode(name).remove();
625 // session.save();
626 } else
627 name = wizard.newName();
628 }
629
630 Node target;
631 if (!isActionUnderMyResult) {// Copy
632 target = targetParentNode.addNode(name, source
633 .getPrimaryNodeType().getName());
634 JcrUtils.copy(source, target);
635 } else {// move
636 String sourcePath = source.getPath();
637 String destPath = targetParentNode.getPath() + "/" + name;
638 session.move(sourcePath, destPath);
639 // session.save();
640 target = session.getNode(destPath);
641 }
642 if (!target.isNodeType(NodeType.MIX_TITLE))
643 target.addMixin(NodeType.MIX_TITLE);
644 target.setProperty(Property.JCR_TITLE, name);
645 ResultParentUtils
646 .updatePassedStatus(target,
647 target.getNode(SlcNames.SLC_STATUS)
648 .getProperty(SlcNames.SLC_SUCCESS)
649 .getBoolean());
650 session.save();
651 } catch (RepositoryException re) {
652 throw new SlcException(
653 "unexpected error while copying dropped node", re);
654 }
655 return true;
656 }
657 }
658
659 class ResultObserver extends AsyncUiEventListener {
660
661 public ResultObserver(Display display) {
662 super(display);
663 }
664
665 @Override
666 protected Boolean willProcessInUiThread(List<Event> events)
667 throws RepositoryException {
668 // unfiltered for the time being
669 return true;
670 }
671
672 protected void onEventInUiThread(List<Event> events)
673 throws RepositoryException {
674 int i = 0;
675
676 for (Event event : events) {
677 i++;
678 // if (log.isDebugEnabled())
679 // log.debug("Received event " + event);
680 int eventType = event.getType();
681 if (eventType == Event.NODE_REMOVED) {
682 String path = event.getPath();
683 String parPath = JcrUtils.parentPath(path);
684 if (session.nodeExists(parPath)) {
685 Node currNode = session.getNode(parPath);
686 if (currNode.isNodeType(NodeType.NT_UNSTRUCTURED)) {
687 // jcrRefresh(currNode);
688 refresh(lastSelectedSourceElementParent);
689 }
690 }
691 } else if (eventType == Event.NODE_ADDED) {
692 // refresh(lastSelectedTargetElement);
693 String path = event.getPath();
694 if (session.nodeExists(path)) {
695 Node currNode = session.getNode(path);
696 if (currNode.isNodeType(SlcTypes.SLC_TEST_RESULT)
697 || currNode
698 .isNodeType(SlcTypes.SLC_RESULT_FOLDER)) {
699 refresh(lastSelectedTargetElement);
700 // resultTreeViewer.expandToLevel(
701 // lastSelectedTargetElement, 1);
702 }
703 }
704 }
705 }
706 if (log.isDebugEnabled())
707 log.debug("treated events: " + i);
708 }
709 }
710
711 class PropertiesContentProvider implements IStructuredContentProvider {
712
713 public void dispose() {
714 }
715
716 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
717 }
718
719 public Object[] getElements(Object inputElement) {
720 try {
721 if (inputElement instanceof Node) {
722 List<Property> props = new ArrayList<Property>();
723 PropertyIterator pit = ((Node) inputElement)
724 .getProperties();
725 while (pit.hasNext())
726 props.add(pit.nextProperty());
727 return props.toArray();
728 }
729 return new Object[] {};
730 } catch (RepositoryException e) {
731 throw new ArgeoException("Cannot get element for "
732 + inputElement, e);
733 }
734 }
735 }
736
737 class MySelectionChangedListener implements ISelectionChangedListener {
738
739 public void selectionChanged(SelectionChangedEvent event) {
740 if (!event.getSelection().isEmpty()) {
741 IStructuredSelection sel = (IStructuredSelection) event
742 .getSelection();
743 ResultParent firstItem = (ResultParent) sel.getFirstElement();
744 if (firstItem instanceof SingleResultNode)
745 propertiesViewer.setInput(((SingleResultNode) firstItem)
746 .getNode());
747 else
748 propertiesViewer.setInput(null);
749 // update cache for Drag & drop
750 lastSelectedTargetElement = firstItem;
751 lastSelectedSourceElement = firstItem;
752 lastSelectedSourceElementParent = (ResultParent) firstItem
753 .getParent();
754 String pPath = "";
755 try {
756
757 if (firstItem instanceof ParentNodeFolder)
758 pPath = ((ParentNodeFolder) firstItem).getNode()
759 .getPath();
760 else if (firstItem instanceof SingleResultNode)
761 pPath = ((SingleResultNode) firstItem).getNode()
762 .getPath();
763 } catch (RepositoryException e) {
764 throw new SlcException(
765 "Unexpected error while checking parent UI tree", e);
766 }
767 if ((pPath.startsWith(SlcJcrResultUtils
768 .getMyResultsBasePath(session))))
769 isActionUnderMyResult = true;
770 else
771 isActionUnderMyResult = false;
772 }
773 }
774 }
775
776 class ViewDoubleClickListener implements IDoubleClickListener {
777 public void doubleClick(DoubleClickEvent evt) {
778 processDoubleClick(evt);
779 }
780
781 }
782
783 /* DEPENDENCY INJECTION */
784 public void setSession(Session session) {
785 this.session = session;
786 }
787
788 }