Bug 552712 - Package explorer context menu slow for big selection

Avoid iterating all elements of a multi selection to calculate whether
common property pages are available for all the elements of that
selection:
* Stop iterating further selection elements when the intersection of
applicable property pages becomes empty, since that intersection cannot
grow again.
* Since almost no property pages are applicable to multi selection (but
only to single selection), check that early instead of at the very end.
Chances are high that the result collection is empty just because of
that.

In my local tests the calculation is now always finished during the very
first iteration, instead of finishing the loop over all selection
elements.

Change-Id: If514738ad60fa7baef94889f2cf84e0fa5d3721b
Signed-off-by: Michael Keppler <Michael.Keppler@gmx.de>
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/PropertyPageContributorManager.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/PropertyPageContributorManager.java
index bf84ea6..817c974 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/PropertyPageContributorManager.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/PropertyPageContributorManager.java
@@ -17,6 +17,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
@@ -230,23 +231,31 @@
 	 * @since 3.7
 	 */
 	public Collection getApplicableContributors(IStructuredSelection selection) {
-		Iterator it = selection.iterator();
-		Collection result = null;
-		while (it.hasNext()) {
-			Object element = it.next();
-			Collection collection = getApplicableContributors(element);
-			if (result == null)
-				result = new LinkedHashSet(collection);
-			else
+		boolean isMultiSelection = selection.size() > 1;
+		Iterator<Object> selIter = selection.iterator();
+		Collection<RegistryPageContributor> result = null;
+		while (selIter.hasNext()) {
+			Object selectionElement = selIter.next();
+			Collection<RegistryPageContributor> collection = getApplicableContributors(selectionElement);
+			if (isMultiSelection) {
+				// Most pages are not available for multi selection.
+				// We can abort early in most cases by checking this during each iteration.
+				Iterator<RegistryPageContributor> resIter = collection.iterator();
+				while (resIter.hasNext()) {
+					RegistryPageContributor contrib = resIter.next();
+					if (!contrib.supportsMultipleSelection()) {
+						resIter.remove();
+					}
+				}
+			}
+			if (result == null) {
+				result = new LinkedHashSet<>(collection);
+			} else {
 				result.retainAll(collection);
-		}
-		if (result != null && !result.isEmpty() && selection.size() > 1) {
-			// only add contributors which can handle multi selection
-			it = result.iterator();
-			while (it.hasNext()) {
-				RegistryPageContributor contrib = (RegistryPageContributor) it.next();
-				if (!contrib.supportsMultipleSelection())
-					it.remove();
+			}
+			// With each iteration the result can only shrink. We can stop if already empty.
+			if (result.isEmpty()) {
+				return Collections.emptyList();
 			}
 		}
 		return result;