/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



package complex.toolkit;

import com.sun.star.awt.XControl;
import com.sun.star.awt.XControlContainer;
import com.sun.star.awt.XControlModel;
import com.sun.star.awt.XToolkit;
import com.sun.star.awt.grid.DefaultGridDataModel;
import com.sun.star.awt.grid.XGridColumn;
import com.sun.star.awt.grid.XGridColumnModel;
import com.sun.star.awt.grid.XGridControl;
import com.sun.star.awt.grid.XGridDataModel;
import com.sun.star.awt.grid.XMutableGridDataModel;
import com.sun.star.awt.grid.XSortableMutableGridDataModel;
import com.sun.star.beans.Pair;
import com.sun.star.beans.XPropertySet;
import com.sun.star.container.ContainerEvent;
import com.sun.star.container.XContainerListener;
import com.sun.star.container.XNameContainer;
import com.sun.star.lang.EventObject;
import com.sun.star.lang.IndexOutOfBoundsException;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XEventListener;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.uno.Exception;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.uno.XInterface;
import com.sun.star.util.XCloneable;
import complex.toolkit.awtgrid.DummyColumn;
import complex.toolkit.awtgrid.TMutableGridDataModel;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.openoffice.test.OfficeConnection;

/** is a unit test for the grid control related implementations
 * @author frank.schoenheit@sun.com
 */
public class GridControl
{
    // -----------------------------------------------------------------------------------------------------------------
    public GridControl()
    {
        m_context = m_connection.getComponentContext();
    }

    // -----------------------------------------------------------------------------------------------------------------
    private static void impl_dispose( final Object... i_components )
    {
        for ( int i=0; i<i_components.length; ++i )
        {
            if ( i_components[i] != null )
            {
                final XComponent component = UnoRuntime.queryInterface( XComponent.class, i_components[i] );
                component.dispose();
            }
        }
    }

    // -----------------------------------------------------------------------------------------------------------------
    private void impl_recreateGridModel() throws Exception
    {
        impl_dispose( m_gridControlModel, m_columnModel, m_dataModel );

        // create a grid control model, and ensure it has a proper data and column model already
        m_gridControlModel = UnoRuntime.queryInterface( XPropertySet.class,
            createInstance( "com.sun.star.awt.grid.UnoControlGridModel" ) );
        assertNotNull( "grid control model does not provide XPropertySet interface", m_gridControlModel );

        // ensure that the model has default column/data models
        m_columnModel = UnoRuntime.queryInterface( XGridColumnModel.class, m_gridControlModel.getPropertyValue( "ColumnModel" ) );
        assertNotNull( "the control model is expected to have an initial column model", m_columnModel );
        final XGridDataModel dataModel = UnoRuntime.queryInterface( XGridDataModel.class, m_gridControlModel.getPropertyValue( "GridDataModel" ) );
        assertNotNull( "the control model is expected to have an initial data model", dataModel );
        m_dataModel = UnoRuntime.queryInterface( XSortableMutableGridDataModel.class,
            dataModel );
        assertNotNull( "the out-of-the-box data model should be mutable and sortable", m_dataModel );
    }

    // -----------------------------------------------------------------------------------------------------------------
    @Test
    public void testGridControlCloning() throws Exception
    {
        impl_recreateGridModel();

        // give the test something to compare, actually
        XGridColumnModel columnModel = UnoRuntime.queryInterface( XGridColumnModel.class,
            m_gridControlModel.getPropertyValue( "ColumnModel" ) );
        columnModel.setDefaultColumns( 10 );

        // clone the grid model
        final XCloneable cloneable = UnoRuntime.queryInterface( XCloneable.class, m_gridControlModel );
        assertNotNull( "all UnoControlModel's are expected to be cloneable", cloneable );

        final XInterface clone = cloneable.createClone();
        final XPropertySet clonedProps = UnoRuntime.queryInterface( XPropertySet.class, clone );

        // TODO: check all those generic properties for equality

        // the data model and the column model should have been cloned, too
        // in particular, the clone should not share the sub models with the orignal
        final XMutableGridDataModel originalDataModel = UnoRuntime.queryInterface( XMutableGridDataModel.class,
            m_gridControlModel.getPropertyValue( "GridDataModel" ) );
        final XMutableGridDataModel clonedDataModel = UnoRuntime.queryInterface( XMutableGridDataModel.class,
            clonedProps.getPropertyValue( "GridDataModel" ) );
        assertFalse( "data model should not be shared after cloning", UnoRuntime.areSame( originalDataModel, clonedDataModel ) );
        impl_assertEquality( originalDataModel, clonedDataModel );

        final XGridColumnModel originalColumnModel = columnModel;
        final XGridColumnModel clonedColumnModel = UnoRuntime.queryInterface( XGridColumnModel.class,
            clonedProps.getPropertyValue( "ColumnModel" ) );
        assertFalse( "column model should not be shared after cloning", UnoRuntime.areSame( originalColumnModel, clonedColumnModel ) );
        impl_assertEquality( originalColumnModel, clonedColumnModel );
    }

    // -----------------------------------------------------------------------------------------------------------------
    @Test
    public void testDisposal() throws Exception
    {
        impl_recreateGridModel();

        final int columnCount = 3;
        m_columnModel.setDefaultColumns( columnCount );

        // add disposal listeners to all columns so far
        final XGridColumn[] columns = m_columnModel.getColumns();
        assertEquals( "creating default columns resulted in unexpected column count", columnCount, columns.length );
        final DisposeListener[] columnListeners = new DisposeListener[columnCount];
        for ( int i=0; i<columnCount; ++i )
            columnListeners[i] = new DisposeListener( columns[i] );

        // add another column, and check that upon removal, it is disposed
        final int newColumnIndex = m_columnModel.addColumn( m_columnModel.createColumn() );
        final DisposeListener columnListener = new DisposeListener( m_columnModel.getColumn( newColumnIndex ) );
        m_columnModel.removeColumn( newColumnIndex );
        assertTrue( "explicit column removal is expected to dispose the column", columnListener.isDisposed() );

        // by definition, the grid control model is the owner of both the column and the data model. So, setting
        // a new column/data model should implicitly dispose the old models
        final DisposeListener oldDataModelListener = new DisposeListener( m_dataModel );
        final DisposeListener oldColumnModelListener = new DisposeListener( m_columnModel );

        final Object newDataModel = createInstance( "com.sun.star.awt.grid.DefaultGridDataModel" );
        final Object newColumnModel = createInstance( "com.sun.star.awt.grid.DefaultGridColumnModel" );
        final DisposeListener newDataModelListener = new DisposeListener( newDataModel );
        final DisposeListener newColumnModelListener = new DisposeListener( newColumnModel );

        m_gridControlModel.setPropertyValue( "GridDataModel", newDataModel );
        assertTrue( "setting a new data model failed", impl_areSameInterface( newDataModel, m_gridControlModel.getPropertyValue( "GridDataModel" ) ) );
        m_gridControlModel.setPropertyValue( "ColumnModel", newColumnModel );
        assertTrue( "setting a new column model failed", impl_areSameInterface( newColumnModel, m_gridControlModel.getPropertyValue( "ColumnModel" ) ) );

        assertTrue( "old data model has not been disposed", oldDataModelListener.isDisposed() );
        assertTrue( "old column model has not been disposed", oldColumnModelListener.isDisposed() );
        for ( int i=0; i<columnCount; ++i )
            assertTrue( "column no. " + i + " has not been disposed", columnListeners[i].isDisposed() );

        // the same holds if the grid control model itself is disposed - it should dispose the depending models, too
        assertFalse( "new data model is already disposed - this is unexpected", newDataModelListener.isDisposed() );
        assertFalse( "new column model is already disposed - this is unexpected", newColumnModelListener.isDisposed() );
        impl_dispose( m_gridControlModel );
        assertTrue( "new data model is not disposed after disposing the grid column model", newDataModelListener.isDisposed() );
        assertTrue( "new column model is not disposed after disposing the grid column model", newColumnModelListener.isDisposed() );
    }

    // -----------------------------------------------------------------------------------------------------------------
    /**
     * tests various aspects of the <code>XMutableGridDataModel</code> interface
     */
    @Test
    public void testMutableGridDataModel() throws Exception
    {
        impl_recreateGridModel();

        TMutableGridDataModel test = new TMutableGridDataModel( m_dataModel );
        test.testAddRow();
        test.testAddRows();
        test.testInsertRow();
        test.testInsertRows();
        test.testRemoveRow();
        test.testRemoveAllRows();
        test.testUpdateCellData();
        test.testUpdateRowData();
        test.testUpdateRowHeading();
        test.cleanup();

        // a somehwat less straight-forward test: the data model is expected to implicitly increase its column count
        // when you add a row which has more columns than currently known
        final XMutableGridDataModel dataModel = DefaultGridDataModel.create( m_context );
        dataModel.addRow( 0, new Object[] { 1 } );
        assertEquals( "unexpected column count after adding the most simple row", 1, dataModel.getColumnCount() );
        dataModel.addRow( 1, new Object[] { 1, 2 } );
        assertEquals( "implicit extension of the column count doesn't work", 2, dataModel.getColumnCount() );
    }

    // -----------------------------------------------------------------------------------------------------------------
    @Test
    public void testGridColumnModel() throws Exception
    {
        impl_recreateGridModel();

        ColumnModelListener listener = new ColumnModelListener();
        m_columnModel.addContainerListener( listener );

        // insert default columns into the previously empty model, ensure we get the right notifications
        final int defaultColumnsCount = 3;
        m_columnModel.setDefaultColumns( defaultColumnsCount );
        impl_assertColumnModelConsistency();
        List< ContainerEvent > events = listener.assertExclusiveInsertionEvents();
        listener.reset();
        assertEquals( "wrong number of events fired by setDefaulColumns", defaultColumnsCount, events.size() );
        for ( int i=0; i<defaultColumnsCount; ++i )
        {
            final ContainerEvent event = events.get(i);
            final int index = impl_assertInteger( event.Accessor );
            assertEquals( "unexpected Accessor value in insert notification", i, index );
            assertTrue( "wrong column object notified in insert notification",
                impl_areSameInterface( event.Element, m_columnModel.getColumn(i) ) );
        }

        // insert some more default columns, ensure that all previously existing columns are removed
        final int moreDefaultColumnsCount = 5;
        m_columnModel.setDefaultColumns( moreDefaultColumnsCount );
        impl_assertColumnModelConsistency();
        assertEquals( "setting default columns is expected to remove all previously existing columns",
            moreDefaultColumnsCount, m_columnModel.getColumnCount() );

        // in this situation, both removal and insertion events have been notified
        final List< ContainerEvent > removalEvents = listener.getRemovalEvents();
        final List< ContainerEvent > insertionEvents = listener.getInsertionEvents();
        listener.reset();

        // for the removal events, check the indexes
        assertEquals( "wrong number of columns removed (or notified) upon setting default columns",
            defaultColumnsCount, removalEvents.size() );
        for ( int i=0; i<removalEvents.size(); ++i )
        {
            final ContainerEvent event = removalEvents.get(i);
            final int removedIndex = impl_assertInteger( event.Accessor );

            // The implementation is allowed to remove the columns from the beginning, in which case the
            // index of the removed column must always be 0, since e.g. the second column has index 0
            // after the first column (which previously had index 0) had been removed.
            // Alternatively, the implementation is allowed to remove columns from the end, which means
            // that the column index given in the event is steadily increasing.
            assertTrue( "unexpected column removal event column index",
                ( removedIndex == 0 ) || ( removedIndex == removalEvents.size() - 1 - i ) );
        }

        // for the insertion events, check the indexes as well
        assertEquals( "wrong number of insertion events when setting default columns over existing columns",
            moreDefaultColumnsCount, insertionEvents.size() );
        for ( int i=0; i<insertionEvents.size(); ++i )
        {
            final ContainerEvent event = insertionEvents.get(i);
            final int index = impl_assertInteger( event.Accessor );
            assertEquals( i, index );
        }

        // okay, remove all those columns
        while ( m_columnModel.getColumnCount() != 0 )
        {
            final int columnCount = m_columnModel.getColumnCount();
            final int removeColumnIndex = m_randomGenerator.nextInt( columnCount );
            m_columnModel.removeColumn( removeColumnIndex );
            events = listener.assertExclusiveRemovalEvents();
            listener.reset();
            assertEquals( "removing a single column should notify a single event", 1, events.size() );
            final ContainerEvent event = events.get(0);
            final int removalIndex = impl_assertInteger( event.Accessor );
            assertEquals( "removing an arbitrary column does not notify the proper accessor",
                removeColumnIndex, removalIndex );
        }

        // calling addColumn with a column not created by the given model/implementatoion should not succeed
        boolean caughtExpected = false;
        try
        {
            m_columnModel.addColumn( new DummyColumn() );
        }
        catch( final com.sun.star.lang.IllegalArgumentException e )
        {
            assertTrue( impl_areSameInterface( e.Context, m_columnModel ) );
            caughtExpected = true;
        }
        assertTrue( "adding a dummy (self-implemented) grid column to the model should not succeed", caughtExpected );

        // adding a single column to the end should succeed, properly notify, and still be consistent
        final XGridColumn newColumn = m_columnModel.createColumn();
        m_columnModel.addColumn( newColumn );
        impl_assertColumnModelConsistency();
        events = listener.assertExclusiveInsertionEvents();
        listener.reset();
        assertEquals( "addColumn notifies the wrong number of insertion events", 1, events.size() );
        final int insertionIndex = impl_assertInteger( events.get(0).Accessor );
        assertEquals( insertionIndex, newColumn.getIndex() );
    }

    // -----------------------------------------------------------------------------------------------------------------
    @Test
    public void testDataModel() throws Exception
    {
        impl_recreateGridModel();

        // ensure that getCellData and getRowData have the same opinion on the data they deliver
        final Object[][] data = new Object[][] {
            new Object[] { 15, 17, 0 },
            new Object[] { 9, 8, 14 },
            new Object[] { 17, 2, 16 },
            new Object[] { 0, 7, 14 },
            new Object[] { 10, 16, 16 },
        };
        m_dataModel.addRows( new Object[ data.length ], data );

        for ( int row = 0; row < data.length; ++row )
        {
            assertArrayEquals( "getRowData delivers wrong data in row " + row, data[row], m_dataModel.getRowData( row ) );
            for ( int col = 0; col < data[row].length; ++col )
            {
                assertEquals( "getCellData delivers wrong data at position (" + col + ", " + row + ")",
                        data[row][col], m_dataModel.getCellData( col, row ) );
            }
        }
    }

    // -----------------------------------------------------------------------------------------------------------------
    @Test
    public void testSortableDataModel() throws Exception
    {
        impl_recreateGridModel();

        final int colCount = 3;
        final int rowCount = 10;
        // initialize with some data
        final Object[][] data = new Object[][] {
            new Object[] { 15, 17, 0 },
            new Object[] { 9, 8, 14 },
            new Object[] { 17, 2, 16 },
            new Object[] { 0, 7, 14 },
            new Object[] { 10, 16, 16 },
            new Object[] { 2, 8, 10 },
            new Object[] { 4, 8, 3 },
            new Object[] { 7, 9, 0 },
            new Object[] { 15, 6, 19 },
            new Object[] { 2, 14, 19 }
        };
        final Object[] rowHeadings = new Object[] {
            0, 1, 2, 3, 4, 5, 6, 7, 8, 9
        };
        // ensure consistency of the test data
        assertEquals( rowHeadings.length, rowCount );
        assertEquals( data.length, rowCount );
        for ( Object[] rowData : data )
            assertEquals( rowData.length, colCount );

        // add the test data
        m_dataModel.addRows( rowHeadings, data );
        assertEquals( rowCount, m_dataModel.getRowCount() );
        assertEquals( colCount, m_dataModel.getColumnCount() );

        // sort by each column
        for ( int colIndex = 0; colIndex < colCount; ++colIndex )
        {
            for ( boolean ascending : new boolean[] { true, false } )
            {
                m_dataModel.sortByColumn( colIndex, ascending );
                Pair currentSortOrder = m_dataModel.getCurrentSortOrder();
                assertEquals( "invalid current sort column (column " + colIndex + ")", ((Integer)currentSortOrder.First).intValue(), colIndex );
                assertEquals( "invalid current sort direction", ((Boolean)currentSortOrder.Second).booleanValue(), ascending );

                /*for ( int i=0; i<rowCount; ++i )
                {
                    for ( int j=0; j<colCount; ++j )
                        System.out.print( m_dataModel.getCellData( j, i ).toString() + ", " );
                    System.out.println();
                }*/

                // verify the data is actually sorted by this column
                for ( int rowIndex = 0; rowIndex < rowCount - 1; ++rowIndex )
                {
                    final Object currentValue = m_dataModel.getCellData( colIndex, rowIndex );
                    final int currentIntValue = impl_assertInteger( currentValue );
                    final Object nextValue = m_dataModel.getCellData( colIndex, rowIndex + 1 );
                    final int nextIntValue = impl_assertInteger( nextValue );
                    assertTrue( "data in row " + rowIndex + " is actually not sorted " + ( ascending ? "ascending" : "descending" ),
                        ascending   ? currentIntValue <= nextIntValue
                                    : currentIntValue >= nextIntValue );

                    // ensure the data in the other columns, and the row headings, are sorted as well
                    final Object rowHeading = m_dataModel.getRowHeading( rowIndex );
                    final int unsortedRowIndex = impl_assertInteger( rowHeading );
                    for ( int innerColIndex = 0; innerColIndex < colCount; ++innerColIndex )
                    {
                        assertEquals( "sorted row " + rowIndex + ", unsorted row " + unsortedRowIndex + ", col " + innerColIndex +
                            ": wrong data",
                            data[unsortedRowIndex][innerColIndex], m_dataModel.getCellData( innerColIndex, rowIndex ) );
                    }
                }
            }
        }
    }

    // -----------------------------------------------------------------------------------------------------------------
    @Test
    public void testView() throws Exception
    {
        final XControl control = impl_createDialogWithGridControl();
        final XPropertySet gridModelProps =
            UnoRuntime.queryInterface( XPropertySet.class, control.getModel() );

        // in the current implementation (not sure this is a good idea at all), the control (more precise: the peer)
        // ensures that if there are no columns in the column model, but in the data model, then the column model
        // will implicitly have the needed columns added.
        // To ensure that clients which rely on this do not break in the future, check this here.
        final XMutableGridDataModel dataModel = UnoRuntime.queryInterface( XMutableGridDataModel.class,
            gridModelProps.getPropertyValue( "GridDataModel" ) );
        assertNotNull( dataModel );
        assertEquals( 0, dataModel.getColumnCount() );

        final XGridColumnModel columnModel = UnoRuntime.queryInterface( XGridColumnModel.class,
            gridModelProps.getPropertyValue( "ColumnModel" ) );
        assertNotNull( columnModel );
        assertEquals( 0, columnModel.getColumnCount() );

        final int columnCount = 3;
        final int rowCount = 2;
        dataModel.addRow( null, new Object[] { 1, 2, 3 } );
        dataModel.addRow( null, new Object[] { 6, 5, 4 } );

        assertEquals( columnCount, dataModel.getColumnCount() );
        assertEquals( columnCount, columnModel.getColumnCount() );

        // some cursor traveling
        final XGridControl gridControl = UnoRuntime.queryInterface( XGridControl.class, control );
        gridControl.goToCell( 0, 0 );
        assertEquals( "wrong 'current column' (1)", 0, gridControl.getCurrentColumn() );
        assertEquals( "wrong 'current row' (1)", 0, gridControl.getCurrentRow() );
        gridControl.goToCell( columnCount - 1, rowCount - 1 );
        assertEquals( "wrong 'current column' (2)", dataModel.getColumnCount() - 1, gridControl.getCurrentColumn() );
        assertEquals( "wrong 'current row' (2)", dataModel.getRowCount() - 1, gridControl.getCurrentRow() );

        // removing the last column, while the active cell is in this very last column, is expected to adjust
        // the active cell
        columnModel.removeColumn( columnCount - 1 );
        assertEquals( "removed the last and active column, active column was not adjusted!",
            columnCount - 2, gridControl.getCurrentColumn() );
        // same holds for rows
        dataModel.removeRow( rowCount - 1 );
        assertEquals( "removed the last and active row, active row was not adjusted!",
            rowCount - 2, gridControl.getCurrentRow() );
    }

    // -----------------------------------------------------------------------------------------------------------------
    private XControl impl_createDialogWithGridControl() throws Exception
    {
        // create a simple dialog model/control/peer trinity
        final XControlModel dialogModel = createInstance( XControlModel.class, "com.sun.star.awt.UnoControlDialogModel" );
        m_disposables.add( dialogModel );
        final XPropertySet dialogProps = UnoRuntime.queryInterface( XPropertySet.class, dialogModel );
        dialogProps.setPropertyValue( "Width", 200 );
        dialogProps.setPropertyValue( "Height", 100 );
        dialogProps.setPropertyValue( "Title", "Grid Control Unit Test" );
        final XControl dialogControl = createInstance( XControl.class, "com.sun.star.awt.UnoControlDialog" );
        m_disposables.add( dialogControl );
        dialogControl.setModel( dialogModel );
        dialogControl.createPeer( createInstance( XToolkit.class, "com.sun.star.awt.Toolkit" ), null );

        // insert a grid control model
        final XMultiServiceFactory controlModelFactory = UnoRuntime.queryInterface( XMultiServiceFactory.class,
            dialogModel );
        final XPropertySet gridModelProps = UnoRuntime.queryInterface( XPropertySet.class,
            controlModelFactory.createInstance( "com.sun.star.awt.grid.UnoControlGridModel" ) );
        m_disposables.add( gridModelProps );
        gridModelProps.setPropertyValue( "PositionX", 6 );
        gridModelProps.setPropertyValue( "PositionY", 6 );
        gridModelProps.setPropertyValue( "Width", 188 );
        gridModelProps.setPropertyValue( "Height", 88 );
        final XNameContainer modelContainer = UnoRuntime.queryInterface( XNameContainer.class, dialogModel );
        modelContainer.insertByName( "grid", gridModelProps );

        // check the respective control has been created
        final XControlContainer controlContainer = UnoRuntime.queryInterface( XControlContainer.class, dialogControl );
        final XControl gridControl = controlContainer.getControl( "grid" );
        assertNotNull( "no grid control created in the dialog", gridControl );

        return gridControl;
    }

    // -----------------------------------------------------------------------------------------------------------------
    private int impl_assertInteger( final Object i_object )
    {
        assertTrue( i_object instanceof Integer );
        return ((Integer)i_object).intValue();
    }

    // -----------------------------------------------------------------------------------------------------------------
    private void impl_assertColumnModelConsistency() throws IndexOutOfBoundsException
    {
        for ( int col = 0; col < m_columnModel.getColumnCount(); ++col )
        {
            final XGridColumn column = m_columnModel.getColumn( col );
            assertNotNull( column );
            assertEquals( "column/model inconsistency: column " + col + " has a wrong index!", col, column.getIndex() );
        }

        final XGridColumn[] allColumns = m_columnModel.getColumns();
        assertEquals( "getColumns returns the wrong number of column objects",
            m_columnModel.getColumnCount(), allColumns.length );
        for ( int col = 0; col < m_columnModel.getColumnCount(); ++col )
        {
            assertTrue( "getColumns inconsistency", impl_areSameInterface( allColumns[col], m_columnModel.getColumn(col) ) );
        }
    }

    // -----------------------------------------------------------------------------------------------------------------
    private void impl_assertEquality( final XGridDataModel i_reference, final XGridDataModel i_compare ) throws IndexOutOfBoundsException
    {
        assertNotNull( i_reference );
        assertNotNull( i_compare );

        assertEquals( "data model comparison: wrong column counts", i_reference.getColumnCount(), i_compare.getColumnCount() );
        assertEquals( "data model comparison: wrong row counts", i_reference.getRowCount(), i_compare.getRowCount() );

        for ( int row = 0; row < i_reference.getRowCount(); ++row )
        {
            assertEquals( "data model comparison: wrong row heading content in row " + row,
                    i_reference.getRowHeading( row ) );
            for ( int col = 0; col < i_reference.getRowCount(); ++col )
            {
                assertEquals( "data model comparison: wrong cell content in cell (" + col + ", " + row + ")",
                    i_reference.getCellData( col, row ) );
                assertEquals( "data model comparison: wrong tooltip content in cell (" + col + ", " + row + ")",
                    i_reference.getCellToolTip( col, row ) );
            }
        }
    }

    // -----------------------------------------------------------------------------------------------------------------
    private void impl_assertEquality( final XGridColumnModel i_reference, final XGridColumnModel i_compare ) throws IndexOutOfBoundsException
    {
        assertEquals( "column model comparison: wrong column counts", i_reference.getColumnCount(), i_compare.getColumnCount() );
        for ( int col = 0; col < i_reference.getColumnCount(); ++col )
        {
            final XGridColumn referenceColumn = i_reference.getColumn( col );
            final XGridColumn compareColumn = i_compare.getColumn( col );
            impl_assertEquality( referenceColumn, compareColumn );
        }
    }

    // -----------------------------------------------------------------------------------------------------------------
    private void impl_assertEquality( final XGridColumn i_reference, final XGridColumn i_compare )
    {
        final Method[] methods = XGridColumn.class.getMethods();
        for ( int m=0; m<methods.length; ++m )
        {
            if ( !methods[m].getName().startsWith( "get" ) )
                continue;
            try
            {
                final Object referenceValue = methods[m].invoke( i_reference );
                final Object compareValue = methods[m].invoke( i_compare );
                assertEquals( "grid column comparison: column attribute '" + methods[m].getName().substring(3) + "' does not match",
                    referenceValue, compareValue );
            }
            catch ( java.lang.Exception ex )
            {
                fail( " could not retrieve object attributes: " + ex.toString() );
            }
        }
    }

    // -----------------------------------------------------------------------------------------------------------------
    private boolean impl_areSameInterface( final Object i_lhs, final Object i_rhs )
    {
        final XInterface lhs = UnoRuntime.queryInterface( XInterface.class, i_lhs );
        final XInterface rhs = UnoRuntime.queryInterface( XInterface.class, i_rhs );
        return UnoRuntime.areSame( lhs, rhs );
    }

    // -----------------------------------------------------------------------------------------------------------------
    @Before
    public void initTestCase()
    {
        m_disposables.clear();
    }

    // -----------------------------------------------------------------------------------------------------------------
    @After
    public void cleanupTestCase()
    {
        impl_dispose( m_disposables.toArray() );
    }

    // -----------------------------------------------------------------------------------------------------------------
    @BeforeClass
    public static void setUpConnection() throws java.lang.Exception
    {
        System.out.println( "--------------------------------------------------------------------------------" );
        System.out.println( "starting class: " + GridControl.class.getName() );
        System.out.print( "connecting ... " );
        m_connection.setUp();
        System.out.println( "done.");

        final long seed = m_randomGenerator.nextLong();
        m_randomGenerator.setSeed( seed );
        System.out.println( "seeding random number generator with " + seed );
    }

    // -----------------------------------------------------------------------------------------------------------------
    @AfterClass
    public static void tearDownConnection()
        throws InterruptedException, com.sun.star.uno.Exception
    {
        System.out.println();
        System.out.println( "tearing down connection" );
        m_connection.tearDown();
        System.out.println( "finished class: " + GridControl.class.getName() );
        System.out.println( "--------------------------------------------------------------------------------" );
    }

    // -----------------------------------------------------------------------------------------------------------------
    public <T> T createInstance( Class<T> i_interfaceClass, final String i_serviceIndentifer ) throws Exception
    {
        return UnoRuntime.queryInterface( i_interfaceClass, createInstance( i_serviceIndentifer ) );
    }

    // -----------------------------------------------------------------------------------------------------------------
    private Object createInstance( final String i_serviceName ) throws Exception
    {
        Object instance = m_context.getServiceManager().createInstanceWithContext( i_serviceName, m_context );
        assertNotNull( "could not create an instance of '" + i_serviceName + "'", instance );
        return instance;
    }
    // -----------------------------------------------------------------------------------------------------------------
    private static final class DisposeListener implements XEventListener
    {
        DisposeListener( final Object i_component )
        {
            m_component = UnoRuntime.queryInterface( XComponent.class, i_component );
            assertNotNull( m_component );
            m_component.addEventListener( this );
        }

        public void disposing( EventObject i_event )
        {
            assertTrue( UnoRuntime.areSame( i_event.Source, m_component ) );
            m_isDisposed = true;
        }

        final boolean isDisposed() { return m_isDisposed; }

        private final XComponent    m_component;
        private boolean             m_isDisposed;
    };

    // -----------------------------------------------------------------------------------------------------------------
    private static final class ColumnModelListener implements XContainerListener
    {
        ColumnModelListener()
        {
        }

        public void elementInserted( ContainerEvent i_event )
        {
            m_insertionEvents.add( i_event );
        }

        public void elementRemoved( ContainerEvent i_event )
        {
            m_removalEvents.add( i_event );
        }

        public void elementReplaced( ContainerEvent i_event )
        {
            m_replacementEvents.add( i_event );
        }

        public void disposing( EventObject eo )
        {
            m_isDisposed = true;
        }

        private List< ContainerEvent > assertExclusiveInsertionEvents()
        {
            assertFalse( m_insertionEvents.isEmpty() );
            assertTrue( m_removalEvents.isEmpty() );
            assertTrue( m_replacementEvents.isEmpty() );
            return m_insertionEvents;
        }

        private List< ContainerEvent > assertExclusiveRemovalEvents()
        {
            assertTrue( m_insertionEvents.isEmpty() );
            assertFalse( m_removalEvents.isEmpty() );
            assertTrue( m_replacementEvents.isEmpty() );
            return m_removalEvents;
        }

        private void reset()
        {
            m_insertionEvents = new ArrayList< ContainerEvent >();
            m_removalEvents = new ArrayList< ContainerEvent >();
            m_replacementEvents = new ArrayList< ContainerEvent >();
        }

        private List< ContainerEvent > getInsertionEvents() { return m_insertionEvents; }
        private List< ContainerEvent > getRemovalEvents() { return m_removalEvents; }

        final boolean isDisposed() { return m_isDisposed; }

        private List< ContainerEvent > m_insertionEvents = new ArrayList< ContainerEvent >();
        private List< ContainerEvent > m_removalEvents = new ArrayList< ContainerEvent >();
        private List< ContainerEvent > m_replacementEvents = new ArrayList< ContainerEvent >();
        private boolean m_isDisposed = false;
    };

    // -----------------------------------------------------------------------------------------------------------------
    private static final OfficeConnection m_connection = new OfficeConnection();
    private static Random m_randomGenerator = new Random();
    private final XComponentContext m_context;

    private XPropertySet                    m_gridControlModel;
    private XGridColumnModel                m_columnModel;
    private XSortableMutableGridDataModel   m_dataModel;
    private final List< Object >            m_disposables = new ArrayList< Object >();
}
