Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Porhel2017-04-19 09:12:21 +0000
committerMaxime Porhel2017-04-28 08:11:32 +0000
commit2ae0818a840c77faa776e855c4d603f7123980a4 (patch)
treeecf53c712992d67a596bd7876b97198e6b76e256
parent015fdd54cf4d578a48f4a0990092ce722d443322 (diff)
downloadorg.eclipse.sirius-2ae0818a840c77faa776e855c4d603f7123980a4.tar.gz
org.eclipse.sirius-2ae0818a840c77faa776e855c4d603f7123980a4.tar.xz
org.eclipse.sirius-2ae0818a840c77faa776e855c4d603f7123980a4.zip
[515819] Do not lose the cross referencer after DND to resource root
Sometimes the model element contents and cross references are modified before the REMOVE notification. If an object is dropped as a new resource root, it has no container after the move to resource.getContents(), the eContainer() is null but the element is still contained in a resource (which has the cross ref adapter) so it should not be removed or we will a sub-tree of the model without the semantic cross referencer. Bug: 515819 Cherry-picked-from: 515684 Change-Id: Ieecc9f652abf7a692745ad4fa6af6b435d5b618b Signed-off-by: Maxime Porhel <maxime.porhel@obeo.fr>
-rw-r--r--plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/util/LazyCrossReferencer.java16
-rw-r--r--plugins/org.eclipse.sirius.tests.junit/src/org/eclipse/sirius/tests/unit/common/SiriusCrossReferenceAdapterTests.java87
2 files changed, 83 insertions, 20 deletions
diff --git a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/util/LazyCrossReferencer.java b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/util/LazyCrossReferencer.java
index 516dbd17d4..23665544a6 100644
--- a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/util/LazyCrossReferencer.java
+++ b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/util/LazyCrossReferencer.java
@@ -21,7 +21,8 @@ import org.eclipse.emf.ecore.resource.Resource;
import com.google.common.collect.Iterables;
/**
- * A lazy cross referencer which does nothing until one of its method is called. <BR>
+ * A lazy cross referencer which does nothing until one of its method is called.
+ * <BR>
* <BR>
* This cross referencer also reacts to {@link EObject} removal from their
* containing reference : it removes itself automatically from their adapters
@@ -192,7 +193,11 @@ public class LazyCrossReferencer extends ECrossReferenceAdapterWithUnproxyCapabi
/**
* This method does not remove the adapter from the notification old value
- * if its new container is already set and also has the adapter.
+ * in two cases:
+ * <ul>
+ * <li>if its new container is already set and also has the adapter</li>
+ * <li>if the element is now a root of a resource which has the adapter</li>
+ * </ul>
*
* @param notification
* a containment notification
@@ -203,7 +208,12 @@ public class LazyCrossReferencer extends ECrossReferenceAdapterWithUnproxyCapabi
boolean toRemove = true;
if (oldValue instanceof EObject) {
- EObject currentContainer = ((EObject) oldValue).eContainer();
+ EObject removedEObject = (EObject) oldValue;
+
+ Notifier currentContainer = removedEObject.eContainer();
+ if (currentContainer == null) {
+ currentContainer = removedEObject.eResource();
+ }
if (currentContainer != null && currentContainer != notification.getNotifier() && currentContainer.eAdapters().contains(this)) {
toRemove = false;
diff --git a/plugins/org.eclipse.sirius.tests.junit/src/org/eclipse/sirius/tests/unit/common/SiriusCrossReferenceAdapterTests.java b/plugins/org.eclipse.sirius.tests.junit/src/org/eclipse/sirius/tests/unit/common/SiriusCrossReferenceAdapterTests.java
index fd98b27099..331b1c2ea2 100644
--- a/plugins/org.eclipse.sirius.tests.junit/src/org/eclipse/sirius/tests/unit/common/SiriusCrossReferenceAdapterTests.java
+++ b/plugins/org.eclipse.sirius.tests.junit/src/org/eclipse/sirius/tests/unit/common/SiriusCrossReferenceAdapterTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * Copyright (c) 2015, 2017 THALES GLOBAL SERVICES 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
@@ -16,8 +16,14 @@ import java.util.Iterator;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.common.command.IdentityCommand;
import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.transaction.RecordingCommand;
@@ -28,14 +34,14 @@ import org.eclipse.sirius.common.tools.api.util.LazyCrossReferencer;
import org.eclipse.sirius.common.tools.api.util.SiriusCrossReferenceAdapter;
import org.eclipse.sirius.tests.sample.component.Component;
import org.eclipse.sirius.tests.sample.component.ComponentFactory;
+import org.eclipse.sirius.tests.sample.component.ComponentPackage;
import org.eclipse.sirius.tests.support.api.SiriusTestCase;
import org.eclipse.sirius.tools.api.command.ICommandFactory;
import org.eclipse.sirius.viewpoint.DAnalysisSessionEObject;
/**
- * Class containing tests to update of {@link SiriusCrossReferenceAdapter} after
- * CRUD action on resources through DAnalysisSessionImpl such
- * unload/reload/remove resource, close session.
+ * Class containing tests to update of {@link SiriusCrossReferenceAdapter} after CRUD action on resources through
+ * DAnalysisSessionImpl such unload/reload/remove resource, close session.
*
* @author <a href="mailto:laurent.fasani@obeo.fr">Laurent Fasani</a>
*/
@@ -50,18 +56,19 @@ public class SiriusCrossReferenceAdapterTests extends SiriusTestCase {
super.setUp();
setWarningCatchActive(true);
+ // create session with empty aird
+ genericSetUp();
+
+ // add semantic resources
+ initSemanticResource();
}
/**
- * Check that fragmented resource is not reloaded during its unload when it
- * has been externally modified.
+ * Check that fragmented resource is not reloaded during its unload when it has been externally modified.
*
* @throws Exception
*/
public void testDisablingCrossReferencerWhileReloadingResource() throws Exception {
- genericSetUp();
-
- initSemanticResource();
// check that semantic crossRefAdapter is set on fragmented resource
Resource fragmentedResource = ((DAnalysisSessionEObject) session).getControlledResources().get(0);
@@ -93,19 +100,12 @@ public class SiriusCrossReferenceAdapterTests extends SiriusTestCase {
}
/**
- * Check that fragmented resource is not reloaded during its unload when it
- * has been externally deleted.
+ * Check that fragmented resource is not reloaded during its unload when it has been externally deleted.
*
* @throws Exception
*/
public void testDisablingCrossReferencerWhileDeletingResource() throws Exception {
- // create session with empty aird
- genericSetUp();
-
- // add semantic resources
- initSemanticResource();
-
// simulation of DELETION of fragmentResource
File fragFile = ResourcesPlugin.getWorkspace().getRoot().getProject(TEMPORARY_PROJECT_NAME).getFile(FRAGMENT_FILE_NAME).getLocation().toFile();
fragFile.delete();
@@ -129,6 +129,59 @@ public class SiriusCrossReferenceAdapterTests extends SiriusTestCase {
}
/**
+ * Check that if that the session cross referencer is not removed if a REMOVE notification is handled after the add,
+ * ie the old value is already added to a resource with the same cross reference adapter.
+ *
+ * @throws Exception
+ */
+ public void testNoAdapterRemovalAfterLateRemoveNotificationReception() throws Exception {
+ // Check the initial check.
+ checkCrossReferenceIsInstalledOnAllSemanticElements();
+
+ final Component compoRoot = (Component) session.getSemanticResources().iterator().next().getContents().get(0);
+ final Component compo1 = compoRoot.getChildren().get(0);
+ final Component compo2 = compo1.getChildren().get(0);
+
+ // DND compo2 as second root of the semantic resource
+ session.getTransactionalEditingDomain().getCommandStack().execute(new RecordingCommand(session.getTransactionalEditingDomain()) {
+
+ @Override
+ protected void doExecute() {
+ compo1.getChildren().remove(compo2);
+ session.getSemanticResources().iterator().next().getContents().add(compo2);
+ }
+ });
+
+ // Check the lazy cross referencer installation
+ checkCrossReferenceIsInstalledOnAllSemanticElements();
+
+ // Simulate the reception of a late reception of the REMOVE notification
+ session.getTransactionalEditingDomain().getCommandStack().execute(new IdentityCommand() {
+ @Override
+ public void execute() {
+ Notification removeNotification = new ENotificationImpl((InternalEObject) compo1, Notification.REMOVE, ComponentPackage.Literals.COMPONENT__CHILDREN, compo2, null);
+ compo1.eNotify(removeNotification);
+ }
+ });
+
+ // Check the lazy cross referencer installation
+ checkCrossReferenceIsInstalledOnAllSemanticElements();
+ }
+
+ private void checkCrossReferenceIsInstalledOnAllSemanticElements() {
+ for (Resource res : session.getSemanticResources()) {
+ assertTrue("The semantic cross referencer is not installed on the resource " + res.getURI(), res.eAdapters().contains(session.getSemanticCrossReferencer()));
+
+ TreeIterator<EObject> eAllContents = res.getAllContents();
+ while (eAllContents.hasNext()) {
+ EObject obj = eAllContents.next();
+ assertTrue("The semantic cross referencer is not installed on " + obj, obj.eAdapters().contains(session.getSemanticCrossReferencer()));
+ }
+
+ }
+ }
+
+ /**
* Initialize semantic resources
*/
private void initSemanticResource() {

Back to the top