/******************************************************************************* * Copyright (c) 2004, 2010 BREDEX GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.client.ui.rcp.controllers.dnd; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerDropAdapter; import org.eclipse.jubula.client.core.businessprocess.ParamNameBPDecorator; import org.eclipse.jubula.client.core.events.DataEventDispatcher; import org.eclipse.jubula.client.core.events.DataEventDispatcher.DataState; import org.eclipse.jubula.client.core.events.DataEventDispatcher.UpdateState; import org.eclipse.jubula.client.core.model.ICommentPO; import org.eclipse.jubula.client.core.model.INodePO; import org.eclipse.jubula.client.core.model.IProjectPO; import org.eclipse.jubula.client.core.model.IRefTestSuitePO; import org.eclipse.jubula.client.core.model.ITestJobPO; import org.eclipse.jubula.client.core.model.ITestSuitePO; import org.eclipse.jubula.client.core.model.NodeMaker; import org.eclipse.jubula.client.core.persistence.GeneralStorage; import org.eclipse.jubula.client.core.persistence.PMAlreadyLockedException; import org.eclipse.jubula.client.core.persistence.PMDirtyVersionException; import org.eclipse.jubula.client.core.persistence.PMException; import org.eclipse.jubula.client.core.persistence.PMReadException; import org.eclipse.jubula.client.ui.rcp.controllers.PMExceptionHandler; import org.eclipse.jubula.client.ui.rcp.editors.AbstractJBEditor; import org.eclipse.jubula.client.ui.rcp.editors.JBEditorHelper; import org.eclipse.jubula.client.ui.rcp.editors.NodeEditorInput; import org.eclipse.jubula.client.ui.rcp.editors.TestJobEditor; import org.eclipse.jubula.client.ui.rcp.views.TestSuiteBrowser; /** * Utility class containing methods for use in drag and drop as well as * cut and paste operations in the Test Job Editor. * * @author BREDEX GmbH * @created Mar 17, 2010 */ public class TJEditorDndSupport extends AbstractEditorDndSupport { /** * Private constructor */ private TJEditorDndSupport() { // Do nothing } /** * * @param targetEditor The editor to which the item is to be pasted. * @param toDrop The items that were copy. * @param dropTarget The paste target. * indicate the drop position relative to the drop * target. * @return <code>true</code> if the paste was successful. * Otherwise <code>false</code>. */ public static boolean copyPaste(AbstractJBEditor targetEditor, IStructuredSelection toDrop, INodePO dropTarget) { final IProjectPO project = GeneralStorage.getInstance().getProject(); if (targetEditor.getEditorHelper().requestEditableState() != JBEditorHelper.EditableState.OK) { return false; } @SuppressWarnings("unchecked") List<Object> selectedElements = toDrop.toList(); ITestJobPO targetNode; if (dropTarget instanceof ITestJobPO) { targetNode = (ITestJobPO)dropTarget; } else { targetNode = (ITestJobPO)dropTarget.getParentNode(); } int position = targetNode.indexOf(dropTarget); INodePO last = null; for (Object obj : selectedElements.toArray()) { position++; if (obj instanceof IRefTestSuitePO) { last = copyPasteTestSuite(targetEditor, (IRefTestSuitePO)obj, targetNode, position, project); } else if (obj instanceof ICommentPO) { INodePO comm = NodeMaker.createCommentPO( ((ICommentPO) obj).getName()); fillNode((INodePO) obj, comm); targetNode.addNode(position, comm); last = comm; } else { return false; } } postDropAction(last, targetEditor); return true; } /** * * @param targetEditor The editor to which the item is to be pasted. * @param refTestSuit The item that was copy. * @param dropPosition One of the values defined in ViewerDropAdapter to * indicate the drop position relative to the drop * target. * @param targetNode target parent node * @param project currently project * @return the created node */ public static INodePO copyPasteTestSuite( AbstractJBEditor targetEditor, IRefTestSuitePO refTestSuit, ITestJobPO targetNode, int dropPosition, IProjectPO project) { IRefTestSuitePO newRefTestSuite = NodeMaker .createRefTestSuitePO(refTestSuit.getTestSuite()); fillRefTestSuit(refTestSuit, newRefTestSuite); ParamNameBPDecorator pMapper = targetEditor.getEditorHelper() .getEditSupport().getParamMapper(); targetNode.addNode(dropPosition, newRefTestSuite); targetEditor.getEditorHelper().setDirty(true); DataEventDispatcher.getInstance() .fireDataChangedListener(newRefTestSuite, DataState.Added, UpdateState.onlyInEditor); return newRefTestSuite; } /** * * @param targetEditor The editor to which the item is to be dropped/pasted. * @param toDrop The items that were dragged/cut. * @param dropTarget The drop/paste target. * @param dropPosition One of the values defined in ViewerDropAdapter to * indicate the drop position relative to the drop * target. * @return <code>true</code> if the drop/paste was successful. * Otherwise <code>false</code>. */ public static boolean performDrop(TestJobEditor targetEditor, IStructuredSelection toDrop, INodePO dropTarget, int dropPosition) { if (targetEditor.getEditorHelper().requestEditableState() != JBEditorHelper.EditableState.OK) { return false; } List<Object> selectedElements = toDrop.toList(); Collections.reverse(selectedElements); Iterator iter = selectedElements.iterator(); while (iter.hasNext()) { Object objectToDrop = iter.next(); if (objectToDrop instanceof ITestSuitePO) { ITestSuitePO testSuite = (ITestSuitePO)objectToDrop; if (dropTarget != testSuite) { try { if (dropTarget instanceof IRefTestSuitePO) { dropOnRefTS( testSuite, dropTarget, dropPosition); } else if (dropTarget instanceof ITestJobPO) { dropOnTJ(testSuite, dropTarget); } } catch (PMException e) { NodeEditorInput inp = (NodeEditorInput)targetEditor. getAdapter(NodeEditorInput.class); INodePO inpNode = inp.getNode(); PMExceptionHandler.handlePMExceptionForMasterSession(e); // If an object was already locked, *and* the locked // object is not the editor Test Case, *and* the editor // is dirty, then we do *not* want to revert all // editor changes. // The additional test as to whether the the editor is // marked as dirty is important because, due to the // requestEditableState() call earlier in this method, // the editor TC is locked (even though the editor // isn't dirty). Reopening the editor removes this lock. if (!(e instanceof PMAlreadyLockedException && ((PMAlreadyLockedException)e) .getLockedObject() != null && !((PMAlreadyLockedException)e) .getLockedObject().equals(inpNode)) || !targetEditor.isDirty()) { try { targetEditor.reOpenEditor(inpNode); } catch (PMException e1) { PMExceptionHandler.handlePMExceptionForEditor(e, targetEditor); } } return false; } } } if (objectToDrop instanceof INodePO) { INodePO nodeToDrop = (INodePO)objectToDrop; if (nodeToDrop instanceof IRefTestSuitePO || nodeToDrop instanceof ICommentPO) { INodePO target = dropTarget; if (target != nodeToDrop && (target instanceof IRefTestSuitePO || target instanceof ICommentPO)) { moveNode(nodeToDrop, target, target.getParentNode(). indexOf(target)); } } postDropAction(nodeToDrop, targetEditor); } } return true; } /** * * @param toDrop The items that were dragged/cut. * @param dropTarget The drop/paste target. * @return <code>true</code> if the given information indicates that the * drop/paste is valid. Otherwise <code>false</code>. */ public static boolean validateCopy(IStructuredSelection toDrop, INodePO dropTarget) { if (toDrop == null || toDrop.isEmpty() || dropTarget == null) { return false; } for (Iterator it = toDrop.iterator(); it.hasNext(); ) { Object next = it.next(); if (!(next instanceof IRefTestSuitePO || next instanceof ICommentPO)) { return false; } } return true; } /** * * @param sourceViewer The viewer containing the dragged/cut item. * @param targetViewer The viewer to which the item is to be dropped/pasted. * @param toDrop The items that were dragged/cut. * @param dropTarget The drop/paste target. * @param allowFromBrowser Whether items from the Test Case Suite are * allowed to be dropped/pasted. * @return <code>true</code> if the given information indicates that the * drop/paste is valid. Otherwise <code>false</code>. */ public static boolean validateDrop(Viewer sourceViewer, Viewer targetViewer, IStructuredSelection toDrop, INodePO dropTarget, boolean allowFromBrowser) { if (toDrop == null || toDrop.isEmpty() || dropTarget == null) { return false; } if (sourceViewer != null && !sourceViewer.equals(targetViewer)) { TestSuiteBrowser tsb = TestSuiteBrowser.getInstance(); if (tsb != null) { if (!(allowFromBrowser && sourceViewer.equals(tsb .getTreeViewer()))) { return false; } } else { return false; } } for (Object toDropElement : toDrop.toArray()) { if (!(toDropElement instanceof ITestSuitePO || toDropElement instanceof IRefTestSuitePO || toDropElement instanceof ICommentPO)) { return false; } } return true; } /** * @param node the node to be dropped. * @param target the target node. * @throws PMReadException in case of db read error * @throws PMDirtyVersionException in case of version conflict (dirty read) * @throws PMAlreadyLockedException if the origSpecTc is already locked by another user * @throws PMException in case of unspecified db error */ private static void dropOnTJ(ITestSuitePO node, INodePO target) throws PMReadException, PMAlreadyLockedException, PMDirtyVersionException, PMException { TestSuiteBrowser tsb = TestSuiteBrowser.getInstance(); if (tsb != null) { tsb.addReferencedTestSuite(node, target, 0); } } /** * @param node the node to be dropped * @param target the target node. * @param location One of the values defined in ViewerDropAdapter to * indicate the drop position relative to the drop * target. * @throws PMReadException in case of db read error * @throws PMDirtyVersionException in case of version conflict (dirty read) * @throws PMAlreadyLockedException if the origSpecTc is already locked by another user * @throws PMException in case of unspecified db error */ private static void dropOnRefTS(ITestSuitePO node, INodePO target, int location) throws PMReadException, PMAlreadyLockedException, PMDirtyVersionException, PMException { INodePO parentGUI = target.getParentNode(); int position = parentGUI.indexOf(target); if (location != ViewerDropAdapter.LOCATION_BEFORE) { position++; } TestSuiteBrowser tsb = TestSuiteBrowser.getInstance(); if (tsb != null) { tsb.addReferencedTestSuite(node, parentGUI, position); } } }