blob: 30f8850dc59242532d8dbc3dec27f880af24573d [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.idea.editors.hprof.views.nodedata;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.TreeNode;
import java.util.*;
public class HeapPackageNode implements HeapNode {
@Nullable private HeapNode myParent;
@NotNull private List<HeapNode> myChildren = new ArrayList<HeapNode>();
@NotNull private HashMap<String, HeapPackageNode> mySubPackages = new HashMap<String, HeapPackageNode>();
@NotNull private Set<HeapClassObjNode> myClasses = new HashSet<HeapClassObjNode>();
@SuppressWarnings("NullableProblems") @NotNull private String myFullPackageName;
@NotNull private String myPackageName;
private int myTotalCount;
private int myHeapInstanceCount;
private int myShallowSize;
private long myRetainedSize;
public HeapPackageNode(@Nullable HeapPackageNode parent, @NotNull String packageName) {
myPackageName = packageName;
setParent(parent);
}
public void update(int currentHeapId) {
myRetainedSize = 0;
for (HeapPackageNode heapPackageNode : mySubPackages.values()) {
heapPackageNode.update(currentHeapId);
updateCounts(heapPackageNode, currentHeapId);
}
for (HeapClassObjNode heapClassObjNode : myClasses) {
updateCounts(heapClassObjNode, currentHeapId);
}
}
private void updateCounts(@NotNull HeapNode heapNode, int currentHeapId) {
myTotalCount += heapNode.getTotalCount();
myHeapInstanceCount += heapNode.getHeapInstancesCount(currentHeapId);
myShallowSize += heapNode.getShallowSize(currentHeapId);
myRetainedSize += heapNode.getRetainedSize();
}
public void classifyClassObj(@NotNull HeapClassObjNode heapClassObjNode) {
String className = heapClassObjNode.getClassObj().getClassName();
assert className.startsWith(myFullPackageName) && className.length() > myFullPackageName.length() + 1; // Mind the dot.
String remainder = myFullPackageName.isEmpty() ? className : className.substring(myFullPackageName.length() + 1);
int dotIndex = remainder.indexOf('.');
if (dotIndex > 0) {
assert remainder.length() > 0;
String subPackageName = remainder.substring(0, dotIndex);
HeapPackageNode heapPackageNode = mySubPackages.get(subPackageName);
if (heapPackageNode == null) {
heapPackageNode = new HeapPackageNode(this, subPackageName);
mySubPackages.put(subPackageName, heapPackageNode);
}
heapPackageNode.classifyClassObj(heapClassObjNode);
}
else {
myClasses.add(heapClassObjNode);
}
}
public void clear() {
removeAllChildren();
mySubPackages.clear();
myClasses.clear();
myTotalCount = 0;
myHeapInstanceCount = 0;
myShallowSize = 0;
myRetainedSize = 0;
}
@NotNull
@Override
public String getFullName() {
return myFullPackageName;
}
@NotNull
@Override
public String getSimpleName() {
return myPackageName;
}
@Override
public int getTotalCount() {
return myTotalCount;
}
@Override
public int getHeapInstancesCount(int heapId) {
return myHeapInstanceCount;
}
@Override
public int getInstanceSize() {
return -1;
}
@Override
public int getShallowSize(int heapId) {
return myShallowSize;
}
@Override
public long getRetainedSize() {
return myRetainedSize;
}
@Override
public void add(@NotNull HeapNode heapNode) {
heapNode.removeFromParent();
heapNode.setParent(this);
myChildren.add(heapNode);
}
@NotNull
@Override
public List<HeapNode> getChildren() {
return myChildren;
}
@Override
public void removeAllChildren() {
for (HeapNode child : myChildren) {
child.setParent(null);
}
myChildren.clear();
}
@NotNull
public HashMap<String, HeapPackageNode> getSubPackages() {
return mySubPackages;
}
public void buildTree() {
for (HeapPackageNode heapPackageNode : mySubPackages.values()) {
add(heapPackageNode);
heapPackageNode.buildTree();
}
for (HeapClassObjNode heapClassObjNode : myClasses) {
// TODO: Handle inner/anonymous classes.
add(heapClassObjNode);
}
}
@Override
public TreeNode getChildAt(int childIndex) {
return myChildren.get(childIndex);
}
@Override
public int getChildCount() {
return myChildren.size();
}
@Override
public TreeNode getParent() {
return myParent;
}
@Override
public int getIndex(TreeNode node) {
assert node instanceof HeapNode;
return myChildren.indexOf(node);
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public boolean isLeaf() {
return myChildren.size() == 0;
}
@Override
public Enumeration children() {
return Collections.enumeration(myChildren);
}
public void remove(@NotNull HeapNode node) {
myChildren.remove(node);
}
@Override
public void removeFromParent() {
if (myParent != null) {
assert myParent instanceof HeapPackageNode;
((HeapPackageNode)myParent).remove(this);
setParent(null);
}
}
@Override
public void setParent(@Nullable HeapNode newParent) {
assert newParent == null || newParent instanceof HeapPackageNode;
myParent = newParent;
myFullPackageName = myParent == null || myParent.getFullName().isEmpty() ? myPackageName : myParent.getFullName() + "." + myPackageName;
}
}