/* * Copyright (c) 2006, 2010 Borland Software Corporation and others * * 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: * bblajer - initial API and implementation */ package org.eclipse.gmf.tests.lite.gef; import java.util.Collections; import java.util.Iterator; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.common.command.AbstractCommand; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.edit.command.AddCommand; import org.eclipse.emf.edit.command.RemoveCommand; import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; import org.eclipse.emf.workspace.EMFCommandOperation; import org.eclipse.gef.EditPart; import org.eclipse.gmf.runtime.notation.Bounds; import org.eclipse.gmf.runtime.notation.CanonicalStyle; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.NotationFactory; import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.gmf.tests.lite.gen.LiteGeneratorConfiguration; import org.eclipse.gmf.tests.rt.GeneratedCanvasTest; public class NotationRefreshTest extends GeneratedCanvasTest { public NotationRefreshTest(String name) { super(name, new LiteGeneratorConfiguration()); } public void testNotationRefreshOnDeleteNode() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); View nodeA = getCanvasInstance().getNodeA(); EObject elementA = nodeA.getElement(); EditPart editPartA = findEditPart(nodeA); Command command = RemoveCommand.create(editingDomain, elementA.eContainer(), elementA.eContainingFeature(), elementA); assertTrue("Failed to obtain command to remove an instance of the domain model element", command != null && command.canExecute()); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertNull("RemoveCommand not executed properly", elementA.eContainer()); assertNull("Notational refresh failed on domain element removal", findView(diagram, elementA)); assertNull("EditPart not removed automatically", findEditPart(nodeA)); assertFalse(editPartA.isActive()); } public void testNotationRefreshOnCreateNode() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); EStructuralFeature feature = getCanvasInstance().getNodeA().getElement().eContainmentFeature(); EClass newChildClass = getCanvasInstance().getNodeA().getElement().eClass(); EObject newChild = newChildClass.getEPackage().getEFactoryInstance().create(newChildClass); Command command = AddCommand.create(editingDomain, diagramElement, feature, newChild); assertTrue("Failed to obtain command to create a new instance of the domain model element", command != null && command.canExecute()); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertSame("AddCommand not executed properly", diagramElement, newChild.eContainer()); View newChildView = findView(diagram, newChild); assertNotNull("Notational refresh failed on domain element creation", newChildView); int visualId = getType(newChildView); assertEquals(getSetup().getGenModel().getNodeA().getVisualID(), visualId); EditPart newChildEP = findEditPart(newChildView); assertNotNull("EditPart not created automatically", newChildEP); } public void testNotationRefreshOnCreateDirectChildNode() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); Node nodeB = getCanvasInstance().getNodeB(); EObject elementB = nodeB.getElement(); EStructuralFeature directNodeFeature = elementB.eClass().getEStructuralFeature("chapters"); assertNotNull("Child feature not found", directNodeFeature); EClass chapterClass = (EClass) directNodeFeature.getEType(); EObject chapter = chapterClass.getEPackage().getEFactoryInstance().create(chapterClass); Command command = AddCommand.create(editingDomain, elementB, directNodeFeature, chapter); assertTrue("Failed to obtain command to create a new instance of the domain model element", command != null && command.canExecute()); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertSame("AddCommand not executed properly", elementB, chapter.eContainer()); View newChildView = findView(nodeB, chapter); assertNotNull("Notational refresh failed on domain element creation", newChildView); EditPart newChildEP = findEditPart(newChildView); assertNotNull("EditPart not created automatically", newChildEP); } public void testNotationRefreshOnAttributeChangeThatAffectsSelector() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); Node nodeB = getCanvasInstance().getNodeB(); EObject elementB = nodeB.getElement(); Bounds bounds = (Bounds) nodeB.getLayoutConstraint(); // if (bounds == null) { // bounds = NotationFactory.eINSTANCE.createBounds(); // } Rectangle rectangle = new Rectangle(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); assertEquals("Unexpected visual ID of the element", getSetup().getGenModel().getNodeB().getVisualID(), getType(nodeB)); EditPart editPartB = findEditPart(nodeB); Edge edge1 = getCanvasInstance().getLinkByClass(); EObject edge1DomainElement = edge1.getElement(); Edge edge2 = getCanvasInstance().getLinkByRef(); checkLinkEnd(edge1, nodeB); checkLinkEnd(edge2, nodeB); EditPart edge1EP = findEditPart(edge1); EditPart edge2EP = findEditPart(edge2); assertTrue(edge1EP.isActive()); assertTrue(edge2EP.isActive()); EClass elementBClass = elementB.eClass(); EStructuralFeature feature = elementBClass.getEStructuralFeature("pages"); //$NON-NLS-1$ assertNotNull("Failed to find the feature that affects selector", feature); Integer newValue = new Integer(400); Command command = SetCommand.create(editingDomain, elementB, feature, newValue); assertTrue("Failed to obtain command to make a change that affects selector", command != null && command.canExecute()); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertEquals("SetCommand not executed properly", newValue, elementB.eGet(feature)); Node newNodeB = (Node) findView(diagram, elementB); assertNotNull("Notational refresh failed to recreate a new node upon a change that affects selector", newNodeB); assertNotSame("Notational refresh failed to replace a new node upon a change that affects selector", nodeB, newNodeB); assertTrue("Notational refresh failed to change visual ID of the element upon a change that affects selector", getSetup().getGenModel().getNodeB().getVisualID() != getType(newNodeB)); EditPart newEditPartB = findEditPart(newNodeB); assertNotNull("EditPart not recreated automatically", newEditPartB); assertNotSame("EditPart not replaced automatically", editPartB, newEditPartB); assertFalse(editPartB.isActive()); assertTrue(newEditPartB.isActive()); Bounds newBounds = (Bounds) newNodeB.getLayoutConstraint(); // if (newBounds == null) { // newBounds = NotationFactory.eINSTANCE.createBounds(); // } Rectangle newRectangle = new Rectangle(newBounds.getX(), newBounds.getY(), newBounds.getWidth(), newBounds.getHeight()); assertEquals("Notational refresh failed to position the new node where the old one was", rectangle, newRectangle); assertFalse(edge2EP.isActive()); Node nodeA = getCanvasInstance().getNodeA(); Edge newEdge2 = findEdgeWithoutElement(diagram, newNodeB, nodeA, 0); assertNotNull("Failed to find the new representation of edge-without-class", newEdge2); EditPart newEdge2EP = findEditPart(newEdge2); assertNotNull("Link EditPart not recreated automatically", newEdge2EP); assertNotSame("Link EditPart not replaced automatically", newEdge2EP, edge2EP); assertTrue(newEdge2EP.isActive()); checkLinkEnd(newEdge2, newNodeB); assertFalse(edge1EP.isActive()); //Should have been replaced //checkLinkEnd(edge1, newNodeB); Edge newEdge1 = findEdgeWithElement(diagram, edge1DomainElement); assertNotNull("Failed to find the new representation of edge-with-class", newEdge1); EditPart newEdge1EP = findEditPart(newEdge1); assertNotNull("Link EditPart not recreated automatically", newEdge1EP); assertNotSame("Link EditPart not replaced automatically", newEdge1EP, edge1EP); assertTrue(newEdge1EP.isActive()); checkLinkEnd(newEdge1, newNodeB); } public void testNotationRefreshOnSemanticRerouteWithClass() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); Node nodeB = getCanvasInstance().getNodeB(); //book Node nodeA = getCanvasInstance().getNodeA(); //writer EditPart bookEP = findEditPart(nodeB); EditPart writerEP = findEditPart(nodeA); assertNotNull(bookEP); assertNotNull(writerEP); Edge opinionsEdge = getCanvasInstance().getLinkByClass(); EObject opinion = opinionsEdge.getElement(); EditPart opinionEP = findEditPart(opinionsEdge); checkLinkEnd(opinionsEdge, nodeA); checkLinkEnd(opinionsEdge, nodeB); //0. Create one element of each type EClass writerClass = nodeA.getElement().eClass(); EObject newWriter = writerClass.getEPackage().getEFactoryInstance().create(writerClass); Command writerCommand = AddCommand.create(editingDomain, diagramElement, nodeA.getElement().eContainmentFeature(), newWriter); EClass bookClass = nodeB.getElement().eClass(); EObject newBook = bookClass.getEPackage().getEFactoryInstance().create(bookClass); Command bookCommand = AddCommand.create(editingDomain, diagramElement, nodeB.getElement().eContainmentFeature(), newBook); new EMFCommandOperation(editingDomain, writerCommand).execute(new NullProgressMonitor(), null); new EMFCommandOperation(editingDomain, bookCommand).execute(new NullProgressMonitor(), null); Node nodeA1 = (Node) findView(diagram, newWriter); Node nodeB1 = (Node) findView(diagram, newBook); //1. Check reroute target of a link-by-class. EStructuralFeature targetByClassFeature = opinion.eClass().getEStructuralFeature("book"); Command command = SetCommand.create(editingDomain, opinion, targetByClassFeature, newBook); assertTrue("Failed to create semantic reroute command", command != null && command.canExecute()); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertSame("Command not executed", newBook, opinion.eGet(targetByClassFeature)); assertTrue(opinionEP.isActive()); checkLinkEnd(opinionsEdge, nodeA); checkLinkEnd(opinionsEdge, nodeB1); //2. Check reroute source of a link-by-class. EStructuralFeature sourceByClassFeature = opinion.eClass().getEStructuralFeature("writer"); command = SetCommand.create(editingDomain, opinion, sourceByClassFeature, newWriter); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertSame("Command not executed", newWriter, opinion.eGet(sourceByClassFeature)); assertTrue(opinionEP.isActive()); checkLinkEnd(opinionsEdge, nodeA1); checkLinkEnd(opinionsEdge, nodeB1); } public void testNotationRefreshOnSemanticRerouteWithFeature() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); Node nodeB = getCanvasInstance().getNodeB(); //book Node nodeA = getCanvasInstance().getNodeA(); //writer EditPart bookEP = findEditPart(nodeB); EditPart writerEP = findEditPart(nodeA); assertNotNull(bookEP); assertNotNull(writerEP); Edge author = getCanvasInstance().getLinkByRef(); checkLinkEnd(author, nodeA); checkLinkEnd(author, nodeB); EditPart authorEP = findEditPart(author); //0. Create one element of each type EClass writerClass = nodeA.getElement().eClass(); final EObject newWriter = writerClass.getEPackage().getEFactoryInstance().create(writerClass); Command writerCommand = AddCommand.create(editingDomain, diagramElement, nodeA.getElement().eContainmentFeature(), newWriter); EClass bookClass = nodeB.getElement().eClass(); final EObject newBook = bookClass.getEPackage().getEFactoryInstance().create(bookClass); Command bookCommand = AddCommand.create(editingDomain, diagramElement, nodeB.getElement().eContainmentFeature(), newBook); new EMFCommandOperation(editingDomain, writerCommand).execute(new NullProgressMonitor(), null); new EMFCommandOperation(editingDomain, bookCommand).execute(new NullProgressMonitor(), null); Node nodeA1 = (Node) findView(diagram, newWriter); Node nodeB1 = (Node) findView(diagram, newBook); //1. Check reroute target of a link-by-class. EStructuralFeature targetFeature = nodeB.getElement().eClass().getEStructuralFeature("author"); Command command = SetCommand.create(editingDomain, nodeB.getElement(), targetFeature, newWriter); assertTrue("Failed to create semantic reroute command", command != null && command.canExecute()); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertSame("Command not executed", newWriter, nodeB.getElement().eGet(targetFeature)); assertTrue(authorEP.isActive()); checkLinkEnd(author, nodeA1); checkLinkEnd(author, nodeB); //2. Check reroute source of a link-by-class. EStructuralFeature sourceFeature = nodeA.getElement().eClass().getEStructuralFeature("books"); final Command rerouteSourceCommand = SetCommand.create(editingDomain, newWriter, sourceFeature, Collections.singletonList(newBook)); //workaround: command.canExecute() fails with an exception, because it actually attempts to modify elements without a write transaction. new EMFCommandOperation(editingDomain, new AbstractCommand() { public boolean canExecute() { return true; } public void redo() { } public void execute() { assertTrue(rerouteSourceCommand != null && rerouteSourceCommand.canExecute()); } }).execute(new NullProgressMonitor(), null); new EMFCommandOperation(editingDomain, rerouteSourceCommand).execute(new NullProgressMonitor(), null); assertNull("Command not executed", nodeB.getElement().eGet(targetFeature)); assertSame("Command not executed", newWriter, nodeB1.getElement().eGet(targetFeature)); assertFalse(authorEP.isActive()); Edge newAuthor = findEdgeWithoutElement(diagram, nodeB1, nodeA1, 0); assertNotNull(newAuthor); EditPart newAuthorEP = findEditPart(newAuthor); assertNotNull(newAuthorEP); assertTrue(newAuthorEP.isActive()); } public void testNotationRefreshOnDeleteLink() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); Node nodeB = getCanvasInstance().getNodeB(); //book Node nodeA = getCanvasInstance().getNodeA(); //writer EditPart bookEP = findEditPart(nodeB); EditPart writerEP = findEditPart(nodeA); assertNotNull(bookEP); assertNotNull(writerEP); Edge author = getCanvasInstance().getLinkByRef(); checkLinkEnd(author, nodeA); checkLinkEnd(author, nodeB); EditPart authorEP = findEditPart(author); assertNotNull(authorEP); assertTrue(authorEP.isActive()); EStructuralFeature targetFeature = nodeB.getElement().eClass().getEStructuralFeature("author"); assertSame(nodeA.getElement(), nodeB.getElement().eGet(targetFeature)); final Command command = SetCommand.create(editingDomain, nodeB.getElement(), targetFeature, SetCommand.UNSET_VALUE); //workaround: command.canExecute() fails with an exception, because it actually attempts to modify elements without a write transaction. new EMFCommandOperation(editingDomain, new AbstractCommand() { public boolean canExecute() { return true; } public void redo() { } public void execute() { assertTrue("Failed to create remove semantic link command", command != null && command.canExecute()); } }).execute(new NullProgressMonitor(), null); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertNull("Command not executed", nodeB.getElement().eGet(targetFeature)); assertNull(author.eContainer()); assertFalse(authorEP.isActive()); } public void testNotationRefreshOnSemanticRerouteLinkToNowhere() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); Node nodeB = getCanvasInstance().getNodeB(); //book Node nodeA = getCanvasInstance().getNodeA(); //writer EditPart bookEP = findEditPart(nodeB); EditPart writerEP = findEditPart(nodeA); assertNotNull(bookEP); assertNotNull(writerEP); Edge opinionsEdge = getCanvasInstance().getLinkByClass(); EObject opinion = opinionsEdge.getElement(); EditPart opinionEP = findEditPart(opinionsEdge); checkLinkEnd(opinionsEdge, nodeA); checkLinkEnd(opinionsEdge, nodeB); EStructuralFeature targetByClassFeature = opinion.eClass().getEStructuralFeature("book"); final Command command = SetCommand.create(editingDomain, opinion, targetByClassFeature, SetCommand.UNSET_VALUE); //the returned command is a strict pessimistic command, so canExecute() can only be called from within a transaction. new EMFCommandOperation(editingDomain, new AbstractCommand() { public void redo() { } public void execute() { assertTrue("Failed to create semantic reroute command", command != null && command.canExecute()); } }).execute(new NullProgressMonitor(), null); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertNull("Command not executed", opinion.eGet(targetByClassFeature)); assertFalse(opinionEP.isActive()); assertNull(opinionsEdge.eContainer()); } public void testNotationRefreshOnCreateLink() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); Node nodeB = getCanvasInstance().getNodeB(); //book Node nodeA = getCanvasInstance().getNodeA(); //writer EditPart bookEP = findEditPart(nodeB); EditPart writerEP = findEditPart(nodeA); assertNotNull(bookEP); assertNotNull(writerEP); EClass bookClass = nodeB.getElement().eClass(); final EObject newBook = bookClass.getEPackage().getEFactoryInstance().create(bookClass); Command bookCommand = AddCommand.create(editingDomain, diagramElement, nodeB.getElement().eContainmentFeature(), newBook); new EMFCommandOperation(editingDomain, bookCommand).execute(new NullProgressMonitor(), null); Node nodeB1 = (Node) findView(diagram, newBook); EStructuralFeature targetFeature = nodeB.getElement().eClass().getEStructuralFeature("author"); Command command = SetCommand.create(editingDomain, newBook, targetFeature, nodeA.getElement()); assertTrue("Failed to create create semantic link command", command != null && command.canExecute()); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertSame("Command not executed", nodeA.getElement(), newBook.eGet(targetFeature)); Edge newAuthor = findEdgeWithoutElement(diagram, nodeB1, nodeA, 0); assertNotNull("Failed to create edge in response to semantic link creation", newAuthor); checkLinkEnd(newAuthor, nodeA); checkLinkEnd(newAuthor, nodeB1); EditPart newAuthorEP = findEditPart(newAuthor); assertNotNull(newAuthorEP); assertTrue(newAuthorEP.isActive()); } public void testCanonicalStyle() throws Exception { EditPart diagramEP = getDiagramEditPart(); Diagram diagram = (Diagram) diagramEP.getModel(); EObject diagramElement = diagram.getElement(); TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(diagramElement); EStructuralFeature feature = getCanvasInstance().getNodeA().getElement().eContainmentFeature(); EClass newChildClass = getCanvasInstance().getNodeA().getElement().eClass(); EObject newChild = newChildClass.getEPackage().getEFactoryInstance().create(newChildClass); CanonicalStyle style = NotationFactory.eINSTANCE.createCanonicalStyle(); style.setCanonical(false); Command uncanonicalizeCommand = AddCommand.create(editingDomain, diagram, NotationPackage.eINSTANCE.getView_Styles(), style); new EMFCommandOperation(editingDomain, uncanonicalizeCommand).execute(new NullProgressMonitor(), null); Command command = AddCommand.create(editingDomain, diagramElement, feature, newChild); assertTrue("Failed to obtain command to create a new instance of the domain model element", command != null && command.canExecute()); new EMFCommandOperation(editingDomain, command).execute(new NullProgressMonitor(), null); assertSame("AddCommand not executed properly", diagramElement, newChild.eContainer()); View newChildView = findView(diagram, newChild); assertNull("Notational child created for a view whose isCanonical() is false", newChildView); Command canonicalizeCommand = SetCommand.create(editingDomain, style, NotationPackage.eINSTANCE.getCanonicalStyle_Canonical(), Boolean.TRUE); new EMFCommandOperation(editingDomain, canonicalizeCommand).execute(new NullProgressMonitor(), null); newChildView = findView(diagram, newChild); assertNotNull("Setting view's isCanonical() to true should create missing notational children", newChildView); int visualId = getType(newChildView); assertEquals(getSetup().getGenModel().getNodeA().getVisualID(), visualId); EditPart newChildEP = findEditPart(newChildView); assertNotNull("EditPart not created automatically", newChildEP); } private void checkLinkEnd(Edge edge, Node node) { assertTrue(node.equals(edge.getSource()) || node.equals(edge.getTarget())); } private int getType(View view) { return Integer.parseInt(view.getType()); } private View findView(View container, EObject child) { for(Iterator<?> it = container.getChildren().iterator(); it.hasNext(); ) { View next = (View) it.next(); if (child.equals(next.getElement())) { return next; } } return null; } private Edge findEdgeWithElement(Diagram diagram, EObject element) { for(Iterator<?> it = diagram.getEdges().iterator(); it.hasNext(); ) { Edge next = (Edge) it.next(); if (next.isSetElement() && next.getElement() == element) { return next; } } return null; } private Edge findEdgeWithoutElement(Diagram diagram, View source, View target, int index) { int count = 0; for(Iterator<?> it = diagram.getEdges().iterator(); it.hasNext(); ) { Edge next = (Edge) it.next(); if (next.isSetElement() && next.getElement() == null) { if (next.getSource() == source && next.getTarget() == target) { if (count == index) { return next; } count++; } } } return null; } }