2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.slc
.client
.ui
.views
;
18 import java
.util
.ArrayList
;
19 import java
.util
.Calendar
;
20 import java
.util
.List
;
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
;
35 import org
.argeo
.ArgeoException
;
36 import org
.argeo
.eclipse
.ui
.jcr
.AsyncUiEventListener
;
37 import org
.argeo
.eclipse
.ui
.utils
.CommandUtils
;
38 import org
.argeo
.jcr
.JcrUtils
;
39 import org
.argeo
.slc
.SlcException
;
40 import org
.argeo
.slc
.client
.ui
.ClientUiPlugin
;
41 import org
.argeo
.slc
.client
.ui
.SlcUiConstants
;
42 import org
.argeo
.slc
.client
.ui
.commands
.AddResultFolder
;
43 import org
.argeo
.slc
.client
.ui
.commands
.RenameResultFolder
;
44 import org
.argeo
.slc
.client
.ui
.commands
.RenameResultNode
;
45 import org
.argeo
.slc
.client
.ui
.editors
.ProcessEditor
;
46 import org
.argeo
.slc
.client
.ui
.editors
.ProcessEditorInput
;
47 import org
.argeo
.slc
.client
.ui
.model
.ParentNodeFolder
;
48 import org
.argeo
.slc
.client
.ui
.model
.ResultFolder
;
49 import org
.argeo
.slc
.client
.ui
.model
.ResultItemsComparator
;
50 import org
.argeo
.slc
.client
.ui
.model
.ResultItemsComparer
;
51 import org
.argeo
.slc
.client
.ui
.model
.ResultParent
;
52 import org
.argeo
.slc
.client
.ui
.model
.ResultParentUtils
;
53 import org
.argeo
.slc
.client
.ui
.model
.SingleResultNode
;
54 import org
.argeo
.slc
.client
.ui
.model
.VirtualFolder
;
55 import org
.argeo
.slc
.client
.ui
.providers
.ResultTreeContentProvider
;
56 import org
.argeo
.slc
.client
.ui
.providers
.ResultTreeLabelProvider
;
57 import org
.argeo
.slc
.client
.ui
.wizards
.ConfirmOverwriteWizard
;
58 import org
.argeo
.slc
.jcr
.SlcJcrResultUtils
;
59 import org
.argeo
.slc
.jcr
.SlcNames
;
60 import org
.argeo
.slc
.jcr
.SlcTypes
;
61 import org
.eclipse
.jface
.action
.IMenuListener
;
62 import org
.eclipse
.jface
.action
.IMenuManager
;
63 import org
.eclipse
.jface
.action
.MenuManager
;
64 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
65 import org
.eclipse
.jface
.viewers
.DecoratingLabelProvider
;
66 import org
.eclipse
.jface
.viewers
.DoubleClickEvent
;
67 import org
.eclipse
.jface
.viewers
.IDoubleClickListener
;
68 import org
.eclipse
.jface
.viewers
.ILabelDecorator
;
69 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
70 import org
.eclipse
.jface
.viewers
.IStructuredContentProvider
;
71 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
72 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
73 import org
.eclipse
.jface
.viewers
.TableViewer
;
74 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
75 import org
.eclipse
.jface
.viewers
.TreePath
;
76 import org
.eclipse
.jface
.viewers
.TreeViewer
;
77 import org
.eclipse
.jface
.viewers
.Viewer
;
78 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
79 import org
.eclipse
.jface
.wizard
.WizardDialog
;
80 import org
.eclipse
.swt
.SWT
;
81 import org
.eclipse
.swt
.custom
.SashForm
;
82 import org
.eclipse
.swt
.dnd
.DND
;
83 import org
.eclipse
.swt
.dnd
.DragSourceEvent
;
84 import org
.eclipse
.swt
.dnd
.DragSourceListener
;
85 import org
.eclipse
.swt
.dnd
.TextTransfer
;
86 import org
.eclipse
.swt
.dnd
.Transfer
;
87 import org
.eclipse
.swt
.dnd
.TransferData
;
88 import org
.eclipse
.swt
.layout
.FillLayout
;
89 import org
.eclipse
.swt
.layout
.GridData
;
90 import org
.eclipse
.swt
.layout
.GridLayout
;
91 import org
.eclipse
.swt
.widgets
.Composite
;
92 import org
.eclipse
.swt
.widgets
.Display
;
93 import org
.eclipse
.swt
.widgets
.Menu
;
94 import org
.eclipse
.ui
.ISharedImages
;
95 import org
.eclipse
.ui
.IWorkbenchPage
;
96 import org
.eclipse
.ui
.IWorkbenchWindow
;
97 import org
.eclipse
.ui
.PlatformUI
;
98 import org
.eclipse
.ui
.part
.ViewPart
;
100 /** SLC generic JCR Result tree view. */
101 public class JcrResultTreeView
extends ViewPart
{
102 public final static String ID
= ClientUiPlugin
.ID
+ ".jcrResultTreeView";
104 // private final static Log log =
105 // LogFactory.getLog(JcrResultTreeView.class);
107 /* DEPENDENCY INJECTION */
108 private Session session
;
111 private TreeViewer resultTreeViewer
;
112 private TableViewer propertiesViewer
;
114 private EventListener myResultsObserver
= null;
115 private EventListener allResultsObserver
= null;
118 private final static String
[] observedNodeTypesUnderMyResult
= {
119 SlcTypes
.SLC_TEST_RESULT
, SlcTypes
.SLC_RESULT_FOLDER
,
120 SlcTypes
.SLC_MY_RESULT_ROOT_FOLDER
};
122 private final static String
[] observedNodeTypesUnderAllResults
= {
123 SlcTypes
.SLC_TEST_RESULT
, NodeType
.NT_UNSTRUCTURED
};
125 // FIXME cache to ease D&D
126 private boolean isActionUnderMyResult
= false;
127 // private ResultParent lastSelectedTargetElement;
128 private ResultParent lastSelectedSourceElement
;
129 private ResultParent lastSelectedSourceElementParent
;
130 private boolean isResultFolder
= false;
132 // FIXME we cache the fact that we are moving a node to avoid exception
133 // triggered by the "Add Node" event while moving
134 // boolean isMoveInProgress = false;
137 * To be overridden to adapt size of form and result frames.
139 protected int[] getWeights() {
140 return new int[] { 70, 30 };
144 public void createPartControl(Composite parent
) {
145 parent
.setLayout(new FillLayout());
147 SashForm sashForm
= new SashForm(parent
, SWT
.VERTICAL
);
148 sashForm
.setSashWidth(4);
149 sashForm
.setLayout(new FillLayout());
151 // Create the tree on top of the view
152 Composite top
= new Composite(sashForm
, SWT
.NONE
);
153 GridLayout gl
= new GridLayout(1, false);
155 resultTreeViewer
= createResultsTreeViewer(top
);
157 // Create the property viewer on the bottom
158 Composite bottom
= new Composite(sashForm
, SWT
.NONE
);
159 bottom
.setLayout(new GridLayout(1, false));
160 propertiesViewer
= createPropertiesViewer(bottom
);
162 sashForm
.setWeights(getWeights());
164 setOrderedInput(resultTreeViewer
);
166 // Initialize observer
168 ObservationManager observationManager
= session
.getWorkspace()
169 .getObservationManager();
170 myResultsObserver
= new MyResultsObserver(resultTreeViewer
171 .getTree().getDisplay());
172 allResultsObserver
= new AllResultsObserver(resultTreeViewer
173 .getTree().getDisplay());
175 // observe tree changes under MyResults
176 observationManager
.addEventListener(myResultsObserver
,
177 Event
.NODE_ADDED
| Event
.NODE_REMOVED
,
178 SlcJcrResultUtils
.getMyResultsBasePath(session
), true,
179 null, observedNodeTypesUnderMyResult
, false);
180 // observe tree changes under All results
181 observationManager
.addEventListener(allResultsObserver
,
182 Event
.NODE_ADDED
| Event
.NODE_REMOVED
,
183 SlcJcrResultUtils
.getSlcResultsBasePath(session
), true,
184 null, observedNodeTypesUnderAllResults
, false);
185 } catch (RepositoryException e
) {
186 throw new SlcException("Cannot register listeners", e
);
191 * Override default behaviour so that default defined order remains
192 * unchanged on first level of the tree
194 private void setOrderedInput(TreeViewer viewer
) {
195 // Add specific ordering
196 resultTreeViewer
.setInput(null);
197 viewer
.setComparator(null);
198 resultTreeViewer
.setInput(initializeResultTree());
199 viewer
.setComparator(new ResultItemsComparator());
202 // The main tree viewer
203 protected TreeViewer
createResultsTreeViewer(Composite parent
) {
204 int style
= SWT
.BORDER
| SWT
.MULTI
;
206 TreeViewer viewer
= new TreeViewer(parent
, style
);
207 viewer
.getTree().setLayoutData(
208 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
210 viewer
.setContentProvider(new ResultTreeContentProvider());
212 // Add label provider with label decorator
213 ResultTreeLabelProvider rtLblProvider
= new ResultTreeLabelProvider();
214 ILabelDecorator decorator
= ClientUiPlugin
.getDefault().getWorkbench()
215 .getDecoratorManager().getLabelDecorator();
216 viewer
.setLabelProvider(new DecoratingLabelProvider(rtLblProvider
,
218 viewer
.addDoubleClickListener(new ViewDoubleClickListener());
220 // Override default behaviour to insure that 2 distincts results that
221 // have the same name will be correctly and distincly returned by
223 // TreeViewer.getSelection() method.
224 viewer
.setComparer(new ResultItemsComparer());
226 // viewer.setLabelProvider(rtLblProvider);
227 getSite().setSelectionProvider(viewer
);
229 // add drag & drop support
230 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
231 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
232 viewer
.addDragSupport(operations
, tt
, new ViewDragListener());
233 viewer
.addDropSupport(operations
, tt
, new ViewDropListener(viewer
));
236 MenuManager menuManager
= new MenuManager();
237 Menu menu
= menuManager
.createContextMenu(viewer
.getTree());
238 menuManager
.addMenuListener(new IMenuListener() {
239 public void menuAboutToShow(IMenuManager manager
) {
240 contextMenuAboutToShow(manager
);
243 viewer
.getTree().setMenu(menu
);
244 getSite().registerContextMenu(menuManager
, viewer
);
246 // add change listener to display TestResult information in the property
248 viewer
.addSelectionChangedListener(new MySelectionChangedListener());
252 // Detailed property viewer
253 protected TableViewer
createPropertiesViewer(Composite parent
) {
254 propertiesViewer
= new TableViewer(parent
);
255 propertiesViewer
.getTable().setLayoutData(
256 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
257 propertiesViewer
.getTable().setHeaderVisible(true);
258 propertiesViewer
.setContentProvider(new PropertiesContentProvider());
259 TableViewerColumn col
= new TableViewerColumn(propertiesViewer
,
261 col
.getColumn().setText("Name");
262 col
.getColumn().setWidth(200);
263 col
.setLabelProvider(new ColumnLabelProvider() {
264 public String
getText(Object element
) {
266 return ((Property
) element
).getName();
267 } catch (RepositoryException e
) {
268 throw new ArgeoException(
269 "Unexpected exception in label provider", e
);
273 col
= new TableViewerColumn(propertiesViewer
, SWT
.NONE
);
274 col
.getColumn().setText("Value");
275 col
.getColumn().setWidth(400);
276 col
.setLabelProvider(new ColumnLabelProvider() {
277 public String
getText(Object element
) {
279 Property property
= (Property
) element
;
280 if (property
.getType() == PropertyType
.BINARY
)
282 else if (property
.isMultiple()) {
283 StringBuffer buf
= new StringBuffer("[");
284 Value
[] values
= property
.getValues();
285 for (int i
= 0; i
< values
.length
; i
++) {
288 buf
.append(values
[i
].getString());
291 return buf
.toString();
293 return property
.getValue().getString();
294 } catch (RepositoryException e
) {
295 throw new ArgeoException(
296 "Unexpected exception in label provider", e
);
300 col
= new TableViewerColumn(propertiesViewer
, SWT
.NONE
);
301 col
.getColumn().setText("Type");
302 col
.getColumn().setWidth(200);
303 col
.setLabelProvider(new ColumnLabelProvider() {
304 public String
getText(Object element
) {
306 return PropertyType
.nameFromValue(((Property
) element
)
308 } catch (RepositoryException e
) {
309 throw new ArgeoException(
310 "Unexpected exception in label provider", e
);
314 propertiesViewer
.setInput(getViewSite());
315 return propertiesViewer
;
319 * Override to provide specific behaviour. Typically to enable the display
324 protected void processDoubleClick(DoubleClickEvent evt
) {
325 Object obj
= ((IStructuredSelection
) evt
.getSelection())
328 if (obj
instanceof SingleResultNode
) {
329 SingleResultNode srNode
= (SingleResultNode
) obj
;
330 Node node
= srNode
.getNode();
331 // FIXME: open a default result editor
332 if (node
.isNodeType(SlcTypes
.SLC_PROCESS
)) {
333 IWorkbenchPage activePage
= PlatformUI
.getWorkbench()
334 .getActiveWorkbenchWindow().getActivePage();
335 activePage
.openEditor(
336 new ProcessEditorInput(node
.getPath()),
340 } catch (Exception e
) {
341 throw new SlcException("Cannot open " + obj
, e
);
346 public void setFocus() {
350 * refreshes the passed resultParent and its corresponding subtree. It
351 * refreshes the whole viewer if null is passed.
353 * @param ResultParent
356 public void refresh(ResultParent resultParent
) {
357 if (resultParent
== null) {
358 if (!resultTreeViewer
.getTree().isDisposed()) {
359 TreePath
[] tps
= resultTreeViewer
.getExpandedTreePaths();
360 setOrderedInput(resultTreeViewer
);
361 resultTreeViewer
.setExpandedTreePaths(tps
);
363 setOrderedInput(resultTreeViewer
);
365 if (resultParent
instanceof ParentNodeFolder
) {
366 ParentNodeFolder currFolder
= (ParentNodeFolder
) resultParent
;
367 jcrRefresh(currFolder
.getNode());
368 currFolder
.forceFullRefresh();
370 // FIXME: specific refresh does not work
371 // resultTreeViewer.refresh(resultParent, true);
377 * refreshes the passed node and its corresponding subtree.
383 public boolean jcrRefresh(Node node
) {
384 // if (log.isDebugEnabled())
385 // log.debug(" JCR refreshing " + node + "...");
386 // Thread.dumpStack();
387 boolean isPassed
= true;
389 if (node
.isNodeType(SlcTypes
.SLC_TEST_RESULT
)) {
390 isPassed
= node
.getNode(SlcNames
.SLC_STATUS
)
391 .getProperty(SlcNames
.SLC_SUCCESS
).getBoolean();
392 } else if (node
.isNodeType(SlcTypes
.SLC_RESULT_FOLDER
)) {
393 NodeIterator ni
= node
.getNodes();
394 while (ni
.hasNext()) {
395 Node currChild
= ni
.nextNode();
396 isPassed
= isPassed
& jcrRefresh(currChild
);
398 if (isPassed
!= node
.getNode(SlcNames
.SLC_STATUS
)
399 .getProperty(SlcNames
.SLC_SUCCESS
).getBoolean()) {
400 node
.getNode(SlcNames
.SLC_STATUS
).setProperty(
401 SlcNames
.SLC_SUCCESS
, isPassed
);
402 node
.getSession().save();
407 } catch (RepositoryException e
) {
408 throw new SlcException("Cannot register listeners", e
);
413 private ResultParent
[] initializeResultTree() {
415 // Force initialization of the tree structure if needed
416 SlcJcrResultUtils
.getSlcResultsParentNode(session
);
417 SlcJcrResultUtils
.getMyResultParentNode(session
);
418 // Remove yesterday and last 7 days virtual folders
419 // ResultParent[] roots = new ResultParent[5];
420 ResultParent
[] roots
= new ResultParent
[3];
423 roots
[0] = new ParentNodeFolder(null,
424 SlcJcrResultUtils
.getMyResultParentNode(session
),
425 SlcUiConstants
.DEFAULT_MY_RESULTS_FOLDER_LABEL
);
428 Calendar cal
= Calendar
.getInstance();
429 String relPath
= JcrUtils
.dateAsPath(cal
);
430 List
<String
> datePathes
= new ArrayList
<String
>();
431 datePathes
.add(relPath
);
432 roots
[1] = new VirtualFolder(null,
433 ResultParentUtils
.getResultsForDates(session
, datePathes
),
437 // cal = Calendar.getInstance();
438 // cal.add(Calendar.DAY_OF_YEAR, -1);
439 // relPath = JcrUtils.dateAsPath(cal);
440 // datePathes = new ArrayList<String>();
441 // datePathes.add(relPath);
442 // roots[2] = new VirtualFolder(null,
443 // ResultParentUtils.getResultsForDates(session, datePathes),
447 // cal = Calendar.getInstance();
448 // datePathes = new ArrayList<String>();
450 // for (int i = 0; i < 7; i++) {
451 // cal.add(Calendar.DAY_OF_YEAR, -i);
452 // relPath = JcrUtils.dateAsPath(cal);
453 // datePathes.add(relPath);
455 // roots[3] = new VirtualFolder(null,
456 // ResultParentUtils.getResultsForDates(session, datePathes),
460 Node otherResultsPar
= session
.getNode(SlcJcrResultUtils
461 .getSlcResultsBasePath(session
));
462 // roots[4] = new ParentNodeFolder(null, otherResultsPar,
464 roots
[2] = new ParentNodeFolder(null, otherResultsPar
,
467 } catch (RepositoryException re
) {
468 throw new ArgeoException(
469 "Unexpected error while initializing ResultTree.", re
);
473 // Manage context menu
475 * Defines the commands that will pop up in the context menu.
477 protected void contextMenuAboutToShow(IMenuManager menuManager
) {
478 IWorkbenchWindow window
= ClientUiPlugin
.getDefault().getWorkbench()
479 .getActiveWorkbenchWindow();
481 IStructuredSelection selection
= (IStructuredSelection
) resultTreeViewer
483 boolean canAddSubfolder
= false;
484 boolean canRenamefolder
= false;
485 boolean isSingleResultNode
= false;
486 // Building conditions
487 if (selection
.size() == 1) {
488 Object obj
= selection
.getFirstElement();
490 if (obj
instanceof SingleResultNode
)
491 isSingleResultNode
= true;
492 else if (obj
instanceof ParentNodeFolder
) {
493 Node cNode
= ((ParentNodeFolder
) obj
).getNode();
494 if (cNode
.isNodeType(SlcTypes
.SLC_RESULT_FOLDER
)) {
495 canAddSubfolder
= true;
496 canRenamefolder
= true;
498 .isNodeType(SlcTypes
.SLC_MY_RESULT_ROOT_FOLDER
)) {
499 canAddSubfolder
= true;
502 } catch (RepositoryException re
) {
503 throw new SlcException(
504 "unexpected error while building condition for context menu",
509 CommandUtils
.refreshCommand(menuManager
, window
, AddResultFolder
.ID
,
510 AddResultFolder
.DEFAULT_LABEL
,
511 ClientUiPlugin
.getDefault().getWorkbench().getSharedImages()
512 .getImageDescriptor(ISharedImages
.IMG_OBJ_ADD
),
515 CommandUtils
.refreshCommand(menuManager
, window
, RenameResultFolder
.ID
,
516 RenameResultFolder
.DEFAULT_LABEL
,
517 RenameResultFolder
.DEFAULT_IMG_DESCRIPTOR
, canRenamefolder
);
519 CommandUtils
.refreshCommand(menuManager
, window
, RenameResultNode
.ID
,
520 RenameResultNode
.DEFAULT_LABEL
,
521 RenameResultNode
.DEFAULT_IMG_DESCRIPTOR
, isSingleResultNode
);
525 class ViewDragListener
implements DragSourceListener
{
527 public void dragStart(DragSourceEvent event
) {
528 // Check if the drag action should start.
529 IStructuredSelection selection
= (IStructuredSelection
) resultTreeViewer
531 boolean doIt
= false;
532 // only one node at a time for the time being.
533 if (selection
.size() == 1) {
535 Object obj
= selection
.getFirstElement();
536 if (obj
instanceof SingleResultNode
) {
537 Node tNode
= ((SingleResultNode
) obj
).getNode();
538 if (tNode
.getPrimaryNodeType().isNodeType(
539 SlcTypes
.SLC_TEST_RESULT
)) {
541 isResultFolder
= false;
543 } else if (obj
instanceof ResultFolder
) {
544 Node tNode
= ((ResultFolder
) obj
).getNode();
545 if (tNode
.getPrimaryNodeType().isNodeType(
546 SlcTypes
.SLC_RESULT_FOLDER
)) {
548 isResultFolder
= true;
551 } catch (RepositoryException re
) {
552 throw new SlcException(
553 "unexpected error while validating drag source", re
);
559 public void dragSetData(DragSourceEvent event
) {
560 IStructuredSelection selection
= (IStructuredSelection
) resultTreeViewer
562 Object obj
= selection
.getFirstElement();
565 if (obj
instanceof SingleResultNode
) {
566 first
= ((SingleResultNode
) obj
).getNode();
567 event
.data
= first
.getIdentifier();
568 } else if (obj
instanceof ResultFolder
) {
569 first
= ((ResultFolder
) obj
).getNode();
570 event
.data
= first
.getIdentifier();
572 } catch (RepositoryException re
) {
573 throw new SlcException("unexpected error while setting data",
578 public void dragFinished(DragSourceEvent event
) {
579 // refresh is done via observer
583 // Implementation of the Drop Listener
584 protected class ViewDropListener
extends ViewerDropAdapter
{
585 private Node targetParentNode
= null;
587 public ViewDropListener(Viewer viewer
) {
592 public boolean validateDrop(Object target
, int operation
,
593 TransferData transferType
) {
594 boolean validDrop
= false;
596 // We can only drop under myResults
598 if (target
instanceof SingleResultNode
) {
599 Node currNode
= ((SingleResultNode
) target
).getNode();
600 String pPath
= currNode
.getParent().getPath();
601 if (pPath
.startsWith(SlcJcrResultUtils
602 .getMyResultsBasePath(session
)))
603 tpNode
= currNode
.getParent();
604 } else if (target
instanceof ResultFolder
) {
605 tpNode
= ((ResultFolder
) target
).getNode();
606 } else if (target
instanceof ParentNodeFolder
) {
607 Node node
= ((ParentNodeFolder
) target
).getNode();
608 if (node
.isNodeType(SlcTypes
.SLC_MY_RESULT_ROOT_FOLDER
))
609 tpNode
= ((ParentNodeFolder
) target
).getNode();
612 if (tpNode
!= null) {
613 // Sanity check : we cannot move a folder to one of its sub
614 // folder or neither move an object in the same parent
618 if (isResultFolder
) {
619 source
= ((ParentNodeFolder
) lastSelectedSourceElement
)
621 if (tpNode
.getPath().startsWith(source
.getPath())
622 || source
.getParent().getPath()
623 .equals(tpNode
.getPath()))
625 } else if (lastSelectedSourceElement
instanceof SingleResultNode
) {
626 source
= ((SingleResultNode
) lastSelectedSourceElement
)
628 String sourceParentPath
= JcrUtils
.parentPath(source
630 if (tpNode
.getPath().equals(sourceParentPath
))
634 targetParentNode
= tpNode
;
636 // lastSelectedTargetElement = (ResultParent) target;
639 } catch (RepositoryException re
) {
640 throw new SlcException(
641 "unexpected error while validating drop target", re
);
647 public boolean performDrop(Object data
) {
648 // clear selection to prevent unwanted scrolling of the UI
649 resultTreeViewer
.setSelection(null);
651 Node source
= session
.getNodeByIdentifier((String
) data
);
654 if (source
.hasProperty(Property
.JCR_TITLE
))
655 name
= source
.getProperty(Property
.JCR_TITLE
).getString();
656 else if (source
.hasProperty(SlcNames
.SLC_TEST_CASE
))
657 name
= source
.getProperty(SlcNames
.SLC_TEST_CASE
)
660 name
= source
.getName();
662 // Check if a user defined folder result with same name exists
664 if (targetParentNode
.hasNode(name
)
665 && targetParentNode
.getNode(name
).isNodeType(
666 SlcTypes
.SLC_RESULT_FOLDER
)) {
667 ConfirmOverwriteWizard wizard
= new ConfirmOverwriteWizard(
668 name
, targetParentNode
);
669 WizardDialog dialog
= new WizardDialog(Display
.getDefault()
670 .getActiveShell(), wizard
);
672 if (dialog
.open() == WizardDialog
.CANCEL
)
675 if (wizard
.overwrite()) {
676 targetParentNode
.getNode(name
).remove();
679 name
= wizard
.newName();
683 boolean passedStatus
= source
.getNode(SlcNames
.SLC_STATUS
)
684 .getProperty(SlcNames
.SLC_SUCCESS
).getBoolean();
685 if (!isActionUnderMyResult
) {// Copy
686 target
= targetParentNode
.addNode(source
.getName(), source
687 .getPrimaryNodeType().getName());
688 JcrUtils
.copy(source
, target
);
690 String sourcePath
= source
.getPath();
691 String destPath
= targetParentNode
.getPath() + "/" + name
;
692 session
.move(sourcePath
, destPath
);
694 // Update passed status of the parent source Node
695 ResultParentUtils
.updatePassedStatus(
696 session
.getNode(JcrUtils
.parentPath(sourcePath
)),
698 target
= session
.getNode(destPath
);
701 if (!target
.isNodeType(NodeType
.MIX_TITLE
))
702 target
.addMixin(NodeType
.MIX_TITLE
);
703 target
.setProperty(Property
.JCR_TITLE
, name
);
704 ResultParentUtils
.updatePassedStatus(target
.getParent(),
707 } catch (RepositoryException re
) {
708 throw new SlcException(
709 "unexpected error while copying dropped node", re
);
715 class MyResultsObserver
extends AsyncUiEventListener
{
717 public MyResultsObserver(Display display
) {
722 protected Boolean
willProcessInUiThread(List
<Event
> events
)
723 throws RepositoryException
{
724 // unfiltered for the time being
728 protected void onEventInUiThread(List
<Event
> events
)
729 throws RepositoryException
{
730 List
<Node
> nodesToRefresh
= new ArrayList
<Node
>();
732 for (Event event
: events
) {
733 String parPath
= JcrUtils
.parentPath(event
.getPath());
734 if (session
.nodeExists(parPath
)) {
735 Node node
= session
.getNode(parPath
);
736 if (!nodesToRefresh
.contains(node
)) {
737 nodesToRefresh
.add(node
);
742 // Update check nodes
743 for (Node node
: nodesToRefresh
)
749 class AllResultsObserver
extends AsyncUiEventListener
{
751 public AllResultsObserver(Display display
) {
756 protected Boolean
willProcessInUiThread(List
<Event
> events
)
757 throws RepositoryException
{
758 // unfiltered for the time being
762 protected void onEventInUiThread(List
<Event
> events
)
763 throws RepositoryException
{
764 if (lastSelectedSourceElementParent
!= null)
765 refresh(lastSelectedSourceElementParent
);
769 class PropertiesContentProvider
implements IStructuredContentProvider
{
771 public void dispose() {
774 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
777 public Object
[] getElements(Object inputElement
) {
779 if (inputElement
instanceof Node
) {
780 List
<Property
> props
= new ArrayList
<Property
>();
781 PropertyIterator pit
= ((Node
) inputElement
)
783 while (pit
.hasNext())
784 props
.add(pit
.nextProperty());
785 return props
.toArray();
787 return new Object
[] {};
788 } catch (RepositoryException e
) {
789 throw new ArgeoException("Cannot get element for "
795 class MySelectionChangedListener
implements ISelectionChangedListener
{
797 public void selectionChanged(SelectionChangedEvent event
) {
798 if (!event
.getSelection().isEmpty()) {
799 IStructuredSelection sel
= (IStructuredSelection
) event
801 ResultParent firstItem
= (ResultParent
) sel
.getFirstElement();
802 if (firstItem
instanceof SingleResultNode
)
803 propertiesViewer
.setInput(((SingleResultNode
) firstItem
)
806 propertiesViewer
.setInput(null);
807 // update cache for Drag & drop
808 // lastSelectedTargetElement = firstItem;
809 lastSelectedSourceElement
= firstItem
;
810 lastSelectedSourceElementParent
= (ResultParent
) firstItem
815 if (firstItem
instanceof ParentNodeFolder
)
816 pPath
= ((ParentNodeFolder
) firstItem
).getNode()
818 else if (firstItem
instanceof SingleResultNode
)
819 pPath
= ((SingleResultNode
) firstItem
).getNode()
821 } catch (RepositoryException e
) {
822 throw new SlcException(
823 "Unexpected error while checking parent UI tree", e
);
825 if ((pPath
.startsWith(SlcJcrResultUtils
826 .getMyResultsBasePath(session
))))
827 isActionUnderMyResult
= true;
829 isActionUnderMyResult
= false;
834 class ViewDoubleClickListener
implements IDoubleClickListener
{
835 public void doubleClick(DoubleClickEvent evt
) {
836 processDoubleClick(evt
);
841 /* DEPENDENCY INJECTION */
842 public void setSession(Session session
) {
843 this.session
= session
;