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