/*******************************************************************************
* 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.rc.rcp.e3.gef.tester;
import static org.eclipse.jubula.rc.common.driver.CheckWithTimeoutQueuer.invokeAndWait;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.Validate;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.jubula.rc.common.driver.ClickOptions;
import org.eclipse.jubula.rc.common.driver.IRobot;
import org.eclipse.jubula.rc.common.driver.IRunnable;
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
import org.eclipse.jubula.rc.common.tester.WidgetTester;
import org.eclipse.jubula.rc.common.util.Comparer;
import org.eclipse.jubula.rc.common.util.MatchUtil;
import org.eclipse.jubula.rc.common.util.MenuUtilBase;
import org.eclipse.jubula.rc.common.util.Verifier;
import org.eclipse.jubula.rc.rcp.e3.gef.factory.DefaultEditPartAdapterFactory;
import org.eclipse.jubula.rc.rcp.e3.gef.identifier.IEditPartIdentifier;
import org.eclipse.jubula.rc.rcp.e3.gef.identifier.IDirectionalEditPartAnchorIdentifier;
import org.eclipse.jubula.rc.rcp.e3.gef.listener.GefPartListener;
import org.eclipse.jubula.rc.rcp.e3.gef.util.FigureCanvasUtil;
import org.eclipse.jubula.rc.swt.driver.DragAndDropHelperSwt;
import org.eclipse.jubula.rc.swt.driver.RobotFactoryConfig;
import org.eclipse.jubula.rc.swt.tester.adapter.ControlAdapter;
import org.eclipse.jubula.rc.swt.tester.util.CAPUtil;
import org.eclipse.jubula.toolkit.enums.ValueSets.AnchorType;
import org.eclipse.jubula.toolkit.enums.ValueSets.Unit;
import org.eclipse.jubula.tools.internal.objects.event.EventFactory;
import org.eclipse.jubula.tools.internal.objects.event.TestErrorEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* Implementation class for Figure Canvas (Eclipse GEF).
*
* @author BREDEX GmbH
* @created May 13, 2009
*/
public class FigureCanvasTester extends WidgetTester {
/**
* the viewer that contains the EditParts corresponding to the FigureCanvas
*/
private GraphicalViewer m_viewer = null;
/**
*
* @return the viewer associated with the canvas to test.
*/
private GraphicalViewer getViewer() {
return m_viewer;
}
/**
*
* @return the control for the canvas to test.
*/
private Control getViewerControl() {
return getViewer().getControl();
}
/**
*
* @return the root edit part of the viewer.
*/
private RootEditPart getRootEditPart() {
return getViewer().getRootEditPart();
}
/**
*
* @return the root of the palette viewer (tool palette).
*/
private RootEditPart getPaletteRoot() {
return getViewer().getEditDomain().getPaletteViewer().getRootEditPart();
}
/**
*
* @param textPath The path to the tool.
* @param operator The operator used for matching.
* @return the EditPart found at the end of the given path. Returns
* <code>null</code> if no EditPart can be found for the given path
* or if the EditPart found is not a GraphicalEditPart.
*/
private GraphicalEditPart findPaletteEditPart(
String textPath, String operator) {
final String[] pathItems = MenuUtilBase.splitPath(textPath);
boolean isExisting = true;
EditPart currentEditPart = getPaletteRoot().getContents();
for (int i = 0; i < pathItems.length && currentEditPart != null; i++) {
List<?> effectiveChildren = currentEditPart.getChildren();
EditPart [] children =
effectiveChildren.toArray(
new EditPart[effectiveChildren.size()]);
boolean itemFound = false;
for (int j = 0; j < children.length && !itemFound; j++) {
Object model = children[j].getModel();
if (model instanceof PaletteEntry) {
String entryLabel = ((PaletteEntry)model).getLabel();
if (entryLabel != null
&& MatchUtil.getInstance().match(
entryLabel, pathItems[i], operator)) {
itemFound = true;
currentEditPart = children[j];
}
}
}
if (!itemFound) {
isExisting = false;
break;
}
}
return isExisting && currentEditPart instanceof GraphicalEditPart
? (GraphicalEditPart)currentEditPart : null;
}
/**
* {@inheritDoc}
*/
public void setComponent(final Object graphicsComponent) {
Composite composite = (Composite) new RobotFactoryConfig()
.getRobotFactory().getEventThreadQueuer()
.invokeAndWait(getClass().getName() + ".setComponent", new IRunnable() { //$NON-NLS-1$
public Object run() throws StepExecutionException {
FigureCanvas figureCanvas =
(FigureCanvas)graphicsComponent;
Composite parent = figureCanvas;
while (parent != null
&& !(parent.getData(
GefPartListener
.TEST_GEF_VIEWER_DATA_KEY)
instanceof GraphicalViewer)) {
parent = parent.getParent();
}
if (parent != null) {
m_viewer =
(GraphicalViewer)parent.getData(
GefPartListener
.TEST_GEF_VIEWER_DATA_KEY);
return parent;
}
return null;
}
});
setAdapter(new ControlAdapter(composite));
}
/**
* Checks whether the figure for the EditPart for the given path exists and
* is visible.
*
* @param textPath The path to the figure.
* @param operator The operator used for matching.
* @param exists Whether the figure is expected to exist.
* @param timeout the time to wait for the status to occur
*/
public void rcCheckFigureExists(
final String textPath, final String operator,
final boolean exists, int timeout) {
invokeAndWait("rcCheckFigureExists", timeout, new Runnable() { //$NON-NLS-1$
public void run() {
boolean isExisting = FigureCanvasUtil.
findFigure(findEditPart(textPath, operator)) != null;
if (!isExisting) {
// See if there's a connection anchor at the given path
isExisting = findConnectionAnchor(textPath, operator)
!= null;
}
Verifier.equals(exists, isExisting);
}
});
}
/**
* Checks the given property of the figure at the given path.
*
* @param textPath The path to the figure.
* @param textPathOperator The operator used for matching the text path.
* @param propertyName The name of the property
* @param expectedPropValue The value of the property as a string
* @param valueOperator The operator used to verify
* @param timeout the time to wait for the status to occur
*/
public void rcVerifyFigureProperty(final String textPath,
final String textPathOperator, final String propertyName,
final String expectedPropValue, final String valueOperator,
int timeout) {
invokeAndWait("rcVerifyFigureProperty", timeout, new Runnable() { //$NON-NLS-1$
public void run() {
IFigure figure = FigureCanvasUtil.
findFigure(findEditPart(textPath, textPathOperator));
nullCheckFigure(figure);
String propToStr = getPropertyFromFigure(propertyName, figure);
Verifier.match(propToStr, expectedPropValue, valueOperator);
}
});
}
/**
*
* @param figure the figure to check
* @throws StepExecutionException if figure is <code>null</code>
*/
private void nullCheckFigure(IFigure figure) {
if (figure == null) {
throw new StepExecutionException(
"No figure could be found for the given text path.", //$NON-NLS-1$
EventFactory.createActionError(
TestErrorEvent.NOT_FOUND));
}
}
/**
* Checks whether the tool for the given path exists and
* is visible.
*
* @param textPath The path to the figure.
* @param operator The operator used for matching.
* @param exists Whether the figure is expected to exist.
* @param timeout the time to wait for the status to occur
*/
public void rcCheckToolExists(final String textPath, final String operator,
final boolean exists, int timeout) {
invokeAndWait("rcCheckToolExists", timeout, new Runnable() { //$NON-NLS-1$
public void run() {
boolean isExisting =
findPaletteFigure(textPath, operator) != null;
Verifier.equals(exists, isExisting);
}
});
}
/**
* Finds and clicks the figure for the given path.
*
* @param textPath The path to the figure.
* @param operator The operator used for matching.
* @param count The number of times to click.
* @param button The mouse button to use for the click.
*/
public void rcClickFigure(String textPath, String operator,
int count, int button) {
IFigure figure = FigureCanvasUtil.findFigure(
findEditPart(textPath, operator));
if (figure == null) {
// it might be a ConnectionAnchor
getRobot().click(getViewerControl(),
getFigureBoundsChecked(textPath, operator),
ClickOptions.create().setScrollToVisible(false)
.setClickCount(count).setMouseButton(button));
return;
}
clickFigure(count, button, figure);
}
/**
* Finds and clicks on a connection between a source figure and a
* target figure.
*
* @param sourceTextPath The path to the source figure.
* @param sourceOperator The operator to use for matching the source
* figure path.
* @param targetTextPath The path to the target figure.
* @param targetOperator The operator to use for matching the target
* figure path.
* @param count The number of times to click.
* @param button The mouse button to use for the click.
*/
public void rcClickConnection(String sourceTextPath, String sourceOperator,
String targetTextPath, String targetOperator,
int count, int button) {
IFigure connectionFigure = getConnectionFigure(sourceTextPath,
sourceOperator, targetTextPath, targetOperator);
nullCheckFigure(connectionFigure);
clickFigure(count, button, connectionFigure);
}
/**
*
* @param count The number of times to click.
* @param button The mouse button to use for the click.
* @param figure the figure to click
*/
private void clickFigure(int count, int button, IFigure figure) {
ClickOptions clickOptions = ClickOptions.create()
.setScrollToVisible(false).setClickCount(count)
.setMouseButton(button);
if (figure instanceof Connection) {
Point midpoint = ((Connection) figure).getPoints()
.getMidpoint();
figure.translateToAbsolute(midpoint);
getRobot().click(getViewerControl(), null, clickOptions, midpoint.x,
true, midpoint.y, true);
} else {
getRobot().click(getViewerControl(), getBounds(figure),
clickOptions);
}
}
/**
* Gets the {@link IFigure} from a {@link ConnectionEditPart} if there is
* one between the {@link EditPart} given by the source and target path.
*
* @param sourceTextPath
* the source path to an {@link EditPart} or its
* {@link ConnectionAnchor}
* @param sourceOperator
* the source operator
* @param targetTextPath
* the target path to an {@link EditPart} or its
* {@link ConnectionAnchor}
* @param targetOperator
* the target operator
* @return a {@link I Figure} from the found {@link ConnectionEditPart} or
* {@link StepExecutionException} will occur.
*/
private IFigure getConnectionFigure(String sourceTextPath,
String sourceOperator, String targetTextPath,
String targetOperator) {
ConnectionAnchor sourceConnectionAnchor = findConnectionAnchor(
sourceTextPath, sourceOperator);
GraphicalEditPart sourceEditPart = getPartWithAnchor(sourceTextPath,
sourceOperator, sourceConnectionAnchor != null);
ConnectionAnchor targetConnectionAnchor = findConnectionAnchor(
targetTextPath, targetOperator);
GraphicalEditPart targetEditPart = getPartWithAnchor(targetTextPath,
targetOperator, targetConnectionAnchor != null);
ConnectionEditPart connectionEditPart = null;
if (sourceEditPart != null) {
ConnectionEditPart[] sourceConnections =
getSourceConnectionEditParts(sourceEditPart);
for (int i = 0; i < sourceConnections.length; i++) {
if (sourceConnections[i].getTarget() == targetEditPart) {
ConnectionEditPart connection = checkConnectionWithAnchor(
sourceConnections[i], sourceConnectionAnchor,
targetConnectionAnchor);
if (connection != null) {
connectionEditPart = connection;
break;
}
}
}
} else if (targetEditPart != null) {
ConnectionEditPart[] targetConnections =
getTargetConnectionEditParts(targetEditPart);
for (int i = 0; i < targetConnections.length
&& connectionEditPart == null; i++) {
if (targetConnections[i].getSource() == targetEditPart) {
ConnectionEditPart connection = checkConnectionWithAnchor(
targetConnections[i],
sourceConnectionAnchor, targetConnectionAnchor);
if (connection != null) {
connectionEditPart = connection;
break;
}
}
}
} else {
throw new StepExecutionException(
"No figures could be found for the given text paths.", //$NON-NLS-1$
EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
}
IFigure connectionFigure = FigureCanvasUtil
.findFigure(connectionEditPart);
if (connectionFigure == null) {
String missingEnd = sourceEditPart == null ? "source" : "target"; //$NON-NLS-1$ //$NON-NLS-2$
throw new StepExecutionException(
"No connection could be found for the given " + missingEnd + " figure.", //$NON-NLS-1$ //$NON-NLS-2$
EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
}
// Scrolling
revealEditPart(connectionEditPart);
return connectionFigure;
}
/**
* Clicks the specified position within the given figure.
*
* @param textPath The path to the figure.
* @param operator The operator used for matching.
* @param count amount of clicks
* @param button what button should be clicked
* @param xPos what x position
* @param xUnits should x position be pixel or percent values
* @param yPos what y position
* @param yUnits should y position be pixel or percent values
* @throws StepExecutionException if step execution fails.
*/
public void rcClickInFigure(String textPath, String operator,
int count, int button, int xPos, String xUnits,
int yPos, String yUnits) throws StepExecutionException {
getRobot().click(getViewerControl(),
getFigureBoundsChecked(textPath, operator),
ClickOptions.create().setScrollToVisible(false)
.setClickCount(count).setMouseButton(button),
xPos, xUnits.equalsIgnoreCase(
Unit.pixel.rcValue()),
yPos, yUnits.equalsIgnoreCase(
Unit.pixel.rcValue()));
}
/**
* Simulates the beginning of a Drag. Moves to the specified position
* within the given figure and stores information related to the drag to
* be used later by a Drop operation.
*
* @param textPath The path to the figure.
* @param operator The operator used for matching.
* @param mouseButton the mouse button.
* @param modifier the modifier, e.g. shift, ctrl, etc.
* @param xPos what x position
* @param xUnits should x position be pixel or percent values
* @param yPos what y position
* @param yUnits should y position be pixel or percent values
*/
public void rcDragFigure(String textPath, String operator,
int mouseButton, String modifier, int xPos,
String xUnits, int yPos, String yUnits) {
// Only store the Drag-Information. Otherwise the GUI-Eventqueue
// blocks after performed Drag!
final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
.getInstance();
dndHelper.setMouseButton(mouseButton);
dndHelper.setModifier(modifier);
dndHelper.setDragComponent(null);
rcClickInFigure(textPath, operator, 0, mouseButton,
xPos, xUnits, yPos, yUnits);
}
/**
* Performs a Drop. Moves to the specified location within the given figure
* and releases the modifier and mouse button pressed by the previous drag
* operation.
*
* @param textPath The path to the figure.
* @param operator The operator used for matching.
* @param xPos what x position
* @param xUnits should x position be pixel or percent values
* @param yPos what y position
* @param yUnits should y position be pixel or percent values
* @param delayBeforeDrop the amount of time (in milliseconds) to wait
* between moving the mouse to the drop point and
* releasing the mouse button
*/
public void rcDropOnFigure(final String textPath, final String operator,
final int xPos, final String xUnits, final int yPos,
final String yUnits, int delayBeforeDrop) {
final DragAndDropHelperSwt dndHelper =
DragAndDropHelperSwt.getInstance();
final IRobot robot = getRobot();
final String modifier = dndHelper.getModifier();
final int mouseButton = dndHelper.getMouseButton();
// Note: This method performs the drag AND drop action in one runnable
// in the GUI-Eventqueue because after the mousePress, the eventqueue
// blocks!
try {
pressOrReleaseModifiers(modifier, true);
getEventThreadQueuer().invokeAndWait("gdStartDragFigure", new IRunnable() { //$NON-NLS-1$
public Object run() throws StepExecutionException {
// drag
robot.mousePress(dndHelper.getDragComponent(), null,
mouseButton);
CAPUtil.shakeMouse();
// drop
rcClickInFigure(textPath, operator, 0,
mouseButton, xPos, xUnits, yPos, yUnits);
return null;
}
});
waitBeforeDrop(delayBeforeDrop);
} finally {
getRobot().mouseRelease(null, null, mouseButton);
pressOrReleaseModifiers(modifier, false);
}
}
/**
* Returns the bounds for the figure for the given path. If no such
* figure can be found, a {@link StepExecutionException} will be thrown.
*
* @param textPath The path to the figure.
* @param operator The operator used for matching.
* @return the bounds of the figure for the given path.
*/
private Rectangle getFigureBoundsChecked(String textPath, String operator) {
GraphicalEditPart editPart =
findEditPart(textPath, operator);
IFigure figure = FigureCanvasUtil.findFigure(editPart);
ConnectionAnchor anchor = null;
if (figure == null) {
// Try to find a connection anchor instead
anchor = findConnectionAnchor(textPath, operator);
if (anchor != null) {
final String[] pathItems = MenuUtilBase.splitPath(textPath);
final String[] editPartPathItems =
new String[pathItems.length - 1];
System.arraycopy(
pathItems, 0, editPartPathItems, 0,
editPartPathItems.length);
editPart = findEditPart(operator, editPartPathItems);
}
if (anchor == null || FigureCanvasUtil
.findFigure(editPart) == null) {
throw new StepExecutionException(
"No figure could be found for the given text path.", //$NON-NLS-1$
EventFactory.createActionError(
TestErrorEvent.NOT_FOUND));
}
}
// Scrolling
revealEditPart(editPart);
return figure != null ? getBounds(figure) : getBounds(anchor);
}
/**
* Clicks the tool found at the given path.
*
* @param textPath The path to the tool.
* @param operator The operator used for matching.
* @param count The number of times to click.
*/
public void rcSelectTool(String textPath, String operator, int count) {
Control paletteControl = getPaletteControl();
IFigure figure =
findPaletteFigureChecked(textPath, operator);
getRobot().click(paletteControl, getBounds(figure),
ClickOptions.create().setScrollToVisible(false)
.setClickCount(count));
}
/**
* @return the control associated with the palette viewer.
*/
private Control getPaletteControl() {
EditDomain editDomain = getViewer().getEditDomain();
if (editDomain == null) {
return null;
}
PaletteViewer paletteViewer = editDomain.getPaletteViewer();
if (paletteViewer == null) {
return null;
}
return paletteViewer.getControl();
}
/**
*
* @param figure The figure for which to find the bounds.
* @return the bounds of the given figure.
*/
private Rectangle getBounds(IFigure figure) {
org.eclipse.draw2d.geometry.Rectangle figureBounds =
new org.eclipse.draw2d.geometry.Rectangle(figure.getBounds());
// Take scrolling and zooming into account
figure.translateToAbsolute(figureBounds);
return new Rectangle(
figureBounds.x, figureBounds.y,
figureBounds.width, figureBounds.height);
}
/**
*
* @param anchor The anchor for which to find the bounds.
* @return the "bounds" of the given anchor. Since the location of an
* anchor is defined as a single point, the bounds are a small
* rectangle with that point at the center.
*/
private Rectangle getBounds(ConnectionAnchor anchor) {
Validate.notNull(anchor);
Point refPoint = anchor.getReferencePoint();
return new Rectangle(
refPoint.x - 1, refPoint.y - 1, 3, 3);
}
/**
*
* @param textPath The path to the GraphicalEditPart.
* @param operator The operator used for matching.
* @return the GraphicalEditPart for the given path. Returns
* <code>null</code> if no EditPart exists for the given path or if
* the found EditPart is not a GraphicalEditPart.
*/
private GraphicalEditPart findEditPart(String textPath, String operator) {
final String[] pathItems = MenuUtilBase.splitPath(textPath);
return findEditPart(operator, pathItems);
}
/**
* @param operator The operator used for matching.
* @param pathItems The path to the GraphicalEditPart. Each element in the
* array represents a single segment of the path.
* @return the GraphicalEditPart for the given path. Returns
* <code>null</code> if no EditPart exists for the given path or if
* the found EditPart is not a GraphicalEditPart.
*/
private GraphicalEditPart findEditPart(String operator,
final String[] pathItems) {
boolean isExisting = true;
EditPart currentEditPart = getRootEditPart().getContents();
for (int i = 0; i < pathItems.length && currentEditPart != null; i++) {
List<EditPart> childrens =
new ArrayList<EditPart>(currentEditPart.getChildren());
if (currentEditPart instanceof GraphicalEditPart) {
GraphicalEditPart graph = (GraphicalEditPart) currentEditPart;
childrens.addAll(graph.getSourceConnections());
}
EditPart[] children =
childrens.toArray(new EditPart[childrens.size()]);
boolean itemFound = false;
for (int j = 0; j < children.length && !itemFound; j++) {
IEditPartIdentifier childFigureIdentifier =
DefaultEditPartAdapterFactory
.loadFigureIdentifier(children[j]);
if (children[j] instanceof ConnectionEditPart) {
ConnectionEditPart connection =
(ConnectionEditPart) children[j];
Entry<String, ConnectionAnchor> anchorWithIdentifier =
FigureCanvasUtil.getConnectionAnchor(connection);
if (anchorWithIdentifier != null && MatchUtil.getInstance()
.match(anchorWithIdentifier.getKey(), pathItems[i],
operator)) {
if (childFigureIdentifier != null) {
String figureId =
childFigureIdentifier.getIdentifier();
if (figureId != null && !(pathItems.length < i + 2)
&& MatchUtil.getInstance().match(figureId,
pathItems[i + 1], operator)) {
itemFound = true;
currentEditPart = children[j];
i++;
}
}
}
} else if (childFigureIdentifier != null) {
String figureId = childFigureIdentifier.getIdentifier();
if (figureId != null && MatchUtil.getInstance()
.match(figureId, pathItems[i], operator)) {
itemFound = true;
currentEditPart = children[j];
}
}
}
if (!itemFound) {
isExisting = false;
break;
}
}
return isExisting && currentEditPart instanceof GraphicalEditPart
? (GraphicalEditPart) currentEditPart : null;
}
/**
*
* @param textPath The path to the figure.
* @param operator The operator used for matching.
* @return the figure for the GraphicalEditPart for the given path within
* the palette. Returns <code>null</code> if no EditPart exists
* for the given path or if the found EditPart does not have a
* figure.
*/
private IFigure findPaletteFigure(String textPath, String operator) {
GraphicalEditPart editPart = findPaletteEditPart(textPath, operator);
// Scrolling
revealEditPart(editPart);
return FigureCanvasUtil.findFigure(editPart);
}
/**
* Finds and returns the palette figure for the given path. If no such
* figure can be found, a {@link StepExecutionException} will be thrown.
*
* @param textPath The path to the figure.
* @param operator The operator used for matching.
* @return the figure for the GraphicalEditPart for the given path within
* the palette.
*/
private IFigure findPaletteFigureChecked(String textPath, String operator) {
IFigure figure = findPaletteFigure(textPath, operator);
if (figure == null) {
throw new StepExecutionException(
"No palette figure could be found for the given text path.", //$NON-NLS-1$
EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
}
return figure;
}
/**
* Attempts to find a connection anchor at the given textpath.
*
* @param textPath The path to the anchor.
* @param operator The operator used for matching.
* @return the anchor found at the given text path, or <code>null</code>
* if no such anchor exists.
*/
private ConnectionAnchor findConnectionAnchor(
String textPath, String operator) {
final String[] pathItems = MenuUtilBase.splitPath(textPath);
final String[] editPartPathItems = new String[pathItems.length - 1];
System.arraycopy(
pathItems, 0, editPartPathItems, 0, editPartPathItems.length);
GraphicalEditPart editPart = findEditPart(operator, editPartPathItems);
if (editPart != null) {
String anchorPathItem = pathItems[pathItems.length - 1];
IEditPartIdentifier editPartIdentifier =
DefaultEditPartAdapterFactory.loadFigureIdentifier(editPart);
if (editPartIdentifier != null) {
Map<String, ConnectionAnchor> anchorMap =
editPartIdentifier.getConnectionAnchors();
if (anchorMap != null) {
Iterator<String> anchorMapIter =
anchorMap.keySet().iterator();
while (anchorMapIter.hasNext()) {
Object anchorMapKey = anchorMapIter.next();
Object anchorMapValue =
anchorMap.get(anchorMapKey);
if (anchorMapKey instanceof String
&& anchorMapValue instanceof ConnectionAnchor
&& MatchUtil.getInstance().match(
(String)anchorMapKey, anchorPathItem,
operator)) {
return (ConnectionAnchor)anchorMapValue;
}
}
}
}
}
return null;
}
/**
* Reveals the given {@link EditPart} within its viewer.
*
* @param editPart the {@link EditPart} to reveal.
*/
private void revealEditPart(final EditPart editPart) {
if (editPart != null) {
getEventThreadQueuer().invokeAndWait(getClass().getName() + ".revealEditPart", new IRunnable() { //$NON-NLS-1$
public Object run() throws StepExecutionException {
editPart.getViewer().reveal(editPart);
return null;
}
});
}
}
/**
* Finds and checks if a connection between a source figure and a
* target figure exists.
*
* @param sourceTextPath The path to the source figure.
* @param sourceOperator The operator to use for matching the source
* figure path.
* @param targetTextPath The path to the target figure.
* @param targetOperator The operator to use for matching the target
* figure path.
* @param exists whether the connection is expected to exist.
* @param timeout the time to wait for the status to occur
*/
public void rcCheckConnectionExists(final String sourceTextPath,
final String sourceOperator, final String targetTextPath,
final String targetOperator, final boolean exists, int timeout) {
invokeAndWait("rcCheckConnectionExists", timeout, new Runnable() { //$NON-NLS-1$
public void run() {
boolean found = true;
try {
getConnectionFigure(sourceTextPath,
sourceOperator, targetTextPath, targetOperator);
} catch (StepExecutionException see) {
found = false;
}
Verifier.equals(exists, found);
}
});
}
/**
* This is a helper method to find a {@link EditPart} which has an {@link ConnectionAnchor} as last path parameter.
* If there is no {@link ConnectionAnchor}
* @param path the complete path including the {@code Anchor} part
* @param operator the operator for the search
* @param pathWithAnchor if there is an {@link ConnectionAnchor} found for this part
* @return the {@link EditPart}
*/
private GraphicalEditPart getPartWithAnchor(String path,
String operator, boolean pathWithAnchor) {
String[] pathItems = MenuUtilBase.splitPath(path);
if (pathWithAnchor) {
final String[] editPartPathItems = new String[pathItems.length - 1];
System.arraycopy(pathItems, 0, editPartPathItems, 0,
editPartPathItems.length);
pathItems = editPartPathItems; // strip of last part because we know
// it is an anchor
}
return findEditPart(operator, pathItems);
}
/**
* Checks if if the <code>connection</code> is connected to the
* <code>sourceConnectionAnchor</code> and
* <code>targetConnectionAnchor</code>. I there are no
* {@link ConnectionAnchor} given the {@code connection} is returned.
*
* @param connection
* the {@link ConnectionEditPart} which should be checked if it
* is connected to the {@link ConnectionAnchor}a
* @param sourceConnectionAnchor
* the source {@link ConnectionAnchor} which the
* {@link ConnectionEditPart} should be connected to. Could be
* <code>null</code> if there is no {@link ConnectionAnchor} or
* we are only checking if there is any connection between the
* {@link EditPart}
* @param targetConnectionAnchor
* the target {@link ConnectionAnchor} which the
* {@link ConnectionEditPart} should be connected to. Could be
* <code>null</code> if there is no {@link ConnectionAnchor} or
* we are only checking if there is any connection between the
* {@link EditPart}
* @return <code>null</code> or the <code>connection </code>
*/
private ConnectionEditPart checkConnectionWithAnchor(
ConnectionEditPart connection,
ConnectionAnchor sourceConnectionAnchor,
ConnectionAnchor targetConnectionAnchor) {
EditPart source = connection.getSource();
EditPart target = connection.getTarget();
boolean isSourceCorrect = false;
boolean isTargetCorrect = false;
if (source instanceof NodeEditPart && sourceConnectionAnchor != null) {
NodeEditPart node = (NodeEditPart) source;
ConnectionAnchor anchor = node
.getSourceConnectionAnchor(
connection);
if (sourceConnectionAnchor == anchor) {
isSourceCorrect = true;
}
}
if (target instanceof NodeEditPart && targetConnectionAnchor != null) {
NodeEditPart node = (NodeEditPart) target;
ConnectionAnchor anchor = node
.getTargetConnectionAnchor(
connection);
if (targetConnectionAnchor == anchor) {
isTargetCorrect = true;
}
}
if (isSourceCorrect && isTargetCorrect
|| isSourceCorrect && (targetConnectionAnchor == null)
|| isTargetCorrect && (sourceConnectionAnchor == null)
|| (targetConnectionAnchor == null)
&& (sourceConnectionAnchor == null)) {
return connection;
}
return null;
// this is still valid since there are simple connections
}
/**
*
* @param textPath
* the textpath to the {@link GraphicalEditPart}
* @param operator
* the operator to find the editpart should be a rcValue from
* {@link org.eclipse.jubula.toolkit.enums.ValueSets.Operator}
* @param anchorType
* the anchor type should be a rc value from {@link AnchorType}
* @param count
* the count to compare
* @param comparisonMethod
* the comparison method should be a rc value from
* {@link org.eclipse.jubula.toolkit.enums.ValueSets.NumberComparisonOperator}
* @param timeout
* the time to wait for the status to occur
*/
public void rcCheckNumberOfAnchors(final String textPath,
final String operator, final String anchorType,
final int count, final String comparisonMethod, int timeout) {
invokeAndWait("rcCheckNumbersOfAnchors", timeout, new Runnable() { //$NON-NLS-1$
public void run() {
GraphicalEditPart editPart = findEditPart(textPath, operator);
if (editPart == null) {
throw new StepExecutionException(
"No Edit Part could be found for the given text path.", //$NON-NLS-1$
EventFactory.createActionError(
TestErrorEvent.NOT_FOUND));
}
IEditPartIdentifier editPartIdentifier =
DefaultEditPartAdapterFactory
.loadFigureIdentifier(editPart);
int connectionCount = 0;
if (anchorType.equals(AnchorType.both.rcValue())) {
connectionCount =
editPartIdentifier.getConnectionAnchors().size();
} else if (editPartIdentifier
instanceof IDirectionalEditPartAnchorIdentifier) {
IDirectionalEditPartAnchorIdentifier extended =
(IDirectionalEditPartAnchorIdentifier)
editPartIdentifier;
if (anchorType.equals(AnchorType.incoming.rcValue())) {
connectionCount =
extended.getIncomingConnectionAnchors().size();
} else if (anchorType
.equals(AnchorType.outgoing.rcValue())) {
connectionCount =
extended.getOutgoingConnectionAnchors().size();
}
} else {
throw new StepExecutionException(
"GraphicalEditPart does not support the anchor type" //$NON-NLS-1$
+ anchorType,
EventFactory.createActionError());
}
Comparer.compare(Integer.toString(connectionCount),
Integer.toString(count), comparisonMethod);
}
});
}
/**
*
* @param textPath
* the textpath to the {@link ConnectionAnchor}
* @param operator
* the operator to find the editpart should be a rcValue from
* {@link org.eclipse.jubula.toolkit.enums.ValueSets.Operator}
* @param hasConnection
* if the anchor has a connection or not
* @param timeout
* the time to wait for the status to occur
*/
public void rcCheckAnchorConnection(final String textPath,
final String operator, final boolean hasConnection,
int timeout) {
invokeAndWait("rcCheckAnchorConnection", timeout, new Runnable() { //$NON-NLS-1$
public void run() {
ConnectionAnchor anchor =
findConnectionAnchor(textPath, operator);
if (anchor == null) {
throw new StepExecutionException(
"No Anchor could be found for the given text path.", //$NON-NLS-1$
EventFactory.createActionError(
TestErrorEvent.NOT_FOUND));
}
GraphicalEditPart anchorEditPart =
getPartWithAnchor(textPath, operator, true);
ConnectionEditPart[] sourceConnections =
getSourceConnectionEditParts(anchorEditPart);
ConnectionEditPart[] targetConnections =
getTargetConnectionEditParts(anchorEditPart);
boolean connection = false;
for (int i = 0; i < sourceConnections.length; i++) {
ConnectionEditPart connectiontest =
checkConnectionWithAnchor(sourceConnections[i],
anchor, null);
if (connectiontest != null) {
connection = true;
break;
}
}
if (!connection) {
for (int i = 0; i < targetConnections.length; i++) {
ConnectionEditPart connectiontest =
checkConnectionWithAnchor(targetConnections[i],
null, anchor);
if (connectiontest != null) {
connection = true;
break;
}
}
}
Verifier.equals(hasConnection, connection);
}
});
}
/**
* gets an array of connections which the {@link GraphicalEditPart} is the source of
* @param editPart the edit part
* @return the connections which are coming from the edit part
*/
private ConnectionEditPart[] getSourceConnectionEditParts(
GraphicalEditPart editPart) {
List<?> sourceConnectionList = editPart
.getSourceConnections();
ConnectionEditPart[] sourceConnections = sourceConnectionList
.toArray(new ConnectionEditPart[sourceConnectionList
.size()]);
return sourceConnections;
}
/**
* gets an array of connections which target the {@link GraphicalEditPart}
* @param editPart the edit part
* @return the connections which are going to another edit part
*/
private ConnectionEditPart[] getTargetConnectionEditParts(
GraphicalEditPart editPart) {
List<?> targetConnectionList = editPart
.getTargetConnections();
ConnectionEditPart[] targetConnections = targetConnectionList
.toArray(new ConnectionEditPart[targetConnectionList
.size()]);
return targetConnections;
}
/**
* Finds and checks if a connection between a source figure and a
* target figure exists.
*
* @param sourceTextPath The path to the source figure.
* @param sourceOperator The operator to use for matching the source
* figure path.
* @param targetTextPath The path to the target figure.
* @param targetOperator The operator to use for matching the target
* figure path.
* @param propertyName The name of the property
* @param expectedPropValue The value of the property as a string
* @param valueOperator The operator used to verify
* @param timeout the time to wait for the status to occur
*/
public void rcVerifyConnectionProperty(final String sourceTextPath,
final String sourceOperator, final String targetTextPath,
final String targetOperator, final String propertyName,
final String expectedPropValue, final String valueOperator,
int timeout) {
invokeAndWait("rcVerifyConnectionProperty", timeout, new Runnable() { //$NON-NLS-1$
public void run() {
final IFigure figure = getConnectionFigure(sourceTextPath,
sourceOperator, targetTextPath, targetOperator);
final String propToStr =
getPropertyFromFigure(propertyName, figure);
Verifier.match(propToStr, expectedPropValue, valueOperator);
}
});
}
/**
*
* @param propertyName The name of the property
* @param figure The figure we want the property from
* @return The property in its String representation
*/
private String getPropertyFromFigure(final String propertyName,
final IFigure figure) {
Object prop = getEventThreadQueuer().invokeAndWait("getProperty", //$NON-NLS-1$
new IRunnable<Object>() {
public Object run() throws StepExecutionException {
try {
return PropertyUtils.getProperty(figure, propertyName);
} catch (IllegalAccessException e) {
throw new StepExecutionException(
e.getMessage(),
EventFactory.createActionError(
TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
} catch (InvocationTargetException e) {
throw new StepExecutionException(
e.getMessage(),
EventFactory.createActionError(
TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
} catch (NoSuchMethodException e) {
throw new StepExecutionException(
e.getMessage(),
EventFactory.createActionError(
TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
}
}
});
final String propToStr = String.valueOf(prop);
return propToStr;
}
}