/** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ export class Tree { /** @internal */ _root: TreeNode; constructor(root: TreeNode) { this._root = root; } get root(): T { return this._root.value; } /** * @internal */ parent(t: T): T|null { const p = this.pathFromRoot(t); return p.length > 1 ? p[p.length - 2] : null; } /** * @internal */ children(t: T): T[] { const n = findNode(t, this._root); return n ? n.children.map(t => t.value) : []; } /** * @internal */ firstChild(t: T): T|null { const n = findNode(t, this._root); return n && n.children.length > 0 ? n.children[0].value : null; } /** * @internal */ siblings(t: T): T[] { const p = findPath(t, this._root); if (p.length < 2) return []; const c = p[p.length - 2].children.map(c => c.value); return c.filter(cc => cc !== t); } /** * @internal */ pathFromRoot(t: T): T[] { return findPath(t, this._root).map(s => s.value); } } // DFS for the node matching the value function findNode(value: T, node: TreeNode): TreeNode|null { if (value === node.value) return node; for (const child of node.children) { const node = findNode(value, child); if (node) return node; } return null; } // Return the path to the node with the given value using DFS function findPath(value: T, node: TreeNode): TreeNode[] { if (value === node.value) return [node]; for (const child of node.children) { const path = findPath(value, child); if (path.length) { path.unshift(node); return path; } } return []; } export class TreeNode { constructor(public value: T, public children: TreeNode[]) {} toString(): string { return `TreeNode(${this.value})`; } } // Return the list of T indexed by outlet name export function nodeChildrenAsMap(node: TreeNode|null) { const map: {[outlet: string]: TreeNode} = {}; if (node) { node.children.forEach(child => map[child.value.outlet] = child); } return map; }