/*******************************************************************************
 * Copyright (c) 2008, 2012 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.common.ui.tests.internal.swt;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jpt.common.ui.internal.swt.ColumnAdapter;
import org.eclipse.jpt.common.ui.internal.swt.TableModelAdapter;
import org.eclipse.jpt.common.ui.internal.swt.TableModelAdapter.SelectionChangeEvent;
import org.eclipse.jpt.common.ui.internal.swt.TableModelAdapter.SelectionChangeListener;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.iterators.CloneListIterator;
import org.eclipse.jpt.common.utility.internal.model.AbstractModel;
import org.eclipse.jpt.common.utility.internal.model.value.ListAspectAdapter;
import org.eclipse.jpt.common.utility.internal.model.value.PropertyAspectAdapter;
import org.eclipse.jpt.common.utility.internal.model.value.PropertyCollectionValueModelAdapter;
import org.eclipse.jpt.common.utility.internal.model.value.SimpleCollectionValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.SimplePropertyValueModel;
import org.eclipse.jpt.common.utility.model.value.CollectionValueModel;
import org.eclipse.jpt.common.utility.model.value.ListValueModel;
import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

@SuppressWarnings("nls")
public class TableModelAdapterTest {

	private Shell shell;
	private ModifiablePropertyValueModel<Manager> subjectHolder;

	private ColumnAdapter<Employee> buildColumnAdapter() {
		return new TableColumnAdapter();
	}

	private ModifiablePropertyValueModel<Employee> buildEmployeeHolder() {
		return new SimplePropertyValueModel<Employee>();
	}

	private SimpleCollectionValueModel<Employee> buildEmployeeHolders() {
		return new SimpleCollectionValueModel<Employee>();
	}

	private ListValueModel<Employee> buildEmployeeListHolder() {
		return new ListAspectAdapter<Manager, Employee>(subjectHolder, Manager.EMPLOYEES_LIST) {
			@Override
			protected ListIterator<Employee> listIterator_() {
				return subject.employees();
			}

			@Override
			protected int size_() {
				return subject.employeesSize();
			}
		};
	}

	private ITableLabelProvider buildLabelProvider() {
		return new TableLabelProvider();
	}

	private SelectionChangeListener<Employee> buildSelectionChangeListener(final Collection<Employee> employees) {
		return new SelectionChangeListener<Employee>() {
			public void selectionChanged(SelectionChangeEvent<Employee> e) {
				employees.clear();
				CollectionTools.addAll(employees, e.selection());
			}
		};
	}

	private ModifiablePropertyValueModel<Manager> buildSubjectHolder() {
		return new SimplePropertyValueModel<Manager>();
	}

	@Before
	public void setUp() throws Exception {

		shell         = new Shell(Display.getCurrent());
		subjectHolder = buildSubjectHolder();
	}

	@After
	public void tearDown() throws Exception {

		if (!shell.isDisposed()) {
			shell.dispose();
		}

		shell         = null;
		subjectHolder = null;
	}

	@Test
	public void testChanged() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create Employees
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		String expectedName3    = "Dali_3";
		String expectedManager3 = "WTP_3";
		String expectedTitle3   = "plug-in_3";

		Employee employee1 = new Employee(expectedName1, expectedTitle1, expectedManager1);
		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		Employee employee3 = new Employee(expectedName3, expectedTitle3, expectedManager3);

		manager.addEmployee(employee1);
		manager.addEmployee(employee2);
		manager.addEmployee(employee3);

		// Make sure the Table was populated
		Assert.assertEquals("The number of TableItems should be 3", 3, table.getItemCount());

		// Change the list of Employees
		ArrayList<Employee> employees = new ArrayList<Employee>(3);
		employees.add(employee3);
		employees.add(employee2);
		employees.add(employee1);
		manager.changeEmployees(employees);

		Assert.assertEquals("The number of TableItems should be 3", 3, table.getItemCount());

		testTableItemProperties(table, 0, expectedName3, expectedManager3, expectedTitle3);
		testTableItemProperties(table, 1, expectedName2, expectedManager2, expectedTitle2);
		testTableItemProperties(table, 2, expectedName1, expectedManager1, expectedTitle1);
	}

	@Test
	public void testCleared() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create Employees
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		String expectedName3    = "Dali_3";
		String expectedManager3 = "WTP_3";
		String expectedTitle3   = "plug-in_3";

		Employee employee1 = new Employee(expectedName1, expectedTitle1, expectedManager1);
		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		Employee employee3 = new Employee(expectedName3, expectedTitle3, expectedManager3);

		manager.addEmployee(employee1);
		manager.addEmployee(employee2);
		manager.addEmployee(employee3);

		// Make sure the Table was populated
		Assert.assertEquals("The number of TableItems should be 3", 3, table.getItemCount());

		// Test removing them all
		manager.removeAllEmployees();

		Assert.assertEquals("The list holder should have been cleared", 0, listHolder.size());
		Assert.assertEquals("The Table should have been cleared", 0, table.getItemCount());
	}

	@Test
	public void testItemAdded() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create a new Employee
		String expectedName    = "Dali";
		String expectedManager = "WTP";
		String expectedTitle   = "plug-in";

		Employee employee = manager.addEmployee(expectedName, expectedTitle, expectedManager);
		Assert.assertNotNull("The new Employee was not created", employee);

		// Retrieve the TableItem representing the new Employee
		int index = tableModel.indexOf(employee);
		Assert.assertEquals("The new Employee was not added to the table model", 0, index);
		Assert.assertEquals("The number of TableItem should be 1", 1, table.getItemCount());

		testTableItemProperties(table, index, expectedName, expectedManager, expectedTitle);
	}

	@Test
	public void testItemMoved() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create Employees
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		String expectedName3    = "Dali_3";
		String expectedManager3 = "WTP_3";
		String expectedTitle3   = "plug-in_3";

		Employee employee1 = new Employee(expectedName1, expectedTitle1, expectedManager1);
		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		Employee employee3 = new Employee(expectedName3, expectedTitle3, expectedManager3);

		manager.addEmployee(employee1);
		manager.addEmployee(employee2);
		manager.addEmployee(employee3);

		// Make sure the Employees were added to the Table
		Assert.assertEquals("The number of TableItem should be 3", 3, table.getItemCount());

		// Move an Employee up the list
		manager.moveEmployeeUp(employee2);

		int index1 = tableModel.indexOf(employee1);
		Assert.assertEquals("The Employee 1 was not moved in the table model", 1, index1);

		int index2 = tableModel.indexOf(employee2);
		Assert.assertEquals("The Employee 2 was not moved in the table model", 0, index2);

		int index3 = tableModel.indexOf(employee3);
		Assert.assertEquals("The Employee 3 should not have been moved in the table model", 2, index3);

		testTableItemProperties(table, index1, expectedName1, expectedManager1, expectedTitle1);
		testTableItemProperties(table, index2, expectedName2, expectedManager2, expectedTitle2);
		testTableItemProperties(table, index3, expectedName3, expectedManager3, expectedTitle3);

		// Move an Employee down the list
		manager.moveEmployeeDown(employee1);

		index1 = tableModel.indexOf(employee1);
		Assert.assertEquals("The Employee 1 should not have been moved in the table model", 2, index1);

		index2 = tableModel.indexOf(employee2);
		Assert.assertEquals("The Employee 2 was not moved in the table model", 0, index2);

		index3 = tableModel.indexOf(employee3);
		Assert.assertEquals("The Employee 3 was not moved in the table model", 1, index3);

		testTableItemProperties(table, index1, expectedName1, expectedManager1, expectedTitle1);
		testTableItemProperties(table, index2, expectedName2, expectedManager2, expectedTitle2);
		testTableItemProperties(table, index3, expectedName3, expectedManager3, expectedTitle3);
	}

	@Test
	public void testItemRemoved() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create a new Employee
		String expectedName    = "Dali";
		String expectedManager = "WTP";
		String expectedTitle   = "plug-in";

		Employee employee = manager.addEmployee(expectedName, expectedTitle, expectedManager);
		Assert.assertNotNull("The new Employee was not created", employee);
		Assert.assertEquals("The number of TableItem should be 1", 1, table.getItemCount());

		// Make sure it was added to the model
		int index = tableModel.indexOf(employee);
		Assert.assertEquals("The new Employee was not added to the table model", 0, index);
		testTableItemProperties(table, index, expectedName, expectedManager, expectedTitle);

		// Retrieve the TableItem representing the new Employee
		TableItem tableItem = table.getItem(index);
		Assert.assertNotNull("No TableItem was found for the new Employee", tableItem);

		// Now test the item being removed
		manager.removeEmployee(employee);
		index = tableModel.indexOf(employee);
		Assert.assertEquals("The Employee was not removed from the table model", -1, index);
		Assert.assertEquals("The number of TableItem should be 0", 0, table.getItemCount());
	}

	@Test
	public void testItemReplaced() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create a new Employee
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		Employee employee1 = manager.addEmployee(expectedName1, expectedTitle1, expectedManager1);
		Assert.assertNotNull("The new Employee was not created", employee1);

		// Make sure it was added to the model
		int index1 = tableModel.indexOf(employee1);
		Assert.assertEquals("The new Employee was not added to the table model", 0, index1);
		Assert.assertEquals("The number of TableItem should be 1", 1, table.getItemCount());

		// Retrieve the TableItem representing the new Employee
		TableItem tableItem = table.getItem(index1);
		Assert.assertNotNull("No TableItem was found for the new Employee", tableItem);

		testTableItemProperties(table, index1, expectedName1, expectedManager1, expectedTitle1);

		// Replace the Employee
		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		manager.replace(employee1, employee2);

		int index2 = tableModel.indexOf(employee2);
		Assert.assertSame("The Employee that got replaced should be at index " + index1, index1, index2);
		Assert.assertEquals("The number of TableItem should be 1", 1, table.getItemCount());

		testTableItemProperties(table, index2, expectedName2, expectedManager2, expectedTitle2);
	}

	@Test
	public void testItemsAdded() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create Employees
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		String expectedName3    = "Dali_3";
		String expectedManager3 = "WTP_3";
		String expectedTitle3   = "plug-in_3";

		Employee employee1 = new Employee(expectedName1, expectedTitle1, expectedManager1);
		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		Employee employee3 = new Employee(expectedName3, expectedTitle3, expectedManager3);

		manager.addEmployee(employee1);
		manager.addEmployee(employee2);
		manager.addEmployee(employee3);

		// Retrieve the TableItems representing the employees
		Assert.assertEquals("The number of TableItem should be 3", 3, table.getItemCount());

		int index = tableModel.indexOf(employee1);
		Assert.assertEquals("The Employee 1 was not added to the table model", 0, index);

		index = tableModel.indexOf(employee2);
		Assert.assertEquals("The Employee 2 was not added to the table model", 1, index);

		index = tableModel.indexOf(employee3);
		Assert.assertEquals("The Employee 3 was not added to the table model", 2, index);

		// Make sure the TableItem was correctly populated
		testTableItemProperties(table, 0, expectedName1, expectedManager1, expectedTitle1);
		testTableItemProperties(table, 1, expectedName2, expectedManager2, expectedTitle2);
		testTableItemProperties(table, 2, expectedName3, expectedManager3, expectedTitle3);
	}

	@Test
	public void testItemsMoved() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create Employees
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		String expectedName3    = "Dali_3";
		String expectedManager3 = "WTP_3";
		String expectedTitle3   = "plug-in_3";

		String expectedName4    = "Dali_4";
		String expectedManager4 = "WTP_4";
		String expectedTitle4   = "plug-in_4";

		String expectedName5    = "Dali_5";
		String expectedManager5 = "WTP_5";
		String expectedTitle5   = "plug-in_5";

		String expectedName6    = "Dali_6";
		String expectedManager6 = "WTP_6";
		String expectedTitle6   = "plug-in_6";

		Employee employee1 = new Employee(expectedName1, expectedTitle1, expectedManager1);
		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		Employee employee3 = new Employee(expectedName3, expectedTitle3, expectedManager3);
		Employee employee4 = new Employee(expectedName4, expectedTitle4, expectedManager4);
		Employee employee5 = new Employee(expectedName5, expectedTitle5, expectedManager5);
		Employee employee6 = new Employee(expectedName6, expectedTitle6, expectedManager6);

		manager.addEmployee(employee1);
		manager.addEmployee(employee2);
		manager.addEmployee(employee3);
		manager.addEmployee(employee4);
		manager.addEmployee(employee5);
		manager.addEmployee(employee6);

		// Make sure the Employees were added to the Table
		Assert.assertEquals("The number of TableItem should be 6", 6, table.getItemCount());

		// Move an Employee up the list
		ArrayList<Employee> employees = new ArrayList<Employee>(3);
		employees.add(employee3);
		employees.add(employee4);
		employees.add(employee5);
		manager.moveEmployees(employees, 0);

		int index1 = tableModel.indexOf(employee1);
		int index2 = tableModel.indexOf(employee2);
		int index3 = tableModel.indexOf(employee3);
		int index4 = tableModel.indexOf(employee4);
		int index5 = tableModel.indexOf(employee5);
		int index6 = tableModel.indexOf(employee6);

		Assert.assertEquals("The Employee 1 is not at the right index", 3, index1);
		Assert.assertEquals("The Employee 2 is not at the right index", 4, index2);
		Assert.assertEquals("The Employee 3 is not at the right index", 0, index3);
		Assert.assertEquals("The Employee 4 is not at the right index", 1, index4);
		Assert.assertEquals("The Employee 5 is not at the right index", 2, index5);
		Assert.assertEquals("The Employee 6 is not at the right index", 5, index6);

		testTableItemProperties(table, index1, expectedName1, expectedManager1, expectedTitle1);
		testTableItemProperties(table, index2, expectedName2, expectedManager2, expectedTitle2);
		testTableItemProperties(table, index3, expectedName3, expectedManager3, expectedTitle3);
		testTableItemProperties(table, index4, expectedName4, expectedManager4, expectedTitle4);
		testTableItemProperties(table, index5, expectedName5, expectedManager5, expectedTitle5);
		testTableItemProperties(table, index6, expectedName6, expectedManager6, expectedTitle6);

		// Move an Employee down the list
		employees = new ArrayList<Employee>(2);
		employees.add(employee1);
		employees.add(employee2);
		manager.moveEmployees(employees, 4);

		index1 = tableModel.indexOf(employee1);
		index2 = tableModel.indexOf(employee2);
		index3 = tableModel.indexOf(employee3);
		index4 = tableModel.indexOf(employee4);
		index5 = tableModel.indexOf(employee5);
		index6 = tableModel.indexOf(employee6);

		Assert.assertEquals("The Employee 1 is not at the right index", 4, index1);
		Assert.assertEquals("The Employee 2 is not at the right index", 5, index2);
		Assert.assertEquals("The Employee 3 is not at the right index", 0, index3);
		Assert.assertEquals("The Employee 4 is not at the right index", 1, index4);
		Assert.assertEquals("The Employee 5 is not at the right index", 2, index5);
		Assert.assertEquals("The Employee 6 is not at the right index", 3, index6);

		testTableItemProperties(table, index1, expectedName1, expectedManager1, expectedTitle1);
		testTableItemProperties(table, index2, expectedName2, expectedManager2, expectedTitle2);
		testTableItemProperties(table, index3, expectedName3, expectedManager3, expectedTitle3);
		testTableItemProperties(table, index4, expectedName4, expectedManager4, expectedTitle4);
		testTableItemProperties(table, index5, expectedName5, expectedManager5, expectedTitle5);
		testTableItemProperties(table, index6, expectedName6, expectedManager6, expectedTitle6);
	}

	@Test
	public void testItemsRemoved() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create Employees
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		String expectedName3    = "Dali_3";
		String expectedManager3 = "WTP_3";
		String expectedTitle3   = "plug-in_3";

		Employee employee1 = new Employee(expectedName1, expectedTitle1, expectedManager1);
		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		Employee employee3 = new Employee(expectedName3, expectedTitle3, expectedManager3);

		manager.addEmployee(employee1);
		manager.addEmployee(employee2);
		manager.addEmployee(employee3);

		// Retrieve the TableItems representing the employees
		Assert.assertEquals("The number of TableItem should be 3", 3, table.getItemCount());

		int index = tableModel.indexOf(employee1);
		Assert.assertEquals("The Employee 1 was not added to the table model", 0, index);

		index = tableModel.indexOf(employee2);
		Assert.assertEquals("The Employee 2 was not added to the table model", 1, index);

		index = tableModel.indexOf(employee3);
		Assert.assertEquals("The Employee 3 was not added to the table model", 2, index);

		// Remove 2 items
		ArrayList<Employee> employees = new ArrayList<Employee>(2);
		employees.add(employee1);
		employees.add(employee3);
		manager.removeEmployees(employees);

		Assert.assertEquals("The number of TableItem should be 1", 1, table.getItemCount());
	}

	@Test
	public void testPropertyChanged() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		ModifiablePropertyValueModel<Employee> selectedItemHolder = buildEmployeeHolder();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create a new Employee
		String expectedName    = "Dali";
		String expectedManager = "WTP";
		String expectedTitle   = "plug-in";

		Employee employee = manager.addEmployee(expectedName, expectedTitle, expectedManager);
		Assert.assertNotNull("The new Employee was not created", employee);

		// Make sure it was added to the model
		int index = tableModel.indexOf(employee);
		Assert.assertEquals("The new Employee was not added to the table model", 0, index);
		Assert.assertEquals("The number of TableItem should be 1", 1, table.getItemCount());

		// Retrieve the TableItem representing the new Employee
		TableItem tableItem = table.getItem(index);
		Assert.assertNotNull("No TableItem was found for the new Employee", tableItem);

		// Name property
		String actualName = tableItem.getText(TableColumnAdapter.NAME_COLUMN);
		Assert.assertEquals("TableItem[NAME_COLUMN] was not set correctly", expectedName, actualName);

		expectedName = "Jpt";
		employee.setName(expectedName);

		actualName = tableItem.getText(TableColumnAdapter.NAME_COLUMN);
		Assert.assertEquals("TableItem[NAME_COLUMN] was not set correctly", expectedName, actualName);

		// Manager property
		String actualManager = tableItem.getText(TableColumnAdapter.MANAGER_COLUMN);
		Assert.assertEquals("TableItem[MANAGER_COLUMN] was not set correctly", expectedManager, actualManager);

		expectedManager = "boss";
		employee.setManager(expectedManager);

		actualManager = tableItem.getText(TableColumnAdapter.MANAGER_COLUMN);
		Assert.assertEquals("TableItem[MANAGER_COLUMN] was not set correctly", expectedManager, actualManager);

		// Title property
		String actualTitle = tableItem.getText(TableColumnAdapter.TITLE_COLUMN);
		Assert.assertEquals("TableItem[TITLE_COLUMN] was not set correctly", expectedTitle, actualTitle);

		expectedTitle = "EclipseLink";
		employee.setTitle(expectedTitle);

		actualTitle = tableItem.getText(TableColumnAdapter.TITLE_COLUMN);
		Assert.assertEquals("TableItem[TITLE_COLUMN] was not set correctly", expectedTitle, actualTitle);
	}

	@Test
	public void testSelectedItemsAddedRemoved() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		SimpleCollectionValueModel<Employee> selectedItemsHolder = buildEmployeeHolders();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemsHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create Employees
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		String expectedName3    = "Dali_3";
		String expectedManager3 = "WTP_3";
		String expectedTitle3   = "plug-in_3";

		Employee employee1 = new Employee(expectedName1, expectedTitle1, expectedManager1);
		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		Employee employee3 = new Employee(expectedName3, expectedTitle3, expectedManager3);

		manager.addEmployee(employee1);
		manager.addEmployee(employee2);
		manager.addEmployee(employee3);

		// Test adding selected items
		ArrayList<Employee> employees = new ArrayList<Employee>(2);
		employees.add(employee1);
		employees.add(employee3);
		selectedItemsHolder.addAll(employees);

		Collection<Employee> actualEmployees = tableModel.selectedItems();
		Assert.assertNotNull("The collection of selected items can't be null", actualEmployees);
		Assert.assertEquals("The count of selected items should be 2", 2, actualEmployees.size());

		actualEmployees.remove(employee1);
		actualEmployees.remove(employee3);

		Assert.assertTrue("The selected items was not retrieved correctly", actualEmployees.isEmpty());

		// Test removing selected items
		selectedItemsHolder.remove(employee1);

		actualEmployees = tableModel.selectedItems();
		Assert.assertNotNull("The collection of selected items can't be null", actualEmployees);
		Assert.assertEquals("The count of selected items should be 1", 1, actualEmployees.size());

		actualEmployees.remove(employee3);

		Assert.assertTrue("The selected items was not retrieved correctly", actualEmployees.isEmpty());
	}

	@Test
	public void testSelectedItemsCleared() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		ListValueModel<Employee> listHolder = buildEmployeeListHolder();
		SimpleCollectionValueModel<Employee> selectedItemsHolder = buildEmployeeHolders();

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			listHolder,
			selectedItemsHolder,
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		// Create Employees
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		String expectedName3    = "Dali_3";
		String expectedManager3 = "WTP_3";
		String expectedTitle3   = "plug-in_3";

		Employee employee1 = new Employee(expectedName1, expectedTitle1, expectedManager1);
		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		Employee employee3 = new Employee(expectedName3, expectedTitle3, expectedManager3);

		manager.addEmployee(employee1);
		manager.addEmployee(employee2);
		manager.addEmployee(employee3);

		// Test adding selected items
		ArrayList<Employee> employees = new ArrayList<Employee>(2);
		employees.add(employee1);
		employees.add(employee3);
		selectedItemsHolder.addAll(employees);

		Collection<Employee> actualEmployees = tableModel.selectedItems();
		Assert.assertNotNull("The collection of selected items can't be null", actualEmployees);
		Assert.assertEquals("The count of selected items should be 2", 2, actualEmployees.size());

		actualEmployees.remove(employee1);
		actualEmployees.remove(employee3);
		Assert.assertTrue("The selected items was not retrieved correctly", actualEmployees.isEmpty());

		// Test removing selected items
		selectedItemsHolder.clear();

		actualEmployees = tableModel.selectedItems();
		Assert.assertNotNull("The collection of selected items can't be null", actualEmployees);
		Assert.assertEquals("The count of selected items should be ", 0, actualEmployees.size());
	}

	@Test
	public void testSelectionChangeListener() {

		Table table = new Table(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		Manager manager = new Manager();
		subjectHolder.setValue(manager);

		TableModel tableModel = new TableModel(
			buildEmployeeListHolder(),
			buildEmployeeHolder(),
			table,
			buildColumnAdapter(),
			buildLabelProvider()
		);

		Collection<Employee> employees = new ArrayList<Employee>();
		tableModel.addSelectionChangeListener(buildSelectionChangeListener(employees));

		// Create Employees
		String expectedName1    = "Dali_1";
		String expectedManager1 = "WTP_1";
		String expectedTitle1   = "plug-in_1";

		String expectedName2    = "Dali_2";
		String expectedManager2 = "WTP_2";
		String expectedTitle2   = "plug-in_2";

		String expectedName3    = "Dali_3";
		String expectedManager3 = "WTP_3";
		String expectedTitle3   = "plug-in_3";

		Employee employee1 = new Employee(expectedName1, expectedTitle1, expectedManager1);
		Employee employee2 = new Employee(expectedName2, expectedTitle2, expectedManager2);
		Employee employee3 = new Employee(expectedName3, expectedTitle3, expectedManager3);

		manager.addEmployee(employee1);
		manager.addEmployee(employee2);
		manager.addEmployee(employee3);

		// Test adding selected items
		table.setSelection(new int[] { 0, 2 });

		// It seems a manual selection doesn't send any selection event
		tableModel.tableSelectionChanged(null);

		Assert.assertNotNull("The collection of selected items can't be null", employees);
		Assert.assertEquals("The count of selected items should be 2", 2, employees.size());

		employees.remove(employee1);
		employees.remove(employee3);
		Assert.assertTrue("The selected items was not retrieved correctly", employees.isEmpty());

		// Test adding selected items
		employees.add(employee1);
		employees.add(employee3);
		table.deselectAll();

		// It seems a manual selection doesn't send any selection event
		tableModel.tableSelectionChanged(null);

		Assert.assertNotNull("The collection of selected items can't be null", employees);
		Assert.assertEquals("The count of selected items should be 0", 0, employees.size());
	}

	private void testTableItemProperties(Table table,
	                                     int index,
	                                     String expectedName,
	                                     String expectedManager,
	                                     String expectedTitle)
	{
		TableItem tableItem = table.getItem(index);
		Assert.assertNotNull("No TableItem was found for the Employee", tableItem);

		String actualName = tableItem.getText(TableColumnAdapter.NAME_COLUMN);
		Assert.assertEquals("TableItem[NAME_COLUMN] was not set correctly", expectedName, actualName);

		String actualTitle = tableItem.getText(TableColumnAdapter.TITLE_COLUMN);
		Assert.assertEquals("TableItem[TITLE_COLUMN] was not set correctly", expectedTitle, actualTitle);

		String actualManager = tableItem.getText(TableColumnAdapter.MANAGER_COLUMN);
		Assert.assertEquals("TableItem[MANAGER_COLUMN] was not set correctly", expectedManager, actualManager);
	}

	private class Employee extends AbstractModel {

		private String manager;
		private String name;
		private String title;

		static final String MANAGER_PROPERTY = "manager";
		static final String NAME_PROPERTY = "name";
		static final String TITLE_PROPERTY = "title";

		Employee(String name, String title, String manager) {
			super();

			this.name    = name;
			this.title   = title;
			this.manager = manager;
		}

		String getManager() {
			return manager;
		}

		String getName() {
			return name;
		}

		String getTitle() {
			return title;
		}

		void setManager(String manager) {
			String oldManager = this.manager;
			this.manager = manager;
			firePropertyChanged(MANAGER_PROPERTY, oldManager, manager);
		}

		void setName(String name) {
			String oldName = this.name;
			this.name = name;
			firePropertyChanged(NAME_PROPERTY, oldName, name);
		}

		void setTitle(String title) {
			String oldTitle = this.title;
			this.title = title;
			firePropertyChanged(TITLE_PROPERTY, oldTitle, title);
		}
	}

	private class Manager extends AbstractModel {

		private List<Employee> employees;

		static final String EMPLOYEES_LIST = "employees";

		Manager() {
			super();
			employees = new ArrayList<Employee>();
		}

		Employee addEmployee(Employee employee) {
			addItemToList(employee, employees, EMPLOYEES_LIST);
			return employee;
		}

		Employee addEmployee(String name, String title, String manager) {
			Employee employee = new Employee(name, title, manager);
			return addEmployee(employee);
		}

		void changeEmployees(List<Employee> newEmployees) {
			this.synchronizeList(newEmployees, this.employees, EMPLOYEES_LIST);
		}

		ListIterator<Employee> employees() {
			return new CloneListIterator<Employee>(employees);
		}

		int employeesSize() {
			return employees.size();
		}

		void moveEmployeeDown(Employee employee) {
			int index = employees.indexOf(employee);
			moveItemInList(index + 1, index, employees, EMPLOYEES_LIST);
		}

		void moveEmployees(Collection<Employee> employees, int targetIndex) {

			int sourceIndex = Integer.MAX_VALUE;

			for (Employee employee : employees) {
				sourceIndex = Math.min(sourceIndex, this.employees.indexOf(employee));
			}

			moveItemsInList(
				targetIndex,
				sourceIndex,
				employees.size(),
				this.employees,
				EMPLOYEES_LIST
			);
		}

		void moveEmployeeUp(Employee employee) {
			int index = employees.indexOf(employee);
			moveItemInList(index - 1, index, employees, EMPLOYEES_LIST);
		}

		void removeAllEmployees() {
			clearList(employees, EMPLOYEES_LIST);
		}

		void removeEmployee(Employee employee) {
			removeItemFromList(employee, employees, EMPLOYEES_LIST);
		}

		void removeEmployees(Collection<Employee> employees) {
			removeItemsFromList(employees.iterator(), this.employees, EMPLOYEES_LIST);
		}

		void replace(Employee oldEmployee, Employee newEmployee) {
			replaceItemInList(oldEmployee, newEmployee, employees, EMPLOYEES_LIST);
		}
	}

	private class TableColumnAdapter implements ColumnAdapter<Employee> {

		static final int COLUMN_COUNT = 3;
		static final int MANAGER_COLUMN = 2;
		static final int NAME_COLUMN = 0;
		static final int TITLE_COLUMN = 1;

		private ModifiablePropertyValueModel<String> buildManagerHolder(Employee subject) {
			return new PropertyAspectAdapter<Employee, String>(Employee.MANAGER_PROPERTY, subject) {
				@Override
				protected String buildValue_() {
					return subject.getManager();
				}

				@Override
				protected void setValue_(String value) {
					subject.setManager(value);
				}
			};
		}

		private ModifiablePropertyValueModel<String> buildNameHolder(Employee subject) {
			return new PropertyAspectAdapter<Employee, String>(Employee.NAME_PROPERTY, subject) {
				@Override
				protected String buildValue_() {
					return subject.getName();
				}

				@Override
				protected void setValue_(String value) {
					subject.setName(value);
				}
			};
		}

		private ModifiablePropertyValueModel<String> buildTitleHolder(Employee subject) {
			return new PropertyAspectAdapter<Employee, String>(Employee.TITLE_PROPERTY, subject) {
				@Override
				protected String buildValue_() {
					return subject.getTitle();
				}

				@Override
				protected void setValue_(String value) {
					subject.setTitle(value);
				}
			};
		}

		public ModifiablePropertyValueModel<?>[] cellModels(Employee subject) {
			ModifiablePropertyValueModel<?>[] holders = new ModifiablePropertyValueModel<?>[3];
			holders[NAME_COLUMN] = buildNameHolder(subject);
			holders[TITLE_COLUMN] = buildTitleHolder(subject);
			holders[MANAGER_COLUMN] = buildManagerHolder(subject);
			return holders;
		}

		public int columnCount() {
			return COLUMN_COUNT;
		}

		public String columnName(int columnIndex) {
			return String.valueOf(columnIndex);
		}
	}

	private class TableLabelProvider extends LabelProvider
	                                 implements ITableLabelProvider {


		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		public String getColumnText(Object element, int columnIndex) {
			Employee employee = (Employee) element;

			if (columnIndex == TableColumnAdapter.NAME_COLUMN) {
				return employee.getName();
			}

			if (columnIndex == TableColumnAdapter.TITLE_COLUMN) {
				return employee.getTitle();
			}

			return employee.getManager();
		}
	}

	private class TableModel extends TableModelAdapter<Employee> {

		TableModel(ListValueModel<Employee> listHolder,
		           CollectionValueModel<Employee> selectedItemsHolder,
		           Table table,
		           ColumnAdapter<Employee> columnAdapter,
		           ITableLabelProvider labelProvider) {

			super(listHolder,
			      selectedItemsHolder,
			      table,
			      columnAdapter,
			      labelProvider);
		}

		TableModel(ListValueModel<Employee> listHolder,
		           ModifiablePropertyValueModel<Employee> selectedItemHolder,
		           Table table,
		           ColumnAdapter<Employee> columnAdapter,
		           ITableLabelProvider labelProvider) {

			super(listHolder,
					new PropertyCollectionValueModelAdapter<Employee>(selectedItemHolder),
			      table,
			      columnAdapter,
			      labelProvider);
		}

		@Override
		protected int indexOf(Employee item) {
			return super.indexOf(item);
		}

		@Override
		protected Collection<Employee> selectedItems() {
			return super.selectedItems();
		}

		@Override
		protected void tableSelectionChanged(SelectionEvent event) {
			super.tableSelectionChanged(event);
		}
	}
}
