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