/*
* $Id$
*
* Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package org.jdesktop.swingx.sort;
import java.awt.Color;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.SortOrder;
import javax.swing.RowSorter.SortKey;
import org.jdesktop.swingx.InteractiveTestCase;
import org.jdesktop.swingx.renderer.StringValue;
import org.jdesktop.swingx.renderer.StringValues;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Common unit test for DefaultSortController implementations.
*
* @author Jeanette Winzenburg
*/
@RunWith(JUnit4.class)
public abstract class AbstractTestSortController<SC extends DefaultSortController<M>, M> extends InteractiveTestCase {
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(AbstractTestSortController.class.getName());
protected SC controller;
/**
* A custom StringValue for Color. Maps to a string composed of the
* prefix "R/G/B: " and the Color's rgb value.
*/
protected StringValue sv;
/** writable version */
protected StringValueRegistry registry;
@Test
public void testStringValueProviderNotNull() {
assertNotNull(controller.getStringValueProvider());
}
@Test
public void testSetStringValueProvider() {
controller.setStringValueProvider(registry);
assertEquals(registry, controller.getStringValueProvider());
}
@Test
public void testLastColumn() {
controller.toggleSortOrder(getColumnCount() - 1);
// was silly mistake ...
controller.toggleSortOrder(getColumnCount() - 1);
}
@Test(expected=NullPointerException.class)
public void testNPEOnNullSortOrderCycle() {
controller.setSortOrderCycle((SortOrder[])null);
}
@Test(expected=NullPointerException.class)
public void testNPEOnNullSortOrderCycleElements() {
controller.setSortOrderCycle((SortOrder) null);
}
@Test
public void testUseSortOrderCycle() {
// empty cylce - does nothing
controller.setSortOrderCycle(new SortOrder[0]);
controller.toggleSortOrder(0);
assertEquals(SortOrder.UNSORTED, controller.getSortOrder(0));
}
@Test
public void testSortOrderCycleSet() {
SortOrder[] cycle = new SortOrder[] {};
controller.setSortOrderCycle(cycle);
assertEqualsArrayByElements(cycle, controller.getSortOrderCycle());
}
/**
* Need to completely take over the toggleSortOrder to support custom cycle.
* So need to check if the exception is thrown as expected
*/
@Test(expected=IndexOutOfBoundsException.class)
public void testColumnIndexCheckedOnToggle() {
controller.toggleSortOrder(getColumnCount());
}
/**
* @param string
* @param first
* @param second
*/
private void assertEqualsArrayByElements(Object[] first,
Object[] second) {
assertEquals("must have same size", first.length, second.length);
for (int i = 0; i < second.length; i++) {
assertEquals("item must be same at index: " + i, first[i], second[i]);
}
}
/**
* Test that sortsOnUpdate property is true by default.
* That's different from core (which is false)
*/
@Test
public void testSortsOnUpdateDefault() {
assertEquals("sortsOnUpdates must be true by default", true, controller.getSortsOnUpdates());
}
/**
* Test that toggle sort order has no effect if column not sortable.
*/
@Test
public void testToggleSortOrderIfSortableFalse() {
controller.setSortable(0, false);
controller.toggleSortOrder(0);
assertEquals(SortOrder.UNSORTED, controller.getSortOrder(0));
}
/**
* Test that set sort order has no effect if column not sortable.
*
*/
@Test
public void testSetSortOrderIfSortableFalse() {
controller.setSortable(0, false);
controller.setSortOrder(0, SortOrder.ASCENDING);
assertEquals(SortOrder.UNSORTED, controller.getSortOrder(0));
}
/**
* Test that resetSortOrders doesn't change sorts at all if controller is not sortable.
* Does nothing if columnCount < 2.
*/
@Test
public void testResetSortOrdersIfSortableFalse() {
if (getColumnCount() < 2) return;
controller.toggleSortOrder(0);
controller.toggleSortOrder(1);
controller.setSortable(false);
List<? extends SortKey> keys = controller.getSortKeys();
assertEquals(2, keys.size());
controller.resetSortOrders();
assertEquals("resetSortOrders must not touch unsortable columns",
keys, controller.getSortKeys());
}
/**
* Test that resetSortOrders doesn't change sorts at all if controller is not sortable.
* Does nothing if columnCount < 2.
*/
@Test
public void testResetSortOrdersIfColumnSortableFalse() {
if (getColumnCount() < 2) return;
controller.toggleSortOrder(0);
controller.toggleSortOrder(1);
controller.setSortable(0, false);
List<? extends SortKey> keys = controller.getSortKeys();
assertEquals(2, keys.size());
controller.resetSortOrders();
assertEquals("resetSortOrders must not touch unsortable columns",
1, controller.getSortKeys().size());
}
/**
* Test that resetSortOrders removes all sorts.
* Does nothing if columnCount < 2.
*/
@Test
public void testResetSortOrders() {
if (getColumnCount() < 2) return;
controller.toggleSortOrder(0);
controller.toggleSortOrder(1);
assertEquals(2, controller.getSortKeys().size());
controller.resetSortOrders();
assertEquals(0, controller.getSortKeys().size());
}
/**
* Test that toggle cycles through sort order cycle.
*/
@Test
public void testToggleSortOrder() {
// PENDING JW: use custom cycle to really test
SortOrder[] cycle = controller.getSortOrderCycle();
for (int i = 0; i < cycle.length; i++) {
controller.toggleSortOrder(0);
assertEquals(cycle[i], controller.getSortOrder(0));
}
}
@Test
public void testGetSortOrder() {
assertEquals(SortOrder.UNSORTED, controller.getSortOrder(0));
}
@Test
public void testSetSortOrder() {
SortOrder toSet = SortOrder.ASCENDING;
controller.setSortOrder(0, toSet);
assertEquals(toSet, controller.getSortOrder(0));
}
/**
* Test per-column sortable setter
*/
@Test
public void testSortableColumn() {
controller.setSortable(0, false);
assertFalse(controller.isSortable(0));
}
/**
* Test that per-controller and per-column sortable getters return false if
* controller sortable is false.
*/
@Test
public void testSortableFalse() {
controller.setSortable(false);
assertFalse("controller must not be sortable", controller.isSortable());
for (int i = 0; i < getColumnCount(); i++) {
assertFalse("columns must not be sortable if controller isn't", controller.isSortable(i));
}
}
/**
* Controller sortable is true by default.
*/
@Test
public void testSortableDefault() {
assertTrue("controller must be sortable by default", controller.isSortable());
}
/**
* per-column sortable is true by default.
*/
@Test
public void testSortableColumnDefault() {
for (int i = 0; i < getColumnCount(); i++) {
assertTrue("columns must be sortable by default", controller.isSortable(i));
}
}
//-------------------- utility methods and setup, abstract methods
/**
* The model's column count. This value is used in some tests defined here.
* @return
*/
protected abstract int getColumnCount();
/**
* Create and return a model as appropriate for the concrete subclass.
* Called in setup only.
* @return
*/
protected abstract M createModel();
/**
* Create and return a SortController as appropriate. Note that the
* parameter is the model as returned by createModel. Called in setup only.
*
* @param model the model to use in the SortController
* @return
*/
protected abstract SC createDefaultSortController(M model);
/**
* initialize model dependent state. Note that the model is the same as returned
* from createModel. Called in setup only
* @param model
*/
protected abstract void setupModelDependentState(M model);
/**
* Creates and returns a StringValue which maps a Color to it's R/G/B rep,
* prepending "R/G/B: "
*
* @return the StringValue for color.
*/
private StringValue createColorStringValue() {
StringValue sv = new StringValue() {
public String getString(Object value) {
if (value instanceof Color) {
Color color = (Color) value;
return "R/G/B: " + color.getRGB();
}
return StringValues.TO_STRING.getString(value);
}
};
return sv;
}
@Before
@Override
public void setUp() throws Exception {
sv = createColorStringValue();
registry = new StringValueRegistry();
M teamModel = createModel();
controller = createDefaultSortController(teamModel);
setupModelDependentState(teamModel);
}
}