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 
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    }