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
.text
.DateFormat
;
19 import java
.text
.SimpleDateFormat
;
20 import java
.util
.ArrayList
;
21 import java
.util
.Calendar
;
22 import java
.util
.Iterator
;
23 import java
.util
.List
;
25 import javax
.jcr
.Node
;
26 import javax
.jcr
.NodeIterator
;
27 import javax
.jcr
.Property
;
28 import javax
.jcr
.RepositoryException
;
29 import javax
.jcr
.Session
;
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
.jcr
.SlcJcrResultUtils
;
58 import org
.argeo
.slc
.jcr
.SlcNames
;
59 import org
.argeo
.slc
.jcr
.SlcTypes
;
60 import org
.eclipse
.jface
.action
.IMenuListener
;
61 import org
.eclipse
.jface
.action
.IMenuManager
;
62 import org
.eclipse
.jface
.action
.MenuManager
;
63 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
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
.swt
.SWT
;
80 import org
.eclipse
.swt
.custom
.SashForm
;
81 import org
.eclipse
.swt
.dnd
.DND
;
82 import org
.eclipse
.swt
.dnd
.DragSourceEvent
;
83 import org
.eclipse
.swt
.dnd
.DragSourceListener
;
84 import org
.eclipse
.swt
.dnd
.TextTransfer
;
85 import org
.eclipse
.swt
.dnd
.Transfer
;
86 import org
.eclipse
.swt
.dnd
.TransferData
;
87 import org
.eclipse
.swt
.layout
.FillLayout
;
88 import org
.eclipse
.swt
.layout
.GridData
;
89 import org
.eclipse
.swt
.layout
.GridLayout
;
90 import org
.eclipse
.swt
.widgets
.Composite
;
91 import org
.eclipse
.swt
.widgets
.Display
;
92 import org
.eclipse
.swt
.widgets
.Menu
;
93 import org
.eclipse
.ui
.ISharedImages
;
94 import org
.eclipse
.ui
.IWorkbenchPage
;
95 import org
.eclipse
.ui
.IWorkbenchWindow
;
96 import org
.eclipse
.ui
.PlatformUI
;
97 import org
.eclipse
.ui
.part
.ViewPart
;
99 /** SLC generic JCR Result tree view. */
100 public class JcrResultTreeView
extends ViewPart
{
101 public final static String ID
= ClientUiPlugin
.ID
+ ".jcrResultTreeView";
103 private final static DateFormat dateFormat
= new SimpleDateFormat(
104 SlcUiConstants
.DEFAULT_DISPLAY_DATE_TIME_FORMAT
);
106 // private final static Log log =
107 // LogFactory.getLog(JcrResultTreeView.class);
109 /* DEPENDENCY INJECTION */
110 private Session session
;
113 private TreeViewer resultTreeViewer
;
114 private TableViewer propertiesViewer
;
116 private EventListener myResultsObserver
= null;
117 private EventListener allResultsObserver
= null;
120 private final static String
[] observedNodeTypesUnderMyResult
= {
121 SlcTypes
.SLC_TEST_RESULT
, SlcTypes
.SLC_RESULT_FOLDER
,
122 SlcTypes
.SLC_MY_RESULT_ROOT_FOLDER
};
124 private final static String
[] observedNodeTypesUnderAllResults
= {
125 SlcTypes
.SLC_TEST_RESULT
, NodeType
.NT_UNSTRUCTURED
};
127 private boolean isResultFolder
= false;
130 * To be overridden to adapt size of form and result frames.
132 protected int[] getWeights() {
133 return new int[] { 70, 30 };
137 public void createPartControl(Composite parent
) {
138 parent
.setLayout(new FillLayout());
140 SashForm sashForm
= new SashForm(parent
, SWT
.VERTICAL
);
141 sashForm
.setSashWidth(4);
142 sashForm
.setLayout(new FillLayout());
144 // Create the tree on top of the view
145 Composite top
= new Composite(sashForm
, SWT
.NONE
);
146 GridLayout gl
= new GridLayout(1, false);
148 resultTreeViewer
= createResultsTreeViewer(top
);
150 // Create the property viewer on the bottom
151 Composite bottom
= new Composite(sashForm
, SWT
.NONE
);
152 bottom
.setLayout(new GridLayout(1, false));
153 propertiesViewer
= createPropertiesViewer(bottom
);
155 sashForm
.setWeights(getWeights());
157 setOrderedInput(resultTreeViewer
);
159 // Initialize observer
161 ObservationManager observationManager
= session
.getWorkspace()
162 .getObservationManager();
163 myResultsObserver
= new MyResultsObserver(resultTreeViewer
164 .getTree().getDisplay());
165 allResultsObserver
= new AllResultsObserver(resultTreeViewer
166 .getTree().getDisplay());
168 // observe tree changes under MyResults
169 observationManager
.addEventListener(myResultsObserver
,
170 Event
.NODE_ADDED
| Event
.NODE_REMOVED
,
171 SlcJcrResultUtils
.getMyResultsBasePath(session
), true,
172 null, observedNodeTypesUnderMyResult
, false);
173 // observe tree changes under All results
174 observationManager
.addEventListener(allResultsObserver
,
175 Event
.NODE_ADDED
| Event
.NODE_REMOVED
,
176 SlcJcrResultUtils
.getSlcResultsBasePath(session
), true,
177 null, observedNodeTypesUnderAllResults
, false);
178 } catch (RepositoryException e
) {
179 throw new SlcException("Cannot register listeners", e
);
184 * Override default behaviour so that default defined order remains
185 * unchanged on first level of the tree
187 private void setOrderedInput(TreeViewer viewer
) {
188 // Add specific ordering
189 resultTreeViewer
.setInput(null);
190 viewer
.setComparator(null);
191 resultTreeViewer
.setInput(initializeResultTree());
192 viewer
.setComparator(new ResultItemsComparator());
195 // The main tree viewer
196 protected TreeViewer
createResultsTreeViewer(Composite parent
) {
197 int style
= SWT
.BORDER
| SWT
.MULTI
;
199 TreeViewer viewer
= new TreeViewer(parent
, style
);
200 viewer
.getTree().setLayoutData(
201 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
203 viewer
.setContentProvider(new ResultTreeContentProvider());
205 // Add label provider with label decorator
206 ResultTreeLabelProvider rtLblProvider
= new ResultTreeLabelProvider();
207 ILabelDecorator decorator
= ClientUiPlugin
.getDefault().getWorkbench()
208 .getDecoratorManager().getLabelDecorator();
209 viewer
.setLabelProvider(new DecoratingLabelProvider(rtLblProvider
,
211 viewer
.addDoubleClickListener(new ViewDoubleClickListener());
213 // Override default behaviour to insure that 2 distincts results that
214 // have the same name will be correctly and distincly returned by
215 // corresponding TreeViewer.getSelection() method.
216 viewer
.setComparer(new ResultItemsComparer());
218 // viewer.setLabelProvider(rtLblProvider);
219 getSite().setSelectionProvider(viewer
);
221 // add drag & drop support
222 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
223 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
224 viewer
.addDragSupport(operations
, tt
, new ViewDragListener());
225 viewer
.addDropSupport(operations
, tt
, new ViewDropListener(viewer
));
228 MenuManager menuManager
= new MenuManager();
229 Menu menu
= menuManager
.createContextMenu(viewer
.getTree());
230 menuManager
.addMenuListener(new IMenuListener() {
231 public void menuAboutToShow(IMenuManager manager
) {
232 contextMenuAboutToShow(manager
);
235 viewer
.getTree().setMenu(menu
);
236 getSite().registerContextMenu(menuManager
, viewer
);
238 // add change listener to display TestResult information in the property
240 viewer
.addSelectionChangedListener(new MySelectionChangedListener());
244 // Detailed property viewer
245 protected TableViewer
createPropertiesViewer(Composite parent
) {
246 propertiesViewer
= new TableViewer(parent
);
247 propertiesViewer
.getTable().setLayoutData(
248 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
249 propertiesViewer
.getTable().setHeaderVisible(true);
250 propertiesViewer
.setContentProvider(new PropertiesContentProvider());
251 TableViewerColumn col
= new TableViewerColumn(propertiesViewer
,
253 col
.getColumn().setText("Name");
254 col
.getColumn().setWidth(100);
255 col
.setLabelProvider(new ColumnLabelProvider() {
256 public String
getText(Object element
) {
258 String name
= ((Property
) element
).getName();
260 if (SlcNames
.SLC_TEST_CASE
.equals(name
))
262 else if (SlcNames
.SLC_COMPLETED
.equals(name
))
263 value
= "Completed on";
264 else if (SlcNames
.SLC_SUCCESS
.equals(name
))
266 else if (SlcNames
.SLC_MESSAGE
.equals(name
))
268 else if (SlcNames
.SLC_ERROR_MESSAGE
.equals(name
))
271 } catch (RepositoryException e
) {
272 throw new ArgeoException(
273 "Unexpected exception in label provider", e
);
277 col
= new TableViewerColumn(propertiesViewer
, SWT
.NONE
);
278 col
.getColumn().setText("Value");
279 col
.getColumn().setWidth(200);
280 col
.setLabelProvider(new ColumnLabelProvider() {
281 public String
getText(Object element
) {
283 Property property
= (Property
) element
;
284 String name
= property
.getName();
287 if (SlcNames
.SLC_TEST_CASE
.equals(name
)
288 || SlcNames
.SLC_ERROR_MESSAGE
.equals(name
)
289 || SlcNames
.SLC_MESSAGE
.equals(name
))
290 value
= property
.getValue().getString();
291 else if (SlcNames
.SLC_COMPLETED
.equals(name
)) {
292 Calendar date
= property
.getValue().getDate();
293 value
= dateFormat
.format(date
.getTime());
294 } else if (SlcNames
.SLC_SUCCESS
.equals(name
)) {
295 if (property
.getValue().getBoolean())
298 if (property
.getParent().hasNode(
299 SlcNames
.SLC_ERROR_MESSAGE
))
306 } catch (RepositoryException e
) {
307 throw new ArgeoException(
308 "Unexpected exception in label provider", e
);
312 propertiesViewer
.setInput(getViewSite());
313 return propertiesViewer
;
317 * Override to provide specific behaviour. Typically to enable the display
322 protected void processDoubleClick(DoubleClickEvent evt
) {
323 Object obj
= ((IStructuredSelection
) evt
.getSelection())
326 if (obj
instanceof SingleResultNode
) {
327 SingleResultNode srNode
= (SingleResultNode
) obj
;
328 Node node
= srNode
.getNode();
329 // FIXME: open a default result editor
330 if (node
.isNodeType(SlcTypes
.SLC_PROCESS
)) {
331 IWorkbenchPage activePage
= PlatformUI
.getWorkbench()
332 .getActiveWorkbenchWindow().getActivePage();
333 activePage
.openEditor(
334 new ProcessEditorInput(node
.getPath()),
338 } catch (Exception e
) {
339 throw new SlcException("Cannot open " + obj
, e
);
344 public void setFocus() {
348 * refreshes the passed resultParent and its corresponding subtree. It
349 * refreshes the whole viewer if null is passed.
351 * @param ResultParent
354 public void refresh(ResultParent resultParent
) {
355 if (resultParent
== null) {
356 if (!resultTreeViewer
.getTree().isDisposed()) {
357 TreePath
[] tps
= resultTreeViewer
.getExpandedTreePaths();
358 setOrderedInput(resultTreeViewer
);
359 resultTreeViewer
.setExpandedTreePaths(tps
);
361 setOrderedInput(resultTreeViewer
);
363 if (resultParent
instanceof ParentNodeFolder
) {
364 ParentNodeFolder currFolder
= (ParentNodeFolder
) resultParent
;
365 jcrRefresh(currFolder
.getNode());
366 currFolder
.forceFullRefresh();
368 // FIXME: specific refresh does not work
369 // resultTreeViewer.refresh(resultParent, true);
375 * refreshes the passed node and its corresponding subtree.
381 public boolean jcrRefresh(Node node
) {
382 // if (log.isDebugEnabled())
383 // log.debug(" JCR refreshing " + node + "...");
384 // Thread.dumpStack();
385 boolean isPassed
= true;
387 if (node
.isNodeType(SlcTypes
.SLC_TEST_RESULT
)) {
388 isPassed
= node
.getNode(SlcNames
.SLC_AGGREGATED_STATUS
)
389 .getProperty(SlcNames
.SLC_SUCCESS
).getBoolean();
390 } else if (node
.isNodeType(SlcTypes
.SLC_RESULT_FOLDER
)) {
391 NodeIterator ni
= node
.getNodes();
392 while (ni
.hasNext()) {
393 Node currChild
= ni
.nextNode();
394 isPassed
= isPassed
& jcrRefresh(currChild
);
396 if (isPassed
!= node
.getNode(SlcNames
.SLC_AGGREGATED_STATUS
)
397 .getProperty(SlcNames
.SLC_SUCCESS
).getBoolean()) {
398 node
.getNode(SlcNames
.SLC_AGGREGATED_STATUS
).setProperty(
399 SlcNames
.SLC_SUCCESS
, isPassed
);
400 node
.getSession().save();
405 } catch (RepositoryException e
) {
406 throw new SlcException("Cannot register listeners", e
);
411 private ResultParent
[] initializeResultTree() {
413 // Force initialization of the tree structure if needed
414 SlcJcrResultUtils
.getSlcResultsParentNode(session
);
415 SlcJcrResultUtils
.getMyResultParentNode(session
);
416 // Remove yesterday and last 7 days virtual folders
417 // ResultParent[] roots = new ResultParent[5];
418 ResultParent
[] roots
= new ResultParent
[3];
421 roots
[0] = new ParentNodeFolder(null,
422 SlcJcrResultUtils
.getMyResultParentNode(session
),
423 SlcUiConstants
.DEFAULT_MY_RESULTS_FOLDER_LABEL
);
426 Calendar cal
= Calendar
.getInstance();
427 String relPath
= JcrUtils
.dateAsPath(cal
);
428 List
<String
> datePathes
= new ArrayList
<String
>();
429 datePathes
.add(relPath
);
430 roots
[1] = new VirtualFolder(null,
431 ResultParentUtils
.getResultsForDates(session
, datePathes
),
435 // cal = Calendar.getInstance();
436 // cal.add(Calendar.DAY_OF_YEAR, -1);
437 // relPath = JcrUtils.dateAsPath(cal);
438 // datePathes = new ArrayList<String>();
439 // datePathes.add(relPath);
440 // roots[2] = new VirtualFolder(null,
441 // ResultParentUtils.getResultsForDates(session, datePathes),
445 // cal = Calendar.getInstance();
446 // datePathes = new ArrayList<String>();
448 // for (int i = 0; i < 7; i++) {
449 // cal.add(Calendar.DAY_OF_YEAR, -i);
450 // relPath = JcrUtils.dateAsPath(cal);
451 // datePathes.add(relPath);
453 // roots[3] = new VirtualFolder(null,
454 // ResultParentUtils.getResultsForDates(session, datePathes),
458 Node otherResultsPar
= session
.getNode(SlcJcrResultUtils
459 .getSlcResultsBasePath(session
));
460 // roots[4] = new ParentNodeFolder(null, otherResultsPar,
462 roots
[2] = new ParentNodeFolder(null, otherResultsPar
,
465 } catch (RepositoryException re
) {
466 throw new ArgeoException(
467 "Unexpected error while initializing ResultTree.", re
);
471 // Manage context menu
473 * Defines the commands that will pop up in the context menu.
475 protected void contextMenuAboutToShow(IMenuManager menuManager
) {
476 IWorkbenchWindow window
= ClientUiPlugin
.getDefault().getWorkbench()
477 .getActiveWorkbenchWindow();
479 IStructuredSelection selection
= (IStructuredSelection
) resultTreeViewer
481 boolean canAddSubfolder
= false;
482 boolean canRenamefolder
= false;
483 boolean isSingleResultNode
= false;
484 // Building conditions
485 if (selection
.size() == 1) {
486 Object obj
= selection
.getFirstElement();
488 if (obj
instanceof SingleResultNode
)
489 isSingleResultNode
= true;
490 else if (obj
instanceof ParentNodeFolder
) {
491 Node cNode
= ((ParentNodeFolder
) obj
).getNode();
492 if (cNode
.isNodeType(SlcTypes
.SLC_RESULT_FOLDER
)) {
493 canAddSubfolder
= true;
494 canRenamefolder
= true;
496 .isNodeType(SlcTypes
.SLC_MY_RESULT_ROOT_FOLDER
)) {
497 canAddSubfolder
= true;
500 } catch (RepositoryException re
) {
501 throw new SlcException(
502 "unexpected error while building condition for context menu",
507 CommandUtils
.refreshCommand(menuManager
, window
, AddResultFolder
.ID
,
508 AddResultFolder
.DEFAULT_LABEL
,
509 ClientUiPlugin
.getDefault().getWorkbench().getSharedImages()
510 .getImageDescriptor(ISharedImages
.IMG_OBJ_ADD
),
513 CommandUtils
.refreshCommand(menuManager
, window
, RenameResultFolder
.ID
,
514 RenameResultFolder
.DEFAULT_LABEL
,
515 RenameResultFolder
.DEFAULT_IMG_DESCRIPTOR
, canRenamefolder
);
517 CommandUtils
.refreshCommand(menuManager
, window
, RenameResultNode
.ID
,
518 RenameResultNode
.DEFAULT_LABEL
,
519 RenameResultNode
.DEFAULT_IMG_DESCRIPTOR
, isSingleResultNode
);
523 class ViewDragListener
implements DragSourceListener
{
525 public void dragStart(DragSourceEvent event
) {
526 // Check if the drag action should start.
527 IStructuredSelection selection
= (IStructuredSelection
) resultTreeViewer
529 boolean doIt
= false;
531 // FIXME clean this code.
533 if (selection
.size() == 1) {
534 Object obj
= selection
.getFirstElement();
535 if (obj
instanceof ResultFolder
) {
536 Node tNode
= ((ResultFolder
) obj
).getNode();
537 if (tNode
.getPrimaryNodeType().isNodeType(
538 SlcTypes
.SLC_RESULT_FOLDER
)) {
540 isResultFolder
= true;
543 isResultFolder
= false;
545 isResultFolder
= false;
547 if (!isResultFolder
) {
548 @SuppressWarnings("rawtypes")
549 Iterator it
= selection
.iterator();
550 while (it
.hasNext()) {
551 Object obj
= it
.next();
552 if (obj
instanceof SingleResultNode
) {
553 Node tNode
= ((SingleResultNode
) obj
).getNode();
554 if (tNode
.getPrimaryNodeType().isNodeType(
555 SlcTypes
.SLC_TEST_RESULT
)) {
562 } catch (RepositoryException re
) {
563 throw new SlcException(
564 "unexpected error while validating drag source", re
);
569 public void dragSetData(DragSourceEvent event
) {
570 IStructuredSelection selection
= (IStructuredSelection
) resultTreeViewer
574 // specific case of a result folder
575 if (isResultFolder
) {
576 Object obj
= selection
.getFirstElement();
577 event
.data
= ((ResultFolder
) obj
).getNode().getIdentifier();
579 @SuppressWarnings("rawtypes")
580 Iterator it
= selection
.iterator();
581 StringBuffer nodes
= new StringBuffer();
582 while (it
.hasNext()) {
583 Object obj
= it
.next();
584 if (obj
instanceof SingleResultNode
) {
585 Node tNode
= ((SingleResultNode
) obj
).getNode();
586 if (tNode
.getPrimaryNodeType().isNodeType(
587 SlcTypes
.SLC_TEST_RESULT
)) {
588 nodes
.append(tNode
.getIdentifier() + ";");
592 event
.data
= nodes
.toString();
594 } catch (RepositoryException re
) {
595 throw new SlcException("unexpected error while setting data",
600 public void dragFinished(DragSourceEvent event
) {
601 // refresh is done via observer
605 // Implementation of the Drop Listener
606 protected class ViewDropListener
extends ViewerDropAdapter
{
607 private Node targetParentNode
= null;
609 public ViewDropListener(Viewer viewer
) {
614 public boolean validateDrop(Object target
, int operation
,
615 TransferData transferType
) {
616 boolean validDrop
= false;
618 // We can only drop under myResults
620 if (target
instanceof SingleResultNode
) {
621 Node currNode
= ((SingleResultNode
) target
).getNode();
622 String pPath
= currNode
.getParent().getPath();
623 if (pPath
.startsWith(SlcJcrResultUtils
624 .getMyResultsBasePath(session
)))
625 tpNode
= currNode
.getParent();
626 } else if (target
instanceof ResultFolder
) {
627 tpNode
= ((ResultFolder
) target
).getNode();
628 } else if (target
instanceof ParentNodeFolder
) {
629 Node node
= ((ParentNodeFolder
) target
).getNode();
630 if (node
.isNodeType(SlcTypes
.SLC_MY_RESULT_ROOT_FOLDER
))
631 tpNode
= ((ParentNodeFolder
) target
).getNode();
634 if (tpNode
!= null) {
635 targetParentNode
= tpNode
;
638 } catch (RepositoryException re
) {
639 throw new SlcException(
640 "unexpected error while validating drop target", re
);
646 public boolean performDrop(Object data
) {
647 // clear selection to prevent unwanted scrolling of the UI
648 resultTreeViewer
.setSelection(null);
650 if (isResultFolder
) {
651 // Sanity check : we cannot move a folder to one of its sub
652 // folder or neither move an object in the same parent
654 Node source
= session
.getNodeByIdentifier((String
) data
);
655 if (targetParentNode
.getPath().startsWith(source
.getPath())
656 || source
.getParent().getPath()
657 .equals(targetParentNode
.getPath()))
661 String sourcePath
= source
.getPath();
662 String destPath
= targetParentNode
.getPath() + "/"
664 session
.move(sourcePath
, destPath
);
665 // Update passed status of the parent source Node
666 ResultParentUtils
.updatePassedStatus(
667 session
.getNode(JcrUtils
.parentPath(sourcePath
)),
669 // Node target = session.getNode(destPath);
674 String
[] datas
= ((String
) data
).split(";");
675 nodesToCopy
: for (String id
: datas
) {
677 Node source
= session
.getNodeByIdentifier(id
);
679 if (source
.hasProperty(Property
.JCR_TITLE
))
680 name
= source
.getProperty(Property
.JCR_TITLE
)
682 else if (source
.hasProperty(SlcNames
.SLC_TEST_CASE
))
683 name
= source
.getProperty(SlcNames
.SLC_TEST_CASE
)
686 name
= source
.getName();
688 // Check if another copy of the same test instance already
690 NodeIterator ni
= targetParentNode
.getNodes();
691 String slcUid
= source
.getProperty(SlcNames
.SLC_UUID
)
693 while (ni
.hasNext()) {
694 Node curr
= ni
.nextNode();
695 if (curr
.hasProperty(SlcNames
.SLC_UUID
)
696 && slcUid
.equals(curr
.getProperty(
697 SlcNames
.SLC_UUID
).getString())) {
700 PlatformUI
.getWorkbench()
703 "Duplicated instance.",
704 "An instance of the same test case ("
706 + ") exists at destination.\n "
707 + "This item will not be neither copied nor moved.");
708 continue nodesToCopy
;
714 boolean passedStatus
= source
715 .getNode(SlcNames
.SLC_AGGREGATED_STATUS
)
716 .getProperty(SlcNames
.SLC_SUCCESS
).getBoolean();
718 boolean isActionUnderMyResult
= source
.getPath()
721 .getMyResultsBasePath(session
));
723 if (!isActionUnderMyResult
) {// Copy
724 target
= targetParentNode
.addNode(source
.getName(),
725 source
.getPrimaryNodeType().getName());
726 JcrUtils
.copy(source
, target
);
728 String sourcePath
= source
.getPath();
729 String destPath
= targetParentNode
.getPath() + "/"
731 session
.move(sourcePath
, destPath
);
733 // Update passed status of the parent source Node
735 .updatePassedStatus(session
.getNode(JcrUtils
736 .parentPath(sourcePath
)), true);
737 target
= session
.getNode(destPath
);
740 if (!target
.isNodeType(NodeType
.MIX_TITLE
))
741 target
.addMixin(NodeType
.MIX_TITLE
);
742 target
.setProperty(Property
.JCR_TITLE
, name
);
743 ResultParentUtils
.updatePassedStatus(target
.getParent(),
748 // Node source = session.getNodeByIdentifier(id);
750 // if (source.hasProperty(Property.JCR_TITLE))
751 // name = source.getProperty(Property.JCR_TITLE)
753 // else if (source.hasProperty(SlcNames.SLC_TEST_CASE))
754 // name = source.getProperty(SlcNames.SLC_TEST_CASE)
757 // name = source.getName();
759 // // Check if a user defined folder result with same name
762 // if (targetParentNode.hasNode(name)
763 // && targetParentNode.getNode(name).isNodeType(
764 // SlcTypes.SLC_RESULT_FOLDER)) {
765 // ConfirmOverwriteWizard wizard = new
766 // ConfirmOverwriteWizard(
767 // name, targetParentNode);
768 // WizardDialog dialog = new WizardDialog(Display
769 // .getDefault().getActiveShell(), wizard);
771 // if (dialog.open() == WizardDialog.CANCEL)
774 // if (wizard.overwrite()) {
775 // targetParentNode.getNode(name).remove();
776 // // session.save();
778 // name = wizard.newName();
782 // boolean passedStatus = source
783 // .getNode(SlcNames.SLC_AGGREGATED_STATUS)
784 // .getProperty(SlcNames.SLC_SUCCESS).getBoolean();
786 // if (!isActionUnderMyResult) {// Copy
787 // target = targetParentNode.addNode(source.getName(),
788 // source.getPrimaryNodeType().getName());
789 // JcrUtils.copy(source, target);
791 // String sourcePath = source.getPath();
792 // String destPath = targetParentNode.getPath() + "/"
794 // session.move(sourcePath, destPath);
795 // // session.save();
796 // // Update passed status of the parent source Node
798 // .updatePassedStatus(session.getNode(JcrUtils
799 // .parentPath(sourcePath)), true);
800 // target = session.getNode(destPath);
803 // if (!target.isNodeType(NodeType.MIX_TITLE))
804 // target.addMixin(NodeType.MIX_TITLE);
805 // target.setProperty(Property.JCR_TITLE, name);
806 // ResultParentUtils.updatePassedStatus(target.getParent(),
811 } catch (RepositoryException re
) {
812 throw new SlcException(
813 "unexpected error while copying dropped node", re
);
820 class MyResultsObserver
extends AsyncUiEventListener
{
822 public MyResultsObserver(Display display
) {
827 protected Boolean
willProcessInUiThread(List
<Event
> events
)
828 throws RepositoryException
{
829 // unfiltered for the time being
833 protected void onEventInUiThread(List
<Event
> events
)
834 throws RepositoryException
{
835 List
<Node
> nodesToRefresh
= new ArrayList
<Node
>();
837 for (Event event
: events
) {
838 String parPath
= JcrUtils
.parentPath(event
.getPath());
839 if (session
.nodeExists(parPath
)) {
840 Node node
= session
.getNode(parPath
);
841 if (!nodesToRefresh
.contains(node
)) {
842 nodesToRefresh
.add(node
);
847 // Update check nodes
848 for (Node node
: nodesToRefresh
)
854 class AllResultsObserver
extends AsyncUiEventListener
{
856 public AllResultsObserver(Display display
) {
861 protected Boolean
willProcessInUiThread(List
<Event
> events
)
862 throws RepositoryException
{
863 // unfiltered for the time being
867 protected void onEventInUiThread(List
<Event
> events
)
868 throws RepositoryException
{
870 // if (lastSelectedSourceElementParent != null)
871 // refresh(lastSelectedSourceElementParent);
875 class PropertiesContentProvider
implements IStructuredContentProvider
{
877 public void dispose() {
880 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
883 public Object
[] getElements(Object inputElement
) {
885 if (inputElement
instanceof Node
) {
886 Node node
= (Node
) inputElement
;
887 if (node
.isNodeType(SlcTypes
.SLC_TEST_RESULT
)) {
888 List
<Property
> props
= new ArrayList
<Property
>();
889 if (node
.hasProperty(SlcNames
.SLC_TEST_CASE
))
890 props
.add(node
.getProperty(SlcNames
.SLC_TEST_CASE
));
891 if (node
.hasProperty(SlcNames
.SLC_COMPLETED
))
892 props
.add(node
.getProperty(SlcNames
.SLC_COMPLETED
));
893 if (node
.hasNode(SlcNames
.SLC_AGGREGATED_STATUS
)) {
895 .getNode(SlcNames
.SLC_AGGREGATED_STATUS
);
896 props
.add(status
.getProperty(SlcNames
.SLC_SUCCESS
));
897 if (status
.hasProperty(SlcNames
.SLC_MESSAGE
))
899 .getProperty(SlcNames
.SLC_MESSAGE
));
900 if (status
.hasProperty(SlcNames
.SLC_ERROR_MESSAGE
))
902 .getProperty(SlcNames
.SLC_ERROR_MESSAGE
));
904 return props
.toArray();
907 return new Object
[] {};
909 } catch (RepositoryException e
) {
910 throw new ArgeoException("Cannot get element for "
916 class MySelectionChangedListener
implements ISelectionChangedListener
{
918 public void selectionChanged(SelectionChangedEvent event
) {
919 if (!event
.getSelection().isEmpty()) {
920 IStructuredSelection sel
= (IStructuredSelection
) event
922 ResultParent firstItem
= (ResultParent
) sel
.getFirstElement();
923 if (firstItem
instanceof SingleResultNode
)
924 propertiesViewer
.setInput(((SingleResultNode
) firstItem
)
927 propertiesViewer
.setInput(null);
928 // update cache for Drag & drop
929 // lastSelectedTargetElement = firstItem;
930 // lastSelectedSourceElement = firstItem;
931 // lastSelectedSourceElementParent = (ResultParent) firstItem
933 // String pPath = "";
936 // if (firstItem instanceof ParentNodeFolder)
937 // pPath = ((ParentNodeFolder) firstItem).getNode()
939 // else if (firstItem instanceof SingleResultNode)
940 // pPath = ((SingleResultNode) firstItem).getNode()
942 // } catch (RepositoryException e) {
943 // throw new SlcException(
944 // "Unexpected error while checking parent UI tree", e);
946 // if ((pPath.startsWith(SlcJcrResultUtils
947 // .getMyResultsBasePath(session))))
948 // isActionUnderMyResult = true;
950 // isActionUnderMyResult = false;
955 class ViewDoubleClickListener
implements IDoubleClickListener
{
956 public void doubleClick(DoubleClickEvent evt
) {
957 processDoubleClick(evt
);
962 /* DEPENDENCY INJECTION */
963 public void setSession(Session session
) {
964 this.session
= session
;