/*******************************************************************************
 * 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.datachange;

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.util.Date;
import java.util.List;

import org.eclipse.nebula.widgets.nattable.command.StructuralRefreshCommand;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.command.RowDeleteCommand;
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.RowInsertCommandHandler;
import org.eclipse.nebula.widgets.nattable.datachange.command.DiscardDataChangesCommand;
import org.eclipse.nebula.widgets.nattable.datachange.command.SaveDataChangesCommand;
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.layer.DataLayer;
import org.eclipse.swt.graphics.Point;
import org.junit.Before;
import org.junit.Test;

public class RowStructuralDataChangeTest {

    private List<Person> dataModel;
    private ListDataProvider<Person> dataProvider;
    private DataLayer dataLayer;
    private DataChangeLayer dataChangeLayer;
    private PersistenceUpdateDataChangeHandler updateHandler;
    private RowInsertDataChangeHandler insertHandler;
    private RowDeleteDataChangeHandler deleteHandler;

    @Before
    public void setup() {
        this.dataModel = PersonService.getFixedPersons();
        this.dataProvider = new ListDataProvider<>(
                this.dataModel,
                new ReflectiveColumnPropertyAccessor<>(new String[] {
                        "firstName",
                        "lastName",
                        "gender",
                        "married",
                        "birthday" }));

        this.dataLayer = new DataLayer(this.dataProvider);
        this.dataLayer.registerCommandHandler(new RowInsertCommandHandler<>(this.dataModel));
        this.dataLayer.registerCommandHandler(new RowDeleteCommandHandler<>(this.dataModel));

        this.dataChangeLayer = new DataChangeLayer(this.dataLayer,
                new PointKeyHandler(),
                // configure persistence mode for data changes
                false,
                // enable tracking of row structural changes
                true);

        for (DataChangeHandler h : this.dataChangeLayer.dataChangeHandler) {
            if (h instanceof RowInsertDataChangeHandler) {
                this.insertHandler = (RowInsertDataChangeHandler) h;
            } else if (h instanceof RowDeleteDataChangeHandler) {
                this.deleteHandler = (RowDeleteDataChangeHandler) h;
            } else if (h instanceof PersistenceUpdateDataChangeHandler) {
                this.updateHandler = (PersistenceUpdateDataChangeHandler) h;
            }
        }
        assertNotNull("RowInsertDataChangeHandler not found", this.insertHandler);
        assertNotNull("RowDeleteDataChangeHandler not found", this.deleteHandler);
        assertNotNull("PersistenceUpdateDataChangeHandler not found", this.updateHandler);
    }

    @Test
    public void shouldTrackRowInsertEvent() {
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph));

        int ralphIndex = this.dataModel.indexOf(ralph);
        Object key = this.insertHandler.keyHandler.getKey(-1, ralphIndex);

        assertEquals(19, this.dataModel.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.dataChanges.size());
        assertEquals(1, this.insertHandler.dataChanges.size());
        // we use the PointKeyHandler so casting is fine
        Point identifier = (Point) this.insertHandler.dataChanges.get(key).getKey();
        assertEquals(-1, identifier.x);
        assertEquals(18, identifier.y);
    }

    @Test
    public void shouldClearRowInsertWithoutReset() {
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(ralph));

        int ralphIndex = this.dataModel.indexOf(ralph);
        Object key = this.insertHandler.keyHandler.getKey(-1, ralphIndex);

        // test some states
        assertEquals(19, this.dataModel.size());

        assertEquals(1, this.dataChangeLayer.dataChanges.size());
        assertEquals(1, this.insertHandler.dataChanges.size());

        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));

        Point identifier = (Point) this.insertHandler.dataChanges.get(key).getKey();
        assertEquals(-1, identifier.x);
        assertEquals(18, identifier.y);

        // only clear no restore, changed data is not reset
        this.dataChangeLayer.clearDataChanges();

        assertEquals(19, this.dataModel.size());
        assertEquals(ralph, this.dataModel.get(18));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.insertHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row " + ralphIndex + " is dirty", this.dataChangeLayer.isRowDirty(ralphIndex));
        assertFalse("Cell 0/" + ralphIndex + " is dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldSaveRowInsertEvent() {
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, ralph));

        int ralphIndex = this.dataModel.indexOf(ralph);

        // we triggered the command to set at index 10, so that should be the
        // index we get
        assertEquals(10, ralphIndex);

        // trigger save operation
        this.dataChangeLayer.doCommand(new SaveDataChangesCommand());

        // test some states
        assertEquals(19, this.dataModel.size());
        assertEquals(ralph, this.dataModel.get(10));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.insertHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row " + ralphIndex + " is dirty", this.dataChangeLayer.isRowDirty(ralphIndex));
        assertFalse("Cell 0/" + ralphIndex + " is dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldDiscardRowInsertEvent() {
        Person prev = this.dataModel.get(10);

        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, ralph));

        assertEquals(19, this.dataModel.size());

        int ralphIndex = this.dataModel.indexOf(ralph);

        // we triggered the command to set at index 10, so that should be the
        // index we get
        assertEquals(10, ralphIndex);

        // trigger discard operation
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        // test some states
        assertEquals(18, this.dataModel.size());
        assertEquals(prev, this.dataModel.get(10));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.insertHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row " + ralphIndex + " is dirty", this.dataChangeLayer.isRowDirty(ralphIndex));
        assertFalse("Cell 0/" + ralphIndex + " is dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldClearRowInsertOnStructuralChange() {
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, ralph));

        int ralphIndex = this.dataModel.indexOf(ralph);

        // perform a full refresh, like changing the underlying data model
        this.dataChangeLayer.doCommand(new StructuralRefreshCommand());

        // test no changes
        assertEquals(19, this.dataModel.size());
        assertEquals(ralph, this.dataModel.get(10));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.insertHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row " + ralphIndex + " is dirty", this.dataChangeLayer.isRowDirty(ralphIndex));
        assertFalse("Cell 0/" + ralphIndex + " is dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldDiscardMultipleRowInsertEvent() {
        Person prev = this.dataModel.get(10);

        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(21, this.dataModel.size());

        int clancyIndex = this.dataModel.indexOf(clancy);
        int sarahIndex = this.dataModel.indexOf(sarah);
        int ralphIndex = this.dataModel.indexOf(ralph);

        // we triggered the command to set at index 10, so that should be the
        // index we get
        assertEquals(10, clancyIndex);
        assertEquals(11, sarahIndex);
        assertEquals(12, ralphIndex);

        // trigger discard operation
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        // test some states
        assertEquals(18, this.dataModel.size());
        assertEquals(prev, this.dataModel.get(10));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.insertHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row " + ralphIndex + " is dirty", this.dataChangeLayer.isRowDirty(ralphIndex));
        assertFalse("Cell 0/" + ralphIndex + " is dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldDiscardMultipleRowInsertEventAppending() {
        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(21, this.dataModel.size());

        int clancyIndex = this.dataModel.indexOf(clancy);
        int sarahIndex = this.dataModel.indexOf(sarah);
        int ralphIndex = this.dataModel.indexOf(ralph);

        // we triggered the command append, so the indexes should start with 19
        assertEquals(18, clancyIndex);
        assertEquals(19, sarahIndex);
        assertEquals(20, ralphIndex);

        // trigger discard operation
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        // test some states
        assertEquals(18, this.dataModel.size());

        for (Person p : this.dataModel) {
            assertFalse("Wiggum found", "Wiggum".equals(p.getLastName()));
        }

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.insertHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row " + ralphIndex + " is dirty", this.dataChangeLayer.isRowDirty(ralphIndex));
        assertFalse("Cell 0/" + ralphIndex + " is dirty", this.dataChangeLayer.isCellDirty(0, ralphIndex));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, ralphIndex).hasLabel(DataChangeLayer.DIRTY));

        int lastRowIndex = this.dataModel.size() - 1;
        assertFalse("Row " + lastRowIndex + " is dirty", this.dataChangeLayer.isRowDirty(lastRowIndex));
        assertFalse("Cell 0/" + lastRowIndex + " is dirty", this.dataChangeLayer.isCellDirty(0, lastRowIndex));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, lastRowIndex).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldTrackRowDeleteEvent() {
        Person toDelete = this.dataModel.get(10);

        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 10));

        assertEquals(17, this.dataModel.size());
        assertFalse(this.dataModel.contains(toDelete));

        // row deleted 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));

        assertFalse("Row 9 is dirty", this.dataChangeLayer.isRowDirty(9));
        assertFalse("Row 10 is dirty", this.dataChangeLayer.isRowDirty(10));
        assertFalse("Row 11 is dirty", this.dataChangeLayer.isRowDirty(11));

        assertFalse("Cell 0/9 is dirty", this.dataChangeLayer.isCellDirty(0, 9));
        assertFalse("Cell 0/10 is dirty", this.dataChangeLayer.isCellDirty(0, 10));
        assertFalse("Cell 0/11 is dirty", this.dataChangeLayer.isCellDirty(0, 11));

        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(0, 9).hasLabel(DataChangeLayer.DIRTY));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 10).hasLabel(DataChangeLayer.DIRTY));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(2, 11).hasLabel(DataChangeLayer.DIRTY));

        assertEquals(1, this.dataChangeLayer.dataChanges.size());
        assertEquals(1, this.deleteHandler.dataChanges.size());

        RowDeleteDataChange change = this.deleteHandler.dataChanges.get(10);
        assertNotNull(change);
        assertEquals(10, change.getKey());
        assertEquals(toDelete, change.getValue());
    }

    @Test
    public void shouldClearRowDeleteWithoutReset() {
        Person toDelete = this.dataModel.get(10);

        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 10));

        // test some states
        assertEquals(17, this.dataModel.size());
        assertFalse(this.dataModel.contains(toDelete));

        assertEquals(1, this.dataChangeLayer.dataChanges.size());
        assertEquals(1, this.deleteHandler.dataChanges.size());

        assertTrue("Column 0 is not dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row 10 is dirty", this.dataChangeLayer.isRowDirty(10));
        assertFalse("Cell 0/10 is dirty", this.dataChangeLayer.isCellDirty(0, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 10).hasLabel(DataChangeLayer.DIRTY));

        RowDeleteDataChange change = this.deleteHandler.dataChanges.get(10);
        assertNotNull(change);
        assertEquals(10, change.getKey());
        assertEquals(toDelete, change.getValue());

        // only clear no restore, changed data is not reset
        this.dataChangeLayer.clearDataChanges();

        assertEquals(17, this.dataModel.size());
        assertFalse(this.dataModel.contains(toDelete));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.deleteHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row 10 is dirty", this.dataChangeLayer.isRowDirty(10));
        assertFalse("Cell 0/10 is dirty", this.dataChangeLayer.isCellDirty(0, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 10).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldSaveRowDeleteEvent() {
        Person toDelete = this.dataModel.get(10);

        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 10));

        // trigger save operation
        this.dataChangeLayer.doCommand(new SaveDataChangesCommand());

        // test some states
        assertEquals(17, this.dataModel.size());
        assertFalse(this.dataModel.contains(toDelete));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.deleteHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row 10 is dirty", this.dataChangeLayer.isRowDirty(10));
        assertFalse("Cell 0/10 is dirty", this.dataChangeLayer.isCellDirty(0, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 10).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldDiscardRowDeleteEvent() {
        Person toDelete = this.dataModel.get(10);

        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 10));

        assertEquals(17, this.dataModel.size());
        assertFalse(this.dataModel.contains(toDelete));

        // trigger discard operation
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        // test some states
        assertEquals(18, this.dataModel.size());
        assertTrue(this.dataModel.contains(toDelete));
        assertEquals(toDelete, this.dataModel.get(10));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.deleteHandler.dataChanges.isEmpty());

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.deleteHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row 10 is dirty", this.dataChangeLayer.isRowDirty(10));
        assertFalse("Cell 0/10 is dirty", this.dataChangeLayer.isCellDirty(0, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 10).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldClearRowDeleteOnStructuralChange() {
        Person toDelete = this.dataModel.get(10);

        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 10));

        // perform a full refresh, like changing the underlying data model
        this.dataChangeLayer.doCommand(new StructuralRefreshCommand());

        // test no changes
        assertEquals(17, this.dataModel.size());
        assertFalse(this.dataModel.contains(toDelete));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.deleteHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row 10 is dirty", this.dataChangeLayer.isRowDirty(10));
        assertFalse("Cell 0/10 is dirty", this.dataChangeLayer.isCellDirty(0, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 10).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldDiscardMultipleRowDeleteEvent() {
        Person toDeleteA = this.dataModel.get(10);
        Person toDeleteB = this.dataModel.get(11);
        Person toDeleteC = this.dataModel.get(12);

        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 10, 11, 12));

        assertEquals(15, this.dataModel.size());
        assertFalse(this.dataModel.contains(toDeleteA));
        assertFalse(this.dataModel.contains(toDeleteB));
        assertFalse(this.dataModel.contains(toDeleteC));

        // trigger discard operation
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        // test some states
        assertEquals(18, this.dataModel.size());
        assertTrue(this.dataModel.contains(toDeleteA));
        assertTrue(this.dataModel.contains(toDeleteB));
        assertTrue(this.dataModel.contains(toDeleteC));
        assertEquals(toDeleteA, this.dataModel.get(10));
        assertEquals(toDeleteB, this.dataModel.get(11));
        assertEquals(toDeleteC, this.dataModel.get(12));

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.deleteHandler.dataChanges.isEmpty());

        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
        assertTrue(this.deleteHandler.dataChanges.isEmpty());

        assertFalse("Column 0 is dirty", this.dataChangeLayer.isColumnDirty(0));
        assertFalse("Row 10 is dirty", this.dataChangeLayer.isRowDirty(10));
        assertFalse("Cell 0/10 is dirty", this.dataChangeLayer.isCellDirty(0, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 10).hasLabel(DataChangeLayer.DIRTY));
    }

    @Test
    public void shouldDiscardInsertAndDeleteAgain() {
        Person prev = this.dataModel.get(10);

        // insert a row
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, ralph));

        assertEquals(19, this.dataModel.size());

        // delete the inserted row again
        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 10));

        assertEquals(18, this.dataModel.size());
        assertEquals(2, this.dataChangeLayer.dataChanges.size());

        // discard the changes
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals(18, this.dataModel.size());
        assertEquals(prev, this.dataModel.get(10));
        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
    }

    @Test
    public void shouldResetUpdateDeleteOnDiscard() {
        // update the value of an item
        assertEquals("Simpson", this.dataLayer.getDataValue(1, 1));

        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 1, "Lovejoy"));

        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 1));

        // delete the changed item
        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 1));

        assertEquals(17, this.dataModel.size());
        assertEquals(2, this.dataChangeLayer.dataChanges.size());

        // discard the changes
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals(18, this.dataModel.size());
        assertEquals("Simpson", this.dataLayer.getDataValue(1, 1));
        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());
    }

    @Test
    public void shouldDiscardInsertAndUpdateInsertedItem() {
        Person prev = this.dataModel.get(10);

        // insert a row
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, ralph));

        assertEquals(19, this.dataModel.size());

        // update the inserted row
        assertEquals("Ralph", this.dataLayer.getDataValue(0, 10));

        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 0, 10, "Clancy"));

        assertEquals("Clancy", this.dataLayer.getDataValue(0, 10));

        // discard the changes
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals(18, this.dataModel.size());
        assertEquals(prev, this.dataModel.get(10));
        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());

        // ensure that there is no Clancy or Ralph in an item afterwards
        for (Person p : this.dataModel) {
            assertFalse("Clancy found", "Clancy".equals(p.getFirstName()));
            assertFalse("Ralph found", "Ralph".equals(p.getFirstName()));
        }
    }

    @Test
    public void shouldDiscardUpdateInsert() {
        // update the value of an item
        assertEquals("Simpson", this.dataLayer.getDataValue(1, 1));

        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 1, "Lovejoy"));

        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 1));
        assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 1));

        Person prev = this.dataModel.get(0);

        // insert a row on top of the change
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 0, ralph));

        assertEquals(19, this.dataModel.size());

        // change has moved one row
        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 2));
        assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 2));
        assertFalse("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 1));

        // discard the changes
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals(18, this.dataModel.size());
        assertEquals(prev, this.dataModel.get(0));
        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());

        // ensure that there is no Wiggum and no Lovejoy in an item afterwards
        for (Person p : this.dataModel) {
            assertFalse("Lovejoy found", "Lovejoy".equals(p.getLastName()));
            assertFalse("Wiggum found", "Wiggum".equals(p.getLastName()));
        }
    }

    @Test
    public void shouldDiscardUpdateInsertAndUpdateBack() {
        // update the value of an item
        assertEquals("Simpson", this.dataLayer.getDataValue(1, 1));

        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 1, "Lovejoy"));

        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 1));
        assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 1));

        Person prev = this.dataModel.get(0);

        // insert a row on top of the change
        Person ralph = new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date());
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 0, ralph));

        assertEquals(19, this.dataModel.size());

        // change has moved one row
        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 2));
        assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 2));
        assertFalse("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 1));

        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 2, "Simpson"));

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 2));
        assertFalse("Cell is dirty", this.dataChangeLayer.isCellDirty(1, 2));

        // discard the changes
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals(18, this.dataModel.size());
        assertEquals(prev, this.dataModel.get(0));
        assertTrue(this.dataChangeLayer.dataChanges.isEmpty());

        // ensure that there is no Wiggum and no Lovejoy in an item afterwards
        for (Person p : this.dataModel) {
            assertFalse("Lovejoy found", "Lovejoy".equals(p.getLastName()));
            assertFalse("Wiggum found", "Wiggum".equals(p.getLastName()));
        }
    }

    @Test
    public void shouldDiscardUpdateAfterDelete() {
        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 9, "Lovejoy"));

        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        // delete a row before the change
        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 2));

        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 8));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataChangeLayer.getDataValueByPosition(1, 9));
        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(1, 8).hasLabel(DataChangeLayer.DIRTY));
        assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1));
        assertTrue("Row 8 is not dirty", this.dataChangeLayer.isRowDirty(8));
        assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 8));

        assertFalse("changed columns are empty", this.updateHandler.changedColumns.isEmpty());
        assertFalse("changed rows are empty", this.updateHandler.changedRows.isEmpty());
        assertFalse("changes are empty", this.updateHandler.dataChanges.isEmpty());
        assertFalse("tracked changes are empty", this.dataChangeLayer.dataChanges.isEmpty());

        // now discard and check that previous state is restored correctly
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 9).hasLabel(DataChangeLayer.DIRTY));
        assertFalse("Column 1 is dirty", this.dataChangeLayer.isColumnDirty(1));
        assertFalse("Row 9 is dirty", this.dataChangeLayer.isRowDirty(9));
        assertFalse("Cell is dirty", this.dataChangeLayer.isCellDirty(1, 9));

        assertTrue("changed columns are not empty", this.updateHandler.changedColumns.isEmpty());
        assertTrue("changed rows are not empty", this.updateHandler.changedRows.isEmpty());
        assertTrue("changes are not empty", this.updateHandler.dataChanges.isEmpty());
        assertTrue("tracked changes are not empty", this.dataChangeLayer.dataChanges.isEmpty());
    }

    @Test
    public void shouldDiscardInsertAfterDelete() {
        assertEquals(18, this.dataModel.size());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date())));

        assertEquals(19, this.dataModel.size());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Wiggum", this.dataLayer.getDataValue(1, 10));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 11));

        // delete a row before the change
        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 2));

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 8));
        assertEquals("Wiggum", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(1, 9).hasLabel(DataChangeLayer.DIRTY));
        assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1));
        assertTrue("Row 9 is not dirty", this.dataChangeLayer.isRowDirty(9));
        assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 9));

        assertTrue("changed columns are empty", this.updateHandler.changedColumns.isEmpty());
        assertTrue("changed rows are empty", this.updateHandler.changedRows.isEmpty());
        assertTrue("changes are empty", this.updateHandler.dataChanges.isEmpty());
        assertFalse("changed columns are empty", this.insertHandler.dataChanges.isEmpty());
        assertFalse("tracked changes are empty", this.dataChangeLayer.dataChanges.isEmpty());

        // now discard and check that previous state is restored correctly
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 9).hasLabel(DataChangeLayer.DIRTY));
        assertFalse("Column 1 is dirty", this.dataChangeLayer.isColumnDirty(1));
        assertFalse("Row 9 is dirty", this.dataChangeLayer.isRowDirty(9));
        assertFalse("Cell is dirty", this.dataChangeLayer.isCellDirty(1, 9));

        assertTrue("changed columns are not empty", this.updateHandler.changedColumns.isEmpty());
        assertTrue("changed rows are not empty", this.updateHandler.changedRows.isEmpty());
        assertTrue("changes are not empty", this.updateHandler.dataChanges.isEmpty());
        assertTrue("changed columns are empty", this.insertHandler.dataChanges.isEmpty());
        assertTrue("tracked changes are not empty", this.dataChangeLayer.dataChanges.isEmpty());
    }

    @Test
    public void shouldDiscardInsertAfterInsert() {
        assertEquals(18, this.dataModel.size());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date())));

        assertEquals(19, this.dataModel.size());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Wiggum", this.dataLayer.getDataValue(1, 10));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 11));

        // insert a row before the change
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 2, new Person(41, "Clancy", "Wiggum", Gender.MALE, false, new Date())));

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 10));
        assertEquals("Wiggum", this.dataLayer.getDataValue(1, 11));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 12));

        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(1, 11).hasLabel(DataChangeLayer.DIRTY));
        assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1));
        assertTrue("Row 9 is not dirty", this.dataChangeLayer.isRowDirty(11));
        assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 11));

        assertTrue("changed columns are empty", this.updateHandler.changedColumns.isEmpty());
        assertTrue("changed rows are empty", this.updateHandler.changedRows.isEmpty());
        assertTrue("changes are empty", this.updateHandler.dataChanges.isEmpty());
        assertFalse("changed columns are empty", this.insertHandler.dataChanges.isEmpty());
        assertFalse("tracked changes are empty", this.dataChangeLayer.dataChanges.isEmpty());

        // now discard and check that previous state is restored correctly
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 9).hasLabel(DataChangeLayer.DIRTY));
        assertFalse("Column 1 is dirty", this.dataChangeLayer.isColumnDirty(1));
        assertFalse("Row 9 is dirty", this.dataChangeLayer.isRowDirty(9));
        assertFalse("Cell is dirty", this.dataChangeLayer.isCellDirty(1, 9));

        assertTrue("changed columns are not empty", this.updateHandler.changedColumns.isEmpty());
        assertTrue("changed rows are not empty", this.updateHandler.changedRows.isEmpty());
        assertTrue("changes are not empty", this.updateHandler.dataChanges.isEmpty());
        assertTrue("changed columns are empty", this.insertHandler.dataChanges.isEmpty());
        assertTrue("tracked changes are not empty", this.dataChangeLayer.dataChanges.isEmpty());
    }

    @Test
    public void shouldDiscardUpdateAfterInsert() {
        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        this.dataChangeLayer.doCommand(new UpdateDataCommand(this.dataChangeLayer, 1, 9, "Lovejoy"));

        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        // add a row before the change
        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 2, new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date())));

        assertEquals("Lovejoy", this.dataLayer.getDataValue(1, 10));
        assertEquals("Lovejoy", this.dataChangeLayer.getDataValueByPosition(1, 10));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 11));
        assertEquals("Flanders", this.dataChangeLayer.getDataValueByPosition(1, 11));
        assertTrue("Dirty label not set", this.dataChangeLayer.getConfigLabelsByPosition(1, 10).hasLabel(DataChangeLayer.DIRTY));
        assertTrue("Column 1 is not dirty", this.dataChangeLayer.isColumnDirty(1));
        assertTrue("Row 1 is not dirty", this.dataChangeLayer.isRowDirty(10));
        assertTrue("Cell is not dirty", this.dataChangeLayer.isCellDirty(1, 10));

        assertFalse("changed columns are empty", this.updateHandler.changedColumns.isEmpty());
        assertFalse("changed rows are empty", this.updateHandler.changedRows.isEmpty());
        assertFalse("changes are empty", this.updateHandler.dataChanges.isEmpty());
        assertFalse("tracked changes are not empty", this.dataChangeLayer.dataChanges.isEmpty());

        // now discard and check that previous state is restored correctly
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));
        assertFalse("Dirty label set", this.dataChangeLayer.getConfigLabelsByPosition(1, 9).hasLabel(DataChangeLayer.DIRTY));
        assertFalse("Column 1 is dirty", this.dataChangeLayer.isColumnDirty(1));
        assertFalse("Row 9 is dirty", this.dataChangeLayer.isRowDirty(9));
        assertFalse("Cell is dirty", this.dataChangeLayer.isCellDirty(1, 9));

        assertTrue("changed columns are not empty", this.updateHandler.changedColumns.isEmpty());
        assertTrue("changed rows are not empty", this.updateHandler.changedRows.isEmpty());
        assertTrue("changes are not empty", this.updateHandler.dataChanges.isEmpty());
        assertTrue("tracked changes are not empty", this.dataChangeLayer.dataChanges.isEmpty());
    }

    @Test
    public void shouldDiscardDeleteInsertedObject() {
        assertEquals(18, this.dataModel.size());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        this.dataChangeLayer.doCommand(new RowInsertCommand<>(this.dataChangeLayer, 10, new Person(42, "Ralph", "Wiggum", Gender.MALE, false, new Date())));

        assertEquals(19, this.dataModel.size());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Wiggum", this.dataLayer.getDataValue(1, 10));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 11));

        // delete a row before the change
        this.dataChangeLayer.doCommand(new RowDeleteCommand(this.dataChangeLayer, 10));

        assertEquals(18, this.dataModel.size());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        // no row dirty
        for (int row = 0; row < this.dataModel.size(); row++) {
            assertFalse("Row " + row + " is dirty", this.dataChangeLayer.isRowDirty(row));
        }

        assertTrue("changed columns are empty", this.updateHandler.changedColumns.isEmpty());
        assertTrue("changed rows are empty", this.updateHandler.changedRows.isEmpty());
        assertTrue("changes are empty", this.updateHandler.dataChanges.isEmpty());
        // now empty because the key handler specifies key updates and the
        // inserted value is removed
        assertTrue("insert handler changes are not empty", this.insertHandler.dataChanges.isEmpty());
        assertFalse("delete handler changes are empty", this.deleteHandler.dataChanges.isEmpty());
        assertFalse("tracked changes are empty", this.dataChangeLayer.dataChanges.isEmpty());

        // now discard and check that previous state is restored correctly
        this.dataChangeLayer.doCommand(new DiscardDataChangesCommand());

        assertEquals("Simpson", this.dataLayer.getDataValue(1, 9));
        assertEquals("Flanders", this.dataLayer.getDataValue(1, 10));

        // no row dirty
        for (int row = 0; row < this.dataModel.size(); row++) {
            assertFalse("Row " + row + " is dirty", this.dataChangeLayer.isRowDirty(row));
        }

        assertTrue("changed columns are not empty", this.updateHandler.changedColumns.isEmpty());
        assertTrue("changed rows are not empty", this.updateHandler.changedRows.isEmpty());
        assertTrue("changes are not empty", this.updateHandler.dataChanges.isEmpty());
        assertTrue("insert handler changes are not empty", this.insertHandler.dataChanges.isEmpty());
        assertTrue("delete handler changes are not empty", this.deleteHandler.dataChanges.isEmpty());
        assertTrue("tracked changes are not empty", this.dataChangeLayer.dataChanges.isEmpty());
    }

}
