Implement copy method, update move method and remove trailing
[arvados.git] / sdk / R / R / Collection.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/RESTService.R")
8 source("./R/util.R")
9
10 #' Collection
11 #'
12 #' Collection class provides interface for working with Arvados collections.
13 #'
14 #' @section Usage:
15 #' \preformatted{collection = Collection$new(arv, uuid)}
16 #'
17 #' @section Arguments:
18 #' \describe{
19 #'   \item{arv}{Arvados object.}
20 #'   \item{uuid}{UUID of a collection.}
21 #' }
22 #'
23 #' @section Methods:
24 #' \describe{
25 #'   \item{add(content)}{Adds ArvadosFile or Subcollection specified by content to the collection.}
26 #'   \item{create(fileNames, relativePath = "")}{Creates one or more ArvadosFiles and adds them to the collection at specified path.}
27 #'   \item{remove(fileNames)}{Remove one or more files from the collection.}
28 #'   \item{move(content, newLocation)}{Moves ArvadosFile or Subcollection to another location in the collection.}
29 #'   \item{getFileListing()}{Returns collections file content as character vector.}
30 #'   \item{get(relativePath)}{If relativePath is valid, returns ArvadosFile or Subcollection specified by relativePath, else returns NULL.}
31 #' }
32 #'
33 #' @name Collection
34 #' @examples
35 #' \dontrun{
36 #' arv <- Arvados$new("your Arvados token", "example.arvadosapi.com")
37 #' collection <- Collection$new(arv, "uuid")
38 #'
39 #' newFile <- ArvadosFile$new("myFile")
40 #' collection$add(newFile, "myFolder")
41 #'
42 #' createdFiles <- collection$create(c("main.cpp", lib.dll), "cpp/src/")
43 #'
44 #' collection$remove("location/to/my/file.cpp")
45 #'
46 #' collection$move("folder/file.cpp", "file.cpp")
47 #'
48 #' arvadosFile <- collection$get("location/to/my/file.cpp")
49 #' arvadosSubcollection <- collection$get("location/to/my/directory/")
50 #' }
51 NULL
52
53 #' @export
54 Collection <- R6::R6Class(
55
56     "Collection",
57
58     public = list(
59
60                 uuid = NULL,
61
62                 initialize = function(api, uuid)
63         {
64             private$REST <- api$getRESTService()
65             self$uuid <- uuid
66         },
67
68         add = function(content, relativePath = "")
69         {
70             if(is.null(private$tree))
71                 private$generateCollectionTreeStructure()
72
73             if(relativePath == ""  ||
74                relativePath == "." ||
75                relativePath == "./")
76             {
77                 subcollection <- private$tree$getTree()
78             }
79             else
80             {
81                 relativePath <- trimFromEnd(relativePath, "/")
82                 subcollection <- self$get(relativePath)
83             }
84
85             if(is.null(subcollection))
86                 stop(paste("Subcollection", relativePath, "doesn't exist."))
87
88             if("ArvadosFile"   %in% class(content) ||
89                "Subcollection" %in% class(content))
90             {
91                 if(content$getName() == "")
92                     stop("Content has invalid name.")
93
94                 subcollection$add(content)
95                 content
96             }
97             else
98             {
99                 stop(paste0("Expected AravodsFile or Subcollection object, got ",
100                             paste0("(", paste0(class(content), collapse = ", "), ")"),
101                             "."))
102             }
103         },
104
105         create = function(fileNames, relativePath = "")
106         {
107             if(is.null(private$tree))
108                 private$generateCollectionTreeStructure()
109
110             if(relativePath == ""  ||
111                relativePath == "." ||
112                relativePath == "./")
113             {
114                 subcollection <- private$tree$getTree()
115             }
116             else
117             {
118                 relativePath  <- trimFromEnd(relativePath, "/")
119                 subcollection <- self$get(relativePath)
120             }
121
122             if(is.null(subcollection))
123                 stop(paste("Subcollection", relativePath, "doesn't exist."))
124
125             if(is.character(fileNames))
126             {
127                 arvadosFiles <- NULL
128                 sapply(fileNames, function(fileName)
129                 {
130                     childWithSameName <- subcollection$get(fileName)
131                     if(!is.null(childWithSameName))
132                         stop("Destination already contains file with same name.")
133
134                     newFile <- ArvadosFile$new(fileName)
135                     subcollection$add(newFile)
136
137                     arvadosFiles <<- c(arvadosFiles, newFile)
138                 })
139
140                 if(length(arvadosFiles) == 1)
141                     return(arvadosFiles[[1]])
142                 else
143                     return(arvadosFiles)
144             }
145             else
146             {
147                 stop(paste0("Expected character vector, got ",
148                             paste0("(", paste0(class(fileNames), collapse = ", "), ")"),
149                             "."))
150             }
151         },
152
153         remove = function(paths)
154         {
155             if(is.null(private$tree))
156                 private$generateCollectionTreeStructure()
157
158             if(is.character(paths))
159             {
160                 sapply(paths, function(filePath)
161                 {
162                     filePath <- trimFromEnd(filePath, "/")
163                     file <- self$get(filePath)
164
165                     if(is.null(file))
166                         stop(paste("File", filePath, "doesn't exist."))
167
168                     parent <- file$getParent()
169
170                     if(is.null(parent))
171                         stop("You can't delete root folder.")
172
173                     parent$remove(file$getName())
174                 })
175
176                 "Content removed"
177             }
178             else
179             {
180                 stop(paste0("Expected character vector, got ",
181                             paste0("(", paste0(class(paths), collapse = ", "), ")"),
182                             "."))
183             }
184         },
185
186         move = function(content, destination)
187         {
188             if(is.null(private$tree))
189                 private$generateCollectionTreeStructure()
190
191             content <- trimFromEnd(content, "/")
192
193             elementToMove <- self$get(content)
194
195             if(is.null(elementToMove))
196                 stop("Content you want to move doesn't exist in the collection.")
197
198             elementToMove$move(destination)
199         },
200
201         copy = function(content, destination)
202         {
203             if(is.null(private$tree))
204                 private$generateCollectionTreeStructure()
205
206             content <- trimFromEnd(content, "/")
207
208             elementToCopy <- self$get(content)
209
210             if(is.null(elementToCopy))
211                 stop("Content you want to copy doesn't exist in the collection.")
212
213             elementToCopy$copy(destination)
214         },
215
216         refresh = function()
217         {
218             private$tree$getTree()$setCollection(NULL, setRecursively = TRUE)
219             private$tree <- NULL
220         },
221
222         getFileListing = function()
223         {
224             if(is.null(private$tree))
225                 private$generateCollectionTreeStructure()
226
227             content <- private$REST$getCollectionContent(self$uuid)
228             content[order(tolower(content))]
229         },
230
231         get = function(relativePath)
232         {
233             if(is.null(private$tree))
234                 private$generateCollectionTreeStructure()
235
236             private$tree$getElement(relativePath)
237         },
238
239         getRESTService = function() private$REST,
240         setRESTService = function(newRESTService) private$REST <- newRESTService
241     ),
242
243     private = list(
244
245         REST        = NULL,
246         tree        = NULL,
247         fileContent = NULL,
248
249         generateCollectionTreeStructure = function()
250         {
251             if(is.null(self$uuid))
252                 stop("Collection uuid is not defined.")
253
254             if(is.null(private$REST))
255                 stop("REST service is not defined.")
256
257             private$fileContent <- private$REST$getCollectionContent(self$uuid)
258             private$tree <- CollectionTree$new(private$fileContent, self)
259         }
260     ),
261
262     cloneable = FALSE
263 )
264
265 #' print.Collection
266 #'
267 #' Custom print function for Collection class
268 #'
269 #' @param x Instance of Collection class
270 #' @param ... Optional arguments.
271 #' @export
272 print.Collection = function(x, ...)
273 {
274     cat(paste0("Type: ", "\"", "Arvados Collection", "\""), sep = "\n")
275     cat(paste0("uuid: ", "\"", x$uuid,               "\""), sep = "\n")
276 }