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.