singrdk/base/Windows/AppReader/AppTree.cs

147 lines
3.9 KiB
C#

// ----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ----------------------------------------------------------------------------
namespace AppReader
{
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
public class AppTree
{
AppNode top;
public AppTree(AppNode top)
{
this.top = top;
}
public AppTree(AppTree other)
{
// we just walk the other tree and get a new copy
this.top = other.top.Copy(null);
}
public void IncrementNode(string treePath)
{
IncrementNode(treePath, 1);
return;
}
public void IncrementWithHashtable(Hashtable whash)
{
// a hashtable of paths in the tree and the weights of their endpoints
// we just walk through the things we found and increment them in the tree
// if they exist in the wxvals hashtable
IEnumerator ienum = whash.GetEnumerator();
while (ienum.MoveNext())
{
string key = (string)((DictionaryEntry)ienum.Current).Key;
int val = (int)((DictionaryEntry)ienum.Current).Value;
this.IncrementNode(key, val);
}
return;
}
public void Dump()
{
if (top != null)
{
Console.WriteLine("\nAppTree");
top.Dump("");
}
return;
}
// this method converts a tree to a representation over which we can do clustering.
// We add the sum of the weights of the children to the weight of their parent
// so that we preserve the tree structure in the data, and then we do a post-order
// traversal of the tree to get our ArrayList of weights. It is thus critical that
// all trees have the same structure and order, but our code guarantees this property.
public ArrayList Flatten()
{
ArrayList ar = new ArrayList();
AppTree treeToFlatten = new AppTree(this);
treeToFlatten.top.Weight();
treeToFlatten.top.Flatten(ar);
return ar;
}
public void IncrementNode(string treePath, int count)
{
// HACK: 10 is a magic number. I just don't think
// my resource trees will ever be 10 deep
string[] pathstr = treePath.Split(new char[] {' '}, 10);
AppNode curNode = top;
for (int i = 0; i < pathstr.Length; i++)
{
if (pathstr[i].Equals("")) continue;
// find the child that has the right name
bool found = false;
for (int j = 0; j < curNode.NumChildren; j++)
{
if (curNode[j].Name == pathstr[i])
{
curNode = curNode[j];
found = true;
break;
}
}
Debug.Assert(found);
}
curNode.Increment(count);
return;
}
public static AppTree CreateAppTree(string filename)
{
// parse the app tree structure here
StreamReader ios = new StreamReader(filename);
string curLine;
// this is the first node we create
AppNode top = null;
AppNode lastNode = null;
int lastTabCount = 0;
while ((curLine = ios.ReadLine()) != null)
{
int tabcount = curLine.LastIndexOf("\t");
tabcount++;
//Console.WriteLine("Got tabcount {0}", tabcount);
Debug.Assert(tabcount >= 0);
string name = curLine.Substring(tabcount);
AppNode parent = lastNode == null ? null : lastNode.Parent;
if (tabcount < lastTabCount)
{
// then walk up the tree to the new parent
int diff = lastTabCount - tabcount;
while (diff-- > 0)
{
parent = parent.Parent;
Debug.Assert(parent != null);
}
}
else if (tabcount > lastTabCount) {
parent = lastNode;
Debug.Assert(tabcount == lastTabCount + 1);
}
// this automatically joins this node to its parent in the tree
AppNode tempNode = new AppNode(name, parent);
if (top == null)
{
Debug.Assert(tabcount == 0);
top = tempNode;
}
lastNode = tempNode;
lastTabCount = tabcount;
}
AppTree outtree = new AppTree(top);
return outtree;
}
}
}