1 //---------------------------------------------------------------------
2 // <copyright file="TreePrinter.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 //---------------------------------------------------------------------
10 using System
.Collections
.Generic
;
11 using System
.Diagnostics
;
12 using System
.Globalization
;
15 namespace System
.Data
.Common
.Utils
18 /// Represents a node in a hierarchical collection of information strings.
19 /// Intended as a common way mechanism to represent tree structures for debugging (using the TreePrinter class).
20 /// A node consists of a string (represented as a StringBuilder), its collection of child nodes, and an optional Tag value.
22 internal class TreeNode
24 private StringBuilder _text
;
25 private List
<TreeNode
> _children
= new List
<TreeNode
>();
26 private int _position
;
28 // Default constructor
31 _text
= new StringBuilder();
35 /// Constructs a new TreeNode with the specified text, tag value and child nodes
37 /// <param name="text">The initial value of the new node's text</param>
38 /// <param name="children">An optional list of initial child nodes</param>
39 internal TreeNode(string text
, params TreeNode
[] children
)
41 if (string.IsNullOrEmpty(text
))
43 _text
= new StringBuilder();
47 _text
= new StringBuilder(text
);
52 _children
.AddRange(children
);
56 // IEnumerable convenience constructors
57 internal TreeNode(string text
, List
<TreeNode
> children
)
62 _children
.AddRange(children
);
66 // 'public' properties
69 /// The current text of this node.
71 internal StringBuilder Text { get { return _text; }
}
74 /// The collection of child nodes for this node, which may be empty.
76 internal IList
<TreeNode
> Children { get { return _children; }
}
78 // Used only by the TreePrinter when generating the output string
79 internal int Position { get { return _position; }
set { _position = value; }
}
83 /// Generates a formatted string from a hierarchy of tree nodes. Derived types may override
84 /// the PreProcess, Before/AfterAppend, Print, PrintNode and PrintChildren methods to add
85 /// specific functionality at particular points in process of building the string.
87 internal abstract class TreePrinter
89 #region Private Instance Members
91 private List
<TreeNode
> _scopes
= new List
<TreeNode
>();
92 private bool _showLines
= true;
93 private char _horizontals
= '_';
94 private char _verticals
= '|';
101 /// Entry point method for the TreePrinter
103 /// <param name="node">The TreeNode instance that is the root of the tree to be printed</param>
104 /// <returns>A string representation of the specified tree</returns>
105 internal virtual string Print(TreeNode node
)
107 this.PreProcess(node
);
109 StringBuilder text
= new StringBuilder();
110 PrintNode(text
, node
);
111 return text
.ToString();
116 #region 'Protected' API
118 // 'protected' constructor
119 internal TreePrinter() { }
121 // 'protected' API that may be overriden to customize printing
124 /// Called once on the root of the tree before printing begins
126 /// <param name="node">The TreeNode that is the root of the tree</param>
127 internal virtual void PreProcess(TreeNode node
) { }
130 /// Called once for every node after indentation, connecting lines and the node's text value
131 /// have been added to the output but before the line suffix (if any) has been added.
133 /// <param name="node">The current node</param>
134 /// <param name="text">The StringBuilder into which the tree is being printed</param>
135 internal virtual void AfterAppend(TreeNode node
, StringBuilder text
) { }
138 /// Called once for every node immediately after the line prefix (if any) and appropriate
139 /// indentation and connecting lines have been added to the output but before the node's
140 /// text value has been added.
142 /// <param name="node">The current node</param>
143 /// <param name="text">The StringBuilder into which the tree is being printed</param>
144 internal virtual void BeforeAppend(TreeNode node
, StringBuilder text
) { }
147 /// The recursive step of the printing process, called once for each TreeNode in the tree
149 /// <param name="text">The StringBuilder into which the tree is being printed</param>
150 /// <param name="node">The current node that should be printed to the StringBuilder</param>
151 internal virtual void PrintNode(StringBuilder text
, TreeNode node
)
155 this.BeforeAppend(node
, text
);
156 text
.Append(node
.Text
.ToString());
157 this.AfterAppend(node
, text
);
159 PrintChildren(text
, node
);
163 /// Called to recursively visit the child nodes of the current TreeNode.
165 /// <param name="text">The StringBuilder into which the tree is being printed</param>
166 /// <param name="node">The current node</param>
167 internal virtual void PrintChildren(StringBuilder text
, TreeNode node
)
171 foreach (TreeNode childNode
in node
.Children
)
175 PrintNode(text
, childNode
);
178 _scopes
.RemoveAt(_scopes
.Count
- 1);
183 #region Private Implementation
185 private void IndentLine(StringBuilder text
)
188 for (int scopeIdx
= 0; scopeIdx
< _scopes
.Count
; scopeIdx
++)
190 TreeNode parentScope
= _scopes
[scopeIdx
];
191 if (!_showLines
|| (parentScope
.Position
== parentScope
.Children
.Count
&& scopeIdx
!= _scopes
.Count
- 1))
197 text
.Append(_verticals
);
201 if (_scopes
.Count
== idx
&& _showLines
)
203 text
.Append(_horizontals
);