001: /*
002: * SQLeonardo :: java database frontend
003: * Copyright (C) 2004 nickyb@users.sourceforge.net
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: *
019: */
020:
021: package nickyb.sqleonardo.environment.ctrl.content;
022:
023: import java.util.Hashtable;
024: import java.util.Vector;
025:
026: import javax.swing.event.TableModelListener;
027: import javax.swing.table.TableModel;
028:
029: import nickyb.sqleonardo.querybuilder.syntax.QueryTokens;
030:
031: public class ContentModel implements TableModel {
032: public static int MAX_BLOCK_RECORDS = 75;
033:
034: private Vector columns = new Vector();
035: private Vector rows = new Vector();
036:
037: private Hashtable content = new Hashtable();
038: private ContentChanges changes = new ContentChanges();
039:
040: private long ridcounter = 0;
041: private int block = 1;
042:
043: public ContentChanges getChanges() {
044: return changes;
045: }
046:
047: public int getBlockCount() {
048: return (this .getFlatRowCount() / MAX_BLOCK_RECORDS)
049: + (this .getFlatRowCount() % MAX_BLOCK_RECORDS == 0 ? 0
050: : 1);
051: }
052:
053: public int getBlock() {
054: return block;
055: }
056:
057: public void setBlock(int idx) {
058: block = idx;
059: }
060:
061: public void addColumn(String text, int type) {
062: columns.add(new Object[] { text, new Integer(type) });
063: }
064:
065: public int getColumnCount() {
066: return columns.size();
067: }
068:
069: public Class getColumnClass(int idx) {
070: return Object.class;
071: }
072:
073: public String getColumnName(int idx) {
074: return ((Object[]) columns.elementAt(idx))[0].toString();
075: }
076:
077: public int getColumnIndex(String name) {
078: for (int idx = 0; idx < columns.size(); idx++) {
079: if (this .getColumnName(idx).equals(name))
080: return idx;
081: }
082:
083: return -1;
084: }
085:
086: public int getColumnType(int idx) {
087: return ((Integer) ((Object[]) columns.elementAt(idx))[1])
088: .intValue();
089: }
090:
091: public void addRow(Object[] rowdata) {
092: addRow(rowdata, false);
093: }
094:
095: public void addRow(Object[] rowdata, boolean newrow) {
096: Long rid = new Long(ridcounter++);
097:
098: rows.add(rid);
099: content.put(rid, rowdata);
100:
101: if (newrow)
102: changes.setInserted(rid);
103: }
104:
105: public void deleteRow(int row) {
106: Long rid = (Long) rows.elementAt(this .toFlatRow(row));
107: rows.removeElement(rid);
108:
109: changes.setDeleted(rid);
110: }
111:
112: public void insertRow(int row) {
113: Object[] rowdata = new Object[this .getColumnCount()];
114: Long rid = new Long(ridcounter++);
115:
116: rows.insertElementAt(rid, this .toFlatRow(row));
117: content.put(rid, rowdata);
118:
119: changes.setInserted(rid);
120: }
121:
122: public boolean isCellEditable(int row, int col) {
123: return true;
124: }
125:
126: public int getRowCount() {
127: int count = rows.size();
128: if (count == 0)
129: return 0;
130:
131: count = count - (MAX_BLOCK_RECORDS * (block - 1));
132: return count > MAX_BLOCK_RECORDS ? MAX_BLOCK_RECORDS : count;
133: }
134:
135: public Object getValueAt(int row, int col) {
136: return getFlatValueAt(this .toFlatRow(row), col);
137: }
138:
139: public boolean isCellChanged(int row, int col) {
140: return isFlatCellChanged(this .toFlatRow(row), col);
141: }
142:
143: public void resetValueAt(int row, int col) {
144: resetFlatValueAt(this .toFlatRow(row), col);
145: }
146:
147: public void setValueAt(Object aValue, int row, int col) {
148: setFlatValueAt(aValue, this .toFlatRow(row), col);
149: }
150:
151: public int getFlatRowCount() {
152: return rows.size();
153: }
154:
155: public Object getFlatValueAt(int row, int col) {
156: Long rid = (Long) rows.elementAt(row);
157: Object[] rowdata = getValues(rid);
158:
159: return rowdata[col] instanceof Object[] ? ((Object[]) rowdata[col])[0]
160: : rowdata[col];
161: }
162:
163: public boolean isFlatCellChanged(int row, int col) {
164: Long rid = (Long) rows.elementAt(row);
165: return changes.exists(ContentChanges.INSERT, rid)
166: || (getValues(rid)[col] instanceof Object[]);
167: }
168:
169: private boolean isFlatRowChanged(int row) {
170: for (int i = 0; i < columns.size(); i++)
171: if (isFlatCellChanged(row, i))
172: return true;
173:
174: return false;
175: }
176:
177: public void resetFlatValueAt(int row, int col) {
178: Long rid = (Long) rows.elementAt(row);
179: Object[] rowdata = getValues(rid);
180:
181: if (rowdata[col] instanceof Object[])
182: setFlatValueAt(((Object[]) rowdata[col])[1], row, col);
183: }
184:
185: public void setFlatValueAt(Object aValue, int row, int col) {
186: Long rid = (Long) rows.elementAt(row);
187:
188: Object[] rowdata = getValues(rid);
189: if (changes.exists(ContentChanges.INSERT, rid)) {
190: rowdata[col] = aValue;
191: } else {
192: Object[] cell = { aValue, null };
193:
194: if (rowdata[col] instanceof Object[])
195: cell[1] = ((Object[]) rowdata[col])[1];
196: else
197: cell[1] = rowdata[col];
198:
199: if (cell[0] == null && cell[1] == null) {
200: rowdata[col] = null;
201: cell = null;
202: } else if (cell[0] != null && cell[1] != null) {
203: if (cell[0].toString().equals(cell[1].toString())) {
204: rowdata[col] = aValue;
205: cell = null;
206: } else
207: cell[0] = aValue;
208: } else
209: cell[0] = aValue;
210:
211: if (cell != null) {
212: rowdata[col] = cell;
213: changes.setUpdated(rid);
214: } else if (!isFlatRowChanged(row)) {
215: changes.aborted(rid);
216: }
217: }
218: }
219:
220: Object[] getValues(int row) {
221: Long rid = (Long) rows.elementAt(row);
222: return getValues(rid);
223: }
224:
225: Object[] getValues(Long rid) {
226: return (Object[]) content.get(rid);
227: }
228:
229: int toFlatRow(int row) {
230: int gap = (block - 1) * MAX_BLOCK_RECORDS;
231:
232: return gap < 0 ? row : row + gap;
233: }
234:
235: private int compare(int col, int row1, int row2, short type) {
236: Object value1, value2;
237:
238: Long rid1 = (Long) rows.elementAt(row1);
239: Long rid2 = (Long) rows.elementAt(row2);
240:
241: Object[] rowdata1 = getValues(rid1);
242: Object[] rowdata2 = getValues(rid2);
243:
244: if (rowdata1[col] instanceof Object[])
245: value1 = ((Object[]) rowdata1[col])[0];
246: else
247: value1 = rowdata1[col];
248:
249: if (rowdata2[col] instanceof Object[])
250: value2 = ((Object[]) rowdata2[col])[0];
251: else
252: value2 = rowdata2[col];
253:
254: int cmp = 0;
255: if (value1 != null && value2 != null) {
256: if (TaskRetrieve.isNumberType(getColumnType(col))) {
257: if (Float.valueOf(value1.toString()).floatValue() > Float
258: .valueOf(value2.toString()).floatValue())
259: cmp = 1;
260: else if (Float.valueOf(value1.toString()).floatValue() < Float
261: .valueOf(value2.toString()).floatValue())
262: cmp = -1;
263: } else {
264: cmp = value1.toString().toLowerCase().compareTo(
265: value2.toString().toLowerCase());
266: }
267: } else if (value1 != null)
268: cmp = 1;
269: else if (value2 != null)
270: cmp = -1;
271:
272: return type == QueryTokens.Sort.ASCENDING ? cmp : cmp * (-1);
273: }
274:
275: private void swap(int i, int j) {
276: Long rid = (Long) rows.elementAt(i);
277: rows.setElementAt(rows.elementAt(j), i);
278: rows.setElementAt(rid, j);
279: }
280:
281: private void sort(int col, int first, int last, short type) {
282: int lower = first + 1;
283: int upper = last;
284:
285: swap(first, (first + last) / 2);
286:
287: while (lower <= upper) {
288: while (compare(col, lower, first, type) < 0)
289: lower++;
290: while (compare(col, first, upper, type) < 0)
291: upper--;
292:
293: if (lower < upper)
294: swap(lower++, upper--);
295: else
296: lower++;
297: }
298:
299: swap(upper, first);
300: if (first < upper - 1)
301: sort(col, first, upper - 1, type);
302: if (upper + 1 < last)
303: sort(col, upper + 1, last, type);
304: }
305:
306: public void sort(int col, short type) {
307: if (getFlatRowCount() < 2)
308: return;
309:
310: int max = 0;
311: for (int i = 1; i < getFlatRowCount(); i++)
312: if (compare(col, max, i, type) < 0)
313: max = i;
314:
315: swap(getFlatRowCount() - 1, max);
316: sort(col, 0, getFlatRowCount() - 2, type);
317: }
318:
319: public void addTableModelListener(TableModelListener l) {
320: }
321:
322: public void removeTableModelListener(TableModelListener l) {
323: }
324: }
|