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    }