| /******************************************************************************* |
| * Copyright (c) 2018, 2020 Dirk Fauth. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Dirk Fauth <dirk.fauth@googlemail.com> - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.nebula.widgets.nattable.extension.glazedlists.test.integration; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.io.Serializable; |
| import java.util.Comparator; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.eclipse.nebula.widgets.nattable.command.DisposeResourcesCommand; |
| import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor; |
| import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider; |
| import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor; |
| import org.eclipse.nebula.widgets.nattable.data.ListDataProvider; |
| import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor; |
| import org.eclipse.nebula.widgets.nattable.data.command.RowDeleteCommandHandler; |
| import org.eclipse.nebula.widgets.nattable.data.command.RowInsertCommand; |
| import org.eclipse.nebula.widgets.nattable.data.command.RowObjectDeleteCommandHandler; |
| import org.eclipse.nebula.widgets.nattable.datachange.DataChangeHandler; |
| import org.eclipse.nebula.widgets.nattable.datachange.DataChangeLayer; |
| import org.eclipse.nebula.widgets.nattable.datachange.IdIndexIdentifier; |
| import org.eclipse.nebula.widgets.nattable.datachange.IdIndexKeyHandler; |
| import org.eclipse.nebula.widgets.nattable.datachange.RowDeleteDataChangeHandler; |
| import org.eclipse.nebula.widgets.nattable.datachange.RowInsertDataChangeHandler; |
| import org.eclipse.nebula.widgets.nattable.datachange.command.DiscardDataChangesCommand; |
| import org.eclipse.nebula.widgets.nattable.datachange.command.KeyRowInsertCommandHandler; |
| import org.eclipse.nebula.widgets.nattable.dataset.person.Person; |
| import org.eclipse.nebula.widgets.nattable.dataset.person.Person.Gender; |
| import org.eclipse.nebula.widgets.nattable.dataset.person.PersonService; |
| import org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommand; |
| import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer; |
| import org.eclipse.nebula.widgets.nattable.layer.DataLayer; |
| import org.eclipse.nebula.widgets.nattable.layer.ILayerListener; |
| import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent; |
| import org.eclipse.nebula.widgets.nattable.layer.event.RowStructuralRefreshEvent; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import ca.odell.glazedlists.EventList; |
| import ca.odell.glazedlists.FilterList; |
| import ca.odell.glazedlists.GlazedLists; |
| import ca.odell.glazedlists.SortedList; |
| import ca.odell.glazedlists.matchers.Matcher; |
| |
| @SuppressWarnings("unchecked") |
| public class RowStructuralDataChangeLayerIntegrationTest { |
| |
| private List<Person> dataModel; |
| private EventList<Person> eventList; |
| private SortedList<Person> sortedList; |
| private FilterList<Person> filterList; |
| private IRowDataProvider<Person> dataProvider; |
| private DataLayer dataLayer; |
| private DataChangeLayer dataChangeLayer; |
| private RowInsertDataChangeHandler insertHandler; |
| private RowDeleteDataChangeHandler deleteHandler; |
| |
| private CountDownLatch lock = new CountDownLatch(1); |
| |
| @Before |
| public void setup() { |
| this.dataModel = PersonService.getFixedPersons(); |
| this.eventList = GlazedLists.eventList(this.dataModel); |
| this.sortedList = new SortedList<>(this.eventList, null); |
| this.filterList = new FilterList<>(this.sortedList); |
| |
| IColumnPropertyAccessor<Person> columnPropertyAccessor = new ReflectiveColumnPropertyAccessor<>(new String[] { |
| "firstName", |
| "lastName", |
| "gender", |
| "married", |
| "birthday" }); |
| |
| IRowIdAccessor<Person> rowIdAccessor = new IRowIdAccessor<Person>() { |
| |
| @Override |
| public Serializable getRowId(Person rowObject) { |
| return rowObject.getId(); |
| } |
| }; |
| |
| this.dataProvider = new ListDataProvider<>( |
| this.filterList, |
| columnPropertyAccessor); |
| this.dataLayer = new DataLayer(this.dataProvider); |
| |
| // register the RowDeleteCommandHandler for delete operations by |
| // index, e.g. used for reverting row insert operations |
| this.dataLayer.registerCommandHandler(new RowDeleteCommandHandler<>(this.eventList)); |
| // register the RowObjectDeleteCommandHandler for delete operations |
| // by object, e.g. delete by UI interaction |
| this.dataLayer.registerCommandHandler(new RowObjectDeleteCommandHandler<>(this.eventList)); |
| // register the KeyRowInsertCommandHandler to be able to revert key |
| // insert operations by firing KeyRowInsertEvents |
| // uses an IdIndexKeyHandler with an alternative ListDataProvider on the |
| // base list in order to be able to discard the change on the base list |
| this.dataLayer.registerCommandHandler( |
| new KeyRowInsertCommandHandler<>( |
| this.eventList, |
| new IdIndexKeyHandler<>(new ListDataProvider<>(this.eventList, columnPropertyAccessor), rowIdAccessor))); |
| |
| GlazedListsEventLayer<Person> glazedListsEventLayer = |
| new GlazedListsEventLayer<>(this.dataLayer, this.filterList); |
| glazedListsEventLayer.setTestMode(true); |
| |
| this.dataChangeLayer = new DataChangeLayer(glazedListsEventLayer, |
| new IdIndexKeyHandler<>( |
| this.dataProvider, |
| rowIdAccessor), |
| // configure persistence mode for data changes |
| false, |
| // enable tracking of row structural changes |
| true); |
| |
| this.dataChangeLayer.addLayerListener(new ILayerListener() { |
| |
| @Override |
| public void handleLayerEvent(ILayerEvent event) { |
| if (event instanceof RowStructuralRefreshEvent) { |
| RowStructuralDataChangeLayerIntegrationTest.this.lock.countDown(); |
| } |
| } |
| }); |
| |
| for (DataChangeHandler h : this.dataChangeLayer.getDataChangeHandler()) { |
| if (h instanceof RowInsertDataChangeHandler) { |
| this.insertHandler = (RowInsertDataChangeHandler) h; |
| } else if (h instanceof RowDeleteDataChangeHandler) { |
| this.deleteHandler = (RowDeleteDataChangeHandler) h; |
| } |
| } |
| assertNotNull("RowInsertDataChangeHandler not found", this.insertHandler); |
| assertNotNull("RowDeleteDataChangeHandler not found", this.deleteHandler); |
| |
| } |
| |
| @After |
| public void tearDown() { |
| this.dataChangeLayer.doCommand(new DisposeResourcesCommand()); |
| } |
| |
| @Test |
| public void shouldUpdateDataInDataLayer() { |
| assertEquals("Simpson", this.dataLayer.getDataValue(1, 1)); |
| |
| this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 1, "Lovejoy")); |
| |
| assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 1)); |
| assertEquals("Lovejoy", this.dataChangeLayer.getDataValueByPosition(1, 1)); |
| assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(1, 1).hasLabel(DataChangeLayer.DIRTY)); |
| assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1)); |
| assertTrue("Row 1 is not dirty", this.dataChangeLayer.isRowDirty(1)); |
| assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 1)); |
| } |
| |
| @Test |
| public void shouldTrackRowInsert() { |
| Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date()); |
| this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph)); |
| |
| int ralphIndex = this.eventList.indexOf(ralph); |
| Object key = this.insertHandler.getKeyHandler().getKey(-1, ralphIndex); |
| |
| assertEquals(19, this.eventList.size()); |
| |
| // row added so all columns are actually dirty |
| assertTrue("Column 0 is not dirty", this.dataChangeLayer.isColumnDirty(0)); |
| assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1)); |
| assertTrue("Column 2 is not dirty", this.dataChangeLayer.isColumnDirty(2)); |
| assertTrue("Column 3 is not dirty", this.dataChangeLayer.isColumnDirty(3)); |
| assertTrue("Column 4 is not dirty", this.dataChangeLayer.isColumnDirty(4)); |
| |
| assertTrue("Row " + ralphIndex + " is not dirty", this.dataChangeLayer.isRowDirty(ralphIndex)); |
| |
| assertTrue("Cell 0/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex)); |
| assertTrue("Cell 1/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(1, ralphIndex)); |
| assertTrue("Cell 2/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(2, ralphIndex)); |
| assertTrue("Cell 3/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(3, ralphIndex)); |
| assertTrue("Cell 4/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(4, ralphIndex)); |
| |
| assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY)); |
| assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(1, ralphIndex).hasLabel(DataChangeLayer.DIRTY)); |
| assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(2, ralphIndex).hasLabel(DataChangeLayer.DIRTY)); |
| assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(3, ralphIndex).hasLabel(DataChangeLayer.DIRTY)); |
| assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(4, ralphIndex).hasLabel(DataChangeLayer.DIRTY)); |
| |
| assertEquals(1, this.dataChangeLayer.getDataChanges().size()); |
| assertEquals(1, this.insertHandler.getDataChanges().size()); |
| // we use the IdIndexKeyHandler so casting is fine |
| IdIndexIdentifier<Person> identifier = (IdIndexIdentifier<Person>) this.insertHandler.getDataChanges().get(key).getKey(); |
| assertEquals(ralph, identifier.rowObject); |
| assertEquals(42, identifier.rowId); |
| } |
| |
| @Test |
| public void shouldTrackRowInsertOnSort() { |
| Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date()); |
| this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph)); |
| |
| assertEquals(18, this.sortedList.indexOf(ralph)); |
| assertEquals(19, this.sortedList.size()); |
| |
| // trigger DESC sorting |
| this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> { |
| return p2.compareTo(p1); |
| })); |
| |
| int ralphIndex = this.sortedList.indexOf(ralph); |
| Object key = this.insertHandler.getKeyHandler().getKey(-1, ralphIndex); |
| |
| assertEquals(0, ralphIndex); |
| assertTrue("Column 0 is not dirty", this.dataChangeLayer.isColumnDirty(0)); |
| assertTrue("Row " + ralphIndex + " is not dirty", this.dataChangeLayer.isRowDirty(ralphIndex)); |
| assertTrue("Cell 0/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex)); |
| assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY)); |
| |
| assertEquals(1, this.dataChangeLayer.getDataChanges().size()); |
| assertEquals(1, this.insertHandler.getDataChanges().size()); |
| // we use the IdIndexKeyHandler so casting is fine |
| IdIndexIdentifier<Person> identifier = (IdIndexIdentifier<Person>) this.insertHandler.getDataChanges().get(key).getKey(); |
| assertEquals(ralph, identifier.rowObject); |
| assertEquals(42, identifier.rowId); |
| } |
| |
| @Test |
| public void shouldTrackRowInsertInSortedState() { |
| assertEquals(18, this.sortedList.size()); |
| |
| // trigger DESC sorting |
| this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> { |
| return p2.compareTo(p1); |
| })); |
| |
| // insert while the list is sorted |
| Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date()); |
| this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph)); |
| |
| assertEquals(19, this.sortedList.size()); |
| int ralphIndex = this.sortedList.indexOf(ralph); |
| Object key = this.insertHandler.getKeyHandler().getKey(-1, ralphIndex); |
| |
| assertEquals(0, ralphIndex); |
| assertTrue("Column 0 is not dirty", this.dataChangeLayer.isColumnDirty(0)); |
| assertTrue("Row " + ralphIndex + " is not dirty", this.dataChangeLayer.isRowDirty(ralphIndex)); |
| assertTrue("Cell 0/" + ralphIndex + " is not dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex)); |
| assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY)); |
| |
| assertEquals(1, this.dataChangeLayer.getDataChanges().size()); |
| assertEquals(1, this.insertHandler.getDataChanges().size()); |
| // we use the IdIndexKeyHandler so casting is fine |
| IdIndexIdentifier<Person> identifier = (IdIndexIdentifier<Person>) this.insertHandler.getDataChanges().get(key).getKey(); |
| assertEquals(ralph, identifier.rowObject); |
| assertEquals(42, identifier.rowId); |
| } |
| |
| @Test |
| public void shouldDiscardRowInsertInSortedState() { |
| Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date()); |
| this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph)); |
| |
| assertEquals(18, this.sortedList.indexOf(ralph)); |
| assertEquals(19, this.sortedList.size()); |
| |
| // trigger DESC sorting |
| this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> { |
| return p2.compareTo(p1); |
| })); |
| |
| assertEquals(0, this.sortedList.indexOf(ralph)); |
| |
| // discard the change |
| this.dataChangeLayer.doCommand(new DiscardDataChangesCommand()); |
| |
| assertEquals(18, this.sortedList.size()); |
| |
| assertTrue(this.dataChangeLayer.getDataChanges().isEmpty()); |
| assertTrue(this.insertHandler.getDataChanges().isEmpty()); |
| |
| // check for states on row 0 |
| assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0)); |
| assertFalse("Row 0 is dirty", this.dataChangeLayer.isRowDirty(0)); |
| assertFalse("Cell 0/0 is dirty", this.dataChangeLayer.isCellDirty(0, 0)); |
| assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, 0).hasLabel(DataChangeLayer.DIRTY)); |
| |
| assertFalse("Ralph is still here", this.sortedList.contains(ralph)); |
| } |
| |
| @Test |
| public void shouldDiscardRowInsertOnChangeSortedState() { |
| // trigger DESC sorting |
| this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> { |
| return p2.compareTo(p1); |
| })); |
| |
| Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date()); |
| this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph)); |
| |
| assertEquals(0, this.sortedList.indexOf(ralph)); |
| assertEquals(19, this.sortedList.size()); |
| |
| this.sortedList.setComparator(null); |
| |
| assertEquals(18, this.sortedList.indexOf(ralph)); |
| |
| // discard the change |
| this.dataChangeLayer.doCommand(new DiscardDataChangesCommand()); |
| |
| assertEquals(18, this.sortedList.size()); |
| |
| assertTrue(this.dataChangeLayer.getDataChanges().isEmpty()); |
| assertTrue(this.insertHandler.getDataChanges().isEmpty()); |
| |
| // check that no row is dirty |
| for (int row = 0; row < this.sortedList.size(); row++) { |
| assertFalse("Row " + row + " is dirty", this.dataChangeLayer.isRowDirty(row)); |
| } |
| |
| assertFalse("Ralph is still here", this.sortedList.contains(ralph)); |
| } |
| |
| @Test |
| public void shouldDiscardMultipleRowInsertOnChangeSortedStateAppending() { |
| // trigger DESC sorting |
| this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> { |
| return p2.compareTo(p1); |
| })); |
| |
| Person clancy = new Person(40, "Clancy", "Wiggum", Gender.MALE, true, new Date()); |
| Person sarah = new Person(41, "Sarah", "Wiggum", Gender.FEMALE, true, new Date()); |
| Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date()); |
| this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, -1, clancy, sarah, ralph)); |
| |
| assertEquals(0, this.sortedList.indexOf(clancy)); |
| assertEquals(1, this.sortedList.indexOf(sarah)); |
| assertEquals(2, this.sortedList.indexOf(ralph)); |
| assertEquals(21, this.sortedList.size()); |
| |
| this.sortedList.setComparator(null); |
| |
| assertEquals(18, this.sortedList.indexOf(clancy)); |
| assertEquals(19, this.sortedList.indexOf(sarah)); |
| assertEquals(20, this.sortedList.indexOf(ralph)); |
| |
| assertTrue("Row 18 is not dirty", this.dataChangeLayer.isRowDirty(18)); |
| assertTrue("Row 19 is not dirty", this.dataChangeLayer.isRowDirty(19)); |
| assertTrue("Row 20 is not dirty", this.dataChangeLayer.isRowDirty(20)); |
| |
| // discard the change |
| this.dataChangeLayer.doCommand(new DiscardDataChangesCommand()); |
| |
| assertEquals(18, this.sortedList.size()); |
| |
| assertTrue(this.dataChangeLayer.getDataChanges().isEmpty()); |
| assertTrue(this.insertHandler.getDataChanges().isEmpty()); |
| |
| // check that no row is dirty |
| for (int row = 0; row < this.sortedList.size(); row++) { |
| assertFalse("Row " + row + " is dirty", this.dataChangeLayer.isRowDirty(row)); |
| } |
| |
| assertFalse("Clancy is still here", this.sortedList.contains(clancy)); |
| assertFalse("Sarah is still here", this.sortedList.contains(sarah)); |
| assertFalse("Ralph is still here", this.sortedList.contains(ralph)); |
| } |
| |
| @Test |
| public void shouldDiscardMultipleRowInsertOnChangeSortedState() { |
| // trigger DESC sorting |
| this.sortedList.setComparator(Comparator.comparing(Person::getLastName, (p1, p2) -> { |
| return p2.compareTo(p1); |
| })); |
| |
| Person clancy = new Person(40, "Clancy", "Wiggum", Gender.MALE, true, new Date()); |
| Person sarah = new Person(41, "Sarah", "Wiggum", Gender.FEMALE, true, new Date()); |
| Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date()); |
| this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, clancy, sarah, ralph)); |
| |
| assertEquals(0, this.sortedList.indexOf(clancy)); |
| assertEquals(1, this.sortedList.indexOf(sarah)); |
| assertEquals(2, this.sortedList.indexOf(ralph)); |
| assertEquals(21, this.sortedList.size()); |
| |
| this.sortedList.setComparator(null); |
| |
| assertEquals(10, this.sortedList.indexOf(clancy)); |
| assertEquals(11, this.sortedList.indexOf(sarah)); |
| assertEquals(12, this.sortedList.indexOf(ralph)); |
| |
| assertTrue("Row 10 is not dirty", this.dataChangeLayer.isRowDirty(10)); |
| assertTrue("Row 11 is not dirty", this.dataChangeLayer.isRowDirty(11)); |
| assertTrue("Row 12 is not dirty", this.dataChangeLayer.isRowDirty(12)); |
| |
| // discard the change |
| this.dataChangeLayer.doCommand(new DiscardDataChangesCommand()); |
| |
| assertEquals(18, this.sortedList.size()); |
| |
| assertTrue(this.dataChangeLayer.getDataChanges().isEmpty()); |
| assertTrue(this.insertHandler.getDataChanges().isEmpty()); |
| |
| // check that no row is dirty |
| for (int row = 0; row < this.sortedList.size(); row++) { |
| assertFalse("Row " + row + " is dirty", this.dataChangeLayer.isRowDirty(row)); |
| } |
| |
| assertFalse("Clancy is still here", this.sortedList.contains(clancy)); |
| assertFalse("Sarah is still here", this.sortedList.contains(sarah)); |
| assertFalse("Ralph is still here", this.sortedList.contains(ralph)); |
| } |
| |
| @Test |
| public void shouldKeepChangeOnFilter() throws InterruptedException { |
| this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 1, "Lovejoy")); |
| |
| this.filterList.setMatcher(new Matcher<Person>() { |
| |
| @Override |
| public boolean matches(Person item) { |
| return item.getLastName().equals("Simpson"); |
| } |
| }); |
| |
| // give the GlazedListsEventLayer some time to trigger the |
| // RowStructuralRefreshEvent |
| boolean completed = this.lock.await(1000, TimeUnit.MILLISECONDS); |
| |
| assertTrue("Timeout - no event received", completed); |
| |
| assertEquals(9, this.filterList.size()); |
| assertFalse(this.dataChangeLayer.getDataChanges().isEmpty()); |
| assertFalse("Column 1 is dirty", this.dataChangeLayer.isColumnDirty(1)); |
| |
| this.lock = new CountDownLatch(1); |
| this.filterList.setMatcher(null); |
| |
| // give the GlazedListsEventLayer some time to trigger the |
| // RowStructuralRefreshEvent |
| completed = this.lock.await(1000, TimeUnit.MILLISECONDS); |
| |
| assertTrue("Timeout - no event received", completed); |
| |
| assertEquals(18, this.filterList.size()); |
| assertFalse(this.dataChangeLayer.getDataChanges().isEmpty()); |
| assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1)); |
| } |
| |
| @Test |
| public void shouldNotThrowAnExceptionOnResize() throws InterruptedException { |
| this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 1, "Lovejoy")); |
| |
| this.filterList.setMatcher(new Matcher<Person>() { |
| |
| @Override |
| public boolean matches(Person item) { |
| return item.getLastName().equals("Simpson"); |
| } |
| }); |
| |
| this.dataLayer.setColumnWidthByPosition(2, 75); |
| |
| assertEquals(9, this.filterList.size()); |
| assertFalse(this.dataChangeLayer.getDataChanges().isEmpty()); |
| assertFalse("Column 1 is dirty", this.dataChangeLayer.isColumnDirty(1)); |
| |
| this.filterList.setMatcher(null); |
| |
| // give the GlazedListsEventLayer some time to trigger the |
| // RowStructuralRefreshEvent |
| boolean completed = this.lock.await(1000, TimeUnit.MILLISECONDS); |
| |
| assertTrue("Timeout - no event received", completed); |
| |
| assertEquals(18, this.filterList.size()); |
| assertFalse(this.dataChangeLayer.getDataChanges().isEmpty()); |
| assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1)); |
| } |
| } |