1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: Apache-2.0
9 #' Subcollection class represents a folder inside Arvados collection.
10 #' It is essentially a composite of arvadosFiles and other subcollections.
13 #' \preformatted{subcollection = Subcollection$new(name)}
15 #' @section Arguments:
17 #' \item{name}{Name of the subcollection.}
22 #' \item{getName()}{Returns name of the subcollection.}
23 #' \item{getRelativePath()}{Returns subcollection path relative to the root.}
24 #' \item{add(content)}{Adds ArvadosFile or Subcollection specified by content to the subcollection.}
25 #' \item{remove(name)}{Removes ArvadosFile or Subcollection specified by name from the subcollection.}
26 #' \item{get(relativePath)}{If relativePath is valid, returns ArvadosFile or Subcollection specified by relativePath, else returns NULL.}
27 #' \item{getFileListing()}{Returns subcollections file content as character vector.}
28 #' \item{getSizeInBytes()}{Returns subcollections content size in bytes.}
29 #' \item{move(destination)}{Moves subcollection to a new location inside collection.}
30 #' \item{copy(destination)}{Copies subcollection to a new location inside collection.}
33 #' @name Subcollection
36 #' myFolder <- Subcollection$new("myFolder")
37 #' myFile <- ArvadosFile$new("myFile")
39 #' myFolder$add(myFile)
40 #' myFolder$get("myFile")
41 #' myFolder$remove("myFile")
43 #' myFolder$move("newLocation/myFolder")
44 #' myFolder$copy("newLocation/myFolder")
49 Subcollection <- R6::R6Class(
55 initialize = function(name)
60 getName = function() private$name,
62 getRelativePath = function()
64 relativePath <- c(private$name)
65 parent <- private$parent
67 while(!is.null(parent))
69 relativePath <- c(parent$getName(), relativePath)
70 parent <- parent$getParent()
73 relativePath <- relativePath[relativePath != ""]
74 paste0(relativePath, collapse = "/")
77 add = function(content)
79 if("ArvadosFile" %in% class(content) ||
80 "Subcollection" %in% class(content))
82 if(!is.null(content$getCollection()))
83 stop("Content already belongs to a collection.")
85 if(content$getName() == "")
86 stop("Content has invalid name.")
88 childWithSameName <- self$get(content$getName())
90 if(!is.null(childWithSameName))
91 stop(paste("Subcollection already contains ArvadosFile",
92 "or Subcollection with same name."))
94 if(!is.null(private$collection))
96 if(self$getRelativePath() != "")
97 contentPath <- paste0(self$getRelativePath(),
98 "/", content$getFileListing())
100 contentPath <- content$getFileListing()
102 REST <- private$collection$getRESTService()
103 REST$create(contentPath, private$collection$uuid)
104 content$setCollection(private$collection)
107 private$children <- c(private$children, content)
108 content$setParent(self)
110 "Content added successfully."
114 stop(paste0("Expected AravodsFile or Subcollection object, got ",
115 paste0("(", paste0(class(content), collapse = ", "), ")"),
120 remove = function(name)
122 if(is.character(name))
124 child <- self$get(name)
127 stop(paste("Subcollection doesn't contains ArvadosFile",
128 "or Subcollection with specified name."))
130 if(!is.null(private$collection))
132 REST <- private$collection$getRESTService()
133 REST$delete(child$getRelativePath(), private$collection$uuid)
135 child$setCollection(NULL)
138 private$removeChild(name)
139 child$setParent(NULL)
145 stop(paste0("Expected character, got ",
146 paste0("(", paste0(class(name), collapse = ", "), ")"),
151 getFileListing = function(fullPath = TRUE)
153 content <- private$getContentAsCharVector(fullPath)
154 content[order(tolower(content))]
157 getSizeInBytes = function()
159 if(is.null(private$collection))
162 REST <- private$collection$getRESTService()
164 fileSizes <- REST$getResourceSize(paste0(self$getRelativePath(), "/"),
165 private$collection$uuid)
166 return(sum(fileSizes))
169 move = function(destination)
171 if(is.null(private$collection))
172 stop("Subcollection doesn't belong to any collection.")
174 destination <- trimFromEnd(destination, "/")
175 nameAndPath <- splitToPathAndName(destination)
177 newParent <- private$collection$get(nameAndPath$path)
179 if(is.null(newParent))
180 stop("Unable to get destination subcollection.")
182 childWithSameName <- newParent$get(nameAndPath$name)
184 if(!is.null(childWithSameName))
185 stop("Destination already contains content with same name.")
187 REST <- private$collection$getRESTService()
188 REST$move(self$getRelativePath(),
189 paste0(newParent$getRelativePath(), "/", nameAndPath$name),
190 private$collection$uuid)
192 private$dettachFromCurrentParent()
193 private$attachToNewParent(self, newParent)
195 private$parent <- newParent
196 private$name <- nameAndPath$name
201 copy = function(destination)
203 if(is.null(private$collection))
204 stop("Subcollection doesn't belong to any collection.")
206 destination <- trimFromEnd(destination, "/")
207 nameAndPath <- splitToPathAndName(destination)
209 newParent <- private$collection$get(nameAndPath$path)
211 if(is.null(newParent) || !("Subcollection" %in% class(newParent)))
212 stop("Unable to get destination subcollection.")
214 childWithSameName <- newParent$get(nameAndPath$name)
216 if(!is.null(childWithSameName))
217 stop("Destination already contains content with same name.")
219 REST <- private$collection$getRESTService()
220 REST$copy(self$getRelativePath(),
221 paste0(newParent$getRelativePath(), "/", nameAndPath$name),
222 private$collection$uuid)
224 newContent <- self$duplicate(nameAndPath$name)
225 newContent$setCollection(self$getCollection(), setRecursively = TRUE)
226 newContent$setParent(newParent)
227 private$attachToNewParent(newContent, newParent)
232 duplicate = function(newName = NULL)
234 name <- if(!is.null(newName)) newName else private$name
235 root <- Subcollection$new(name)
236 for(child in private$children)
237 root$add(child$duplicate())
244 for(child in private$children)
246 if(child$getName() == name)
253 getFirst = function()
255 if(length(private$children) == 0)
258 private$children[[1]]
261 setCollection = function(collection, setRecursively = TRUE)
263 private$collection = collection
267 for(child in private$children)
268 child$setCollection(collection)
272 getCollection = function() private$collection,
274 getParent = function() private$parent,
276 setParent = function(newParent) private$parent <- newParent
286 removeChild = function(name)
288 numberOfChildren = length(private$children)
289 if(numberOfChildren > 0)
291 for(childIndex in 1:numberOfChildren)
293 if(private$children[[childIndex]]$getName() == name)
295 private$children = private$children[-childIndex]
302 attachToNewParent = function(content, newParent)
304 # We temporary set parents collection to NULL. This will ensure that
305 # add method doesn't post this subcollection to REST.
306 # We also need to set content's collection to NULL because
307 # add method throws exception if we try to add content that already
308 # belongs to a collection.
309 parentsCollection <- newParent$getCollection()
310 content$setCollection(NULL, setRecursively = FALSE)
311 newParent$setCollection(NULL, setRecursively = FALSE)
312 newParent$add(content)
313 content$setCollection(parentsCollection, setRecursively = FALSE)
314 newParent$setCollection(parentsCollection, setRecursively = FALSE)
317 dettachFromCurrentParent = function()
319 # We temporary set parents collection to NULL. This will ensure that
320 # remove method doesn't remove this subcollection from REST.
321 parent <- private$parent
322 parentsCollection <- parent$getCollection()
323 parent$setCollection(NULL, setRecursively = FALSE)
324 parent$remove(private$name)
325 parent$setCollection(parentsCollection, setRecursively = FALSE)
328 getContentAsCharVector = function(fullPath = TRUE)
334 for(child in private$children)
335 content <- c(content, child$getFileListing())
337 if(private$name != "")
338 content <- unlist(paste0(private$name, "/", content))
342 for(child in private$children)
343 content <- c(content, child$getName())
353 #' print.Subcollection
355 #' Custom print function for Subcollection class
357 #' @param x Instance of Subcollection class
358 #' @param ... Optional arguments.
360 print.Subcollection = function(x, ...)
363 relativePath <- x$getRelativePath()
365 if(!is.null(x$getCollection()))
367 collection <- x$getCollection()$uuid
369 if(!x$getName() == "")
370 relativePath <- paste0("/", relativePath)
373 cat(paste0("Type: ", "\"", "Arvados Subcollection", "\""), sep = "\n")
374 cat(paste0("Name: ", "\"", x$getName(), "\""), sep = "\n")
375 cat(paste0("Relative path: ", "\"", relativePath, "\""), sep = "\n")
376 cat(paste0("Collection: ", "\"", collection, "\""), sep = "\n")