001    package org.shiftone.jrat.provider.tree;
002    
003    
004    import org.shiftone.jrat.core.Accumulator;
005    import org.shiftone.jrat.core.MethodKey;
006    import org.shiftone.jrat.util.log.Logger;
007    
008    import java.io.Externalizable;
009    import java.io.IOException;
010    import java.io.ObjectInput;
011    import java.io.ObjectOutput;
012    import java.util.ArrayList;
013    import java.util.HashMap;
014    import java.util.List;
015    
016    
017    /**
018     * Class TreeNode
019     *
020     * @author jeff@shiftone.org (Jeff Drost)
021     */
022    public class TreeNode implements Externalizable {
023    
024        private static final Logger LOG = Logger.getLogger(TreeNode.class);
025        private static final long serialVersionUID = 1;
026        protected MethodKey methodKey;
027        protected TreeNode parent;
028        private Accumulator accumulator;
029        protected HashMap children = new HashMap(5);
030    
031    
032        public void writeExternal(ObjectOutput out) throws IOException {
033    
034            out.writeObject(accumulator);
035            out.writeObject(methodKey);
036    
037            // column a copy of the children
038            List list = getChildren();
039    
040            // write a child count
041            int childCount = list.size();
042            out.writeInt(childCount);
043    
044            // write the children
045            for (int i = 0; i < childCount; i++) {
046                TreeNode child = (TreeNode) list.get(i);
047                child.writeExternal(out);
048            }
049        }
050    
051        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
052    
053            this.accumulator = (Accumulator) in.readObject();
054            this.methodKey = (MethodKey) in.readObject();
055    
056            int childCount = in.readInt();
057            for (int i = 0; i < childCount; i++) {
058    
059                TreeNode child = new TreeNode();
060    
061                child.readExternal(in);
062    
063                children.put(child.getMethodKey(), child);
064                child.parent = this;
065            }
066    
067        }
068    
069        public TreeNode() {
070    
071            // root node
072            this.methodKey = null;
073            this.parent = null;
074            this.accumulator = new Accumulator();
075        }
076    
077    
078        public TreeNode(MethodKey methodKey, TreeNode treeNode) {
079            this.methodKey = methodKey;
080            this.parent = treeNode;
081            this.accumulator = new Accumulator();
082        }
083    
084        public List getChildren() {
085    
086            List list = new ArrayList();
087    
088            synchronized (children) {
089                list.addAll(children.values());
090            }
091    
092            return list;
093        }
094    
095    
096        /**
097         * Method gets <b>AND CREATES IF NEEDED</b> the requested tree node
098         */
099        public TreeNode getChild(MethodKey methodKey) {
100    
101            TreeNode treeNode = null;
102    
103            synchronized (children) {
104                treeNode = (TreeNode) children.get(methodKey);
105    
106                if (treeNode == null) {
107                    treeNode = new TreeNode(methodKey, this);
108    
109                    children.put(methodKey, treeNode);
110                }
111            }
112    
113            return treeNode;
114        }
115    
116    
117        public final TreeNode getParentNode() {
118            return parent;
119        }
120    
121    
122        public final boolean isRootNode() {
123            return (methodKey == null);
124        }
125    
126    
127        public Accumulator getAccumulator() {
128            return accumulator;
129        }
130    
131        public MethodKey getMethodKey() {
132            return methodKey;
133        }
134    
135        // ---------------------------------------------------------------
136    
137        public synchronized void reset() {
138    
139            // need to clone map - concurrency issues
140            List list = new ArrayList();
141    
142            synchronized (children) {
143                list.addAll(children.values());
144            }
145    
146            for (int i = 0; i < list.size(); i++) {
147                TreeNode treeNode = (TreeNode) list.get(i);
148    
149                treeNode.reset();
150            }
151    
152            accumulator.reset();  // this is the actual call to reset
153        }
154    
155    
156    }