Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Redor2014-10-23 09:39:02 +0000
committerLaurent Redor2014-10-23 09:39:02 +0000
commit944921c401572231d6cb68489c94b63637e47112 (patch)
treecc785629c9b24aaf830466ec0ddabf97bc4b5b6b
parent2443346918ec6a33b9dd888365dfcdff30da6ab2 (diff)
downloadorg.eclipse.sirius-944921c401572231d6cb68489c94b63637e47112.tar.gz
org.eclipse.sirius-944921c401572231d6cb68489c94b63637e47112.tar.xz
org.eclipse.sirius-944921c401572231d6cb68489c94b63637e47112.zip
[448398] Fix the LazyCrossReferencer behavior after a container change
A model element loses its LazyCrossReferencer adapter after changing the container in case where the REMOVE/ADD notifications are handled in reverse order. If the new container is already set and also has the adapter then we add again the adapter. Sometimes the model element contents and cross references are modified before the REMOVE notification, in this case the inverse cross referencer map is not properly cleaned. So we also remove target key from the map in order to force future computation. Bug: 448398 Change-Id: I439d93778cb66a857f374b6a143d8060aa37b620 Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
-rw-r--r--plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/util/LazyCrossReferencer.java48
1 files changed, 44 insertions, 4 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 73c8c9f437..1f8ea75368 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,13 +21,17 @@ import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
import com.google.common.collect.Iterables;
/**
- * A lazy cross referencer which does nothing until one of its method is called. <BR><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
- * and recursively from those of their contents. <BR><BR>
+ * and recursively from those of their contents. If the new container is already
+ * set and also has the cross referencer then we add it again.<BR>
+ * <BR>
* This cross referencer also provide a way to disable the resolution of proxy.
* This can be useful to avoid reloading of a resource during the unloading of
- * it (caused by resolution of some proxy with crossReferencer).<BR><BR>
+ * it (caused by resolution of some proxy with crossReferencer).<BR>
+ * <BR>
*
* @see {@link org.eclipse.emf.transaction.impl.ResourceSetManager#observe(org.eclipse.emf.ecore.resource.Resource, Notification)}
* and message
@@ -36,6 +40,7 @@ import com.google.common.collect.Iterables;
*
* @author mchauvin
*/
+@SuppressWarnings("restriction")
public class LazyCrossReferencer extends ECrossReferenceAdapter {
private boolean resolveEnabled = true;
@@ -222,7 +227,7 @@ public class LazyCrossReferencer extends ECrossReferenceAdapter {
/**
* This method removes the current cross referencer adapter from
- * adapters of removed elements. The removeAdapter method propagate the
+ * adapters of removed elements. The removeAdapter method propagates the
* removal to all contents of its parameter.
*
* @param notification
@@ -237,12 +242,16 @@ public class LazyCrossReferencer extends ECrossReferenceAdapter {
Object oldValue = notification.getOldValue();
if (oldValue instanceof Notifier) {
removeAdapter((Notifier) oldValue);
+ // restore the adapter if necessary
+ restoreAdapter(notification, (Notifier) oldValue);
}
break;
case Notification.REMOVE_MANY:
for (Notifier oldVal : Iterables.filter((Collection<?>) notification.getOldValue(), Notifier.class)) {
removeAdapter(oldVal);
+ // restore the adapter if necessary
+ restoreAdapter(notification, oldVal);
}
break;
@@ -250,5 +259,36 @@ public class LazyCrossReferencer extends ECrossReferenceAdapter {
break;
}
}
+
+ /**
+ * This method restores the current cross referencer adapter from
+ * adapters of the removed element if necessary.
+ *
+ * @param notification
+ * a containment notification
+ * @param removedElement
+ * removed element on which the adapter has been removed
+ */
+ private void restoreAdapter(Notification notification, Notifier removedElement) {
+ // Specific code for case where the REMOVE/ADD notifications are
+ // handled in reverse order: if the new container is already set and
+ // also has the adapter then we add again the adapter.
+ EObject currentContainer = ((EObject) removedElement).eContainer();
+ if (currentContainer != null && currentContainer != notification.getNotifier() && currentContainer.eAdapters().contains(this)) {
+ addAdapter(removedElement);
+ }
+ }
+
+ @Override
+ protected void unsetTarget(EObject target) {
+ super.unsetTarget(target);
+
+ // Sometimes target contents and cross references are modified
+ // before the notification, in this case the inverse cross
+ // referencer map is not properly cleaned. So we also remove target
+ // key from the map in order to force future computation.
+ this.inverseCrossReferencer.remove(target);
+ }
+
};
}

Back to the top