/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.tools.workbench.platformsplugin.ui; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.List; import javax.swing.JComboBox; import javax.swing.JList; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.eclipse.persistence.tools.workbench.framework.uitools.SwingComponentFactory; import org.eclipse.persistence.tools.workbench.platformsmodel.DatabasePlatform; import org.eclipse.persistence.tools.workbench.platformsmodel.DatabasePlatformRepository; import org.eclipse.persistence.tools.workbench.uitools.app.ListValueModel; import org.eclipse.persistence.tools.workbench.uitools.app.PropertyValueModel; import org.eclipse.persistence.tools.workbench.uitools.app.SimpleListValueModel; import org.eclipse.persistence.tools.workbench.uitools.app.swing.ComboBoxModelAdapter; import org.eclipse.persistence.tools.workbench.uitools.cell.SimpleListCellRenderer; import org.eclipse.persistence.tools.workbench.utility.CollectionTools; /** * Factory class that creates a platform combo box or list that shows the * database platform in which the Oracle platforms are shown first. */ public final class PlatformComponentFactory { private PlatformComponentFactory() { super(); } /** * for now, this is a static list that does not stay in synch with * the platform model; the list contains all the platforms in the * platform repository, sorted in a "marketing-sensitive" fashion * and with a null separating the Oracle platforms from the * competition; the renderer will need to handle the null appropriately */ static ListValueModel buildDatabasePlatformCollectionHolder() { // first sort the platforms in a "marketing-sensitive" fashion List platforms = new ArrayList(DatabasePlatformRepository.getDefault().platformsSize()); CollectionTools.addAll(platforms, DatabasePlatformRepository.getDefault().platforms()); CollectionTools.sort(platforms, new PlatformComparator()); // add a separator (null) between the Oracle platforms and the others for (int i = 0; i < platforms.size(); i++) { DatabasePlatform platform = (DatabasePlatform) platforms.get(i); String platformName = platform.getName().toLowerCase(); if (platformName.indexOf("oracle") == -1) { platforms.add(i, null); break; } } return new SimpleListValueModel(platforms); } public static JComboBox buildPlatformChooser(PropertyValueModel selectionHolder) { return new PlatformChooser(selectionHolder); } public static JList buildPlatformList(PropertyValueModel selectionHolder) { return new PlatformList(selectionHolder); } // ********** inner classes ********** /** * list the platforms with the Oracle platforms at the top (most recent * version first) and with a line separating the Oracle platforms from * the competition */ private static class PlatformChooser extends JComboBox { /** * Construct a platform chooser for the specified selection. */ public PlatformChooser(PropertyValueModel platformSelectionHolder) { super(); this.setModel(new PlatformModelAdapter(buildDatabasePlatformCollectionHolder(), platformSelectionHolder)); this.setRenderer(new PlatformCellRenderer()); } } /** * render a null value as a separator */ private static class PlatformCellRenderer extends SimpleListCellRenderer { private String buildSeparator(JList list) { // calculate the separator's length int width = list.getSize().width - list.getInsets().left - list.getInsets().right; int length = width / SwingUtilities.computeStringWidth(list.getFontMetrics(list.getFont()), "\u2212") - 2; StringBuffer sb = new StringBuffer(" "); for (int i = 0; i < length; i++) { sb.append("\u2212"); } return sb.toString(); } protected String buildText(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { return (value == null) ? this.buildSeparator(list) : ((DatabasePlatform) value).getName(); } } /** * sort the original list of database platforms in a "marketing-sensitive" fashion * (i.e. Oracle platforms first, latest Oracle version first). */ private static class PlatformComparator implements Comparator { public int compare(Object o1, Object o2) { DatabasePlatform platform1 = (DatabasePlatform) o1; DatabasePlatform platform2 = (DatabasePlatform) o2; String platformName1 = platform1.getName().toLowerCase(); String platformName2 = platform2.getName().toLowerCase(); boolean oraclePlatform1 = platformName1.indexOf("oracle") != -1; boolean oraclePlatform2 = platformName2.indexOf("oracle") != -1; // Oracle platforms come first (!) if (oraclePlatform1 && ! oraclePlatform2) return -1; // non-Oracle platforms come after all the Oracle platforms if ( ! oraclePlatform1 && oraclePlatform2) return 1; // Oracle platforms are sorted in reverse numerical order (10, 9, 8,...) if (oraclePlatform1) { return this.oracleVersionNumber(platformName2) - this.oracleVersionNumber(platformName1); } // non-Oracle platforms are sorted alphabetically return platform1.compareTo(platform2); } /** * extract the version number from the specified Oracle platform * name (e.g. Oracle10g -> 10) */ private int oracleVersionNumber(String oraclePlatformName) { StringBuffer sb = new StringBuffer(); int len = oraclePlatformName.length(); for (int i = 0; i < len; i++) { char c = oraclePlatformName.charAt(i); if (Character.isDigit(c)) { sb.append(c); } } return (sb.length() == 0) ? 0 : Integer.parseInt(sb.toString()); } } /** * list the platforms with the Oracle platforms at the top (most recent * version first) and with a line separating the Oracle platforms from * the competition */ private static class PlatformList extends SwingComponentFactory.AccessibleList { /** * Construct a platform chooser for the specified selection. */ public PlatformList(PropertyValueModel platformSelectionHolder) { super(); this.setModel(new PlatformModelAdapter(buildDatabasePlatformCollectionHolder(), platformSelectionHolder)); this.setCellRenderer(new PlatformCellRenderer()); this.addListSelectionListener(buildListSelectionListener(platformSelectionHolder)); } /** * JList does persist the selection model into its model so we need to add * a ListSelectionListener. */ private ListSelectionListener buildListSelectionListener(final PropertyValueModel platformSelectionHolder) { return new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { platformSelectionHolder.setValue(getSelectedValue()); } } }; } } /** * tweak the standard adapter to prevent selection of the divider, * which is represented by a null in the list */ private static class PlatformModelAdapter extends ComboBoxModelAdapter { PlatformModelAdapter(ListValueModel listHolder, PropertyValueModel selectionHolder) { super(listHolder, selectionHolder); } public int indexOf(Object item) { Iterator iter = (Iterator) this.listHolder.getValue(); int index = 0; boolean found = false; while (iter.hasNext()) { if (item == iter.next()) { found = true; break; } index++; } if (!found) { index = -1; } return index; } public void setSelectedItem(Object item) { // If null is to be selected because it's the separator, then select // the next item in the list: which could be either the item above or // below the separator, this is required when traversing the combo box // using the keyboard if (item == null) { int newIndex = indexOf(item); int oldIndex = indexOf(getSelectedItem()); if (newIndex > oldIndex) item = getElementAt(++newIndex); else item = getElementAt(--newIndex); } super.setSelectedItem(item); } } }