Bug 569512 - CCE in State.writeBinaryLocations

Change-Id: I158eaca271b60b0ca8433174187d87b4c6063c65
Signed-off-by: Stephan Herrmann <stephan.herrmann@berlin.de>
Also-by: Stephan Herrmann <stephan.herrmann@berlin.de>
Signed-off-by: Gunnar Wagenknecht <gunnar@wagenknecht.org>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
index 0bad63d..8c9d5a2 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -31,6 +31,7 @@
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.IAccessRule;
 import org.eclipse.jdt.core.IClasspathAttribute;
@@ -6811,6 +6812,11 @@
 					);
 			project1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
 
+			// regression test for Bug 569512 - CCE in State.writeBinaryLocations:
+			IStatus saveStatus = project1.getProject().getWorkspace().save(true, null);
+			if (!saveStatus.isOK() && saveStatus.isMultiStatus())
+				throw new AssertionError(saveStatus.getChildren()[0].getException());
+
 			IMarker[] markers2 = project2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
 			sortMarkers(markers2);
 			assertMarkers("Unexpected markers",
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java
index 092f13d..836c64b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java
@@ -128,7 +128,7 @@
 	public void addReadUnnamedForNonEmptyClasspath(JavaProject project, IClasspathEntry[] expandedClasspath)
 			throws JavaModelException {
 		for (String moduleName : determineModulesOfProjectsWithNonEmptyClasspath(project, expandedClasspath)) {
-			addModuleUpdate(moduleName, m -> m.addReads(ModuleBinding.ALL_UNNAMED), UpdateKind.MODULE);
+			addModuleUpdate(moduleName, new IUpdatableModule.AddReads(ModuleBinding.ALL_UNNAMED), UpdateKind.MODULE);
 		}
 	}
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index e855d95..f84285e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -790,19 +790,17 @@
 		if (c.updates != null) {
 			List<Consumer<IUpdatableModule>> pu = c.updates.getList(UpdateKind.PACKAGE, false);
 			if (pu != null) {
-				Map<String, List<Consumer<IUpdatableModule>>> map = pu.stream().
-						collect(Collectors.groupingBy(
-								update -> CharOperation.charToString(((IUpdatableModule.AddExports)update).getName())));
+				Map<String, List<AddExports>> map = pu.stream().filter(AddExports.class::isInstance)
+						.map(AddExports.class::cast)
+						.collect(Collectors.groupingBy(addExport -> CharOperation.charToString(addExport.getName())));
 				out.writeInt(map.size());
 				map.entrySet().stream().forEach(entry -> {
 					String pkgName = entry.getKey();
 					try {
 						writeName(pkgName.toCharArray(), out);
 						char[][] targetModules = entry.getValue().stream()
-								.map(consumer -> ((IUpdatableModule.AddExports) consumer).getTargetModules())
-								.filter(targets -> targets != null)
-								.reduce((f,s) -> CharOperation.arrayConcat(f,s))
-								.orElse(null);
+								.map(addExport -> addExport.getTargetModules()).filter(targets -> targets != null)
+								.reduce((f, s) -> CharOperation.arrayConcat(f, s)).orElse(null);
 						writeNames(targetModules, out);
 					} catch (IOException e) {
 						// ignore
@@ -814,9 +812,10 @@
 			}
 			List<Consumer<IUpdatableModule>> mu = c.updates.getList(UpdateKind.MODULE, false);
 			if (mu != null) {
-				out.writeInt(mu.size());
-				for (Consumer<IUpdatableModule> cons : mu) {
-					AddReads m = (AddReads) cons;
+				// TODO, here we cannot handle MODULE_MAIN_CLASS nor MODULE_PACKAGES (ModuleUpdater stores a lambda), should we?
+				List<AddReads> allReads = mu.stream().filter(AddReads.class::isInstance).map(AddReads.class::cast).collect(Collectors.toList());
+				out.writeInt(allReads.size());
+				for (AddReads m : allReads) {
 					writeName(m.getTarget(), out);
 				}
 			} else {