001// Copyright 2004, 2005 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry.contrib.table.model.simple;
016
017import java.util.Arrays;
018import java.util.Comparator;
019import java.util.Iterator;
020
021import org.apache.tapestry.contrib.table.model.CTableDataModelEvent;
022import org.apache.tapestry.contrib.table.model.IFullTableModel;
023import org.apache.tapestry.contrib.table.model.ITableColumn;
024import org.apache.tapestry.contrib.table.model.ITableColumnModel;
025import org.apache.tapestry.contrib.table.model.ITableDataModel;
026import org.apache.tapestry.contrib.table.model.ITableDataModelListener;
027import org.apache.tapestry.contrib.table.model.ITableSortingState;
028import org.apache.tapestry.contrib.table.model.common.AbstractTableModel;
029import org.apache.tapestry.contrib.table.model.common.ArrayIterator;
030import org.apache.tapestry.contrib.table.model.common.ReverseComparator;
031
032/**
033 * A simple generic table model implementation.
034 *
035 * @author mindbridge
036 */
037public class SimpleTableModel extends AbstractTableModel 
038        implements IFullTableModel, ITableDataModelListener
039{
040        private static final long serialVersionUID = 1L;
041        
042    private ITableDataModel m_objDataModel = null;
043    private Object[] m_arrRows = null;
044    private ITableColumnModel m_objColumnModel = null;
045
046    private SimpleTableSortingState m_objLastSortingState;
047
048    public SimpleTableModel(Object[] arrData, ITableColumn[] arrColumns)
049    {
050        this(new SimpleListTableDataModel(arrData), new SimpleTableColumnModel(arrColumns));
051    }
052
053    public SimpleTableModel(Object[] arrData, ITableColumnModel objColumnModel)
054    {
055        this(new SimpleListTableDataModel(arrData), objColumnModel);
056    }
057
058    public SimpleTableModel(ITableDataModel objDataModel, ITableColumnModel objColumnModel)
059    {
060        this(objDataModel, objColumnModel, new SimpleTableState());
061    }
062
063    public SimpleTableModel(ITableDataModel objDataModel, ITableColumnModel objColumnModel, SimpleTableState objState)
064    {
065        super(objState);
066        
067        m_arrRows = null;
068        m_objColumnModel = objColumnModel;
069        m_objLastSortingState = new SimpleTableSortingState();
070
071        setDataModel(objDataModel);
072    }
073
074    public ITableColumnModel getColumnModel()
075    {
076        return m_objColumnModel;
077    }
078
079    public Iterator getCurrentPageRows()
080    {
081        sortRows();
082
083        int nPageSize = getPagingState().getPageSize();
084        if (nPageSize <= 0)
085            return new ArrayIterator(m_arrRows);
086
087        int nCurrentPage = getPagingState().getCurrentPage();
088        int nFrom = nCurrentPage * nPageSize;
089        int nTo = (nCurrentPage + 1) * nPageSize;
090
091        return new ArrayIterator(m_arrRows, nFrom, nTo);
092    }
093
094    public int getRowCount()
095    {
096        updateRows();
097        return m_arrRows.length;
098    }
099
100    private void updateRows()
101    {
102        // If it is not null, then there is no need to extract the data
103        if (m_arrRows != null)
104            return;
105
106        // Extract the data from the model
107        m_objLastSortingState = new SimpleTableSortingState();
108
109        int nRowCount = m_objDataModel.getRowCount();
110        Object[] arrRows = new Object[nRowCount];
111
112        int i = 0;
113        for (Iterator it = m_objDataModel.getRows(); it.hasNext();)
114            arrRows[i++] = it.next();
115
116        m_arrRows = arrRows;
117    }
118
119    protected void sortRows()
120    {
121        updateRows();
122
123        ITableSortingState objSortingState = getSortingState();
124
125        // see if there is sorting required
126        String strSortColumn = objSortingState.getSortColumn();
127        if (strSortColumn == null)
128            return;
129
130        boolean bSortOrder = objSortingState.getSortOrder();
131
132        // See if the table is already sorted this way. If so, return.
133        if (strSortColumn.equals(m_objLastSortingState.getSortColumn())
134            && m_objLastSortingState.getSortOrder() == bSortOrder)
135            return;
136
137        ITableColumn objColumn = getColumnModel().getColumn(strSortColumn);
138        if (objColumn == null || !objColumn.getSortable())
139            return;
140
141        Comparator objCmp = objColumn.getComparator();
142        if (objCmp == null)
143            return;
144
145        // Okay, we have everything in place. Sort the rows.
146        if (bSortOrder == ITableSortingState.SORT_DESCENDING)
147            objCmp = new ReverseComparator(objCmp);
148
149        Arrays.sort(m_arrRows, objCmp);
150
151        m_objLastSortingState.setSortColumn(strSortColumn, bSortOrder);
152    }
153
154    public void tableDataChanged(CTableDataModelEvent objEvent)
155    {
156        m_arrRows = null;
157    }
158
159    /**
160     * Returns the dataModel.
161     * @return ITableDataModel
162     */
163    public ITableDataModel getDataModel()
164    {
165        return m_objDataModel;
166    }
167
168    /**
169     * Sets the dataModel.
170     * @param dataModel The dataModel to set
171     */
172    public void setDataModel(ITableDataModel dataModel)
173    {
174        if (m_objDataModel != null)
175            m_objDataModel.removeTableDataModelListener(this);
176            
177        m_objDataModel = dataModel;
178        m_objDataModel.addTableDataModelListener(this);
179        
180        m_arrRows = null;
181    }
182
183        public Iterator getRows() {
184                updateRows();
185                return new ArrayIterator(m_arrRows);
186        }
187
188}