Bug 545768 - Generic Editor Diagnostic Cache not updating initially
Change-Id: Ia5fa19d1431167c0d4e26d6e2b3053e77926f221
Signed-off-by: Eugen Neufeld <eneufeld@eclipsesource.com>
(cherry picked from commit c1ba3fa67760162e36a61f8e55d3c986a0ac956a)
diff --git a/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateEditor.java b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateEditor.java
index 132bfbb..6c181ff 100644
--- a/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateEditor.java
+++ b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateEditor.java
@@ -11,12 +11,14 @@
******************************************************************************/
package org.eclipse.emfforms.internal.datatemplate.tooling.editor;
+import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emfforms.datatemplate.TemplateCollection;
import org.eclipse.emfforms.spi.editor.GenericEditor;
+import org.eclipse.emfforms.spi.swt.treemasterdetail.util.RootObject;
/**
* The DataTemplateEditor for editing {@link TemplateCollection}.
- *
+ *
* @author Eugen Neufeld
*
*/
@@ -27,4 +29,12 @@
return true;
}
+ @Override
+ protected Object modifyEditorInput(ResourceSet resourceSet) {
+ /* this access is save, otherwise we would have thrown a part init exception in init */
+ final TemplateCollection collection = TemplateCollection.class
+ .cast(resourceSet.getResources().get(0).getContents().get(0));
+ return new RootObject(collection);
+ }
+
}
diff --git a/bundles/org.eclipse.emfforms.editor.ecore/src/org/eclipse/emfforms/internal/editor/ecore/EcoreDiagnosticCache.java b/bundles/org.eclipse.emfforms.editor.ecore/src/org/eclipse/emfforms/internal/editor/ecore/EcoreDiagnosticCache.java
index 0334ae1..803aeb7 100644
--- a/bundles/org.eclipse.emfforms.editor.ecore/src/org/eclipse/emfforms/internal/editor/ecore/EcoreDiagnosticCache.java
+++ b/bundles/org.eclipse.emfforms.editor.ecore/src/org/eclipse/emfforms/internal/editor/ecore/EcoreDiagnosticCache.java
@@ -12,16 +12,8 @@
******************************************************************************/
package org.eclipse.emfforms.internal.editor.ecore;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
import org.eclipse.emf.common.notify.Notifier;
-import org.eclipse.emf.common.util.Diagnostic;
-import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-import org.eclipse.emf.ecp.common.spi.cachetree.CachedTreeNode;
import org.eclipse.emfforms.spi.swt.treemasterdetail.diagnostic.DiagnosticCache;
/**
@@ -35,41 +27,6 @@
public EcoreDiagnosticCache(Notifier input) {
super(input);
- final Set<EObject> rootObjects = new LinkedHashSet<>();
- if (ResourceSet.class.isInstance(input)) {
- final EList<Resource> resources = ResourceSet.class.cast(input).getResources();
- resources.stream().map(Resource::getContents).forEach(rootObjects::addAll);
- } else if (Resource.class.isInstance(input)) {
- rootObjects.addAll(Resource.class.cast(input).getContents());
- } else if (EObject.class.isInstance(input)) {
- rootObjects.add(EObject.class.cast(input));
- } else {
- return;
- }
-
- // The super implementation builds the cache tree on initialization, but does not propagate validation results
- // of children to their parents. This means, the own diagnostic for every EObject in the containment history is
- // known but nodes do not know about the diagnostics of their children, yet. As a consequence, validation errors
- // can only be shown where they occur.
- // In order to show the errors at the parents, we walk down the containment hierarchy in a depth-first search
- // approach and propagate the validation results upwards. On the way up, each node propagates its aggregated
- // validation result which is the most severe diagnostic of itself and its children. With this we only need to
- // propagate the results one time from bottom to the top.
- rootObjects.forEach(this::depthFirstCacheUpdate);
- }
-
- /**
- * Recursively walks down the containment hierarchy of the given root object and puts the children's diagnostics
- * into the cache of root's cached tree node. Afterwards, the most severe diagnostic of root's subtree (including
- * root) is returned which allows caching it in root's parent.
- *
- * @param root The root object of the current depth first search
- * @return The most severe Diagnostic in the subtree of the root object
- */
- private Diagnostic depthFirstCacheUpdate(EObject root) {
- final CachedTreeNode<Diagnostic> treeNode = getNodes().get(root);
- root.eContents().stream().forEach(c -> treeNode.putIntoCache(c, depthFirstCacheUpdate(c)));
- return treeNode.getDisplayValue();
}
@Override
diff --git a/bundles/org.eclipse.emfforms.editor/src/org/eclipse/emfforms/spi/editor/GenericEditor.java b/bundles/org.eclipse.emfforms.editor/src/org/eclipse/emfforms/spi/editor/GenericEditor.java
index 087cc4c..70473d0 100644
--- a/bundles/org.eclipse.emfforms.editor/src/org/eclipse/emfforms/spi/editor/GenericEditor.java
+++ b/bundles/org.eclipse.emfforms.editor/src/org/eclipse/emfforms/spi/editor/GenericEditor.java
@@ -388,7 +388,7 @@
/**
* Get the Notifier from the tree input.
- *
+ *
* @param editorInput The editor input to transform
* @return {@link Notifier}
* @throws IllegalStateException if the editor input is not a Notifier
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 e2bcad2..6f42062 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
@@ -28,6 +28,7 @@
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
@@ -74,6 +75,28 @@
});
init(input);
+
+ final Set<EObject> rootObjects = new LinkedHashSet<>();
+ if (ResourceSet.class.isInstance(input)) {
+ final EList<Resource> resources = ResourceSet.class.cast(input).getResources();
+ resources.stream().map(Resource::getContents).forEach(rootObjects::addAll);
+ } else if (Resource.class.isInstance(input)) {
+ rootObjects.addAll(Resource.class.cast(input).getContents());
+ } else if (EObject.class.isInstance(input)) {
+ rootObjects.add(EObject.class.cast(input));
+ } else {
+ return;
+ }
+
+ // The implementation builds the cache tree on initialization, but does not propagate validation results
+ // of children to their parents. This means, the own diagnostic for every EObject in the containment history is
+ // known but nodes do not know about the diagnostics of their children, yet. As a consequence, validation errors
+ // can only be shown where they occur.
+ // In order to show the errors at the parents, we walk down the containment hierarchy in a depth-first search
+ // approach and propagate the validation results upwards. On the way up, each node propagates its aggregated
+ // validation result which is the most severe diagnostic of itself and its children. With this we only need to
+ // propagate the results one time from bottom to the top.
+ rootObjects.forEach(this::depthFirstCacheUpdate);
}
private void init(Notifier input) {
@@ -89,10 +112,11 @@
} else if (Resource.class.isInstance(input)) {
allContents = EcoreUtil.getAllContents(Resource.class.cast(input), false);
} else if (EObject.class.isInstance(input)) {
- allContents = EcoreUtil.getAllContents(EObject.class.cast(input), false);
+ allContents = EcoreUtil.getAllContents(Collections.singleton(EObject.class.cast(input)), false);
} else {
return;
}
+
while (allContents.hasNext()) {
final Object next = allContents.next();
if (!EObject.class.isInstance(next)) {
@@ -106,6 +130,24 @@
}
/**
+ * Recursively walks down the containment hierarchy of the given root object and puts the children's diagnostics
+ * into the cache of root's cached tree node. Afterwards, the most severe diagnostic of root's subtree (including
+ * root) is returned which allows caching it in root's parent.
+ *
+ * @param root The root object of the current depth first search
+ * @return The most severe Diagnostic in the subtree of the root object
+ */
+ private Diagnostic depthFirstCacheUpdate(EObject root) {
+ final CachedTreeNode<Diagnostic> treeNode = getNodes().get(root);
+ if (treeNode == null) {
+ return getDefaultValue();
+ }
+ root.eContents().stream()
+ .forEach(c -> treeNode.putIntoCache(c, depthFirstCacheUpdate(c)));
+ return treeNode.getDisplayValue();
+ }
+
+ /**
* Queries whether the cache is in the process of initializing itself. This is useful
* to avoid doing redundant work, such as back-tracking up an EMF containment tree
* to update parents that have already been covered during the initialization.