001    package org.shiftone.jrat.provider.tree.ui;
002    
003    
004    import org.shiftone.jrat.core.Accumulator;
005    import org.shiftone.jrat.core.MethodKey;
006    import org.shiftone.jrat.provider.tree.TreeNode;
007    import org.shiftone.jrat.util.collection.ArrayEnumeration;
008    import org.shiftone.jrat.util.log.Logger;
009    
010    import java.util.Arrays;
011    import java.util.Comparator;
012    import java.util.Enumeration;
013    import java.util.List;
014    
015    
016    /**
017     * @author jeff@shiftone.org (Jeff Drost)
018     */
019    public class TraceTreeNode implements javax.swing.tree.TreeNode {
020    
021        private static final Logger LOG = Logger.getLogger(TraceTreeNode.class);
022    
023        private final MethodKey methodKey;
024        private final Accumulator accumulator;
025    
026        private final Double averageMethodDuration;
027        private final long totalMethodDuration;
028    
029        private final int depth;
030        private final TraceTreeNode[] childArray;
031        private final TraceTreeNode parent;
032        private double pctOfAvgRootDuration;
033        private double pctOfAvgParentDuration;
034    
035        private int totalChildren;   // total # of children and all children's children
036        private int maxDepth;        // depth deepest child
037    
038    
039        public TraceTreeNode(TreeNode node) {
040            this(node, 0, null, null);
041        }
042    
043    
044        private TraceTreeNode(TreeNode node, int depth, TraceTreeNode parent, TraceTreeNode root) {
045    
046            this.methodKey = node.getMethodKey();
047            this.accumulator = node.getAccumulator();
048            this.depth = depth;
049            this.parent = parent;
050    
051    
052            if ((parent != null) && (getTotalExits() > 0)) {
053    
054                long parentTotalDuration = parent.getTotalDuration();
055    
056                if (parentTotalDuration > 0) {
057                    pctOfAvgParentDuration = (100.0 * getTotalDuration()) / parentTotalDuration;
058                }
059    
060            }
061    
062            if ((root != null) && (getTotalExits() > 0)) {
063    
064                long rootTotalDuration = root.getTotalDuration();
065    
066                if (rootTotalDuration > 0) {
067                    pctOfAvgRootDuration = (100.0 * getTotalDuration()) / rootTotalDuration;
068                }
069    
070            }
071    
072            List c = node.getChildren();  // <TreeNode>
073    
074            this.childArray = new TraceTreeNode[c.size()];
075    
076    
077            for (int i = 0; i < childArray.length; i++) {
078    
079                TreeNode childNode = (TreeNode) c.get(i);
080                TraceTreeNode childStackTreeNode = new TraceTreeNode(childNode, depth + 1, this, root);
081    
082                totalChildren += (1 + childStackTreeNode.totalChildren);
083                maxDepth = Math.max(maxDepth, 1 + childStackTreeNode.maxDepth);
084    
085                childArray[i] = childStackTreeNode;
086            }
087    
088            Arrays.sort(childArray, TotalChildrenComparator.INSTANCE);
089    
090    
091            { // total method duration
092    
093                long duration = getTotalDuration();
094    
095                for (int i = 0; i < childArray.length; i++) {
096                    duration -= childArray[i].getTotalDuration();
097                }
098    
099                totalMethodDuration = duration;
100            }
101    
102            { // average method duration
103    
104                if (getTotalExits() == 0) {
105                    averageMethodDuration = null;
106                } else {
107                    averageMethodDuration = new Double(totalMethodDuration / getTotalExits());
108                }
109            }
110    
111    //        this.rootAverageDurationNanos = (childOfRoot)
112    //                ? this.averageDurationNanos
113    //                : parent.rootAverageDurationNanos;
114    //
115    //        //
116    //        this.rootTotalDurationNanos = (childOfRoot)
117    //                ? node.getTotalDuration()
118    //                : parent.rootTotalDurationNanos;
119    //
120    //        if (rootAverageDurationNanos > 0) {
121    //            pctOfAvgRootDuration = (100.0 * averageDurationNanos) / rootAverageDurationNanos;
122    //        }
123    //
124    //        if (rootTotalDurationNanos > 0) {
125    //            pctOfRootTotalDuration = ((100.0 * node.getTotalDuration()) / rootTotalDurationNanos);
126    //        }
127        }
128    
129    
130        public int getMaxDepth() {
131            return maxDepth;
132        }
133    
134        public int getDepth() {
135            return depth;
136        }
137    
138    
139        public double getPctOfAvgParentDuration() {
140            return pctOfAvgParentDuration;
141        }
142    
143    
144        public double getPctOfAvgRootDuration() {
145            return pctOfAvgRootDuration;
146        }
147    
148        public Double getAverageMethodDuration() {
149            return averageMethodDuration;
150        }
151    
152        public long getTotalMethodDuration() {
153            return totalMethodDuration;
154        }
155    
156        // ----------------------------------------------------------
157    
158    
159        public int getMaxConcurrentThreads() {
160            return accumulator.getMaxConcurrentThreads();
161        }
162    
163        public long getSumOfSquares() {
164            return accumulator.getSumOfSquares();
165        }
166    
167        public Accumulator getAccumulator() {
168            return accumulator;
169        }
170    
171        public MethodKey getMethodKey() {
172            return methodKey;
173        }
174    
175        public Double getAverageDuration() {
176            return accumulator.getAverageDuration();
177        }
178    
179        public Double getStdDeviation() {
180            return accumulator.getStdDeviation();
181        }
182    
183        public long getTotalDuration() {
184            return accumulator.getTotalDuration();
185        }
186    
187        public int getConcurrentThreads() {
188            return accumulator.getConcurrentThreads();
189        }
190    
191        public long getTotalErrors() {
192            return accumulator.getTotalErrors();
193        }
194    
195        public long getTotalEnters() {
196            return accumulator.getTotalEnters();
197        }
198    
199        public long getTotalExits() {
200            return accumulator.getTotalExits();
201        }
202    
203        public long getMinDuration() {
204            return accumulator.getMinDuration();
205        }
206    
207    
208        public long getMaxDuration() {
209            return accumulator.getMaxDuration();
210        }
211    
212        public boolean isRootNode() {
213            return methodKey == null;
214        }
215    
216    
217        // -------------------------------------------------------------
218        public String toString() {
219    
220            return (isRootNode())
221                    ? "Root"
222                    : methodKey.getMethodName();
223        }
224    
225    
226        public Enumeration children() {
227            return new ArrayEnumeration(childArray);
228        }
229    
230    
231        public boolean getAllowsChildren() {
232            return true;
233        }
234    
235    
236        public javax.swing.tree.TreeNode getChildAt(int childIndex) {
237            return childArray[childIndex];
238        }
239    
240        public TraceTreeNode getChildNodeAt(int childIndex) {
241            return childArray[childIndex];
242        }
243    
244        public int getChildCount() {
245            return childArray.length;
246        }
247    
248    
249        public javax.swing.tree.TreeNode getParent() {
250            return parent;
251        }
252    
253        public TraceTreeNode getParentNode() {
254            return parent;
255        }
256    
257        public int getIndex(javax.swing.tree.TreeNode node) {
258            for (int i = 0; i < childArray.length; i++) {
259                if (node == childArray[i]) {
260                    return i;
261                }
262            }
263            return -1;
264        }
265    
266    
267        public boolean isLeaf() {
268            return (getChildCount() == 0);
269        }
270    
271    
272        private static class TotalChildrenComparator implements Comparator {
273    
274            private static final Comparator INSTANCE = new TotalChildrenComparator();
275    
276            public int compare(Object o1, Object o2) {
277    
278                TraceTreeNode stn1 = (TraceTreeNode) o1;
279                TraceTreeNode stn2 = (TraceTreeNode) o2;
280                int diff = stn1.totalChildren - stn2.totalChildren;
281    
282                return (diff == 0)
283                        ? 0
284                        : (diff < 0)
285                        ? 1
286                        : -1;
287            }
288        }
289    
290    
291    }