/*******************************************************************************
* 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.Iterator;
import java.util.List;
import org.eclipse.jface.dialogs.MessageDialog;
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.db.TestCaseBP;
import org.eclipse.jubula.client.core.model.IAbstractContainerPO;
import org.eclipse.jubula.client.core.model.ICommentPO;
import org.eclipse.jubula.client.core.model.ICompNamesPairPO;
import org.eclipse.jubula.client.core.model.IControllerPO;
import org.eclipse.jubula.client.core.model.IExecTestCasePO;
import org.eclipse.jubula.client.core.model.INodePO;
import org.eclipse.jubula.client.core.model.IParamNodePO;
import org.eclipse.jubula.client.core.model.ISpecTestCasePO;
import org.eclipse.jubula.client.core.model.ITestSuitePO;
import org.eclipse.jubula.client.core.model.NodeMaker;
import org.eclipse.jubula.client.ui.rcp.controllers.MultipleTCBTracker;
import org.eclipse.jubula.client.ui.rcp.editors.AbstractTestCaseEditor;
import org.eclipse.jubula.client.ui.rcp.editors.JBEditorHelper;
import org.eclipse.jubula.client.ui.rcp.i18n.Messages;
import org.eclipse.jubula.client.ui.rcp.utils.NodeTargetCalculator;
import org.eclipse.jubula.client.ui.rcp.utils.NodeTargetCalculator.NodeTarget;
import org.eclipse.jubula.client.ui.rcp.views.TestCaseBrowser;
/**
* Utility class containing methods for use in drag and drop as well as
* cut and paste operations in the Test Suite Editor.
*
* @author BREDEX GmbH
* @created 27.03.2008
*/
public class TSEditorDndSupport extends AbstractEditorDndSupport {
/** For copy actions the last copied node */
private INodePO m_last = null;
/** Constructor */
public TSEditorDndSupport() {
// for copy actions....
// ugly, but still nicer than other options...
}
/**
*
* @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(AbstractTestCaseEditor targetEditor,
IStructuredSelection toDrop, INodePO dropTarget, int dropPosition) {
return TCEditorDndSupport.performDrop(targetEditor, toDrop, dropTarget,
dropPosition);
}
/**
*
* @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 boolean copyPaste(AbstractTestCaseEditor targetEditor,
IStructuredSelection toDrop, INodePO dropTarget) {
if (targetEditor.getEditorHelper().requestEditableState()
!= JBEditorHelper.EditableState.OK) {
return false;
}
for (Iterator it = toDrop.iterator(); it.hasNext(); ) {
if (!(it.next() instanceof INodePO)) {
return false;
}
}
if (toDrop.isEmpty()) {
return false;
}
NodeTarget tar = NodeTargetCalculator.calcNodeTarget(
(INodePO) toDrop.getFirstElement(), dropTarget,
ViewerDropAdapter.LOCATION_ON, false);
@SuppressWarnings("unchecked")
int warning = copyPasteNodes(tar.getNode(),
toDrop.toList(), tar.getPos());
if ((warning & 1) != 0) {
MessageDialog.openInformation(null,
Messages.NotUseReferenceParameterTitle,
Messages.NotUseReferenceParameter);
}
if ((warning & 2) != 0) {
MessageDialog.openInformation(null,
Messages.NotUsePropagatedComponentNameTitle,
Messages.NotUsePropagatedComponentName);
}
postDropAction(m_last, targetEditor);
return true;
}
/**
* Copies a list of nodes to a node
* @param target the target
* @param nodes the nodes
* @param pos the position
* @return the message mask whether there were parameter / propagation issues
*/
private int copyPasteNodes(INodePO target, List<INodePO> nodes,
int pos) {
int position = pos;
int msg = 0;
for (INodePO node : nodes) {
if (node instanceof IParamNodePO
&& ((IParamNodePO) node).getParamReferencesIterator().
hasNext()) {
msg |= 1;
}
if (node instanceof IExecTestCasePO) {
msg |= copyPasteExecTestCase((IExecTestCasePO) node,
target, position);
} else if (node instanceof IControllerPO) {
// we assume a very strict structure here
// controllers have Container children which in turn can only have
// CapPO, ExecTCPO, CommentPO, ... children (so no Controllers or Containers)
IControllerPO controller = NodeMaker.
createControllerPO((IControllerPO) node);
List<INodePO> nodeList = node.getUnmodifiableNodeList();
List<INodePO> contList = controller.getUnmodifiableNodeList();
if (node instanceof IParamNodePO) {
fillParamNode((IParamNodePO) node,
(IParamNodePO) controller);
deleteRefDatas((IParamNodePO) controller);
} else {
fillNode(node, controller);
}
target.addNode(position, controller);
for (int i = 0; i < nodeList.size(); i++) {
copyPasteNodes(contList.get(i),
nodeList.get(i).getUnmodifiableNodeList(), 0);
}
m_last = controller;
} else if (node instanceof ICommentPO) {
INodePO comm = NodeMaker.createCommentPO(
((ICommentPO) node).getName());
fillNode(node, comm);
target.addNode(pos, comm);
m_last = comm;
}
position++;
}
return msg;
}
/**
* @param exec original exec test case node
* @return <code>false</code> if paramNodePO contain propagated component name
*/
private static boolean checkCompName(
IExecTestCasePO exec) {
boolean was = false;
for (ICompNamesPairPO origPair : exec.getCompNamesPairs()) {
if (origPair.isPropagated()) {
origPair.setPropagated(false);
was = true;
}
}
return was;
}
/**
* @param execTestCase The item that was dragged/cut.
* @param dropPosition One of the values defined in ViewerDropAdapter to
* indicate the drop position relative to the drop
* target.
* @param targetNode target parent node
* @return <code>true</code> if the paste was successful.
* Otherwise <code>false</code>.
*/
private int copyPasteExecTestCase(IExecTestCasePO execTestCase,
INodePO targetNode, int dropPosition) {
int msg = 0;
IExecTestCasePO newExecTestCase = NodeMaker.createExecTestCasePO(
execTestCase.getSpecTestCase());
m_last = newExecTestCase;
fillExec(execTestCase, newExecTestCase, true);
if (checkCompName(newExecTestCase)) {
msg = 2;
}
TestCaseBP.addReferencedTestCase(targetNode, newExecTestCase,
dropPosition);
return msg;
}
/**
* Checks whether the nodes in the given selection can legally be copied
* to the given target location.
*
* @param toDrop The selection to check.
* @param target The target location to check.
* @return <code>true</code> if the move is legal. Otherwise,
* <code>false</code>.
*/
public static boolean validateCopy(IStructuredSelection toDrop,
INodePO target) {
if (toDrop == null || toDrop.isEmpty() || target == null) {
return false;
}
for (Iterator it = toDrop.iterator(); it.hasNext(); ) {
Object next = it.next();
if (!(next instanceof IExecTestCasePO || next instanceof ICommentPO
|| next instanceof IControllerPO)) {
return false;
}
}
return true;
}
/**
* Checks whether the nodes in the given selection can legally be moved
* to the given target location.
*
* @param sourceViewer The viewer containing the dragged/cut item.
* @param targetViewer The viewer to which the item is to be dropped/pasted.
* @param selection The selection to check.
* @param target The target location to check.
* @param allowFromBrowser Whether items from the Test Case Browser are
* allowed to be dropped/pasted.
* @return <code>true</code> if the move is legal. Otherwise,
* <code>false</code>.
*/
public static boolean validateDrop(Viewer sourceViewer, Viewer targetViewer,
IStructuredSelection selection,
Object target, boolean allowFromBrowser) {
if (selection == null || !(target instanceof INodePO)) {
return false;
}
INodePO targNode = (INodePO) target;
if (sourceViewer != null && !sourceViewer.equals(targetViewer)) {
boolean foundOne = false;
for (TestCaseBrowser tcb : MultipleTCBTracker.getInstance()
.getOpenTCBs()) {
if (sourceViewer.equals(tcb.getTreeViewer())) {
foundOne = true;
}
}
if (!(allowFromBrowser && foundOne)) {
return false;
}
}
Iterator iter = selection.iterator();
while (iter.hasNext()) {
Object next = iter.next();
if (!(next instanceof INodePO)
|| next instanceof IAbstractContainerPO) {
return false;
}
if (next instanceof IControllerPO
&& !(targNode instanceof ITestSuitePO)
&& !(targNode.getParentNode() instanceof ITestSuitePO)) {
return false;
}
INodePO node = (INodePO)next;
if (!((node instanceof IExecTestCasePO
&& sourceViewer == targetViewer)
|| (node instanceof ICommentPO
&& sourceViewer == targetViewer)
|| (node instanceof ISpecTestCasePO)
|| (node instanceof IControllerPO))) {
return false;
}
}
return true;
}
}