5f7a29455ae4a58aaae6792f6dd1eb26ae30ae4e
[arvados.git] / sdk / R / R / CollectionTree.R
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: Apache-2.0
4
5 source("./R/Subcollection.R")
6 source("./R/ArvadosFile.R")
7 source("./R/util.R")
8
9 CollectionTree <- R6::R6Class(
10     "CollectionTree",
11     public = list(
12
13         pathsList = NULL,
14
15         initialize = function(fileContent, collection)
16         {
17             self$pathsList <- fileContent
18             treeBranches <- sapply(fileContent, function(filePath) self$createBranch(filePath))
19             root <- Subcollection$new("")
20             sapply(treeBranches, function(branch) self$addBranch(root, branch))
21             root$setCollection(collection)
22             private$tree <- root
23         },
24
25         createBranch = function(filePath)
26         {
27             splitPath <- unlist(strsplit(filePath, "/", fixed = TRUE))
28             branch <- NULL
29             lastElementIndex <- length(splitPath)
30
31             for(elementIndex in lastElementIndex:1)
32             {
33                 if(elementIndex == lastElementIndex)
34                 {
35                     branch <- ArvadosFile$new(splitPath[[elementIndex]])
36                 }
37                 else
38                 {
39                     newFolder <- Subcollection$new(splitPath[[elementIndex]])
40                     newFolder$add(branch)
41                     branch <- newFolder
42                 }
43             }
44
45             branch
46         },
47
48         addBranch = function(container, node)
49         {
50             child <- container$get(node$getName())
51
52             if(is.null(child))
53             {
54                 # Make sure we are don't make any REST call while adding child
55                 collection <- container$getCollection()
56                 container$setCollection(NULL, setRecursively = FALSE)
57                 container$add(node)
58                 container$setCollection(collection, setRecursively = FALSE)
59             }
60             else
61             {
62                 # Note: REST always returns folder name alone before other folder
63                 # content, so in first iteration we don't know if it's a file
64                 # or folder since its just a name, so we assume it's a file.
65                 # If we encounter that same name again we know
66                 # it's a folder so we need to replace ArvadosFile with Subcollection.
67                 if("ArvadosFile" %in% class(child))
68                     child = private$replaceFileWithSubcollection(child)
69
70                 self$addBranch(child, node$getFirst())
71             }
72         },
73
74         getElement = function(relativePath)
75         {
76             relativePath <- trimFromStart(relativePath, "./")
77             relativePath <- trimFromEnd(relativePath, "/")
78
79             if(endsWith(relativePath, "/"))
80                 relativePath <- substr(relativePath, 0, nchar(relativePath) - 1)
81
82             splitPath <- unlist(strsplit(relativePath, "/", fixed = TRUE))
83             returnElement <- private$tree
84
85             for(pathFragment in splitPath)
86             {
87                 returnElement <- returnElement$get(pathFragment)
88
89                 if(is.null(returnElement))
90                     return(NULL)
91             }
92
93             returnElement
94         },
95
96         getTree = function() private$tree
97     ),
98
99     private = list(
100
101         tree = NULL,
102
103         replaceFileWithSubcollection = function(arvadosFile)
104         {
105             subcollection <- Subcollection$new(arvadosFile$getName())
106             fileParent <- arvadosFile$getParent()
107             fileParent$remove(arvadosFile$getName())
108             fileParent$add(subcollection)
109
110             arvadosFile$setParent(NULL)
111
112             subcollection
113         }
114     )
115 )