1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: Apache-2.0
7 #' Subcollection class represents a folder inside Arvados collection.
8 #' It is essentially a composite of arvadosFiles and other subcollections.
11 #' \preformatted{subcollection = Subcollection$new(name)}
13 #' @section Arguments:
15 #' \item{name}{Name of the subcollection.}
20 #' \item{getName()}{Returns name of the subcollection.}
21 #' \item{getRelativePath()}{Returns subcollection path relative to the root.}
22 #' \item{add(content)}{Adds ArvadosFile or Subcollection specified by content to the subcollection.}
23 #' \item{remove(name)}{Removes ArvadosFile or Subcollection specified by name from the subcollection.}
24 #' \item{get(relativePath)}{If relativePath is valid, returns ArvadosFile or Subcollection specified by relativePath, else returns NULL.}
25 #' \item{getFileListing()}{Returns subcollections file content as character vector.}
26 #' \item{getSizeInBytes()}{Returns subcollections content size in bytes.}
27 #' \item{move(destination)}{Moves subcollection to a new location inside collection.}
28 #' \item{copy(destination)}{Copies subcollection to a new location inside collection.}
31 #' @name Subcollection
34 #' myFolder <- Subcollection$new("myFolder")
35 #' myFile <- ArvadosFile$new("myFile")
37 #' myFolder$add(myFile)
38 #' myFolder$get("myFile")
39 #' myFolder$remove("myFile")
41 #' myFolder$move("newLocation/myFolder")
42 #' myFolder$copy("newLocation/myFolder")
47 Subcollection <- R6::R6Class(
53 initialize = function(name)
58 getName = function() private$name,
60 getRelativePath = function()
62 relativePath <- c(private$name)
63 parent <- private$parent
65 while(!is.null(parent))
67 relativePath <- c(parent$getName(), relativePath)
68 parent <- parent$getParent()
71 relativePath <- relativePath[relativePath != ""]
72 paste0(relativePath, collapse = "/")
75 add = function(content)
77 if("ArvadosFile" %in% class(content) ||
78 "Subcollection" %in% class(content))
80 if(!is.null(content$getCollection()))
81 stop("Content already belongs to a collection.")
83 if(content$getName() == "")
84 stop("Content has invalid name.")
86 childWithSameName <- self$get(content$getName())
88 if(!is.null(childWithSameName))
89 stop(paste("Subcollection already contains ArvadosFile",
90 "or Subcollection with same name."))
92 if(!is.null(private$collection))
94 if(self$getRelativePath() != "")
95 contentPath <- paste0(self$getRelativePath(),
96 "/", content$getFileListing())
98 contentPath <- content$getFileListing()
100 REST <- private$collection$getRESTService()
101 REST$create(contentPath, private$collection$uuid)
102 content$setCollection(private$collection)
105 private$children <- c(private$children, content)
106 content$setParent(self)
108 "Content added successfully."
112 stop(paste0("Expected AravodsFile or Subcollection object, got ",
113 paste0("(", paste0(class(content), collapse = ", "), ")"),
118 remove = function(name)
120 if(is.character(name))
122 child <- self$get(name)
125 stop(paste("Subcollection doesn't contains ArvadosFile",
126 "or Subcollection with specified name."))
128 if(!is.null(private$collection))
130 REST <- private$collection$getRESTService()
131 REST$delete(child$getRelativePath(), private$collection$uuid)
133 child$setCollection(NULL)
136 private$removeChild(name)
137 child$setParent(NULL)
143 stop(paste0("Expected character, got ",
144 paste0("(", paste0(class(name), collapse = ", "), ")"),
149 getFileListing = function(fullPath = TRUE)
151 content <- private$getContentAsCharVector(fullPath)
152 content[order(tolower(content))]
155 getSizeInBytes = function()
157 if(is.null(private$collection))
160 REST <- private$collection$getRESTService()
162 fileSizes <- REST$getResourceSize(paste0(self$getRelativePath(), "/"),
163 private$collection$uuid)
164 return(sum(fileSizes))
167 move = function(destination)
169 if(is.null(private$collection))
170 stop("Subcollection doesn't belong to any collection.")
172 destination <- trimFromEnd(destination, "/")
173 nameAndPath <- splitToPathAndName(destination)
175 newParent <- private$collection$get(nameAndPath$path)
177 if(is.null(newParent))
178 stop("Unable to get destination subcollection.")
180 childWithSameName <- newParent$get(nameAndPath$name)
182 if(!is.null(childWithSameName))
183 stop("Destination already contains content with same name.")
185 REST <- private$collection$getRESTService()
186 REST$move(self$getRelativePath(),
187 paste0(newParent$getRelativePath(), "/", nameAndPath$name),
188 private$collection$uuid)
190 private$dettachFromCurrentParent()
191 private$attachToNewParent(self, newParent)
193 private$parent <- newParent
194 private$name <- nameAndPath$name
199 copy = function(destination)
201 if(is.null(private$collection))
202 stop("Subcollection doesn't belong to any collection.")
204 destination <- trimFromEnd(destination, "/")
205 nameAndPath <- splitToPathAndName(destination)
207 newParent <- private$collection$get(nameAndPath$path)
209 if(is.null(newParent) || !("Subcollection" %in% class(newParent)))
210 stop("Unable to get destination subcollection.")
212 childWithSameName <- newParent$get(nameAndPath$name)
214 if(!is.null(childWithSameName))
215 stop("Destination already contains content with same name.")
217 REST <- private$collection$getRESTService()
218 REST$copy(self$getRelativePath(),
219 paste0(newParent$getRelativePath(), "/", nameAndPath$name),
220 private$collection$uuid)
222 newContent <- self$duplicate(nameAndPath$name)
223 newContent$setCollection(self$getCollection(), setRecursively = TRUE)
224 newContent$setParent(newParent)
225 private$attachToNewParent(newContent, newParent)
230 duplicate = function(newName = NULL)
232 name <- if(!is.null(newName)) newName else private$name
233 root <- Subcollection$new(name)
234 for(child in private$children)
235 root$add(child$duplicate())
242 for(child in private$children)
244 if(child$getName() == name)
251 getFirst = function()
253 if(length(private$children) == 0)
256 private$children[[1]]
259 setCollection = function(collection, setRecursively = TRUE)
261 private$collection = collection
265 for(child in private$children)
266 child$setCollection(collection)
270 getCollection = function() private$collection,
272 getParent = function() private$parent,
274 setParent = function(newParent) private$parent <- newParent
284 removeChild = function(name)
286 numberOfChildren = length(private$children)
287 if(numberOfChildren > 0)
289 for(childIndex in 1:numberOfChildren)
291 if(private$children[[childIndex]]$getName() == name)
293 private$children = private$children[-childIndex]
300 attachToNewParent = function(content, newParent)
302 # We temporary set parents collection to NULL. This will ensure that
303 # add method doesn't post this subcollection to REST.
304 # We also need to set content's collection to NULL because
305 # add method throws exception if we try to add content that already
306 # belongs to a collection.
307 parentsCollection <- newParent$getCollection()
308 content$setCollection(NULL, setRecursively = FALSE)
309 newParent$setCollection(NULL, setRecursively = FALSE)
310 newParent$add(content)
311 content$setCollection(parentsCollection, setRecursively = FALSE)
312 newParent$setCollection(parentsCollection, setRecursively = FALSE)
315 dettachFromCurrentParent = function()
317 # We temporary set parents collection to NULL. This will ensure that
318 # remove method doesn't remove this subcollection from REST.
319 parent <- private$parent
320 parentsCollection <- parent$getCollection()
321 parent$setCollection(NULL, setRecursively = FALSE)
322 parent$remove(private$name)
323 parent$setCollection(parentsCollection, setRecursively = FALSE)
326 getContentAsCharVector = function(fullPath = TRUE)
332 for(child in private$children)
333 content <- c(content, child$getFileListing())
335 if(private$name != "")
336 content <- unlist(paste0(private$name, "/", content))
340 for(child in private$children)
341 content <- c(content, child$getName())
351 #' print.Subcollection
353 #' Custom print function for Subcollection class
355 #' @param x Instance of Subcollection class
356 #' @param ... Optional arguments.
358 print.Subcollection = function(x, ...)
361 relativePath <- x$getRelativePath()
363 if(!is.null(x$getCollection()))
365 collection <- x$getCollection()$uuid
367 if(!x$getName() == "")
368 relativePath <- paste0("/", relativePath)
371 cat(paste0("Type: ", "\"", "Arvados Subcollection", "\""), sep = "\n")
372 cat(paste0("Name: ", "\"", x$getName(), "\""), sep = "\n")
373 cat(paste0("Relative path: ", "\"", relativePath, "\""), sep = "\n")
374 cat(paste0("Collection: ", "\"", collection, "\""), sep = "\n")