Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 432021

Summary: ClassCastException in BorderItemAwareLayoutProvider
Product: [Modeling] Sirius Reporter: Florian Noyrit <florian.noyrit>
Component: DiagramAssignee: Pierre-Charles David <pierre-charles.david>
Status: CLOSED FIXED QA Contact: Julien Dupont <julien.dupont>
Severity: critical    
Priority: P2 CC: julien.dupont, maxime.porhel, pierre-charles.david
Version: 1.0.0M6Keywords: triaged
Target Milestone: 1.0.0M7   
Hardware: PC   
OS: Windows 7   
Whiteboard:

Description Florian Noyrit CLA 2014-04-04 08:41:33 EDT
---Context---
-> In master branch, commit efbcf21541c6ec059530ce7b1e12b00d48345c9a
-> In the class: org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider
-> In the method: protected Rectangle getBounds(final IGraphicalEditPart, final double, final Dimension, final boolean, final boolean)
-> On line 1377: 
final IGraphicalEditPart parent = (IGraphicalEditPart) graphicalEditPart.getParent();

---problem---
the getParent method returns a org.eclipse.gef.EditPart that must not be casted to 
org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart without instanceof test.
Comment 1 Pierre-Charles David CLA 2014-04-04 09:08:54 EDT
While I agree there could be a problem in theory, I don't see in which practical circumstances where this would happen. Can you give us more details on how to reproduce the exception, and attach the stack trace? Thanks.
Comment 2 Florian Noyrit CLA 2014-04-04 09:23:17 EDT
 java.lang.ClassCastException: org.eclipse.gmf.runtime.diagram.ui.render.editparts.RenderedDiagramRootEditPart cannot be cast to org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1377)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1323)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1305)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1378)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1323)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1305)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1378)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1323)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1305)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutBorderItems(BorderItemAwareLayoutProvider.java:808)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutBorderItems(BorderItemAwareLayoutProvider.java:759)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutBorderItems(BorderItemAwareLayoutProvider.java:677)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutEditParts(BorderItemAwareLayoutProvider.java:514)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutEditParts(BorderItemAwareLayoutProvider.java:435)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.ArrangeSelectionLayoutProvider.lauchPrimaryArrangeAll(ArrangeSelectionLayoutProvider.java:245)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.ArrangeSelectionLayoutProvider.layoutEditParts(ArrangeSelectionLayoutProvider.java:164)
	at org.eclipse.sirius.diagram.ui.tools.api.layout.provider.DefaultLayoutProvider.layoutEditParts(DefaultLayoutProvider.java:89)
	at org.eclipse.gmf.runtime.diagram.ui.services.layout.AbstractLayoutEditPartProvider.layoutLayoutNodes(AbstractLayoutEditPartProvider.java:56)
	at org.eclipse.gmf.runtime.diagram.ui.internal.services.layout.LayoutNodesOperation.execute(LayoutNodesOperation.java:74)
	at org.eclipse.gmf.runtime.common.core.service.ExecutionStrategy$1.execute(ExecutionStrategy.java:70)
	at org.eclipse.gmf.runtime.common.core.service.Service.execute(Service.java:651)
	at org.eclipse.gmf.runtime.diagram.ui.services.layout.LayoutService.execute(LayoutService.java:66)
	at org.eclipse.gmf.runtime.diagram.ui.services.layout.LayoutService.layoutLayoutNodes(LayoutService.java:299)
	at org.eclipse.gmf.runtime.diagram.ui.commands.ArrangeCommand.getCommandForExecution(ArrangeCommand.java:124)
	at org.eclipse.gmf.runtime.diagram.ui.commands.ArrangeCommand.doExecuteWithResult(ArrangeCommand.java:93)
	at org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand.doExecute(AbstractTransactionalCommand.java:247)
	at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:150)
	at org.eclipse.emf.workspace.CompositeEMFOperation.doExecute(CompositeEMFOperation.java:217)
	at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:150)
	at org.eclipse.gmf.runtime.diagram.ui.commands.DeferredLayoutCommand.doExecuteWithResult(DeferredLayoutCommand.java:200)
	at org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand.doExecute(AbstractTransactionalCommand.java:247)
	at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:150)
	at org.eclipse.gmf.runtime.common.core.command.CompositeCommand.doExecuteWithResult(CompositeCommand.java:403)
	at org.eclipse.gmf.runtime.common.core.command.AbstractCommand.execute(AbstractCommand.java:134)
	at org.eclipse.core.commands.operations.DefaultOperationHistory.execute(DefaultOperationHistory.java:513)
	... 54 more
Comment 3 Pierre-Charles David CLA 2014-04-04 09:43:32 EDT
Thanks, but I have still no idea on the actual circumstances where this happens, and thus how to reproduce. We have never seen this exception ourselves.

Blindly adding an "instanceof" check would probably fix the immediate symptom, but I'm reluctant to do that without actually understanding why this happens, and what other issues the root cause could trigger. I see you are a Papyrus commiter, did you get this while using Papyrus with Sirius installed? The more context you give us the quicker we can help.
Comment 4 Maxime Porhel CLA 2014-04-18 09:12:59 EDT
DefaultLayoutProvider is provided in org.eclipse.sirius.diagram.ui (1.0.0M7) with a medium priority.

  <extension
        point="org.eclipse.gmf.runtime.diagram.ui.layoutProviders">
     <layoutProvider class="org.eclipse.sirius.diagram.ui.tools.api.layout.provider.DefaultLayoutProvider">
        <Priority name="Medium"/>
     </layoutProvider>
  </extension>


Its provide operation does not check we are on a Sirius diagram, see org.eclipse.sirius.diagram.ui.tools.api.layout.provider.DefaultLayoutProvider.provides(IOperation).

We should at least add a check on the layout hint to provides our layout only when one of our edit part is found.

The layout is build as this:
  List<Object> hints = new ArrayList<Object>(2);
  hints.add(layoutDesc);
  hints.add(getHost());
  IAdaptable layoutHint = new ObjectAdapter(hints);

I found the foolowing potential types of host : DDiagramEditPart, DNodeContainerViewNodeContainerCompartmentEditPart (selection child of a container), DNodeContainerViewNodeContainerCompartment2EditPart (selection child of container in a container).

layoutHint.getAdapter(EditPart.class) or with IGraphicalEditPart could be a good start to get the current edit part and then we could check thaht it is one of our type. 

We have to look for the proper and safer condition
Comment 5 Maxime Porhel CLA 2014-04-18 09:27:00 EDT
See org.eclipse.gmf.examples.runtime.diagram.logic.internal.nonactivating.LogicLayoutProvider.provides(IOperation), we could also check the type of the parentDiagram of the node to layout (or its element which should be a DDiagram)

    if (operation instanceof ILayoutNodeOperation) {
            Iterator nodes = ((ILayoutNodeOperation) operation)
                .getLayoutNodes().listIterator();
            if (nodes.hasNext()) {
                View node = ((ILayoutNode) nodes.next()).getNode();
                Diagram container = node.getDiagram();
                if (container == null
                    || !(container.getType().equals("logic"))) //$NON-NLS-1$
                    return false;
            }
Comment 6 Maxime Porhel CLA 2014-04-18 09:30:58 EDT
Sirius provides its layout provider to all GMF diagrams.


Steps to reproduce:  
* In a runtime with Sirius
* Create the logic sample GMF projects
* Remove the LogicLayoutProvider or reduce its priority (see "org.eclipse.gmf.runtime.diagram.ui.layoutProviders" extension point in org.eclipse.gmf.examples.runtime.diagram.logic/plugin.xml)
* Put a breakpoint in  org.eclipse.sirius.diagram.ui.tools.api.layout.provider.DefaultLayoutProvider.provide()
* Create/Open a logic diagram
* org.eclipse.sirius.diagram.ui.tools.api.layout.provider.DefaultLayoutProvider.provides(IOperation) must not return true for a non Sirius diagram.
Comment 7 Pierre-Charles David CLA 2014-04-24 08:47:29 EDT
Steps to reproduce the original bug:
1. From a Luna M6 package, install both Sirius 1.0M6 and the GMF Examples.
2. Create a new basic project, and then inside it a new Example > Logic Diagram (choose a already popuplated diagram with a 4-bit adder).
3. Open the error log. At this point I already have several errors, but they seem completely unrelated (CNFEs from the GMF examples themselves).
4. Select the diagram and click on the Arrange All button in the tabbar. Nothing happens except a new ERROR entry in the error log:

eclipse.buildId=4.4.0.I20140306-1200
java.version=1.7.0_51
java.vendor=Oracle Corporation
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=fr_FR
Command-line arguments:  -os linux -ws gtk -arch x86_64

org.eclipse.gmf.runtime.diagram.ui
Error
Thu Apr 24 14:43:23 CEST 2014
execute

org.eclipse.core.commands.ExecutionException: While executing the operation, an exception occurred
	at org.eclipse.core.commands.operations.DefaultOperationHistory.execute(DefaultOperationHistory.java:521)
	at org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack.execute(DiagramCommandStack.java:194)
	at org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack.execute(DiagramCommandStack.java:169)
	at org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction.execute(DiagramAction.java:141)
	at org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction.doRun(DiagramAction.java:103)
	at org.eclipse.gmf.runtime.diagram.ui.actions.internal.ArrangeAction.doRun(ArrangeAction.java:278)
	at org.eclipse.gmf.runtime.common.ui.action.AbstractActionHandler.run(AbstractActionHandler.java:359)
	at org.eclipse.gmf.runtime.common.ui.action.ActionManager$1.run(ActionManager.java:225)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
	at org.eclipse.gmf.runtime.common.ui.action.ActionManager.run(ActionManager.java:223)
	at org.eclipse.gmf.runtime.common.ui.action.AbstractActionHandler.runWithEvent(AbstractActionHandler.java:377)
	at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:595)
	at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:511)
	at org.eclipse.jface.action.ActionContributionItem$6.handleEvent(ActionContributionItem.java:462)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4425)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1388)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3773)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3393)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1122)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1006)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:147)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:630)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:574)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:125)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:133)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:103)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:378)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:232)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:648)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:603)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1462)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1438)
Caused by: java.lang.ClassCastException: org.eclipse.gmf.runtime.diagram.ui.render.editparts.RenderedDiagramRootEditPart cannot be cast to org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1377)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1323)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1305)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1378)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1323)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.getBounds(BorderItemAwareLayoutProvider.java:1305)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutBorderItems(BorderItemAwareLayoutProvider.java:808)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutBorderItems(BorderItemAwareLayoutProvider.java:759)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutBorderItems(BorderItemAwareLayoutProvider.java:677)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutEditParts(BorderItemAwareLayoutProvider.java:514)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.BorderItemAwareLayoutProvider.layoutEditParts(BorderItemAwareLayoutProvider.java:435)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.ArrangeSelectionLayoutProvider.lauchPrimaryArrangeAll(ArrangeSelectionLayoutProvider.java:245)
	at org.eclipse.sirius.diagram.ui.tools.internal.layout.provider.ArrangeSelectionLayoutProvider.layoutEditParts(ArrangeSelectionLayoutProvider.java:164)
	at org.eclipse.sirius.diagram.ui.tools.api.layout.provider.AbstractLayoutProvider.getCommandFromDiagramLayoutProvider(AbstractLayoutProvider.java:173)
	at org.eclipse.sirius.diagram.ui.tools.api.layout.provider.AbstractLayoutProvider.layoutEditParts(AbstractLayoutProvider.java:122)
	at org.eclipse.gmf.runtime.diagram.ui.services.layout.AbstractLayoutEditPartProvider.layoutLayoutNodes(AbstractLayoutEditPartProvider.java:69)
	at org.eclipse.gmf.runtime.diagram.ui.internal.services.layout.LayoutNodesOperation.execute(LayoutNodesOperation.java:74)
	at org.eclipse.gmf.runtime.common.core.service.ExecutionStrategy$1.execute(ExecutionStrategy.java:70)
	at org.eclipse.gmf.runtime.common.core.service.Service.execute(Service.java:651)
	at org.eclipse.gmf.runtime.diagram.ui.services.layout.LayoutService.execute(LayoutService.java:66)
	at org.eclipse.gmf.runtime.diagram.ui.services.layout.LayoutService.layoutLayoutNodes(LayoutService.java:299)
	at org.eclipse.gmf.runtime.diagram.ui.commands.ArrangeCommand.getCommandForExecution(ArrangeCommand.java:124)
	at org.eclipse.gmf.runtime.diagram.ui.commands.ArrangeCommand.doExecuteWithResult(ArrangeCommand.java:93)
	at org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand.doExecute(AbstractTransactionalCommand.java:247)
	at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:150)
	at org.eclipse.emf.workspace.CompositeEMFOperation.doExecute(CompositeEMFOperation.java:217)
	at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:150)
	at org.eclipse.core.commands.operations.DefaultOperationHistory.execute(DefaultOperationHistory.java:513)
	... 40 more
Comment 8 Pierre-Charles David CLA 2014-04-24 09:44:42 EDT
See https://git.eclipse.org/r/25484 for a patch. It needs a little more review and testing but it looks like it fixes the issue.
Comment 9 Pierre-Charles David CLA 2014-04-25 10:55:11 EDT
Fixed by 27b38906b4060aabb2b9701c1e7cf41436acb7c2.

Florian, could you try to reproduce your initial problem with a nightly (http://download.eclipse.org/sirius/updates/nightly/latest/luna) and confirm your case is indeed fixed, or reopen otherwise? Thanks.
Comment 10 Pierre-Charles David CLA 2014-05-12 03:45:58 EDT
Available in Sirius 1.0.0M7 (see https://wiki.eclipse.org/Sirius/1.0.0M7 & http://git.eclipse.org/c/sirius/org.eclipse.sirius.git/tag/?id=v1.0.0M7).