using System;
using System.Collections.Generic;
using System.Linq;
namespace ZeroLevel.Services.Trees
{
public static class TreesVisitor
{
///
/// Extract tree branches to plain array
///
/// Node type
/// Tree root
/// Extractor of node children
/// Array of tree branches
public static List ExtractBranches(T root, Func> childrenExtractor)
{
if (root == null!)
throw new ArgumentNullException(nameof(root));
if (childrenExtractor == null!)
throw new ArgumentNullException(nameof(childrenExtractor));
var result = new List();
TraversTreeBrunches(root, childrenExtractor, brunch =>
{
result.Add(brunch.ToArray());
});
return result;
}
///
/// Selects all branches of the tree, returning an array of branches consisting of the specified node values.
///
/// Type of tree nodes
/// Value type for returned branch elements
/// Root
/// Selects child nodes for the current node.
/// Select the value of the node
/// List of tree branches
public static List SpecifyExtractBranches(T root,
Func> childrenExtractor,
Func codeExtractor)
{
if (root == null!)
throw new ArgumentNullException(nameof(root));
if (childrenExtractor == null!)
throw new ArgumentNullException(nameof(childrenExtractor));
if (codeExtractor == null!)
throw new ArgumentNullException(nameof(codeExtractor));
var result = new List();
TraversTreeBrunches(root, childrenExtractor, brunch =>
{
result.Add(brunch.Select(i => codeExtractor(i)).ToArray());
});
return result;
}
///
/// Performs tree branch traversal.
///
public static void TraversTreeBrunches(T root,
Func> childrenExtractor,
Action> handler)
{
if (root == null!)
throw new ArgumentNullException(nameof(root));
if (childrenExtractor == null!)
throw new ArgumentNullException(nameof(childrenExtractor));
if (handler == null!)
throw new ArgumentNullException(nameof(handler));
var brunch = new List();
brunch.Add(root);
foreach (var child in childrenExtractor(root))
{
TraversNode(child, brunch, childrenExtractor, handler);
}
}
private static void TraversNode(T node, List brunch, Func> childrenExtractor, Action> handler)
{
if (node == null!)
{
handler(brunch);
return;
}
var currentBrunch = new List(brunch);
currentBrunch.Add(node);
var children = childrenExtractor(node);
if (children != null && children.Any())
{
foreach (var child in childrenExtractor(node))
{
TraversNode(child, currentBrunch, childrenExtractor, handler);
}
}
else
{
handler(currentBrunch);
}
}
}
}