Extract tree data structure
[arvados-workbench2.git] / src / models / collection-file.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { uniqBy } from 'lodash';
6 import { KeepManifestStream, KeepManifestStreamFile, KeepManifest } from "./keep-manifest";
7 import { Tree, TreeNode, setNode, createTree } from './tree';
8
9 export type CollectionFilesTree = Tree<CollectionDirectory | CollectionFile>;
10
11 export enum CollectionFileType {
12     DIRECTORY = 'directory',
13     FILE = 'file'
14 }
15
16 export interface CollectionDirectory {
17     parentId: string;
18     id: string;
19     name: string;
20     type: CollectionFileType.DIRECTORY;
21 }
22
23 export interface CollectionFile {
24     parentId: string;
25     id: string;
26     name: string;
27     size: number;
28     type: CollectionFileType.FILE;
29 }
30
31 export const mapManifestToCollectionFilesTree = (manifest: KeepManifest): CollectionFilesTree =>
32     manifestToCollectionFiles(manifest)
33         .map(mapCollectionFileToTreeNode)
34         .reduce((tree, node) => setNode(node)(tree), createTree<CollectionFile>());
35
36
37 export const mapCollectionFileToTreeNode = (file: CollectionFile): TreeNode<CollectionFile> => ({
38     children: [],
39     id: file.id,
40     parent: file.parentId,
41     value: file
42 });
43
44 export const manifestToCollectionFiles = (manifest: KeepManifest): Array<CollectionDirectory | CollectionFile> => ([
45     ...mapManifestToDirectories(manifest),
46     ...mapManifestToFiles(manifest)
47 ]);
48
49 export const mapManifestToDirectories = (manifest: KeepManifest): CollectionDirectory[] =>
50     uniqBy(
51         manifest
52             .map(mapStreamDirectory)
53             .map(splitDirectory)
54             .reduce((all, splitted) => ([...all, ...splitted]), []),
55         directory => directory.id);
56
57 export const mapManifestToFiles = (manifest: KeepManifest): CollectionFile[] =>
58     manifest
59         .map(stream => stream.files.map(mapStreamFile(stream)))
60         .reduce((all, current) => ([...all, ...current]), []);
61
62 const splitDirectory = (directory: CollectionDirectory): CollectionDirectory[] => {
63     return directory.name
64         .split('/')
65         .slice(1)
66         .map(mapPathComponentToDirectory);
67 };
68
69 const mapPathComponentToDirectory = (component: string, index: number, components: string[]): CollectionDirectory =>
70     createDirectory({
71         parentId: index === 0 ? '' : joinPathComponents(components, index),
72         id: joinPathComponents(components, index + 1),
73         name: component,
74     });
75
76 const joinPathComponents = (components: string[], index: number) =>
77     `/${components.slice(0, index).join('/')}`;
78
79 const mapStreamDirectory = (stream: KeepManifestStream): CollectionDirectory =>
80     createDirectory({
81         parentId: '',
82         id: stream.name,
83         name: stream.name,
84     });
85
86 const mapStreamFile = (stream: KeepManifestStream) =>
87     (file: KeepManifestStreamFile): CollectionFile =>
88         createFile({
89             parentId: stream.name,
90             id: `${stream.name}/${file.name}`,
91             name: file.name,
92             size: file.size,
93         });
94
95 export const createDirectory = (data: Partial<CollectionDirectory>): CollectionDirectory => ({
96     id: '',
97     name: '',
98     parentId: '',
99     type: CollectionFileType.DIRECTORY,
100     ...data
101 });
102
103 export const createFile = (data: Partial<CollectionFile>): CollectionFile => ({
104     id: '',
105     name: '',
106     parentId: '',
107     size: 0,
108     type: CollectionFileType.FILE,
109     ...data
110 });