Bug 546777 - Workbench opens closed/moved fragment on restart
Change-Id: I6f36b451727c31984b8c2aaf09145f71db4c6c61
Signed-off-by: Stefan Nöbauer <stefan.noebauer@kgu-consulting.com>
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
index 97c958e..6d8db66 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2018 BestSolution.at and others.
+ * Copyright (c) 2010, 2019 BestSolution.at and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -14,6 +14,7 @@
* René Brandstetter - Bug 419749
* Brian de Alwis (MTI) - Bug 433053
* Alexandra Buzila - Refactoring, Bug 475934
+ * Stefan Noebauer - Bug 546777
******************************************************************************/
package org.eclipse.e4.ui.internal.workbench;
@@ -121,7 +122,7 @@
* @param initial <code>true</code> if running from a non-persisted state
*
*/
- private void processFragments(IExtension[] extensions, boolean initial) {
+ public void processFragments(IExtension[] extensions, boolean initial) {
List<ModelFragmentWrapper> wrappers = new ArrayList<>();
for (IExtension extension : extensions) {
IConfigurationElement[] ces = extension.getConfigurationElements();
@@ -334,12 +335,15 @@
return new ArrayList<>();
}
+ List<MApplicationElement> existingElements = new ArrayList<>();
+
for (MApplicationElement el : elements) {
EObject o = (EObject) el;
E4XMIResource r = (E4XMIResource) o.eResource();
if (checkExist && applicationResource.getIDToEObjectMap().containsKey(r.getID(o))) {
+ existingElements.add(el);
continue;
}
@@ -360,6 +364,8 @@
applicationResource.setID(eObj, r.getInternalId(eObj));
}
}
+ // remove all existing Elements including all children.
+ fragment.getElements().removeAll(existingElements);
return fragment.merge(application);
}
diff --git a/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/NotExistsNonInitalFragmet.e4xmi b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/NotExistsNonInitalFragmet.e4xmi
new file mode 100644
index 0000000..99b1f95
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/NotExistsNonInitalFragmet.e4xmi
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="ASCII"?>
+<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmi:id="_hpfZ0NsLEeWEUpR9iKVK6Q">
+ <imports xsi:type="basic:PartStack" xmi:id="_Y0PC0H1YEemug7TLPAdneg" elementId="partStackBottom"/>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_OETVYH1YEemug7TLPAdneg" featurename="children" parentElementId="partStackBottom">
+ <elements xsi:type="basic:Part" xmi:id="_gXKowH1YEemug7TLPAdneg" elementId="part2Id"/>
+ <elements xsi:type="basic:Part" xmi:id="_KjQaEH1kEemug7TLPAdneg" elementId="part3Id"/>
+ </fragments>
+</fragment:ModelFragments>
diff --git a/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/fragment_initial.xml b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/fragment_initial.xml
new file mode 100644
index 0000000..26e8bad
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/fragment_initial.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin>
+ <extension id="id1" point="org.eclipse.e4.workbench.model">
+ <fragment apply="initial"
+ uri="data/ModelAssembler/NotExistsInitalFragmet.e4xmi">
+ </fragment>
+ </extension>
+</plugin>
\ No newline at end of file
diff --git a/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/fragment_notexists.xml b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/fragment_notexists.xml
new file mode 100644
index 0000000..1548ec5
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/fragment_notexists.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin>
+ <extension id="id1" point="org.eclipse.e4.workbench.model">
+ <fragment apply="notexists"
+ uri="data/ModelAssembler/NotExistsNonInitalFragmet.e4xmi">
+ </fragment>
+ </extension>
+</plugin>
\ No newline at end of file
diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java
index 7095eda..2d3909d 100644
--- a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java
+++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016 EclipseSource Muenchen GmbH and others.
+ * Copyright (c) 2016, 2019 EclipseSource Muenchen GmbH and others.
*
*
* This program and the accompanying materials
@@ -11,10 +11,14 @@
*
* Contributors:
* Alexandra Buzila - initial API and implementation
+ * Stefan Noebauer - Bug 546777
******************************************************************************/
package org.eclipse.e4.ui.tests.workbench;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
@@ -47,6 +51,8 @@
import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.fragment.MFragmentFactory;
@@ -61,7 +67,6 @@
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
@SuppressWarnings("nls")
@@ -141,8 +146,7 @@
// create fragment
MStringModelFragment fragment = MFragmentFactory.INSTANCE.createStringModelFragment();
fragment.setFeaturename("children");
- final String fragmentParentId = "org.eclipse.e4.ui.tests.modelassembler.app";
- fragment.setParentElementId(fragmentParentId);
+ fragment.setParentElementId(APPLICATION_ID);
fragment.getElements().add(window);
// add fragment to resource
Resource fragmentResource = factory.createResource(URI.createURI("fragmentvirtualuri"));
@@ -160,7 +164,7 @@
assertTrue(elements.contains(window));
MUIElement found = modelService.find(contributedElementId, application);
assertEquals(window, found);
- assertEquals(fragmentParentId, found.getParent().getElementId());
+ assertEquals(APPLICATION_ID, found.getParent().getElementId());
verifyZeroInteractions(logger);
@@ -168,12 +172,12 @@
}
@Test
- @Ignore // currently ignored due to bug 487748
+// @Ignore // currently ignored due to bug 487748
public void testFragments_existingXMIID_checkExists() throws Exception {
// create fragment
MStringModelFragment fragment = MFragmentFactory.INSTANCE.createStringModelFragment();
fragment.setFeaturename("children");
- fragment.setParentElementId("org.eclipse.e4.ui.tests.modelassembler.app");
+ fragment.setParentElementId(APPLICATION_ID);
// create fragment resource
E4XMIResource fragmentResource = (E4XMIResource) factory.createResource(URI.createURI("fragmentvirtualuri"));
resourceSet.getResources().add(fragmentResource);
@@ -221,7 +225,7 @@
// create fragment
MStringModelFragment fragment = MFragmentFactory.INSTANCE.createStringModelFragment();
fragment.setFeaturename("children");
- fragment.setParentElementId("org.eclipse.e4.ui.tests.modelassembler.app");
+ fragment.setParentElementId(APPLICATION_ID);
// create fragment resource
E4XMIResource fragmentResource = (E4XMIResource) factory.createResource(URI.createURI("fragmentvirtualuri"));
resourceSet.getResources().add(fragmentResource);
@@ -507,7 +511,121 @@
assertEquals("simpleprocessor.post", application.getDescriptors().get(0).getElementId());
}
+ @Test
+ public void testNotExistsNonInitialFragmentApply() throws IOException {
+ // ### arrange
+
+ // In this test case we assume that the given application comes from a persisted
+ // model (workbench.xmi file) where part 2 has been moved to the partStackTop.
+ // But the fragment contributes part 2 to the partStackBottom.
+ // By using apply=notexists part 2 from the fragment will not be applied since
+ // it is already present in the model
+ IExtension[] createExtensions = createExtensions(
+ "org.eclipse.e4.ui.tests/data/ModelAssembler/fragment_notexists.xml");
+ MWindow mainWindow = modelService.createModelElement(MWindow.class);
+ mainWindow.setElementId("mainWindow");
+
+ MPartSashContainer partSashContainer = modelService.createModelElement(MPartSashContainer.class);
+ MPartStack partStackTop = modelService.createModelElement(MPartStack.class);
+ partStackTop.setElementId("partStackTop");
+ MPartStack partStackBottom = modelService.createModelElement(MPartStack.class);
+ partStackBottom.setElementId("partStackBottom");
+
+ MPart part1 = modelService.createModelElement(MPart.class);
+ part1.setElementId("part1Id");
+ MPart part2 = modelService.createModelElement(MPart.class);
+ part2.setElementId("part2Id");
+ part2.getPersistedState().put("id", "kgu");
+
+ // initially add both parts to top stack, while contributing fragment
+ // contributes part 2 to the partStackBottom
+ partStackTop.getChildren().add(part1);
+ partStackTop.getChildren().add(part2);
+
+ partSashContainer.getChildren().add(partStackTop);
+ partSashContainer.getChildren().add(partStackBottom);
+
+ mainWindow.getChildren().add(partSashContainer);
+ application.getChildren().add(mainWindow);
+
+ // set same id from fragment file
+ EObject ePart2 = (EObject) part2;
+ E4XMIResource r = (E4XMIResource) ePart2.eResource();
+ r.setID(ePart2, "_gXKowH1YEemug7TLPAdneg");
+
+ // ### act
+ assembler.processFragments(createExtensions, false);
+
+ // ### assert
+ List<MPart> findElements = modelService.findElements(application, "part2Id", MPart.class);
+ // due to apply=notexists the part from the fragment should not have been merged
+ // into the model, because the part from the fragment is already part of
+ // the model
+ assertThat(findElements, hasSize(1));
+ MPart mPart = findElements.get(0);
+ assertThat(mPart.getPersistedState(), hasEntry("id", "kgu"));
+
+ // part 3 is not part of the persisted application yet and is therefore added by
+ // the fragment merge
+ List<MPart> findPart3 = modelService.findElements(application, "part3Id", MPart.class);
+ assertThat(findPart3, hasSize(1));
+
+ // --> part 2 will not be merged due to apply=notexists, but part 3 is added,
+ // because it does not exist yet.
+ }
+
+ @Test
+ public void testInitialApplyButNonInitialStartupFragment() throws IOException {
+ // arrange
+ IExtension[] createExtensions = createExtensions(
+ "org.eclipse.e4.ui.tests/data/ModelAssembler/fragment_initial.xml");
+ MWindow mainWindow = modelService.createModelElement(MWindow.class);
+ mainWindow.setElementId("mainWindow");
+
+ MPartSashContainer partSashContainer = modelService.createModelElement(MPartSashContainer.class);
+ MPartStack partStackTop = modelService.createModelElement(MPartStack.class);
+ partStackTop.setElementId("partStackTop");
+ MPartStack partStackBottom = modelService.createModelElement(MPartStack.class);
+ partStackBottom.setElementId("partStackBottom");
+
+ MPart part1 = modelService.createModelElement(MPart.class);
+ part1.setElementId("part1Id");
+ MPart part2 = modelService.createModelElement(MPart.class);
+ part2.setElementId("part2Id");
+
+ // initially add both parts to top stack, while contributing fragment
+ // contributes part 2 to the partStackBottom
+ partStackTop.getChildren().add(part1);
+ partStackTop.getChildren().add(part2);
+
+ partSashContainer.getChildren().add(partStackTop);
+ partSashContainer.getChildren().add(partStackBottom);
+
+ mainWindow.getChildren().add(partSashContainer);
+ application.getChildren().add(mainWindow);
+
+ // act
+ assembler.processFragments(createExtensions, false);
+
+ // assert
+ List<MPart> findElements = modelService.findElements(application, "part2Id", MPart.class);
+
+ // due to apply=initial the part from the fragment should not have been merged
+ // into the application, because the fragment is not being processed
+ assertThat(findElements, hasSize(1));
+ }
+
private void testProcessor(String filePath, boolean initial, boolean afterFragments) throws Exception {
+ IExtension[] extensions = createExtensions(filePath);
+ assembler.runProcessors(extensions, initial, afterFragments);
+ }
+
+ /**
+ * @param filePath
+ * @return
+ * @throws IOException
+ */
+ private IExtension[] createExtensions(String filePath) throws IOException {
IContributor contributor = ContributorFactorySimple.createContributor(BUNDLE_SYMBOLIC_NAME);
IExtensionRegistry registry = createTestExtensionRegistry();
assertEquals(0, registry.getConfigurationElementsFor(EXTENSION_POINT_ID).length);
@@ -515,7 +633,7 @@
IExtensionPoint extPoint = registry.getExtensionPoint(EXTENSION_POINT_ID);
IExtension[] extensions = new ExtensionsSort().sort(extPoint.getExtensions());
assertEquals(0, application.getDescriptors().size());
- assembler.runProcessors(extensions, initial, afterFragments);
+ return extensions;
}
private IExtensionRegistry createTestExtensionRegistry() {