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