Bug 551088 - DiagnosticCache throws NPE when deleting a reference
* Add Null check to AbstractCachedTree
* Handle external references in DiagnosticCache
Change-Id: If0345b264d216c2b8b4b6386142cace8fa5f6e6a
Signed-off-by: Eugen Neufeld <eneufeld@eclipsesource.com>
diff --git a/bundles/org.eclipse.emf.ecp.common/src/org/eclipse/emf/ecp/common/spi/cachetree/AbstractCachedTree.java b/bundles/org.eclipse.emf.ecp.common/src/org/eclipse/emf/ecp/common/spi/cachetree/AbstractCachedTree.java
index d02a4e0..c3d58f2 100644
--- a/bundles/org.eclipse.emf.ecp.common/src/org/eclipse/emf/ecp/common/spi/cachetree/AbstractCachedTree.java
+++ b/bundles/org.eclipse.emf.ecp.common/src/org/eclipse/emf/ecp/common/spi/cachetree/AbstractCachedTree.java
@@ -194,6 +194,9 @@
}
CachedTreeNode<T> node = nodes.get(eObject);
+ if (node == null) {
+ return;
+ }
final Object parentObject = node.getParent();
final CachedTreeNode<T> parentNode = parentObject == null ? null : nodes.get(parentObject);
diff --git a/bundles/org.eclipse.emfforms.swt.treemasterdetail/src/org/eclipse/emfforms/spi/swt/treemasterdetail/diagnostic/DiagnosticCache.java b/bundles/org.eclipse.emfforms.swt.treemasterdetail/src/org/eclipse/emfforms/spi/swt/treemasterdetail/diagnostic/DiagnosticCache.java
index b185ab2..cecfc27 100644
--- a/bundles/org.eclipse.emfforms.swt.treemasterdetail/src/org/eclipse/emfforms/spi/swt/treemasterdetail/diagnostic/DiagnosticCache.java
+++ b/bundles/org.eclipse.emfforms.swt.treemasterdetail/src/org/eclipse/emfforms/spi/swt/treemasterdetail/diagnostic/DiagnosticCache.java
@@ -34,6 +34,7 @@
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
@@ -106,15 +107,28 @@
initializing = true;
try {
+ if (input == null) {
+ return;
+ }
this.input = input;
validationChangeListener = new ValidationChangeListener(input);
TreeIterator<Object> allContents;
+ final Set<EObject> externalReferences = new LinkedHashSet<EObject>();
if (ResourceSet.class.isInstance(input)) {
- allContents = EcoreUtil.getAllContents(ResourceSet.class.cast(input), false);
+ final ResourceSet resourceSet = ResourceSet.class.cast(input);
+ allContents = EcoreUtil.getAllContents(resourceSet, false);
+ final Map<EObject, Collection<Setting>> map = EcoreUtil.ExternalCrossReferencer.find(resourceSet);
+ externalReferences.addAll(map.keySet());
} else if (Resource.class.isInstance(input)) {
- allContents = EcoreUtil.getAllContents(Resource.class.cast(input), false);
+ final Resource resource = Resource.class.cast(input);
+ allContents = EcoreUtil.getAllContents(resource, false);
+ final Map<EObject, Collection<Setting>> map = EcoreUtil.ExternalCrossReferencer.find(resource);
+ externalReferences.addAll(map.keySet());
} else if (EObject.class.isInstance(input)) {
- allContents = EcoreUtil.getAllContents(Collections.singleton(EObject.class.cast(input)), false);
+ final Set<EObject> set = Collections.singleton(EObject.class.cast(input));
+ allContents = EcoreUtil.getAllContents(set, false);
+ final Map<EObject, Collection<Setting>> map = EcoreUtil.ExternalCrossReferencer.find(set);
+ externalReferences.addAll(map.keySet());
} else {
return;
}
@@ -126,6 +140,7 @@
}
updateCacheWithoutRefresh(EObject.class.cast(next), this);
}
+ externalReferences.forEach(e -> updateCacheWithoutRefresh(e, this));
} finally {
initializing = wasInitializing;
}
diff --git a/tests/org.eclipse.emfforms.swt.treemasterdetail.test/src/org/eclipse/emfforms/swt/treemasterdetail/test/DiagnosticCache_Test.java b/tests/org.eclipse.emfforms.swt.treemasterdetail.test/src/org/eclipse/emfforms/swt/treemasterdetail/test/DiagnosticCache_Test.java
new file mode 100644
index 0000000..707e58e
--- /dev/null
+++ b/tests/org.eclipse.emfforms.swt.treemasterdetail.test/src/org/eclipse/emfforms/swt/treemasterdetail/test/DiagnosticCache_Test.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2019 EclipseSource Muenchen GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * eugen - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emfforms.swt.treemasterdetail.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emfforms.spi.swt.treemasterdetail.diagnostic.DiagnosticCache;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * DiagnosticCache Test.
+ *
+ * @author Eugen Neufeld
+ *
+ */
+public class DiagnosticCache_Test {
+
+ @Before
+ public void setUp() throws Exception {
+
+ }
+
+ @Test
+ public void testNull() {
+ final EObject object = null;
+ final DiagnosticCache cache = new DiagnosticCache(object);
+ assertEquals(0, cache.getObjects().size());
+ }
+
+ @Test
+ public void testExternalReferences() {
+ final EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
+
+ final DiagnosticCache cache = new DiagnosticCache(ePackage);
+ assertEquals(2, cache.getObjects().size());
+ assertTrue(cache.getObjects().contains(ePackage));
+ assertTrue(cache.getObjects().contains(ePackage.getEFactoryInstance()));
+ }
+
+ @Test
+ public void testNoExternalReferences() {
+ final EClass eClass = EcoreFactory.eINSTANCE.createEClass();
+
+ final DiagnosticCache cache = new DiagnosticCache(eClass);
+ assertEquals(1, cache.getObjects().size());
+ assertTrue(cache.getObjects().contains(eClass));
+ }
+}