Create a function for appending a subtree to existing tree
authorMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Wed, 14 Nov 2018 12:03:36 +0000 (13:03 +0100)
committerMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Wed, 14 Nov 2018 12:03:36 +0000 (13:03 +0100)
Feature #14471

Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski@contractors.roche.com>

src/models/tree.test.ts
src/models/tree.ts

index 54b11d47aadd2795cc32f8ce1f2ef095270d9b8e..3c7fdca9afdee6357b204ac4f4edad199155d79b 100644 (file)
@@ -18,6 +18,14 @@ describe('Tree', () => {
         expect(Tree.getNode('Node 1')(newTree)).toEqual(initTreeNode({ id: 'Node 1', value: 'Value 1' }));
     });
 
+    it('appends a subtree', () => {
+        const newTree = Tree.setNode(initTreeNode({ id: 'Node 1', value: 'Value 1' }))(tree);
+        const subtree = Tree.setNode(initTreeNode({ id: 'Node 2', value: 'Value 2' }))(Tree.createTree());
+        const mergedTree = Tree.appendSubtree('Node 1', subtree)(newTree);
+        expect(Tree.getNode('Node 1')(mergedTree)).toBeDefined();
+        expect(Tree.getNode('Node 2')(mergedTree)).toBeDefined();
+    });
+
     it('adds new node reference to parent children', () => {
         const newTree = pipe(
             Tree.setNode(initTreeNode({ id: 'Node 1', parent: '', value: 'Value 1' })),
@@ -89,6 +97,6 @@ describe('Tree', () => {
             initTreeNode({ id: 'Node 2', parent: 'Node 1', value: 'Value 2' }),
         ].reduce((tree, node) => Tree.setNode(node)(tree), tree);
         const mappedTree = Tree.mapTreeValues<string, number>(value => parseInt(value.split(' ')[1], 10))(newTree);
-        expect(Tree.getNode('Node 2')(mappedTree)).toEqual(initTreeNode({id: 'Node 2', parent: 'Node 1', value: 2 }));
+        expect(Tree.getNode('Node 2')(mappedTree)).toEqual(initTreeNode({ id: 'Node 2', parent: 'Node 1', value: 2 }));
     });
 });
index 8e18f9fab78cd9e9ee27a2a9345aa1e5b223cd58..fe52a97b0fcdd3806579318d968f2efc8206f364 100644 (file)
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { pipe } from 'lodash/fp';
+import { pipe, map, reduce } from 'lodash/fp';
 export type Tree<T> = Record<string, TreeNode<T>>;
 
 export const TREE_ROOT_ID = '';
@@ -34,6 +34,13 @@ export const createTree = <T>(): Tree<T> => ({});
 
 export const getNode = (id: string) => <T>(tree: Tree<T>): TreeNode<T> | undefined => tree[id];
 
+export const appendSubtree = <T>(id: string, subtree: Tree<T>) => (tree: Tree<T>) =>
+    pipe(
+        getNodeDescendants(''),
+        map(node => node.parent === '' ? { ...node, parent: id } : node),
+        reduce((newTree, node) => setNode(node)(newTree), tree)
+    )(subtree) as Tree<T>;
+
 export const setNode = <T>(node: TreeNode<T>) => (tree: Tree<T>): Tree<T> => {
     return pipe(
         (tree: Tree<T>) => getNode(node.id)(tree) === node