001: /*
002: * Copyright (C) Jahia Ltd. All rights reserved.
003: *
004: * This software is published under the terms of the Jahia Open Software
005: * License version 1.1, a copy of which has been included with this
006: * distribution in the LICENSE.txt file.
007: */
008: package org.jahia.sqlprofiler.gui;
009:
010: import javax.swing.table.*;
011: import java.util.*;
012: import java.text.*;
013: import java.awt.event.MouseAdapter;
014: import java.awt.event.MouseEvent;
015: import java.awt.event.InputEvent;
016: import javax.swing.JTable;
017:
018: /**
019: * <p>Title: SQL Profiler</p>
020: * <p>Description: </p>
021: * <p>Copyright: Copyright (c) 2003</p>
022: * <p>Company: Jahia Ltd</p>
023: * @author Serge Huber
024: * @version 1.0
025: */
026:
027: public class ProfileResultTableModel extends AbstractTableModel
028: implements Comparator {
029:
030: private ArrayList profileResults = new ArrayList();
031: protected int currCol = 0;
032: protected Vector ascendCol = new Vector(); // this vector stores the state (ascending or descending) of each column
033: protected Integer one = new Integer(1);
034: protected Integer minusOne = new Integer(-1);
035:
036: private static final String[] COLUMN_NAMES = { "%", "Time[ms]",
037: "Count", "Table(s)", "Column(s)" };
038:
039: public ProfileResultTableModel() {
040: for (int i = 0; i < COLUMN_NAMES.length; i++) {
041: ascendCol.add(one);
042: }
043: }
044:
045: public int getRowCount() {
046: return profileResults.size();
047: }
048:
049: public int getColumnCount() {
050: return COLUMN_NAMES.length;
051: }
052:
053: public String getColumnName(int aCol) {
054: // does not need to be synchronized
055: return COLUMN_NAMES[aCol];
056: }
057:
058: public Object getValueAt(int rowIndex, int columnIndex) {
059: ProfileReportResult curResult = (ProfileReportResult) profileResults
060: .get(rowIndex);
061: NumberFormat nf = NumberFormat.getInstance();
062: nf.setMaximumFractionDigits(2);
063: Object result = null;
064: switch (columnIndex) {
065: case 0:
066: result = nf.format(curResult.getPercentage());
067: break;
068: case 1:
069: result = new Long(curResult.getTotalElapsedTime());
070: break;
071: case 2:
072: result = new Integer(curResult.getOccurences());
073: break;
074: case 3:
075: StringBuffer resultBuf = new StringBuffer();
076: Iterator tableNameIter = curResult.getTableNames()
077: .iterator();
078: while (tableNameIter.hasNext()) {
079: String curTableName = (String) tableNameIter.next();
080: resultBuf.append(curTableName);
081: if (tableNameIter.hasNext()) {
082: resultBuf.append(",");
083: }
084: }
085: result = resultBuf.toString();
086: break;
087: case 4:
088: StringBuffer resultBuf2 = new StringBuffer();
089: Iterator columnNameIter = curResult.getColumnNames()
090: .iterator();
091: while (columnNameIter.hasNext()) {
092: String curColumnName = (String) columnNameIter.next();
093: resultBuf2.append(curColumnName);
094: if (columnNameIter.hasNext()) {
095: resultBuf2.append(",");
096: }
097: }
098: result = resultBuf2.toString();
099: break;
100: }
101: return result;
102: }
103:
104: public void clear() {
105: profileResults.clear();
106: currCol = 0;
107: fireTableDataChanged();
108: }
109:
110: public void addProfileReportResult(
111: ProfileReportResult profileReportResult) {
112: profileResults.add(profileReportResult);
113: }
114:
115: /*
116: * This method is the implementation of the Comparator interface.
117: * It is used for sorting the rows
118: */
119: public int compare(Object v1, Object v2) {
120:
121: // the comparison is between 2 vectors, each representing a row
122: // the comparison is done between 2 objects from the different rows that are in the column that is being sorted
123:
124: int ascending = ((Integer) ascendCol.get(currCol)).intValue();
125: if (v1 == null && v2 == null) {
126: return 0;
127: } else if (v2 == null) { // Define null less than everything.
128: return 1 * ascending;
129: } else if (v1 == null) {
130: return -1 * ascending;
131: }
132:
133: ProfileReportResult left = (ProfileReportResult) v1;
134: ProfileReportResult right = (ProfileReportResult) v2;
135:
136: Object o1 = null;
137: Object o2 = null;
138: switch (currCol) {
139: case 0:
140: o1 = new Double(left.getPercentage());
141: o2 = new Double(right.getPercentage());
142: break;
143: case 1:
144: o1 = new Long(left.getTotalElapsedTime());
145: o2 = new Long(right.getTotalElapsedTime());
146: break;
147: case 2:
148: o1 = new Integer(left.getOccurences());
149: o2 = new Integer(right.getOccurences());
150: break;
151: case 3:
152: o1 = left.getTableNames();
153: o2 = right.getTableNames();
154: break;
155: case 4:
156: o1 = left.getColumnNames();
157: o2 = right.getColumnNames();
158: break;
159: }
160:
161: // If both values are null, return 0.
162: if (o1 == null && o2 == null) {
163: return 0;
164: } else if (o2 == null) { // Define null less than everything.
165: return 1 * ascending;
166: } else if (o1 == null) {
167: return -1 * ascending;
168: }
169:
170: if (o1 instanceof Number && o2 instanceof Number) {
171: Number n1 = (Number) o1;
172: double d1 = n1.doubleValue();
173: Number n2 = (Number) o2;
174: double d2 = n2.doubleValue();
175:
176: if (d1 == d2) {
177: return 0;
178: } else if (d1 > d2) {
179: return 1 * ascending;
180: } else {
181: return -1 * ascending;
182: }
183:
184: } else if (o1 instanceof Boolean && o2 instanceof Boolean) {
185: Boolean bool1 = (Boolean) o1;
186: boolean b1 = bool1.booleanValue();
187: Boolean bool2 = (Boolean) o2;
188: boolean b2 = bool2.booleanValue();
189:
190: if (b1 == b2) {
191: return 0;
192: } else if (b1) {
193: return 1 * ascending;
194: } else {
195: return -1 * ascending;
196: }
197:
198: } else {
199: // default case
200: if (o1 instanceof Comparable && o2 instanceof Comparable) {
201: Comparable c1 = (Comparable) o1;
202: Comparable c2 = (Comparable) o2; // superflous cast, no need for it!
203:
204: try {
205: return c1.compareTo(c2) * ascending;
206: } catch (ClassCastException cce) {
207: // forget it... we'll deal with them like 2 normal objects below.
208: }
209: }
210:
211: String s1 = o1.toString();
212: String s2 = o2.toString();
213: return s1.compareTo(s2) * ascending;
214: }
215: }
216:
217: /*
218: * This method sorts the rows using Java's Collections class.
219: * After sorting, it changes the state of the column -
220: * if the column was ascending, its new state is descending, and vice versa.
221: */
222: public void sort() {
223: Collections.sort(profileResults, this );
224: Integer val = (Integer) ascendCol.get(currCol);
225: ascendCol.remove(currCol);
226: if (val.equals(one)) // change the state of the column
227: ascendCol.add(currCol, minusOne);
228: else
229: ascendCol.add(currCol, one);
230: }
231:
232: public void sortByColumn(int column) {
233: this .currCol = column;
234: sort();
235: fireTableDataChanged();
236: }
237:
238: // Add a mouse listener to the Table to trigger a table sort
239: // when a column heading is clicked in the JTable.
240: public void addMouseListenerToHeaderInTable(JTable table) {
241: final ProfileResultTableModel sorter = this ;
242: final JTable tableView = table;
243: tableView.setColumnSelectionAllowed(false);
244: MouseAdapter listMouseListener = new MouseAdapter() {
245: public void mouseClicked(MouseEvent e) {
246: TableColumnModel columnModel = tableView
247: .getColumnModel();
248: int viewColumn = columnModel
249: .getColumnIndexAtX(e.getX());
250: int column = tableView
251: .convertColumnIndexToModel(viewColumn);
252: if (e.getClickCount() == 1 && column != -1) {
253: int shiftPressed = e.getModifiers()
254: & InputEvent.SHIFT_MASK;
255: boolean ascending = (shiftPressed == 0);
256: sorter.sortByColumn(column);
257: }
258: }
259: };
260: JTableHeader th = tableView.getTableHeader();
261: th.addMouseListener(listMouseListener);
262: }
263:
264: }
|