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 }