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