Bug 139375 - Unable to edit diagrams generated from XSD schemas
Summary: Unable to edit diagrams generated from XSD schemas
Status: RESOLVED FIXED
Alias: None
Product: GMF-Tooling (ARCHIVED)
Classification: Modeling
Component: Core (show other bugs)
Version: 1.0   Edit
Hardware: PC Windows XP
: P2 major (vote)
Target Milestone: 1.0   Edit
Assignee: Artem Tikhomirov CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-04-29 03:57 EDT by Jerome Louvel CLA
Modified: 2010-07-19 22:20 EDT (History)
1 user (show)

See Also:


Attachments
Failed attempt to reproduce the problem (136.03 KB, application/x-zip)
2006-05-01 21:02 EDT, Christian Damus CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jerome Louvel CLA 2006-04-29 03:57:40 EDT
This report started as a post "ArrayStoreException when creating a node" from 04/27 in the GMF and EMF newsgroup. 

Some excerpts: I'm getting stuck by a weird behavior in GMF 3.2M6. I started from a rather simple XSD schema and generated the ECore and other models without apparent problem. I've done what seems to be a proper mapping as my editor generates and launches successfully, displaying the correct palette.

However when I drop a node on the canvas nothing visually appears and internally an ArrayStoreException is thrown because the EMFCoreUtil class is trying to assign an XMLNSPrefixMap feature instead of a DOCUMENT_ROOT_MODEL one to the container's array.

--

I can confirm that the issue is coming from the XSD to ECore mapping. I've manually modified the generated ECore file to remove annotations and everything specific to XSD, including the automatically generation "DocumentRoot" and it now works fine!

I've also tried to explicitly set the document root to my model root but the XSD to ECore mapping insist on creating a separate element, even though my XSD already contains a valid root element.

--

It is indeed internally expecting an EStringToStringMapEntryImpl but I don't see why because I'm dropping an EMF domain class and not an xmlns prefix entry... After tracing the code, it seems that it is mixing containers and attempts to use the feature ID of one container into another one. That's what puzzles me.

Again, after cleaning the ECore model manually and removing the extra "DocumentRoot", everything works as expected.

It's like if the code internally attempts to store the new node/element into the DocumentRoot instead of the specified Model which acts as a diagram root. It really sounds like a bug to me. 

--

Ed Merks wrote:
Yes, it sounds like a bug.   Using feature IDs across containers (across different types of objects) must be done with care.  Because of multiple inheritance, a feature with ID 0 relative to one class might well have ID > 0 relative to another class. 

--

Below is the full stack trace.

!ENTRY org.eclipse.gmf.runtime.diagram.ui 4 4 2006-04-27 21:53:45.421
!MESSAGE execute
!STACK 0
org.eclipse.core.commands.ExecutionException: While executing the operation, an exception occurred
    at org.eclipse.core.commands.operations.DefaultOperationHistory.execute(DefaultOperationHistory.java:517)
    at org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack.execute(DiagramCommandStack.java:204)
    at org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack.execute(DiagramCommandStack.java:167)
    at org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack.execute(DiagramCommandStack.java:154)
    at org.eclipse.gef.tools.AbstractTool.executeCommand(AbstractTool.java:388)
    at org.eclipse.gef.tools.AbstractTool.executeCurrentCommand(AbstractTool.java:400)
    at org.eclipse.gmf.runtime.diagram.ui.tools.CreationTool.performCreation(CreationTool.java:133)
    at org.eclipse.gef.tools.CreationTool.handleButtonUp(CreationTool.java:178)
    at org.eclipse.gef.tools.AbstractTool.mouseUp(AbstractTool.java:1053)
    at org.eclipse.gef.EditDomain.mouseUp(EditDomain.java:259)
    at org.eclipse.gef.ui.parts.DomainEventDispatcher.dispatchMouseReleased(DomainEventDispatcher.java:374)
    at org.eclipse.draw2d.LightweightSystem$EventHandler.mouseUp(LightweightSystem.java:538)
    at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:137)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:66)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:925)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3346)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2966)
    at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:1914)
    at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1878)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:419)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:143)
    at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplication.java:95)
    at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:78)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:92)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:68)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:376)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:169)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at org.eclipse.core.launcher.Main.invokeFramework(Main.java:336)
    at org.eclipse.core.launcher.Main.basicRun(Main.java:280)
    at org.eclipse.core.launcher.Main.run(Main.java:977)
    at org.eclipse.core.launcher.Main.main(Main.java:952)
Caused by: java.lang.ArrayStoreException: com.supplyinsight.designer.model.impl.LogicalSourceImpl
    at org.eclipse.emf.common.util.BasicEList.assign(BasicEList.java:188)
    at org.eclipse.emf.common.util.BasicEList.addUnique(BasicEList.java:619)
    at org.eclipse.emf.common.notify.impl.NotifyingListImpl.doAddUnique(NotifyingListImpl.java:314)
    at org.eclipse.emf.common.notify.impl.NotifyingListImpl.addUnique(NotifyingListImpl.java:298)
    at org.eclipse.emf.common.util.BasicEList.add(BasicEList.java:600)
    at org.eclipse.emf.common.util.BasicEMap.add(BasicEMap.java:1576)
    at org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil.create(EMFCoreUtil.java:79)
    at org.eclipse.gmf.runtime.emf.type.core.commands.CreateElementCommand.doDefaultElementCreation(CreateElementCommand.java:119)
    at org.eclipse.gmf.runtime.emf.type.core.commands.CreateElementCommand.doExecuteWithResult(CreateElementCommand.java:72)
    at org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand.doExecute(AbstractTransactionalCommand.java:245)
    at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:111)
    at org.eclipse.gmf.runtime.diagram.ui.commands.SemanticCreateCommand.doExecuteWithResult(SemanticCreateCommand.java:66)
    at org.eclipse.gmf.runtime.common.core.command.AbstractCommand.execute(AbstractCommand.java:128)
    at org.eclipse.gmf.runtime.common.core.command.CompositeCommand.doExecuteWithResult(CompositeCommand.java:400)
    at org.eclipse.gmf.runtime.common.core.command.AbstractCommand.execute(AbstractCommand.java:128)
    at org.eclipse.gmf.runtime.common.core.command.CompositeCommand.doExecuteWithResult(CompositeCommand.java:400)
    at org.eclipse.gmf.runtime.common.core.command.AbstractCommand.execute(AbstractCommand.java:128)
    at org.eclipse.gmf.runtime.common.core.command.CompositeCommand.doExecuteWithResult(CompositeCommand.java:400)
    at org.eclipse.gmf.runtime.common.core.command.AbstractCommand.execute(AbstractCommand.java:128)
    at org.eclipse.core.commands.operations.DefaultOperationHistory.execute(DefaultOperationHistory.java:509)
    ... 34 more
Comment 1 Christian Damus CLA 2006-05-01 21:02:20 EDT
Created attachment 40014 [details]
Failed attempt to reproduce the problem

Hi, Jerome,

I tried to reproduce your problem with the projects attached.  One is an Ecore model generated from the XSD that you attached to your original newsgroup posting, and the other contains a small JUnit test.

I tried using a CreateElementRequest to obtain a CreateElementCommand to create a LogicalSource as a child of a Model, as I expect your generated editor would have done.  I was able to do this both when the Model is contained in a DocumentRoot and when it isn't.

Can you please provide more information about your circumstance?  For example, did you customize the code generated by GMF to change the way the CreateElementRequest is configured and executed?  I don't see how it can be that the container element is changed during this process, so that the containment feature with which the CreateElementCommand is constructed would no longer be valid when it is executed.

Some reduction of your code (perhaps a JUnit test that fails in a similar way to your application) would be most helpful for debugging.
Comment 2 Jerome Louvel CLA 2006-05-02 11:15:58 EDT
Hi Christian,

I only used standard GMF generated code, with no modifications. I restarted from scratch several times with no success so either it's probably an issue with the GMF models (graph/tool/map) and how they use the GMF runtime.

I'm also going to send you by email the GMF models (Ecore, graph, map and tool) that will help you recreate the editor and reproduce the issue.

Thanks,
Jerome
Comment 3 Christian Damus CLA 2006-05-03 11:26:05 EDT
Using the models that Jerome sent me, I was able to track the problem down to the generated diagram editor plug-in creating empty XML documents.

Using the new diagram wizard, what I get is a *.model_diagram file that contains a Diagram object whose "element" reference references the DocumentRoot element of the domain (*.model) model.  However, the domain model document is an empty text file (no content), so upon subsequently loading the diagram in the editor, the diagram's element reference does not resolve to a Model, but is a DocumentRoot (a proxy).  Now, the creation tools in the palette expect that the Diagram's domain element is a Model, so they attempt to create objects in containment references of the Model eclass.  These features do not apply to the DocumentRoot.

If, instead, I use the EMF-generated editor to create a valid domain model file then initialize a diagram file from it, I end up with an empty diagram document and the editor fails to open because it cannot find the diagram object.
Comment 4 Artem Tikhomirov CLA 2006-05-03 11:36:52 EDT
Jerome, could you please attach model files you mentioned in #2?
Comment 5 Artem Tikhomirov CLA 2006-05-03 12:43:01 EDT
Looks like we should just mirror behaviour of emf/templates/editor/ModelWizard.javajet#createInitialModel in DiagramEditorUtil#createNewDiagramFile

Jerome, could you please find next two lines in ModelDiagramEditorUtil#createNewDiagramFile (line 117 in the sources you sent):
EObject model = ModelFactory.eINSTANCE.create(ModelPackage.eINSTANCE.getModel());
modelResource.getContents().add(model);

and replace with:

Model model = ModelFactory.eINSTANCE.create(ModelPackage.eINSTANCE.getModel());
DocumentRoot rootObject = ModelFactory.eINSTANCE.createDocumentRoot();
rootObject.setModel(model);
modelResource.getContents().add(rootObject);

and try to use wizard (create diagram file) once again? 
Comment 6 Artem Tikhomirov CLA 2006-05-03 16:14:31 EDT
I've just committed updated DiagramEditorUtil. The way one have to deal with DocumentRoot (mainly, reflective access in generated code) is odd to me :)
Finding out feature to add model element to is tricky as well.
Comment 7 Artem Tikhomirov CLA 2006-05-10 13:15:48 EDT
Another issue was that Resource.save modifies contained elements during save operation, leading to:

java.lang.IllegalStateException: Cannot modify resource set without a write transaction
	at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.assertWriting(TransactionChangeRecorder.java:291)
	at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.appendNotification(TransactionChangeRecorder.java:253)
	at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.processObjectNotification(TransactionChangeRecorder.java:235)
	at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.notifyChanged(TransactionChangeRecorder.java:191)
	at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:230)
	at org.eclipse.emf.ecore.util.EcoreEList.dispatchNotification(EcoreEList.java:234)
	at org.eclipse.emf.common.notify.impl.NotifyingListImpl.addUnique(NotifyingListImpl.java:292)
	at org.eclipse.emf.common.util.BasicEList.add(BasicEList.java:600)
	at org.eclipse.emf.common.util.BasicEMap.put(BasicEMap.java:572)
	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.endSave(XMLSaveImpl.java:270)
	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.save(XMLSaveImpl.java:247)
	at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.doSave(XMLResourceImpl.java:203)
	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.save(ResourceImpl.java:981)
	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.save(ResourceImpl.java:876)
	at xy.designer.model.diagram.part.ModelDiagramEditorUtil.createNewDiagramFile(ModelDiagramEditorUtil.java:142)
	at xy.designer.model.diagram.part.ModelDiagramEditorUtil.createAndOpenDiagram(ModelDiagramEditorUtil.java:61)
	at xy.designer.model.diagram.part.ModelCreationWizardPage.createAndOpenDiagram(ModelCreationWizardPage.java:39)

That behaviour of Resource.save was not known to us :), let experts shed some light: news://news.eclipse.org/e3t6d1$nar$1@utils.eclipse.org 

Save code was moved inside transaction command, and I managed to create diagram and model file, thus, the original issue seems to be fixed now.

Left the request open to remind myself to utilize GenModel accessor to DocumentRoot, https://bugs.eclipse.org/bugs/show_bug.cgi?id=140165
Comment 8 Artem Tikhomirov CLA 2006-05-15 13:28:18 EDT
Reflective access gone in favour of qualified.
Comment 9 Dmitry Stadnik CLA 2007-01-23 07:57:04 EST
It looks like DiagramEditorUtil is broken; I set "Same File For Diagram And Model" to true and generated DiagramEditorUtil still uses Map as domain model root though mindmap.ecore contains DocumentRoot.

Related request https://bugs.eclipse.org/bugs/show_bug.cgi?id=171060
Comment 10 Artem Tikhomirov CLA 2007-01-26 13:24:12 EST
I'm not quite confident whether it's right to put DocumentRoot when resource has few top objects. Ed might shed some light news://news.eclipse.org/epdglv$80n$1@utils.eclipse.org
Comment 11 Artem Tikhomirov CLA 2007-02-02 16:54:21 EST
According to Ed, DocumentRoot is necessary. DiagramEditorUtil has been updated to create DocumentRoot regardless of sameModelDiagramFile attribute.
Comment 12 Richard Gronback CLA 2008-08-13 13:04:21 EDT
[target cleanup] 1.0 RC was the original target milestone for this bug
Comment 13 Eclipse Webmaster CLA 2010-07-19 22:20:08 EDT
[GMF Restructure] Bug 319140 : product GMF and component
Generation was the original product and component for this bug