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 }