blob: 8faf4a5d02e8e59102bb5618416f225602dd7dd2 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2005, 2019 SAP SE and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* SAP SE - initial API, implementation and documentation
* mwenz - Bug 356828 - Escaped diagram name is used as editor title
* Bug 336488 - DiagramEditor API
* mwenz - Felix Velasco - Bug 374918 - Let default paste use LocalSelectionTransfer
* mwenz - Bug 378342 - Cannot store more than a diagram per file
* pjpaulin - Bug 352120 - Now uses IDiagramContainerUI interface
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.graphiti.bot.tests;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable.syncExec;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.graphiti.bot.pageobjects.PoDiagramEditor;
import org.eclipse.graphiti.bot.pageobjects.PoWorkbenchPage;
import org.eclipse.graphiti.bot.tests.util.ITestConstants;
import org.eclipse.graphiti.dt.IDiagramTypeProvider;
import org.eclipse.graphiti.examples.common.ExampleProjectNature;
import org.eclipse.graphiti.examples.common.FileService;
import org.eclipse.graphiti.features.ConfigurableFeatureProviderWrapper;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.ICreateConnectionFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.IMoveShapeFeature;
import org.eclipse.graphiti.features.context.ICreateContext;
import org.eclipse.graphiti.features.context.impl.AddContext;
import org.eclipse.graphiti.features.context.impl.AreaContext;
import org.eclipse.graphiti.features.context.impl.CreateConnectionContext;
import org.eclipse.graphiti.features.context.impl.CreateContext;
import org.eclipse.graphiti.features.context.impl.MoveShapeContext;
import org.eclipse.graphiti.mm.pictograms.Anchor;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.platform.IDiagramBehavior;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.services.IPeService;
import org.eclipse.graphiti.testtool.sketch.SketchFeatureProvider;
import org.eclipse.graphiti.ui.editor.IDiagramContainerUI;
import org.eclipse.graphiti.ui.internal.config.IConfigurationProviderInternal;
import org.eclipse.graphiti.ui.internal.services.GraphitiUiInternal;
import org.eclipse.graphiti.ui.platform.IConfigurationProvider;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swtbot.eclipse.gef.finder.SWTBotGefTestCase;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.results.Result;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.ui.PlatformUI;
import org.junit.Before;
import org.junit.BeforeClass;
public abstract class AbstractGFTests extends SWTBotGefTestCase {
public static final IPath SOURCE_FOLDER = new Path("src"); //$NON-NLS-1$
private static IPath DIAGRAMS_FOLDER = SOURCE_FOLDER.append("diagrams");
final protected PoDiagramEditor ed = new PoDiagramEditor();
final protected PoWorkbenchPage page = new PoWorkbenchPage();
private static final String PROJECT_NAME = "GraphitiTestProject";
private IProject project;
public AbstractGFTests() {
super();
setName(getClass().getName());
}
@BeforeClass
public static void beforeClass() {
}
protected void addClassToDiagram(IFeatureProvider fp, Diagram diagram, int x, int y, String className) {
// create add context
AreaContext areaContext = new AreaContext();
areaContext.setLocation(x, y);
EClass newEClass = createEClass(diagram, className);
AddContext addContext = new AddContext(areaContext, newEClass);
addContext.setTargetContainer(diagram);
// get add class feature
IAddFeature feature = fp.getAddFeature(addContext);
assertNotNull("add class feature not available", feature);
if (feature.canAdd(addContext)) {
feature.execute(addContext);
}
}
public static void executeInRecordingCommand(IDiagramBehavior diagramBehavior, final Runnable run) {
TransactionalEditingDomain editingDomain = diagramBehavior.getEditingDomain();
editingDomain.getCommandStack().execute(new RecordingCommand(editingDomain) {
@Override
protected void doExecute() {
run.run();
}
});
}
public static void executeInRecordingCommand(TransactionalEditingDomain domain, final Runnable run) {
domain.getCommandStack().execute(new RecordingCommand(domain) {
@Override
protected void doExecute() {
run.run();
}
});
}
public static void executeInRecordingCommandInUIThread(final IDiagramBehavior diagramBehavior, final Runnable run) {
syncExec(new VoidResult() {
public void run() {
executeInRecordingCommand(diagramBehavior, run);
}
});
}
protected void addClassesAndReferenceToDiagram(IFeatureProvider fp, Diagram diagram, int sourceX, int sourceY,
String sourceClassName, int targetX, int targetY, String targetClassName) {
addClassToDiagram(fp, diagram, sourceX, sourceY, sourceClassName);
addClassToDiagram(fp, diagram, targetX, targetY, targetClassName);
addReferenceToDiagram(fp, diagram, sourceClassName, targetClassName);
}
protected void addEnumToDiagram(IFeatureProvider fp, Diagram diagram, int x, int y, String enumName) {
// create add context
AreaContext areaContext = new AreaContext();
areaContext.setLocation(x, y);
EEnum newEEnum = createEEnum(diagram, enumName);
AddContext addContext = new AddContext(areaContext, newEEnum);
addContext.setTargetContainer(diagram);
// get add class feature
IAddFeature addFeature = fp.getAddFeature(addContext);
assertNotNull("add class feature not available", addFeature);
if (addFeature.canAdd(addContext)) {
addFeature.execute(addContext);
}
}
protected Diagram createDiagram(String diagramTypeId) {
return createDiagram(diagramTypeId, "xmi");
}
/**
* Create Diagram and diagram file.
*
* @param diagramTypeId
* @param fileExtension
* @return
*/
protected Diagram createDiagram(String diagramTypeId, String fileExtension) {
return createDiagram(diagramTypeId, fileExtension, "diagram");
}
/**
* Create Diagram and diagram file.
*
* @param diagramTypeId
* @param fileExtension
* @return
*/
protected Diagram createDiagram(String diagramTypeId, String fileExtension, String diagramName) {
String fileName = createDiagramFileName(fileExtension);
URI diagramUri = createDiagramFileUri(fileName);
final Diagram diagram = getPeService().createDiagram(diagramTypeId, diagramName, true);
FileService.createEmfFileForDiagram(diagramUri, diagram);
final TransactionalEditingDomain editingDomain = GraphitiUiInternal.getEmfService()
.createResourceSetAndEditingDomain();
final ResourceSet resourceSet = editingDomain.getResourceSet();
resourceSet.createResource(diagramUri);
ed.setEditingDomain(editingDomain);
return diagram;
}
protected EEnum createEEnum(Diagram diagram, String enumName) {
EEnum newEnum = EcoreFactory.eINSTANCE.createEEnum();
newEnum.setName(enumName);
diagram.eResource().getContents().add(newEnum);
return newEnum;
}
protected EClass createEClass(Diagram diagram, String className) {
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName(className);
diagram.eResource().getContents().add(eClass);
return eClass;
}
protected Shape findShapeForEClass(Diagram diagram, String className) {
Object[] allShapes = getPeService().getAllContainedShapes(diagram).toArray();
Shape shape = null;
for (int i = 0; i < allShapes.length; i++) {
shape = (Shape) allShapes[i];
if (shape instanceof ContainerShape) {
Object bo = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(shape);
if (bo instanceof EClass) {
String boName = ((EClass) bo).getName();
if (boName.equals(className)) {
return shape;
}
}
}
}
return null;
}
protected void moveClassShape(IFeatureProvider fp, Diagram diagram, int x, int y, String className) {
Shape shape = findShapeForEClass(diagram, className);
MoveShapeContext moveShapeContext = new MoveShapeContext(shape);
moveShapeContext.setSourceContainer(shape.getContainer());
moveShapeContext.setTargetContainer(shape.getContainer());
moveShapeContext.setLocation(x, y);
moveShapeContext.setDeltaX(x - shape.getGraphicsAlgorithm().getX());
moveShapeContext.setDeltaY(y - shape.getGraphicsAlgorithm().getY());
IMoveShapeFeature moveShapeFeature = fp.getMoveShapeFeature(moveShapeContext);
assertNotNull("move shape feature not available", moveShapeFeature);
if (moveShapeFeature.canMoveShape(moveShapeContext)) {
moveShapeFeature.execute(moveShapeContext);
}
}
protected IDiagramContainerUI openDiagramEditor(final String type) {
return openDiagramEditor(type, "xmi", "diagram");
}
protected IDiagramContainerUI openDiagramEditor(final String type, final String fileExtension, final String diagramName) {
IDiagramContainerUI diagramEditor = syncExec(new Result<IDiagramContainerUI>() {
public IDiagramContainerUI run() {
final Diagram newDiagram = createDiagram(type, fileExtension, diagramName);
assertTrue("create diagram does not work", newDiagram != null);
IDiagramContainerUI diagramEditor = (IDiagramContainerUI) GraphitiUiInternal.getWorkbenchService()
.openDiagramEditor(newDiagram);
return diagramEditor;
}
});
if (ITestConstants.DIAGRAM_TYPE_ID_SKETCH.equals(type)) {
IFeatureProvider featureProvider = diagramEditor.getDiagramTypeProvider().getFeatureProvider();
if (featureProvider instanceof ConfigurableFeatureProviderWrapper) {
ConfigurableFeatureProviderWrapper fpw = (ConfigurableFeatureProviderWrapper) featureProvider;
IFeatureProvider innerFeatureProvider = fpw.getInnerFeatureProvider();
if (innerFeatureProvider instanceof SketchFeatureProvider) {
((SketchFeatureProvider) innerFeatureProvider).setTestMode(true);
}
}
}
return diagramEditor;
}
@Override
@Before
protected void setUp() throws Exception {
// T.racer().setInfoAlwaysTrue(true); // tracing enabled for testing
super.setUp();
// Force activation of current shell to avoid "no widget found"
// exceptions
// see http://www.eclipse.org/forums/index.php?t=msg&goto=484090&
UIThreadRunnable.syncExec(new VoidResult() {
public void run() {
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().forceActive();
}
});
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
IProject project = root.getProject(PROJECT_NAME);
project.create(null);
project.open(null);
IProjectDescription desc = project.getDescription();
desc.setNatureIds(new String[] { ExampleProjectNature.NATURE_ID });
project.setDescription(desc, null);
this.project = project;
page.closeWelcomeView(this);
page.openGraphitiTestPerspective();
}
@Override
protected void tearDown() throws Exception {
page.closeAllEditors();
if (this.project != null) {
this.project.close(null);
this.project.delete(true, null);
}
super.tearDown();
}
protected String createDiagramFileName(String extension) {
List<String> currentDiagramNames = new ArrayList<String>();
IFolder folder = getProject().getFolder(DIAGRAMS_FOLDER);
try {
if (folder.exists()) {
IResource[] members = folder.members();
for (IResource resource : members) {
if (resource instanceof IFile) {
String fileName = ((IFile) resource).getName();
if (fileName.startsWith(ITestConstants.TEST_DIAGRAM_PREFIX)) {
int indexOf = fileName.indexOf('.');
if (indexOf > 0) {
fileName = fileName.substring(0, indexOf);
}
currentDiagramNames.add(fileName);
}
}
}
}
} catch (CoreException e) {
e.printStackTrace();
}
int i = 0;
String diagramName;
do {
diagramName = ITestConstants.TEST_DIAGRAM_PREFIX + i++;
} while (currentDiagramNames.contains(diagramName));
diagramName = diagramName + "." + extension;
return diagramName;
}
protected URI createDiagramFileUri(String diagramName) {
URI uri = null;
IFolder folder = getProject().getFolder(DIAGRAMS_FOLDER);
IFile file = folder.getFile(diagramName);
uri = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
return uri;
}
private IProject getProject() {
return this.project;
}
private void addReferenceToDiagram(IFeatureProvider fp, Diagram diagram, String sourceClass, String targetClass) {
ICreateConnectionFeature[] ccfs = fp.getCreateConnectionFeatures();
if (ccfs != null) {
Shape sourceShape = findShapeForEClass(diagram, sourceClass);
Anchor sourceAnchor = getPeService().getChopboxAnchor(sourceShape);
Shape targetShape = findShapeForEClass(diagram, targetClass);
Anchor targetAnchor = getPeService().getChopboxAnchor(targetShape);
CreateConnectionContext ccc = new CreateConnectionContext();
ccc.setSourceAnchor(sourceAnchor);
ccc.setTargetAnchor(targetAnchor);
// question instantiate create feature directly?
for (ICreateConnectionFeature ccf : ccfs) {
if (ccf.canCreate(ccc)) {
ccf.execute(ccc);
break;
}
}
}
}
protected IPeService getPeService() {
return Graphiti.getPeService();
}
protected ICreateContext createCreateContext(ContainerShape target, Rectangle rect) {
CreateContext ret = new CreateContext();
ret.setTargetContainer(target);
ret.setX(rect.x);
ret.setY(rect.y);
ret.setWidth(rect.width);
ret.setHeight(rect.height);
return ret;
}
protected void createClassesAndConnection(final int x, final int y, final IDiagramTypeProvider diagramTypeProvider,
final String toolToActivate, final String shapename) {
syncExec(new VoidResult() {
public void run() {
final IFeatureProvider fp = diagramTypeProvider.getFeatureProvider();
final Diagram currentDiagram = diagramTypeProvider.getDiagram();
executeInRecordingCommand(diagramTypeProvider.getDiagramBehavior(), new Runnable() {
public void run() {
addClassesAndReferenceToDiagram(fp, currentDiagram, x, y, shapename, x, y + 300,
"ConnectionDecorator");
}
});
if (toolToActivate != null)
ed.getGefEditor().activateTool(toolToActivate);
}
});
}
protected Event createMouseEvent(int x, int y, int button, int stateMask, int count) {
Event event = new Event();
event.time = (int) System.currentTimeMillis();
event.x = x;
event.y = y;
event.button = button;
event.stateMask = stateMask;
event.count = count;
return event;
}
protected IConfigurationProvider getConfigProviderMock(IDiagramTypeProvider dtp, IDiagramContainerUI ed) {
IConfigurationProvider configurationProviderMock = createNiceMock(IConfigurationProviderInternal.class);
expect(configurationProviderMock.getDiagramTypeProvider()).andReturn(dtp).anyTimes();
expect(configurationProviderMock.getDiagramContainer()).andReturn(ed).anyTimes();
expect(configurationProviderMock.getDiagramBehavior()).andReturn(ed.getDiagramBehavior()).anyTimes();
replay(configurationProviderMock);
return configurationProviderMock;
}
}