| /********************************************************************* |
| * 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; |
| } |
| } |