Bug 537688 - Java 'User Library' entries are jumbled without any
alphabetical sorting

Change-Id: I8c8530d2b4ac18f7c8f967b0b743286b4fe8425b
Signed-off-by: Stephan Herrmann <stephan.herrmann@berlin.de>
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/AutomatedSuite.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/AutomatedSuite.java
index 2782e82..7cd8ad9 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/AutomatedSuite.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/AutomatedSuite.java
@@ -20,7 +20,7 @@
 import org.eclipse.jdt.ui.tests.browsing.PackagesViewContentProviderTests;
 import org.eclipse.jdt.ui.tests.browsing.PackagesViewContentProviderTests2;
 import org.eclipse.jdt.ui.tests.browsing.PackagesViewDeltaTests;
-import org.eclipse.jdt.ui.tests.buildpath.BuildpathModifierActionTest;
+import org.eclipse.jdt.ui.tests.buildpath.BuildpathTestSuite;
 import org.eclipse.jdt.ui.tests.callhierarchy.CallHierarchyContentProviderTest;
 import org.eclipse.jdt.ui.tests.core.CoreTests;
 import org.eclipse.jdt.ui.tests.jarexport.JarExportTests;
@@ -75,7 +75,7 @@
 		addTest(SearchTest.suite());
 		addTest(JUnitJUnitTests.suite());
 
-		addTest(BuildpathModifierActionTest.suite());
+		addTest(BuildpathTestSuite.suite());
 
 		addTest(JarExportTests.suite());
 		addTest(PackageJavadocTests.suite());
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/buildpath/BuildpathTestSuite.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/buildpath/BuildpathTestSuite.java
index 0ef8d59..bf98e06 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/buildpath/BuildpathTestSuite.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/buildpath/BuildpathTestSuite.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008 IBM Corporation and others.
+ * Copyright (c) 2008, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,6 +24,7 @@
 		//$JUnit-BEGIN$
 		suite.addTest(BuildpathModifierActionEnablementTest.suite());
 		suite.addTest(BuildpathModifierActionTest.suite());
+		suite.addTest(CPUserLibraryTest.suite());
 		//$JUnit-END$
 		return suite;
 	}
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/buildpath/CPUserLibraryTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/buildpath/CPUserLibraryTest.java
new file mode 100644
index 0000000..8e7ed6f
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/buildpath/CPUserLibraryTest.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2018 GK Software SE and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.ui.tests.buildpath;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementSorter;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPUserLibraryElement;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.ITreeListAdapter;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.TreeListDialogField;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class CPUserLibraryTest extends TestCase {
+
+	/** Make {@link #getSortedChildren(Object)} accessible. */
+	static class MyTreeViewer extends TreeViewer {
+		public MyTreeViewer(Tree tree) {
+			super(tree);
+		}
+		@Override
+		public Object[] getSortedChildren(Object parentElementOrTreePath) {
+			return super.getSortedChildren(parentElementOrTreePath);
+		}
+	}
+	/** Install our own {@link MyTreeViewer}. 
+	 * @param <E> the type of the root elements.
+	 */
+	static class MyTreeListDialogField<E> extends TreeListDialogField<E> {
+		public MyTreeListDialogField(ITreeListAdapter<E> adapter, String[] buttonLabels, ILabelProvider lprovider) {
+			super(adapter, buttonLabels, lprovider);
+		}
+		@Override
+		protected MyTreeViewer createTreeViewer(Composite parent) {
+			Tree tree= new Tree(parent, getTreeStyle());
+			tree.setFont(parent.getFont());
+			return new MyTreeViewer(tree);
+		}
+		@Override
+		public MyTreeViewer getTreeViewer() {
+			return (MyTreeViewer) super.getTreeViewer();
+		}
+	}
+
+	public CPUserLibraryTest(String name) {
+		super(name);
+	}
+
+	public static Test suite() {
+		return new TestSuite(CPUserLibraryTest.class);
+	}
+
+	public void testUserLibrarySorting() {
+		Shell parent= new Shell();
+		try {
+			String[] buttonLabels = { "OK", "CANCEL" };
+			MyTreeListDialogField<CPUserLibraryElement> listDialogField= new MyTreeListDialogField<>(null, buttonLabels, new CPListLabelProvider());
+			listDialogField.setElements(getLibraryElements("BLIB", "CLIB", "ALIB"));
+			listDialogField.setViewerComparator(new CPListElementSorter());
+			listDialogField.getTreeControl(parent);
+			MyTreeViewer treeViewer= listDialogField.getTreeViewer();
+			Object[] sortedChildren= treeViewer.getSortedChildren(listDialogField);
+			String result = Arrays.stream(sortedChildren)
+					.map(e -> ((CPUserLibraryElement)e).getName())
+					.collect(Collectors.joining(":"));
+			assertEquals("Unexpected element", "ALIB:BLIB:CLIB", result);
+		} finally {
+			parent.dispose();
+		}
+	}
+
+	private List<CPUserLibraryElement> getLibraryElements(String... libNames) {
+		return Arrays.stream(libNames)
+				.map(n -> new CPUserLibraryElement(n, false, null))
+				.collect(Collectors.toList());
+	}
+}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElementSorter.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElementSorter.java
index 3e43c37..fcbad12 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElementSorter.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElementSorter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.ui.wizards.buildpaths;
 
 import org.eclipse.jface.viewers.ContentViewer;
+import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
 import org.eclipse.jface.viewers.IBaseLabelProvider;
 import org.eclipse.jface.viewers.ILabelProvider;
 import org.eclipse.jface.viewers.Viewer;
@@ -77,6 +78,9 @@
 
 		if (viewer instanceof ContentViewer) {
 			IBaseLabelProvider prov = ((ContentViewer) viewer).getLabelProvider();
+			if (prov instanceof DelegatingStyledCellLabelProvider) {
+				prov = ((DelegatingStyledCellLabelProvider) prov).getStyledStringProvider();
+			}
             if (prov instanceof ILabelProvider) {
                 ILabelProvider lprov = (ILabelProvider) prov;
                 String name1 = lprov.getText(e1);