001 package org.shiftone.jrat.provider.tree.ui.trace.stack; 002 003 004 import org.shiftone.jrat.core.MethodKey; 005 import org.shiftone.jrat.desktop.util.Table; 006 import org.shiftone.jrat.provider.tree.ui.TraceTreeNode; 007 import org.shiftone.jrat.util.Percent; 008 import org.shiftone.jrat.util.log.Logger; 009 010 import javax.swing.table.AbstractTableModel; 011 import java.util.ArrayList; 012 import java.util.List; 013 014 015 /** 016 * Class StackTableModel 017 * 018 * @author jeff@shiftone.org (Jeff Drost) 019 */ 020 public class StackTableModel extends AbstractTableModel { 021 022 private static final Logger LOG = Logger.getLogger(StackTableModel.class); 023 private List stack = new ArrayList(); 024 private long rootTotalDuration; 025 026 private static final Table TABLE = new Table(); // enum please? 027 public static final Table.Column PACKAGE = TABLE.column("Package", false); 028 public static final Table.Column CLASS = TABLE.column("Class"); 029 public static final Table.Column METHOD = TABLE.column("Method"); 030 public static final Table.Column SIGNATURE = TABLE.column("Signature"); 031 public static final Table.Column ENTERS = TABLE.column("Enters", false); 032 public static final Table.Column EXITS = TABLE.column("Exits"); 033 public static final Table.Column ERRORS = TABLE.column("Errors", false); 034 public static final Table.Column THREADS = TABLE.column("Concurrent Threads", false); 035 public static final Table.Column TOTAL = TABLE.column("Total ms"); 036 public static final Table.Column AVERAGE = TABLE.column("Average ms", false); 037 public static final Table.Column TOTAL_METHOD = TABLE.column("Total Method ms"); 038 public static final Table.Column AVERAGE_METHOD = TABLE.column("Average Method ms"); 039 public static final Table.Column STANDARD_DEVIATION = TABLE.column("Standard Deviation", false); 040 public static final Table.Column MIN = TABLE.column("Min ms", false); 041 public static final Table.Column MAX = TABLE.column("Max ms", false); 042 public static final Table.Column PERCENT_OF_PARENT = TABLE.column("% of Parent"); 043 public static final Table.Column PERCENT_OF_ROOT = TABLE.column("% of Root"); 044 045 046 public Object getValueAt(int rowIndex, int columnIndex) { 047 048 TraceTreeNode node = (TraceTreeNode) stack.get(rowIndex); 049 MethodKey methodKey = node.getMethodKey(); 050 051 if (methodKey == null) { 052 return "?"; 053 } 054 055 // yea, an enum would be nice 056 057 if (columnIndex == PACKAGE.getIndex()) { 058 return methodKey.getPackageName(); 059 } 060 if (columnIndex == CLASS.getIndex()) { 061 return methodKey.getClassName(); 062 } 063 if (columnIndex == METHOD.getIndex()) { 064 return methodKey.getMethodName(); 065 } 066 if (columnIndex == SIGNATURE.getIndex()) { 067 return methodKey.getSig().getShortText(); 068 } 069 070 if (columnIndex == ENTERS.getIndex()) { 071 return new Long(node.getTotalEnters()); 072 } 073 if (columnIndex == EXITS.getIndex()) { 074 return new Long(node.getTotalExits()); 075 } 076 if (columnIndex == ERRORS.getIndex()) { 077 return new Long(node.getTotalErrors()); 078 } 079 080 if (columnIndex == THREADS.getIndex()) { 081 return new Integer(node.getMaxConcurrentThreads()); 082 } 083 if (columnIndex == TOTAL.getIndex()) { 084 return new Long(node.getTotalDuration()); 085 } 086 if (columnIndex == AVERAGE.getIndex()) { 087 return node.getAverageDuration(); 088 } 089 if (columnIndex == TOTAL_METHOD.getIndex()) { 090 return new Long(node.getTotalMethodDuration()); 091 } 092 if (columnIndex == AVERAGE_METHOD.getIndex()) { 093 return node.getAverageMethodDuration(); 094 } 095 096 if (columnIndex == STANDARD_DEVIATION.getIndex()) { 097 return node.getStdDeviation(); 098 } 099 if (columnIndex == MIN.getIndex()) { 100 return new Long(node.getMinDuration()); 101 } 102 if (columnIndex == MAX.getIndex()) { 103 return new Long(node.getMaxDuration()); 104 } 105 if (columnIndex == PERCENT_OF_PARENT.getIndex()) { 106 return new Percent(node.getPctOfAvgParentDuration()); 107 } 108 if (columnIndex == PERCENT_OF_ROOT.getIndex()) { 109 return new Percent(getPctOfAvgRootDuration(node)); 110 } 111 112 return null; 113 } 114 115 public synchronized void setStackTreeNode(TraceTreeNode root, TraceTreeNode node) { 116 117 List newStack = new ArrayList(); 118 TraceTreeNode currNode = node; 119 120 while (currNode.getParent() != null) { 121 newStack.add(currNode); 122 123 if (currNode == root) { 124 break; 125 } 126 127 currNode = currNode.getParentNode(); 128 } 129 130 // ------------------------------------- 131 // I'm calcing the %of root on the fly - which allows any node to be 132 // set as the root node of the view. To do that, I need to know the 133 // total 134 // duration of the effective root. aka the last node on the stack. 135 // this is different from "root" because the that object may be the 136 // fake base node. 137 if (newStack.isEmpty()) { 138 rootTotalDuration = 0; 139 } else { 140 TraceTreeNode viewRoot = (TraceTreeNode) newStack.get(newStack.size() - 1); 141 142 rootTotalDuration = viewRoot.getTotalDuration(); 143 } 144 145 stack = newStack; 146 147 fireTableDataChanged(); 148 } 149 150 151 public int getRowCount() { 152 return stack.size(); 153 } 154 155 156 public static List getColumns() { 157 return TABLE.getColumns(); 158 } 159 160 public int getColumnCount() { 161 return TABLE.getColumnCount(); 162 } 163 164 165 public String getColumnName(int columnIndex) { 166 return TABLE.getColumn(columnIndex).getName(); 167 } 168 169 170 public Class getColumnClass(int columnIndex) { 171 return TABLE.getColumn(columnIndex).getType(); 172 } 173 174 175 public boolean isCellEditable(int rowIndex, int columnIndex) { 176 return false; 177 } 178 179 180 public double getPctOfAvgRootDuration(TraceTreeNode node) { 181 182 return (rootTotalDuration > 0) 183 ? ((100.0 * node.getTotalDuration()) / rootTotalDuration) 184 : 0; 185 } 186 }