package com.jetbrains.actionscript.profiler.calltree;
import com.jetbrains.actionscript.profiler.base.FilePathProducer;
import com.jetbrains.actionscript.profiler.base.FrameInfoProducer;
import com.jetbrains.actionscript.profiler.sampler.FrameInfo;
import gnu.trove.THashMap;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
class CallTreeNode implements FrameInfoProducer, FilePathProducer {
private final FrameInfo frameInfo;
private long duration;
private final THashMap<FrameInfo, CallTreeNode> children = new THashMap<>();
public CallTreeNode() {
frameInfo = null;
}
public CallTreeNode(FrameInfo frameInfo, long duration) {
this.frameInfo = frameInfo;
this.duration = duration;
}
public FrameInfo getFrameInfo() {
return frameInfo;
}
public long getCumulativeTiming() {
return duration;
}
public void addChildrenRecursive(List<CallTreeNode> children) {
for (CallTreeNode child : children) {
addChildRecursive(child);
}
}
void addChildRecursive(CallTreeNode newChildNode) {
CallTreeNode child = findChildByName(newChildNode.getFrameInfo());
if (child != null) {
child.duration += newChildNode.getCumulativeTiming();
for (CallTreeNode node : newChildNode.getChildren()) {
child.addChildRecursive(node);
}
}
else {
addChild(newChildNode);
}
}
private void addChild(CallTreeNode newChildNode) {
children.put(newChildNode.getFrameInfo(), newChildNode);
}
@Nullable
public CallTreeNode findChildByName(FrameInfo frame) {
return children.get(frame);
}
int calcSelfTiming() {
int count = 0;
for (CallTreeNode child : children.values()) {
count += child.getCumulativeTiming();
}
return count;
}
List<CallTreeNode> getChildren() {
return new ArrayList<>(children.values());
}
@Override
public boolean equals(Object obj) {
/*
* compare references cause we don't have needed information
* nodes equal if and only if they have same parent
* we may have many nodes with the same name and children e.g. in recursive functions
*/
return obj == this;
}
@Override
public String toString() {
return frameInfo.toString() + " (" + children.size() + ")";
}
public void addChildren(List<FrameInfo> reversedFrames, long duration) {
CallTreeNode node = this;
for (FrameInfo frame : reversedFrames) {
CallTreeNode child = node.findChildByName(frame);
if (child == null) {
child = new CallTreeNode(frame, 0);
node.addChild(child);
}
child.duration += duration;
node = child;
}
}
@Override
public String getFilePath() {
return frameInfo.getFilePath();
}
@Nullable
public CallTreeNode getChildDeep(FrameInfo[] frames) {
CallTreeNode currentNode = this;
for (FrameInfo frame : frames) {
currentNode = currentNode.findChildByName(frame);
if (currentNode == null) {
return null;
}
}
return currentNode;
}
}