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 }